diff --git a/bin/msvc14/x64/xerces-c_3_1.dll b/bin/msvc14/x64/xerces-c_3_1.dll new file mode 100644 index 0000000..71a6e81 Binary files /dev/null and b/bin/msvc14/x64/xerces-c_3_1.dll differ diff --git a/bin/msvc14/x64/xerces-c_3_1D.dll b/bin/msvc14/x64/xerces-c_3_1D.dll new file mode 100644 index 0000000..6d740f3 Binary files /dev/null and b/bin/msvc14/x64/xerces-c_3_1D.dll differ diff --git a/include/xercesc/NLS/EN_US/XMLErrList_EN_US.Xml b/include/xercesc/NLS/EN_US/XMLErrList_EN_US.Xml new file mode 100644 index 0000000..271f008 --- /dev/null +++ b/include/xercesc/NLS/EN_US/XMLErrList_EN_US.Xml @@ -0,0 +1,846 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/xercesc/NLS/XMLErrList.dtd b/include/xercesc/NLS/XMLErrList.dtd new file mode 100644 index 0000000..12357c8 --- /dev/null +++ b/include/xercesc/NLS/XMLErrList.dtd @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/include/xercesc/dom/DOM.hpp b/include/xercesc/dom/DOM.hpp new file mode 100644 index 0000000..1cf3dc2 --- /dev/null +++ b/include/xercesc/dom/DOM.hpp @@ -0,0 +1,87 @@ +/* + * 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: DOM.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOM_HPP) +#define XERCESC_INCLUDE_GUARD_DOM_HPP + +// +// This is the primary header file for inclusion in application +// programs using the C++ XML Document Object Model API. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Introduced in DOM Level 2 +#include +#include +#include +#include +#include +#include +#include + +// Introduced in DOM Level 3 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#endif diff --git a/include/xercesc/dom/DOMAttr.hpp b/include/xercesc/dom/DOMAttr.hpp new file mode 100644 index 0000000..9f94942 --- /dev/null +++ b/include/xercesc/dom/DOMAttr.hpp @@ -0,0 +1,176 @@ +/* + * 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: DOMAttr.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMATTR_HPP) +#define XERCESC_INCLUDE_GUARD_DOMATTR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMElement; +class DOMTypeInfo; + +/** + * The DOMAttr class refers to an attribute of an XML element. + * + * Typically the allowable values for the + * attribute are defined in a documenttype definition. + *

DOMAttr objects inherit the DOMNode interface, but + * since attributes are not actually child nodes of the elements they are associated with, the + * DOM does not consider them part of the document tree. Thus, the + * DOMNode attributes parentNode, + * previousSibling, and nextSibling have a null + * value for DOMAttr objects. The DOM takes the view that + * attributes are properties of elements rather than having a separate + * identity from the elements they are associated with; this should make it + * more efficient to implement such features as default attributes associated + * with all elements of a given type. Furthermore, attribute nodes + * may not be immediate children of a DOMDocumentFragment. However, + * they can be associated with DOMElement nodes contained within a + * DOMDocumentFragment. In short, users of the DOM + * need to be aware that DOMAttr nodes have some things in common + * with other objects inheriting the DOMNode interface, but they + * also are quite distinct. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMAttr: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMAttr() {} + DOMAttr(const DOMAttr &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMAttr & operator = (const DOMAttr &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMAttr() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMAttr interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the name of this attribute. + * @since DOM Level 1 + */ + virtual const XMLCh * getName() const = 0; + + /** + * + * Returns true if the attribute received its value explicitly in the + * XML document, or if a value was assigned programatically with + * the setValue function. Returns false if the attribute value + * came from the default value declared in the document's DTD. + * @since DOM Level 1 + */ + virtual bool getSpecified() const = 0; + + /** + * Returns the value of the attribute. + * + * The value of the attribute is returned as a string. + * Character and general entity references are replaced with their values. + * @since DOM Level 1 + */ + virtual const XMLCh * getValue() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Sets the value of the attribute. A text node with the unparsed contents + * of the string will be created. + * + * @param value The value of the DOM attribute to be set + * @since DOM Level 1 + */ + virtual void setValue(const XMLCh *value) = 0; + //@} + + /** @name Functions introduced in DOM Level 2. */ + //@{ + /** + * The DOMElement node this attribute is attached to or + * null if this attribute is not in use. + * + * @since DOM Level 2 + */ + virtual DOMElement *getOwnerElement() const = 0; + //@} + + /** @name Functions introduced in DOM Level 3. */ + //@{ + /** + * Returns whether this attribute is known to be of type ID or not. + * When it is and its value is unique, the ownerElement of this attribute + * can be retrieved using getElementById on DOMDocument. + * + * @return bool stating if this DOMAttr is an ID + * @since DOM level 3 + */ + virtual bool isId() const = 0; + + + /** + * Returns the type information associated with this attribute. + * + * @return the DOMTypeInfo associated with this attribute + * @since DOM level 3 + */ + virtual const DOMTypeInfo * getSchemaTypeInfo() const = 0; + + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMCDATASection.hpp b/include/xercesc/dom/DOMCDATASection.hpp new file mode 100644 index 0000000..624c6c2 --- /dev/null +++ b/include/xercesc/dom/DOMCDATASection.hpp @@ -0,0 +1,104 @@ +/* + * 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: DOMCDATASection.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCDATASECTION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCDATASECTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * CDATA sections are used to escape blocks of text containing characters that + * would otherwise be regarded as markup. The only delimiter that is + * recognized in a CDATA section is the "]]>" string that ends the CDATA + * section. CDATA sections cannot be nested. Their primary purpose is for + * including material such as XML fragments, without needing to escape all + * the delimiters. + *

The data attribute of the DOMText node holds + * the text that is contained by the CDATA section. Note that this may + * contain characters that need to be escaped outside of CDATA sections and + * that, depending on the character encoding ("charset") chosen for + * serialization, it may be impossible to write out some characters as part + * of a CDATA section. + *

The DOMCDATASection interface inherits from the + * DOMCharacterData interface through the DOMText + * interface. Adjacent DOMCDATASection nodes are not merged by use + * of the normalize method of the DOMNode interface. + * Because no markup is recognized within a DOMCDATASection, + * character numeric references cannot be used as an escape mechanism when + * serializing. Therefore, action needs to be taken when serializing a + * DOMCDATASection with a character encoding where some of the + * contained characters cannot be represented. Failure to do so would not + * produce well-formed XML.One potential solution in the serialization + * process is to end the CDATA section before the character, output the + * character using a character reference or entity reference, and open a new + * CDATA section for any further characters in the text node. Note, however, + * that some code conversion libraries at the time of writing do not return + * an error or exception when a character is missing from the encoding, + * making the task of ensuring that data is not corrupted on serialization + * more difficult. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMCDATASection: public DOMText { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMCDATASection() {} + DOMCDATASection(const DOMCDATASection &other) : DOMText(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMCDATASection & operator = (const DOMCDATASection &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMCDATASection() {}; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMCharacterData.hpp b/include/xercesc/dom/DOMCharacterData.hpp new file mode 100644 index 0000000..9dc4f1c --- /dev/null +++ b/include/xercesc/dom/DOMCharacterData.hpp @@ -0,0 +1,215 @@ +/* + * 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: DOMCharacterData.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCHARACTERDATA_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCHARACTERDATA_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * The DOMCharacterData interface extends DOMNode with a set of + * attributes and methods for accessing character data in the DOM. For + * clarity this set is defined here rather than on each object that uses + * these attributes and methods. No DOM objects correspond directly to + * DOMCharacterData, though DOMText and others do + * inherit the interface from it. All offsets in this interface + * start from 0. + *

As explained in the DOM spec, text strings in + * the DOM are represented in UTF-16, i.e. as a sequence of 16-bit units. In + * the following, the term 16-bit units is used whenever necessary to + * indicate that indexing on DOMCharacterData is done in 16-bit units. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMCharacterData: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMCharacterData() {} + DOMCharacterData(const DOMCharacterData &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMCharacterData & operator = (const DOMCharacterData &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMCharacterData() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMCharacterData interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the character data of the node that implements this interface. + * + * The DOM implementation may not put arbitrary limits on the amount of data that + * may be stored in a DOMCharacterData node. However, + * implementation limits may mean that the entirety of a node's data may + * not fit into a single XMLCh* String. In such cases, the user + * may call substringData to retrieve the data in + * appropriately sized pieces. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + * @since DOM Level 1 + */ + virtual const XMLCh * getData() const = 0; + + /** + * Returns the number of characters that are available through data and + * the substringData method below. + * + * This may have the value + * zero, i.e., CharacterData nodes may be empty. + * @since DOM Level 1 + */ + virtual XMLSize_t getLength() const = 0; + + /** + * Extracts a range of data from the node. + * + * @param offset Start offset of substring to extract. + * @param count The number of characters to extract. + * @return The specified substring. If the sum of offset and + * count exceeds the length, then all + * characters to the end of the data are returned. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater + * than the number of characters in data, or if the + * specified count is negative. + * @since DOM Level 1 + */ + virtual const XMLCh * substringData(XMLSize_t offset, + XMLSize_t count) const = 0; + + // ----------------------------------------------------------------------- + // String methods + // ----------------------------------------------------------------------- + /** + * Append the string to the end of the character data of the node. + * + * Upon success, data provides access to the concatenation of + * data and the XMLCh* String specified. + * @param arg The XMLCh* String to append. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual void appendData(const XMLCh *arg) = 0; + + /** + * Insert a string at the specified character offset. + * + * @param offset The character offset at which to insert. + * @param arg The XMLCh* String to insert. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater + * than the number of characters in data. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual void insertData(XMLSize_t offset, const XMLCh *arg) = 0; + + /** + * Remove a range of characters from the node. + * + * Upon success, + * data and length reflect the change. + * @param offset The offset from which to remove characters. + * @param count The number of characters to delete. If the sum of + * offset and count exceeds length + * then all characters from offset to the end of the data + * are deleted. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater + * than the number of characters in data, or if the + * specified count is negative. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual void deleteData(XMLSize_t offset, + XMLSize_t count) = 0; + + /** + * Replace the characters starting at the specified character offset with + * the specified string. + * + * @param offset The offset from which to start replacing. + * @param count The number of characters to replace. If the sum of + * offset and count exceeds length + * , then all characters to the end of the data are replaced (i.e., the + * effect is the same as a remove method call with the same + * range, followed by an append method invocation). + * @param arg The XMLCh* String with which the range must be + * replaced. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater + * than the number of characters in data, or if the + * specified count is negative. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual void replaceData(XMLSize_t offset, + XMLSize_t count, + const XMLCh *arg) = 0; + + /** + * Sets the character data of the node that implements this interface. + * + * @param data The XMLCh* String to set. + * @since DOM Level 1 + */ + virtual void setData(const XMLCh *data) = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMComment.hpp b/include/xercesc/dom/DOMComment.hpp new file mode 100644 index 0000000..96d197d --- /dev/null +++ b/include/xercesc/dom/DOMComment.hpp @@ -0,0 +1,76 @@ +/* + * 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: DOMComment.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCOMMENT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCOMMENT_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * This interface inherits from CharacterData and represents the + * content of a comment, i.e., all the characters between the starting ' + * <!--' and ending '-->'. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMComment: public DOMCharacterData { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMComment() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMComment(const DOMComment &); + DOMComment & operator = (const DOMComment &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMComment() {}; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/DOMConfiguration.hpp b/include/xercesc/dom/DOMConfiguration.hpp new file mode 100644 index 0000000..bbd8809 --- /dev/null +++ b/include/xercesc/dom/DOMConfiguration.hpp @@ -0,0 +1,454 @@ +/* + * 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. + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCONFIGURATION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCONFIGURATION_HPP + +//------------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------------ + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * The DOMConfiguration interface represents the configuration of + * a document and maintains a table of recognized parameters. + * Using the configuration, it is possible to change + * Document.normalizeDocument behavior, such as replacing + * CDATASection nodes with Text nodes or + * specifying the type of the schema that must be used when the + * validation of the Document is requested. DOMConfiguration + * objects are also used in [DOM Level 3 Load and Save] in + * the DOMLSParser and DOMLSSerializer interfaces. + * + * The DOMConfiguration distinguish two types of parameters: + * boolean (boolean parameters) and DOMUserData + * (parameters). The names used by the DOMConfiguration object are + * defined throughout the DOM Level 3 specifications. Names are + * case-insensitive. To avoid possible conflicts, as a + * convention, names referring to boolean parameters and + * parameters defined outside the DOM specification should be made + * unique. Names are recommended to follow the XML name + * production rule but it is not enforced by the DOM + * implementation. DOM Level 3 Core Implementations are required + * to recognize all boolean parameters and parameters defined in + * this specification. Each boolean parameter state or parameter + * value may then be supported or not by the implementation. Refer + * to their definition to know if a state or a value must be + * supported or not. + * + * Note: Parameters are similar to features and properties used in + * SAX2 [SAX]. + * + * The following list of parameters defined in the DOM: + * + * "error-handler" + * [required] + * A DOMErrorHandler object. If an error is + * encountered in the document, the implementation will call + * back the DOMErrorHandler registered using this + * parameter. + * When called, DOMError.relatedData will contain the + * closest node to where the error occured. If the + * implementation is unable to determine the node where the + * error occurs, DOMError.relatedData will contain the + * Document node. Mutations to the document from + * within an error handler will result in implementation + * dependent behaviour. + * + * "schema-type" + * [optional] + * A DOMString object containing an absolute URI and + * representing the type of the schema language used to + * validate a document against. Note that no lexical + * checking is done on the absolute URI. + * If this parameter is not set, a default value may be + * provided by the implementation, based on the schema + * languages supported and on the schema language used at + * load time. + * + * Note: For XML Schema [XML Schema Part 1], + * applications must use the value + * "http://www.w3.org/2001/XMLSchema". For XML DTD + * [XML 1.0], applications must use the value + * "http://www.w3.org/TR/REC-xml". Other schema languages + * are outside the scope of the W3C and therefore should + * recommend an absolute URI in order to use this method. + * + * "schema-location" + * [optional] + * A DOMString object containing a list of URIs, + * separated by white spaces (characters matching the + * nonterminal production S defined in section 2.3 + * [XML 1.0]), that represents the schemas against + * which validation should occur. The types of schemas + * referenced in this list must match the type specified + * with schema-type, otherwise the behaviour of an + * implementation is undefined. If the schema type is XML + * Schema [XML Schema Part 1], only one of the XML + * Schemas in the list can be with no namespace. + * If validation occurs against a namespace aware schema, + * i.e. XML Schema, and the targetNamespace of a schema + * (specified using this property) matches the + * targetNamespace of a schema occurring in the instance + * document, i.e in schemaLocation attribute, the schema + * specified by the user using this property will be used + * (i.e., in XML Schema the schemaLocation attribute in the + * instance document or on the import element will be + * effectively ignored). + * + * Note: It is illegal to set the schema-location parameter + * if the schema-type parameter value is not set. It is + * strongly recommended that DOMInputSource.baseURI will be + * set, so that an implementation can successfully resolve + * any external entities referenced. + * + * The following list of boolean parameters (features) defined in + * the DOM: + * + * "canonical-form" + * + * true + * [optional] + * Canonicalize the document according to the rules + * specified in [Canonical XML]. Note that this + * is limited to what can be represented in the DOM. + * In particular, there is no way to specify the order + * of the attributes in the DOM. + * + * false + * [required] (default) + * Do not canonicalize the document. + * + * "cdata-sections" + * + * true + * [required] (default) + * Keep CDATASection nodes in the document. + * + * false + * [required] + * Transform CDATASection nodes in the document + * into Text nodes. The new Text node is + * then combined with any adjacent Text node. + * + * "comments" + * + * true + * [required] (default) + * Keep Comment nodes in the document. + * + * false + * [required] + * Discard Comment nodes in the Document. + * + * "datatype-normalization" + * + * true + * [required] + * Exposed normalized values in the tree. + * + * false + * [required] (default) + * Do not perform normalization on the tree. + * + * "discard-default-content" + * + * true + * [required] (default) + * Use whatever information available to the + * implementation (i.e. XML schema, DTD, the specified + * flag on Attr nodes, and so on) to decide what + * attributes and content should be discarded or not. + * Note that the specified flag on Attr nodes in + * itself is not always reliable, it is only reliable + * when it is set to false since the only case where + * it can be set to false is if the attribute was + * created by the implementation. The default content + * won't be removed if an implementation does not have + * any information available. + * + * false + * [required] + * Keep all attributes and all content. + * + * "entities" + * + * true + * [required] + * Keep EntityReference and Entity nodes + * in the document. + * + * false + * [required] (default) + * Remove all EntityReference and Entity + * nodes from the document, putting the entity + * expansions directly in their place. Text + * nodes are into "normal" form. Only + * EntityReference nodes to non-defined entities + * are kept in the document. + * + * "infoset" + * + * true + * [required] + * Only keep in the document the information defined + * in the XML Information Set [XML Information + * set]. + * This forces the following features to false: + * namespace-declarations, validate-if-schema, + * entities, datatype-normalization, cdata-sections. + * This forces the following features to true: + * whitespace-in-element-content, comments, + * namespaces. + * Other features are not changed unless explicitly + * specified in the description of the features. + * Note that querying this feature with getFeature + * returns true only if the individual features + * specified above are appropriately set. + * + * false + * Setting infoset to false has no effect. + * + * "namespaces" + * + * true + * [required] (default) + * Perform the namespace processing as defined in + * [XML Namespaces]. + * + * false + * [optional] + * Do not perform the namespace processing. + * + * "namespace-declarations" + * + * true + * [required] (default) + * Include namespace declaration attributes, specified + * or defaulted from the schema or the DTD, in the + * document. See also the section Declaring + * Namespaces in [XML Namespaces]. + * + * false + * [required] + * Discard all namespace declaration attributes. The + * Namespace prefixes are retained even if this + * feature is set to false. + * + * "normalize-characters" + * + * true + * [optional] + * Perform the W3C Text Normalization of the + * characters [CharModel] in the document. + * + * false + * [required] (default) + * Do not perform character normalization. + * + * "split-cdata-sections" + * + * true + * [required] (default) + * Split CDATA sections containing the CDATA section + * termination marker ']]>'. When a CDATA section is + * split a warning is issued. + * + * false + * [required] + * Signal an error if a CDATASection contains an + * unrepresentable character. + * + * "validate" + * + * true + * [optional] + * Require the validation against a schema (i.e. XML + * schema, DTD, any other type or representation of + * schema) of the document as it is being normalized + * as defined by [XML 1.0]. If validation errors + * are found, or no schema was found, the error + * handler is notified. Note also that normalized + * values will not be exposed to the schema in used + * unless the feature datatype-normalization is true. + * + * Note: validate-if-schema and validate are mutually + * exclusive, setting one of them to true will set the + * other one to false. + * + * false + * [required] (default) + * Only XML 1.0 non-validating processing must be + * done. Note that validation might still happen if + * validate-if-schema is true. + * + * "validate-if-schema" + * + * true + * [optional] + * Enable validation only if a declaration for the + * document element can be found (independently of + * where it is found, i.e. XML schema, DTD, or any + * other type or representation of schema). If + * validation errors are found, the error handler is + * notified. Note also that normalized values will not + * be exposed to the schema in used unless the feature + * datatype-normalization is true. + * + * Note: validate-if-schema and validate are mutually + * exclusive, setting one of them to true will set the + * other one to false. + * + * false + * [required] (default) + * No validation should be performed if the document + * has a schema. Note that validation must still + * happen if validate is true. + * + * "element-content-whitespace" + * + * true + * [required] (default) + * Keep all white spaces in the document. + * + * false + * [optional] + * Discard white space in element content while + * normalizing. The implementation is expected to use + * the isWhitespaceInElementContent flag on Text + * nodes to determine if a text node should be written + * out or not. + * + * The resolutions of entities is done using Document.baseURI. + * However, when the features "LS-Load" or "LS-Save" defined in + * [DOM Level 3 Load and Save] are supported by the DOM + * implementation, the parameter "entity-resolver" can also be + * used on DOMConfiguration objects attached to Document + * nodes. If this parameter is set, + * Document.normalizeDocument will invoke the entity + * resolver instead of using Document.baseURI. + */ +class CDOM_EXPORT DOMConfiguration +{ +protected: + //----------------------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMConfiguration() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMConfiguration(const DOMConfiguration &); + DOMConfiguration & operator = (const DOMConfiguration &); + //@} + +public: + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** Set the value of a parameter. + * @param name The name of the parameter to set. + * @param value The new value or null if the user wishes to unset the + * parameter. While the type of the value parameter is defined as + * DOMUserData, the object type must match the type defined + * by the definition of the parameter. For example, if the parameter is + * "error-handler", the value must be of type DOMErrorHandler + * @exception DOMException (NOT_SUPPORTED_ERR) Raised when the + * parameter name is recognized but the requested value cannot be set. + * @exception DOMException (NOT_FOUND_ERR) Raised when the + * parameter name is not recognized. + * @since DOM level 3 + **/ + virtual void setParameter(const XMLCh* name, const void* value) = 0; + virtual void setParameter(const XMLCh* name, bool value) = 0; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** Return the value of a parameter if known. + * @param name The name of the parameter. + * @return The current object associated with the specified parameter or + * null if no object has been associated or if the parameter is not + * supported. + * @exception DOMException (NOT_FOUND_ERR) Raised when the i + * boolean parameter + * name is not recognized. + * @since DOM level 3 + **/ + virtual const void* getParameter(const XMLCh* name) const = 0; + + + // ----------------------------------------------------------------------- + // Query methods + // ----------------------------------------------------------------------- + + /** Check if setting a parameter to a specific value is supported. + * @param name The name of the parameter to check. + * @param value An object. if null, the returned value is true. + * @return true if the parameter could be successfully set to the specified + * value, or false if the parameter is not recognized or the requested value + * is not supported. This does not change the current value of the parameter + * itself. + * @since DOM level 3 + **/ + virtual bool canSetParameter(const XMLCh* name, const void* value) const = 0; + virtual bool canSetParameter(const XMLCh* name, bool value) const = 0; + + /** + * The list of the parameters supported by this DOMConfiguration object and + * for which at least one value can be set by the application. + * Note that this list can also contain parameter names defined outside this specification. + * + * @return The list of parameters that can be used with setParameter/getParameter + * @since DOM level 3 + **/ + virtual const DOMStringList* getParameterNames() const = 0; + + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMConfiguration() {}; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DOMConfiguration.hpp + */ diff --git a/include/xercesc/dom/DOMDocument.hpp b/include/xercesc/dom/DOMDocument.hpp new file mode 100644 index 0000000..1505b7d --- /dev/null +++ b/include/xercesc/dom/DOMDocument.hpp @@ -0,0 +1,819 @@ +/* + * 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: DOMDocument.hpp 932887 2010-04-11 13:04:59Z borisk $ +*/ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENT_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMConfiguration; +class DOMDocumentType; +class DOMElement; +class DOMDocumentFragment; +class DOMComment; +class DOMCDATASection; +class DOMProcessingInstruction; +class DOMAttr; +class DOMEntity; +class DOMEntityReference; +class DOMImplementation; +class DOMNodeFilter; +class DOMNodeList; +class DOMNotation; +class DOMText; +class DOMNode; + + +/** + * The DOMDocument interface represents the entire XML + * document. Conceptually, it is the root of the document tree, and provides + * the primary access to the document's data. + *

Since elements, text nodes, comments, processing instructions, etc. + * cannot exist outside the context of a DOMDocument, the + * DOMDocument interface also contains the factory methods needed + * to create these objects. The DOMNode objects created have a + * ownerDocument attribute which associates them with the + * DOMDocument within whose context they were created. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + */ + +class CDOM_EXPORT DOMDocument: public DOMDocumentRange, + public DOMXPathEvaluator, + public DOMDocumentTraversal, + public DOMNode { + + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMDocument() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMDocument(const DOMDocument &); + DOMDocument & operator = (const DOMDocument &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMDocument() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMDocument interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + /** + * Creates an element of the type specified. Note that the instance + * returned implements the DOMElement interface, so attributes + * can be specified directly on the returned object. + *
In addition, if there are known attributes with default values, + * DOMAttr nodes representing them are automatically created + * and attached to the element. + *
To create an element with a qualified name and namespace URI, use + * the createElementNS method. + * @param tagName The name of the element type to instantiate. For XML, + * this is case-sensitive. + * @return A new DOMElement object with the + * nodeName attribute set to tagName, and + * localName, prefix, and + * namespaceURI set to null. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + * @since DOM Level 1 + */ + virtual DOMElement *createElement(const XMLCh *tagName) = 0; + + /** + * Creates an empty DOMDocumentFragment object. + * @return A new DOMDocumentFragment. + * @since DOM Level 1 + */ + virtual DOMDocumentFragment *createDocumentFragment() = 0; + + /** + * Creates a DOMText node given the specified string. + * @param data The data for the node. + * @return The new DOMText object. + * @since DOM Level 1 + */ + virtual DOMText *createTextNode(const XMLCh *data) = 0; + + /** + * Creates a DOMComment node given the specified string. + * @param data The data for the node. + * @return The new DOMComment object. + * @since DOM Level 1 + */ + virtual DOMComment *createComment(const XMLCh *data) = 0; + + /** + * Creates a DOMCDATASection node whose value is the specified + * string. + * @param data The data for the DOMCDATASection contents. + * @return The new DOMCDATASection object. + * @since DOM Level 1 + */ + virtual DOMCDATASection *createCDATASection(const XMLCh *data) = 0; + + /** + * Creates a DOMProcessingInstruction node given the specified + * name and data strings. + * @param target The target part of the processing instruction. + * @param data The data for the node. + * @return The new DOMProcessingInstruction object. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified target contains an + * illegal character. + * @since DOM Level 1 + */ + virtual DOMProcessingInstruction *createProcessingInstruction(const XMLCh *target, + const XMLCh *data) = 0; + + + /** + * Creates an DOMAttr of the given name. Note that the + * DOMAttr instance can then be set on an DOMElement + * using the setAttributeNode method. + *
To create an attribute with a qualified name and namespace URI, use + * the createAttributeNS method. + * @param name The name of the attribute. + * @return A new DOMAttr object with the nodeName + * attribute set to name, and localName, + * prefix, and namespaceURI set to + * null. The value of the attribute is the empty string. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + * @since DOM Level 1 + */ + virtual DOMAttr *createAttribute(const XMLCh *name) = 0; + + + /** + * Creates an DOMEntityReference object. In addition, if the + * referenced entity is known, the child list of the + * DOMEntityReference node is made the same as that of the + * corresponding DOMEntity node.If any descendant of the + * DOMEntity node has an unbound namespace prefix, the + * corresponding descendant of the created DOMEntityReference + * node is also unbound; (its namespaceURI is + * null). The DOM Level 2 does not support any mechanism to + * resolve namespace prefixes. + * @param name The name of the entity to reference. + * @return The new DOMEntityReference object. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + * @since DOM Level 1 + */ + virtual DOMEntityReference *createEntityReference(const XMLCh *name) = 0; + + /** + * The Document Type Declaration (see DOMDocumentType) + * associated with this document. For XML + * documents without a document type declaration this returns + * null. The DOM Level 2 does not support editing the + * Document Type Declaration. docType cannot be altered in + * any way, including through the use of methods inherited from the + * DOMNode interface, such as insertNode or + * removeNode. + * @since DOM Level 1 + */ + virtual DOMDocumentType *getDoctype() const = 0; + + /** + * The DOMImplementation object that handles this document. A + * DOM application may use objects from multiple implementations. + * @since DOM Level 1 + */ + virtual DOMImplementation *getImplementation() const = 0; + + /** + * This is a convenience attribute that allows direct access to the child + * node that is the root element of the document. + * @since DOM Level 1 + */ + virtual DOMElement *getDocumentElement() const = 0; + + /** + * Returns a DOMNodeList of all the DOMElement(s) with a + * given tag name in the order in which they are encountered in a + * preorder traversal of the DOMDocument tree. + * + * The returned node list is "live", in that changes + * to the document tree made after a nodelist was initially + * returned will be immediately reflected in the node list. + * @param tagname The name of the tag to match on. The special value "*" + * matches all tags. + * @return A new DOMNodeList object containing all the matched + * DOMElement(s). + * @since DOM Level 1 + */ + virtual DOMNodeList *getElementsByTagName(const XMLCh *tagname) const = 0; + + //@} + + /** @name Functions introduced in DOM Level 2. */ + //@{ + + /** + * Imports a node from another document to this document. The returned + * node has no parent; (parentNode is null). + * The source node is not altered or removed from the original document; + * this method creates a new copy of the source node. + *
For all nodes, importing a node creates a node object owned by the + * importing document, with attribute values identical to the source + * node's nodeName and nodeType, plus the + * attributes related to namespaces (prefix, + * localName, and namespaceURI). As in the + * cloneNode operation on a DOMNode, the source + * node is not altered. + *
Additional information is copied as appropriate to the + * nodeType, attempting to mirror the behavior expected if + * a fragment of XML source was copied from one document to + * another, recognizing that the two documents may have different DTDs + * in the XML case. The following list describes the specifics for each + * type of node. + *

+ *
ATTRIBUTE_NODE
+ *
The ownerElement attribute + * is set to null and the specified flag is + * set to true on the generated DOMAttr. The + * descendants of the source DOMAttr are recursively imported + * and the resulting nodes reassembled to form the corresponding subtree. + * Note that the deep parameter has no effect on + * DOMAttr nodes; they always carry their children with them + * when imported.
+ *
DOCUMENT_FRAGMENT_NODE
+ *
If the deep option + * was set to true, the descendants of the source element + * are recursively imported and the resulting nodes reassembled to form + * the corresponding subtree. Otherwise, this simply generates an empty + * DOMDocumentFragment.
+ *
DOCUMENT_NODE
+ *
DOMDocument + * nodes cannot be imported.
+ *
DOCUMENT_TYPE_NODE
+ *
DOMDocumentType + * nodes cannot be imported.
+ *
ELEMENT_NODE
+ *
Specified attribute nodes of the + * source element are imported, and the generated DOMAttr + * nodes are attached to the generated DOMElement. Default + * attributes are not copied, though if the document being imported into + * defines default attributes for this element name, those are assigned. + * If the importNode deep parameter was set to + * true, the descendants of the source element are + * recursively imported and the resulting nodes reassembled to form the + * corresponding subtree.
+ *
ENTITY_NODE
+ *
DOMEntity nodes can be + * imported, however in the current release of the DOM the + * DOMDocumentType is readonly. Ability to add these imported + * nodes to a DOMDocumentType will be considered for addition + * to a future release of the DOM.On import, the publicId, + * systemId, and notationName attributes are + * copied. If a deep import is requested, the descendants + * of the the source DOMEntity are recursively imported and + * the resulting nodes reassembled to form the corresponding subtree.
+ *
+ * ENTITY_REFERENCE_NODE
+ *
Only the DOMEntityReference itself is + * copied, even if a deep import is requested, since the + * source and destination documents might have defined the entity + * differently. If the document being imported into provides a + * definition for this entity name, its value is assigned.
+ *
NOTATION_NODE
+ *
+ * DOMNotation nodes can be imported, however in the current + * release of the DOM the DOMDocumentType is readonly. Ability + * to add these imported nodes to a DOMDocumentType will be + * considered for addition to a future release of the DOM.On import, the + * publicId and systemId attributes are copied. + * Note that the deep parameter has no effect on + * DOMNotation nodes since they never have any children.
+ *
+ * PROCESSING_INSTRUCTION_NODE
+ *
The imported node copies its + * target and data values from those of the + * source node.
+ *
TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE
+ *
These three + * types of nodes inheriting from DOMCharacterData copy their + * data and length attributes from those of + * the source node.
+ *
+ * @param importedNode The node to import. + * @param deep If true, recursively import the subtree under + * the specified node; if false, import only the node + * itself, as explained above. This has no effect on DOMAttr + * , DOMEntityReference, and DOMNotation nodes. + * @return The imported node that belongs to this DOMDocument. + * @exception DOMException + * NOT_SUPPORTED_ERR: Raised if the type of node being imported is not + * supported. + * @since DOM Level 2 + */ + virtual DOMNode *importNode(const DOMNode *importedNode, bool deep) = 0; + + /** + * Creates an element of the given qualified name and namespace URI. + * @param namespaceURI The namespace URI of the element to create. + * @param qualifiedName The qualified name of the element type to + * instantiate. + * @return A new DOMElement object with the following + * attributes: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Attribute + * Value
DOMNode.nodeName + * qualifiedName
DOMNode.namespaceURI + * namespaceURI
DOMNode.prefixprefix, extracted + * from qualifiedName, or null if there is + * no prefix
DOMNode.localNamelocal name, extracted from + * qualifiedName
DOMElement.tagName + * qualifiedName
+ * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character, per the XML 1.0 specification . + *
NAMESPACE_ERR: Raised if the qualifiedName is + * malformed per the Namespaces in XML specification, if the + * qualifiedName has a prefix and the + * namespaceURI is null, or if the + * qualifiedName has a prefix that is "xml" and the + * namespaceURI is different from " + * http://www.w3.org/XML/1998/namespace" . + *
NOT_SUPPORTED_ERR: Always thrown if the current document does not + * support the "XML" feature, since namespaces were + * defined by XML. + * @since DOM Level 2 + */ + virtual DOMElement *createElementNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName) = 0; + + /** + * Creates an attribute of the given qualified name and namespace URI. + * @param namespaceURI The namespace URI of the attribute to create. + * @param qualifiedName The qualified name of the attribute to + * instantiate. + * @return A new DOMAttr object with the following attributes: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Attribute + * Value
DOMNode.nodeNamequalifiedName
+ * DOMNode.namespaceURInamespaceURI
+ * DOMNode.prefixprefix, extracted from + * qualifiedName, or null if there is no + * prefix
DOMNode.localNamelocal name, extracted from + * qualifiedName
DOMAttr.name + * qualifiedName
DOMNode.nodeValuethe empty + * string
+ * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character, per the XML 1.0 specification . + *
NAMESPACE_ERR: Raised if the qualifiedName is + * malformed per the Namespaces in XML specification, if the + * qualifiedName has a prefix and the + * namespaceURI is null, if the + * qualifiedName has a prefix that is "xml" and the + * namespaceURI is different from " + * http://www.w3.org/XML/1998/namespace", or if the + * qualifiedName, or its prefix, is "xmlns" and the + * namespaceURI is different from " + * http://www.w3.org/2000/xmlns/". + *
NOT_SUPPORTED_ERR: Always thrown if the current document does not + * support the "XML" feature, since namespaces were + * defined by XML. + * @since DOM Level 2 + */ + virtual DOMAttr *createAttributeNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName) = 0; + + /** + * Returns a DOMNodeList of all the DOMElement(s) with a + * given local name and namespace URI in the order in which they are + * encountered in a preorder traversal of the DOMDocument tree. + * @param namespaceURI The namespace URI of the elements to match on. The + * special value "*" matches all namespaces. + * @param localName The local name of the elements to match on. The + * special value "*" matches all local names. + * @return A new DOMNodeList object containing all the matched + * DOMElement(s). + * @since DOM Level 2 + */ + virtual DOMNodeList *getElementsByTagNameNS(const XMLCh *namespaceURI, + const XMLCh *localName) const = 0; + + /** + * Returns the DOMElement whose ID is given by + * elementId. If no such element exists, returns + * null. Behavior is not defined if more than one element + * has this ID. The DOM implementation must have + * information that says which attributes are of type ID. Attributes + * with the name "ID" are not of type ID unless so defined. + * Implementations that do not know whether attributes are of type ID or + * not are expected to return null. + * @param elementId The unique id value for an element. + * @return The matching element. + * @since DOM Level 2 + */ + virtual DOMElement * getElementById(const XMLCh *elementId) const = 0; + //@} + + /** @name Functions introduced in DOM Level 3. */ + //@{ + + /** + * An attribute specifying the encoding used for this document at the time of the parsing. + * This is null when it is not known, such as when the DOMDocument was created in memory. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getInputEncoding() const = 0; + + /** + * An attribute specifying, as part of the XML declaration, the encoding of this document. + * This is null when unspecified or when it is not known, such as when the + * DOMDocument was created in memory. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getXmlEncoding() const = 0; + + /** + * An attribute specifying, as part of the XML declaration, whether this document is standalone. + * This is false when unspecified. + * + * @since DOM Level 3 + */ + virtual bool getXmlStandalone() const = 0; + + /** + * An attribute specifying, as part of the XML declaration, whether this + * document is standalone. + *
This attribute represents the property [standalone] defined in . + * + * @since DOM Level 3 + */ + virtual void setXmlStandalone(bool standalone) = 0; + + /** + * An attribute specifying, as part of the XML declaration, the version + * number of this document. This is null when unspecified. + *
This attribute represents the property [version] defined in . + * + * @since DOM Level 3 + */ + virtual const XMLCh* getXmlVersion() const = 0; + + /** + * An attribute specifying, as part of the XML declaration, the version + * number of this document. This is null when unspecified. + *
This attribute represents the property [version] defined in . + * + * @since DOM Level 3 + */ + virtual void setXmlVersion(const XMLCh* version) = 0; + + /** + * The location of the document or null if undefined. + *
Beware that when the DOMDocument supports the feature + * "HTML" , the href attribute of the HTML BASE element takes precedence + * over this attribute. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getDocumentURI() const = 0; + /** + * The location of the document or null if undefined. + *
Beware that when the DOMDocument supports the feature + * "HTML" , the href attribute of the HTML BASE element takes precedence + * over this attribute. + * + * @since DOM Level 3 + */ + virtual void setDocumentURI(const XMLCh* documentURI) = 0; + + /** + * An attribute specifying whether errors checking is enforced or not. + * When set to false, the implementation is free to not + * test every possible error case normally defined on DOM operations, + * and not raise any DOMException. In case of error, the + * behavior is undefined. This attribute is true by + * defaults. + * + * @since DOM Level 3 + */ + virtual bool getStrictErrorChecking() const = 0; + /** + * An attribute specifying whether errors checking is enforced or not. + * When set to false, the implementation is free to not + * test every possible error case normally defined on DOM operations, + * and not raise any DOMException. In case of error, the + * behavior is undefined. This attribute is true by + * defaults. + * + * @since DOM Level 3 + */ + virtual void setStrictErrorChecking(bool strictErrorChecking) = 0; + + /** + * Rename an existing node. When possible this simply changes the name of + * the given node, otherwise this creates a new node with the specified + * name and replaces the existing node with the new node as described + * below. This only applies to nodes of type ELEMENT_NODE + * and ATTRIBUTE_NODE. + *
When a new node is created, the following operations are performed: + * the new node is created, any registered event listener is registered + * on the new node, any user data attached to the old node is removed + * from that node, the old node is removed from its parent if it has + * one, the children are moved to the new node, if the renamed node is + * an DOMElement its attributes are moved to the new node, the + * new node is inserted at the position the old node used to have in its + * parent's child nodes list if it has one, the user data that was + * attached to the old node is attach to the new node, the user data + * event NODE_RENAMED is fired. + *
When the node being renamed is an DOMAttr that is + * attached to an DOMElement, the node is first removed from + * the DOMElement attributes map. Then, once renamed, either + * by modifying the existing node or creating a new one as described + * above, it is put back. + * + * @param n The node to rename. + * @param namespaceURI The new namespaceURI. + * @param qualifiedName The new qualified name. + * @return The renamed node. This is either the specified node or the new + * node that was created to replace the specified node. + * @exception DOMException + * NOT_SUPPORTED_ERR: Raised when the type of the specified node is + * neither ELEMENT_NODE nor ATTRIBUTE_NODE. + *
WRONG_DOCUMENT_ERR: Raised when the specified node was created + * from a different document than this document. + *
NAMESPACE_ERR: Raised if the qualifiedName is + * malformed per the Namespaces in XML specification, if the + * qualifiedName has a prefix and the + * namespaceURI is null, or if the + * qualifiedName has a prefix that is "xml" and the + * namespaceURI is different from " + * http://www.w3.org/XML/1998/namespace" . Also raised, when the node + * being renamed is an attribute, if the qualifiedName, + * or its prefix, is "xmlns" and the namespaceURI is + * different from "http://www.w3.org/2000/xmlns/". + * @since DOM Level 3 + */ + virtual DOMNode* renameNode(DOMNode* n, const XMLCh* namespaceURI, const XMLCh* qualifiedName) = 0; + + + /** + * Changes the ownerDocument of a node, its children, as well + * as the attached attribute nodes if there are any. If the node has a + * parent it is first removed from its parent child list. This + * effectively allows moving a subtree from one document to another. The + * following list describes the specifics for each type of node. + * + *
+ *
+ * ATTRIBUTE_NODE
+ *
The ownerElement attribute is set to + * null and the specified flag is set to + * true on the adopted DOMAttr. The descendants + * of the source DOMAttr are recursively adopted.
+ *
+ * DOCUMENT_FRAGMENT_NODE
+ *
The descendants of the source node are + * recursively adopted.
+ *
DOCUMENT_NODE
+ *
DOMDocument nodes cannot + * be adopted.
+ *
DOCUMENT_TYPE_NODE
+ *
DOMDocumentType nodes cannot + * be adopted.
+ *
ELEMENT_NODE
+ *
Specified attribute nodes of the source + * element are adopted, and the generated DOMAttr nodes. + * Default attributes are discarded, though if the document being + * adopted into defines default attributes for this element name, those + * are assigned. The descendants of the source element are recursively + * adopted.
+ *
ENTITY_NODE
+ *
DOMEntity nodes cannot be adopted.
+ *
+ * ENTITY_REFERENCE_NODE
+ *
Only the DOMEntityReference node + * itself is adopted, the descendants are discarded, since the source + * and destination documents might have defined the entity differently. + * If the document being imported into provides a definition for this + * entity name, its value is assigned.
+ *
NOTATION_NODE
+ *
DOMNotation + * nodes cannot be adopted.
+ *
PROCESSING_INSTRUCTION_NODE, TEXT_NODE, + * CDATA_SECTION_NODE, COMMENT_NODE
+ *
These nodes can all be adopted. No + * specifics.
+ *
+ * @param source The node to move into this document. + * @return The adopted node, or null if this operation + * fails, such as when the source node comes from a different + * implementation. + * @exception DOMException + * NOT_SUPPORTED_ERR: Raised if the source node is of type + * DOCUMENT, DOCUMENT_TYPE. + *
NO_MODIFICATION_ALLOWED_ERR: Raised when the source node is + * readonly. + * @since DOM Level 3 + */ + virtual DOMNode* adoptNode(DOMNode* source) = 0; + + /** + * This method acts as if the document was going through a save and load + * cycle, putting the document in a "normal" form. The actual result + * depends on the features being set. See DOMConfiguration for + * details. + * + *
Noticeably this method normalizes DOMText nodes, makes + * the document "namespace wellformed", according to the algorithm + * described below in pseudo code, by adding missing namespace + * declaration attributes and adding or changing namespace prefixes, + * updates the replacement tree of DOMEntityReference nodes, + * normalizes attribute values, etc. + *
Mutation events, when supported, are generated to reflect the + * changes occurring on the document. + * Note that this is a partial implementation. Not all the required features are implemented. + * Currently DOMAttr and DOMText nodes are normalized. + * Features to remove DOMComment and DOMCDATASection work. + * @since DOM Level 3 + * + */ + virtual void normalizeDocument() = 0; + + + /** + * The configuration used when DOMDocument::normalizeDocument is invoked. + * + * @return The DOMConfiguration from this DOMDocument + * + * @since DOM Level 3 + */ + virtual DOMConfiguration* getDOMConfig() const = 0; + + //@} + + // ----------------------------------------------------------------------- + // Non-standard extension + // ----------------------------------------------------------------------- + /** @name Non-standard extension */ + //@{ + /** + * Non-standard extension + * + * Create a new entity. + * @param name The name of the entity to instantiate + * + */ + virtual DOMEntity *createEntity(const XMLCh *name) = 0; + + /** + * Non-standard extension + * + * Create a DOMDocumentType node. + * @return A DOMDocumentType that references the newly + * created DOMDocumentType node. + * + */ + virtual DOMDocumentType *createDocumentType(const XMLCh *name) = 0; + + /*** + * Provide default implementation to maintain source code compatibility + ***/ + virtual DOMDocumentType* createDocumentType(const XMLCh *qName, + const XMLCh*, //publicId, + const XMLCh* //systemId + ) + { + return createDocumentType(qName); + } + + /** + * Non-standard extension. + * + * Create a Notation. + * @param name The name of the notation to instantiate + * @return A DOMNotation that references the newly + * created DOMNotation node. + */ + virtual DOMNotation *createNotation(const XMLCh *name) = 0; + + /** + * Non-standard extension. + * + * Creates an element of the given qualified name and + * namespace URI, and also stores line/column number info. + * Used by internally XSDXercesDOMParser during schema traversal. + * + * @see createElementNS(const XMLCh *namespaceURI, const XMLCh *qualifiedName) + */ + virtual DOMElement *createElementNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + const XMLFileLoc lineNum, + const XMLFileLoc columnNum) = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMDocumentFragment.hpp b/include/xercesc/dom/DOMDocumentFragment.hpp new file mode 100644 index 0000000..6f0dceb --- /dev/null +++ b/include/xercesc/dom/DOMDocumentFragment.hpp @@ -0,0 +1,108 @@ +/* + * 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: DOMDocumentFragment.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTFRAGMENT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTFRAGMENT_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * DOMDocumentFragment is a "lightweight" or "minimal" + * DOMDocument object. + * + * It is very common to want to be able to + * extract a portion of a document's tree or to create a new fragment of a + * document. Imagine implementing a user command like cut or rearranging a + * document by moving fragments around. It is desirable to have an object + * which can hold such fragments and it is quite natural to use a DOMNode for + * this purpose. While it is true that a DOMDocument object could + * fulfill this role, a DOMDocument object can potentially be a + * heavyweight object, depending on the underlying implementation. What is + * really needed for this is a very lightweight object. + * DOMDocumentFragment is such an object. + *

Furthermore, various operations -- such as inserting nodes as children + * of another DOMNode -- may take DOMDocumentFragment + * objects as arguments; this results in all the child nodes of the + * DOMDocumentFragment being moved to the child list of this node. + *

The children of a DOMDocumentFragment node are zero or more + * nodes representing the tops of any sub-trees defining the structure of the + * document. DOMDocumentFragment nodes do not need to be + * well-formed XML documents (although they do need to follow the rules + * imposed upon well-formed XML parsed entities, which can have multiple top + * nodes). For example, a DOMDocumentFragment might have only one + * child and that child node could be a DOMText node. Such a + * structure model represents neither an HTML document nor a well-formed XML + * document. + *

When a DOMDocumentFragment is inserted into a + * DOMDocument (or indeed any other DOMNode that may take + * children) the children of the DOMDocumentFragment and not the + * DOMDocumentFragment itself are inserted into the + * DOMNode. This makes the DOMDocumentFragment very + * useful when the user wishes to create nodes that are siblings; the + * DOMDocumentFragment acts as the parent of these nodes so that the + * user can use the standard methods from the DOMNode interface, + * such as insertBefore() and appendChild(). + * + * @since DOM Level 1 + */ + +class CDOM_EXPORT DOMDocumentFragment: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMDocumentFragment() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMDocumentFragment(const DOMDocumentFragment &); + DOMDocumentFragment & operator = (const DOMDocumentFragment &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMDocumentFragment() {}; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMDocumentRange.hpp b/include/xercesc/dom/DOMDocumentRange.hpp new file mode 100644 index 0000000..da94deb --- /dev/null +++ b/include/xercesc/dom/DOMDocumentRange.hpp @@ -0,0 +1,95 @@ +/* + * 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: DOMDocumentRange.hpp 527149 2007-04-10 14:56:39Z amassari $ +*/ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTRANGE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTRANGE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMRange; + + +/** + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * @since DOM Level 2 + */ +class CDOM_EXPORT DOMDocumentRange { + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMDocumentRange() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMDocumentRange(const DOMDocumentRange &); + DOMDocumentRange & operator = (const DOMDocumentRange &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMDocumentRange() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMDocumentRange interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + /** + * To create the range consisting of boundary-points and offset of the + * selected contents + * + * @return The initial state of the Range such that both the boundary-points + * are positioned at the beginning of the corresponding DOMDOcument, before + * any content. The range returned can only be used to select content + * associated with this document, or with documentFragments and Attrs for + * which this document is the ownerdocument + * @since DOM Level 2 + */ + virtual DOMRange *createRange() = 0; + + //@} +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMDocumentTraversal.hpp b/include/xercesc/dom/DOMDocumentTraversal.hpp new file mode 100644 index 0000000..f2897a7 --- /dev/null +++ b/include/xercesc/dom/DOMDocumentTraversal.hpp @@ -0,0 +1,155 @@ +/* + * 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: DOMDocumentTraversal.hpp 671894 2008-06-26 13:29:21Z borisk $ +*/ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTTRAVERSAL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTTRAVERSAL_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; +class DOMNodeIterator; +class DOMTreeWalker; + + +/** + * DOMDocumentTraversal contains methods that create + * DOMNodeIterators and DOMTreeWalkers to traverse a + * node and its children in document order (depth first, pre-order + * traversal, which is equivalent to the order in which the start tags occur + * in the text representation of the document). In DOMs which support the + * Traversal feature, DOMDocumentTraversal will be implemented by + * the same objects that implement the DOMDocument interface. + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * @since DOM Level 2 + */ +class CDOM_EXPORT DOMDocumentTraversal { + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMDocumentTraversal() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMDocumentTraversal(const DOMDocumentTraversal &); + DOMDocumentTraversal & operator = (const DOMDocumentTraversal &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMDocumentTraversal() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMDocumentRange interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + /** + * Creates a NodeIterator object. (DOM2) + * + * NodeIterators are used to step through a set of nodes, e.g. the set of nodes in a NodeList, the + * document subtree governed by a particular node, the results of a query, or any other set of nodes. + * The set of nodes to be iterated is determined by the implementation of the NodeIterator. DOM Level 2 + * specifies a single NodeIterator implementation for document-order traversal of a document subtree. + * Instances of these iterators are created by calling DOMDocumentTraversal.createNodeIterator(). + * + * To produce a view of the document that has entity references expanded and does not + * expose the entity reference node itself, use the whatToShow flags to hide the entity + * reference node and set expandEntityReferences to true when creating the iterator. To + * produce a view of the document that has entity reference nodes but no entity expansion, + * use the whatToShow flags to show the entity reference node and set + * expandEntityReferences to false. + * + * @param root The root node of the DOM tree + * @param whatToShow This attribute determines which node types are presented via the iterator. + * @param filter The filter used to screen nodes + * @param entityReferenceExpansion The value of this flag determines whether the children of entity reference nodes are + * visible to the iterator. If false, they will be skipped over. + * @since DOM Level 2 + */ + + virtual DOMNodeIterator *createNodeIterator(DOMNode* root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* filter, + bool entityReferenceExpansion) = 0; + /** + * Creates a TreeWalker object. (DOM2) + * + * TreeWalker objects are used to navigate a document tree or subtree using the view of the document defined + * by its whatToShow flags and any filters that are defined for the TreeWalker. Any function which performs + * navigation using a TreeWalker will automatically support any view defined by a TreeWalker. + * + * Omitting nodes from the logical view of a subtree can result in a structure that is substantially different from + * the same subtree in the complete, unfiltered document. Nodes that are siblings in the TreeWalker view may + * be children of different, widely separated nodes in the original view. For instance, consider a Filter that skips + * all nodes except for DOMText nodes and the root node of a document. In the logical view that results, all text + * nodes will be siblings and appear as direct children of the root node, no matter how deeply nested the + * structure of the original document. + * + * To produce a view of the document that has entity references expanded + * and does not expose the entity reference node itself, use the whatToShow + * flags to hide the entity reference node and set expandEntityReferences to + * true when creating the TreeWalker. To produce a view of the document + * that has entity reference nodes but no entity expansion, use the + * whatToShow flags to show the entity reference node and set + * expandEntityReferences to false + * + * @param root The root node of the DOM tree + * @param whatToShow This attribute determines which node types are presented via the tree-walker. + * @param filter The filter used to screen nodes + * @param entityReferenceExpansion The value of this flag determines whether the children of entity reference nodes are + * visible to the tree-walker. If false, they will be skipped over. + * @since DOM Level 2 + */ + + virtual DOMTreeWalker *createTreeWalker(DOMNode* root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* filter, + bool entityReferenceExpansion) = 0; + + //@} +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMDocumentType.hpp b/include/xercesc/dom/DOMDocumentType.hpp new file mode 100644 index 0000000..29fe50c --- /dev/null +++ b/include/xercesc/dom/DOMDocumentType.hpp @@ -0,0 +1,160 @@ +/* + * 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: DOMDocumentType.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTTYPE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTTYPE_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNamedNodeMap; + +/** + * Each DOMDocument has a doctype attribute whose value + * is either null or a DOMDocumentType object. The + * DOMDocumentType interface in the DOM Core provides an interface + * to the list of entities that are defined for the document, and little + * else because the effect of namespaces and the various XML schema efforts + * on DTD representation are not clearly understood as of this writing. + *

The DOM Level 2 doesn't support editing DOMDocumentType nodes. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMDocumentType: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMDocumentType() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMDocumentType(const DOMDocumentType &); + DOMDocumentType & operator = (const DOMDocumentType &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMDocumentType() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMDocumentType interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + /** + * The name of DTD; i.e., the name immediately following the + * DOCTYPE keyword. + * + * @since DOM Level 1 + */ + virtual const XMLCh * getName() const = 0; + + /** + * A DOMNamedNodeMap containing the general entities, both + * external and internal, declared in the DTD. Parameter entities are + * not contained. Duplicates are discarded. For example in: + * <!DOCTYPE
+ * ex SYSTEM "ex.dtd" [ <!ENTITY foo "foo"> <!ENTITY bar
+ * "bar"> <!ENTITY bar "bar2"> <!ENTITY % baz "baz">
+ * ]> <ex/>
+ * the interface provides access to foo + * and the first declaration of bar but not the second + * declaration of bar or baz. Every node in + * this map also implements the DOMEntity interface. + *
The DOM Level 2 does not support editing entities, therefore + * entities cannot be altered in any way. + * + * @since DOM Level 1 + */ + virtual DOMNamedNodeMap *getEntities() const = 0; + + + /** + * A DOMNamedNodeMap containing the notations declared in the + * DTD. Duplicates are discarded. Every node in this map also implements + * the DOMNotation interface. + *
The DOM Level 2 does not support editing notations, therefore + * notations cannot be altered in any way. + * + * @since DOM Level 1 + */ + virtual DOMNamedNodeMap *getNotations() const = 0; + //@} + + /** @name Functions introduced in DOM Level 2. */ + //@{ + /** + * Get the public identifier of the external subset. + * + * @return The public identifier of the external subset. + * @since DOM Level 2 + */ + virtual const XMLCh * getPublicId() const = 0; + + /** + * Get the system identifier of the external subset. + * + * @return The system identifier of the external subset. + * @since DOM Level 2 + */ + virtual const XMLCh * getSystemId() const = 0; + + /** + * The internal subset as a string, or null if there is none. + * This is does not contain the delimiting square brackets.The actual + * content returned depends on how much information is available to the + * implementation. This may vary depending on various parameters, + * including the XML processor used to build the document. + * + * @return The internal subset as a string. + * @since DOM Level 2 + */ + virtual const XMLCh * getInternalSubset() const = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMElement.hpp b/include/xercesc/dom/DOMElement.hpp new file mode 100644 index 0000000..e158626 --- /dev/null +++ b/include/xercesc/dom/DOMElement.hpp @@ -0,0 +1,528 @@ +/* + * 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: DOMElement.hpp 792236 2009-07-08 17:22:35Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMELEMENT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMELEMENT_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMAttr; +class DOMNodeList; +class DOMTypeInfo; + + +/** + * By far the vast majority of objects (apart from text) that authors + * encounter when traversing a document are DOMElement nodes. + * + * Assume the following XML document:<elementExample id="demo"> + * <subelement1/> + * <subelement2><subsubelement/></subelement2> + * </elementExample> + *

When represented using DOM, the top node is an DOMElement node + * for "elementExample", which contains two child DOMElement nodes, + * one for "subelement1" and one for "subelement2". "subelement1" contains no + * child nodes. + *

Elements may have attributes associated with them; since the + * DOMElement interface inherits from DOMNode, the generic + * DOMNode interface method getAttributes may be used + * to retrieve the set of all attributes for an element. There are methods on + * the DOMElement interface to retrieve either an DOMAttr + * object by name or an attribute value by name. In XML, where an attribute + * value may contain entity references, an DOMAttr object should be + * retrieved to examine the possibly fairly complex sub-tree representing the + * attribute value. On the other hand, in HTML, where all attributes have + * simple string values, methods to directly access an attribute value can + * safely be used as a convenience. + * + * @since DOM Level 1 + * + * It also defines the ElementTraversal helper interface defined by http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/ + * + */ + +class CDOM_EXPORT DOMElement: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMElement() {} + DOMElement(const DOMElement &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMElement & operator = (const DOMElement &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMElement() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMElement interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * The name of the element. + * + * For example, in: <elementExample + * id="demo"> ... </elementExample> , tagName has + * the value "elementExample". Note that this is + * case-preserving in XML, as are all of the operations of the DOM. + * @since DOM Level 1 + */ + virtual const XMLCh * getTagName() const = 0; + + /** + * Retrieves an attribute value by name. + * + * @param name The name of the attribute to retrieve. + * @return The DOMAttr value as a string, or the empty string if + * that attribute does not have a specified or default value. + * @since DOM Level 1 + */ + virtual const XMLCh * getAttribute(const XMLCh *name) const = 0; + + /** + * Retrieves an DOMAttr node by name. + * + * @param name The name (nodeName) of the attribute to retrieve. + * @return The DOMAttr node with the specified name (nodeName) or + * null if there is no such attribute. + * @since DOM Level 1 + */ + virtual DOMAttr * getAttributeNode(const XMLCh *name) const = 0; + + /** + * Returns a DOMNodeList of all descendant elements with a given + * tag name, in the order in which they would be encountered in a preorder + * traversal of the DOMElement tree. + * + * @param name The name of the tag to match on. The special value "*" + * matches all tags. + * @return A list of matching DOMElement nodes. + * @since DOM Level 1 + */ + virtual DOMNodeList * getElementsByTagName(const XMLCh *name) const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Adds a new attribute. + * + * If an attribute with that name is already present + * in the element, its value is changed to be that of the value parameter. + * This value is a simple string, it is not parsed as it is being set. So + * any markup (such as syntax to be recognized as an entity reference) is + * treated as literal text, and needs to be appropriately escaped by the + * implementation when it is written out. In order to assign an attribute + * value that contains entity references, the user must create an + * DOMAttr node plus any DOMText and + * DOMEntityReference nodes, build the appropriate subtree, and + * use setAttributeNode to assign it as the value of an + * attribute. + * @param name The name of the attribute to create or alter. + * @param value Value to set in string form. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual void setAttribute(const XMLCh *name, + const XMLCh *value) = 0; + /** + * Adds a new attribute. + * + * If an attribute with that name (nodeName) is already present + * in the element, it is replaced by the new one. + * @param newAttr The DOMAttr node to add to the attribute list. + * @return If the newAttr attribute replaces an existing + * attribute, the replaced + * DOMAttr node is returned, otherwise null is + * returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if newAttr was created from a + * different document than the one that created the element. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + *
INUSE_ATTRIBUTE_ERR: Raised if newAttr is already an + * attribute of another DOMElement object. The DOM user must + * explicitly clone DOMAttr nodes to re-use them in other + * elements. + * @since DOM Level 1 + */ + virtual DOMAttr * setAttributeNode(DOMAttr *newAttr) = 0; + + /** + * Removes the specified attribute node. + * If the removed DOMAttr + * has a default value it is immediately replaced. The replacing attribute + * has the same namespace URI and local name, as well as the original prefix, + * when applicable. + * + * @param oldAttr The DOMAttr node to remove from the attribute + * list. + * @return The DOMAttr node that was removed. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + *
NOT_FOUND_ERR: Raised if oldAttr is not an attribute + * of the element. + * @since DOM Level 1 + */ + virtual DOMAttr * removeAttributeNode(DOMAttr *oldAttr) = 0; + + /** + * Removes an attribute by name. + * + * If the removed attribute + * is known to have a default value, an attribute immediately appears + * containing the default value as well as the corresponding namespace URI, + * local name, and prefix when applicable.
To remove an attribute by local + * name and namespace URI, use the removeAttributeNS method. + * @param name The name of the attribute to remove. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual void removeAttribute(const XMLCh *name) = 0; + //@} + + /** @name Functions introduced in DOM Level 2. */ + //@{ + /** + * Retrieves an attribute value by local name and namespace URI. + * + * @param namespaceURI The namespace URI of + * the attribute to retrieve. + * @param localName The local name of the + * attribute to retrieve. + * @return The DOMAttr value as a string, or an null if + * that attribute does not have a specified or default value. + * @since DOM Level 2 + */ + virtual const XMLCh * getAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const = 0; + + /** + * Adds a new attribute. If an attribute with the same + * local name and namespace URI is already present on the element, its prefix + * is changed to be the prefix part of the qualifiedName, and + * its value is changed to be the value parameter. This value is + * a simple string, it is not parsed as it is being set. So any markup (such + * as syntax to be recognized as an entity reference) is treated as literal + * text, and needs to be appropriately escaped by the implementation when it + * is written out. In order to assign an attribute value that contains entity + * references, the user must create an DOMAttr + * node plus any DOMText and DOMEntityReference + * nodes, build the appropriate subtree, and use + * setAttributeNodeNS or setAttributeNode to assign + * it as the value of an attribute. + * + * @param namespaceURI The namespace URI of + * the attribute to create or alter. + * @param qualifiedName The qualified name of the + * attribute to create or alter. + * @param value The value to set in string form. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an + * illegal character. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + *
+ * NAMESPACE_ERR: Raised if the qualifiedName is + * malformed, if the qualifiedName has a prefix and the + * namespaceURI is null or an empty string, + * if the qualifiedName has a prefix that is "xml" and the + * namespaceURI is different from + * "http://www.w3.org/XML/1998/namespace", if the + * qualifiedName has a prefix that is "xmlns" and the + * namespaceURI is different from + * "http://www.w3.org/2000/xmlns/", or if the + * qualifiedName is "xmlns" and the + * namespaceURI is different from + * "http://www.w3.org/2000/xmlns/". + * @since DOM Level 2 + */ + virtual void setAttributeNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, const XMLCh *value) = 0; + + /** + * Removes an attribute by local name and namespace URI. If the + * removed attribute has a default value it is immediately replaced. + * The replacing attribute has the same namespace URI and local name, as well as + * the original prefix. + * + * @param namespaceURI The namespace URI of + * the attribute to remove. + * @param localName The local name of the + * attribute to remove. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 2 + */ + virtual void removeAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) = 0; + + /** + * Retrieves an DOMAttr node by local name and namespace URI. + * + * @param namespaceURI The namespace URI of + * the attribute to retrieve. + * @param localName The local name of the + * attribute to retrieve. + * @return The DOMAttr node with the specified attribute local + * name and namespace URI or null if there is no such attribute. + * @since DOM Level 2 + */ + virtual DOMAttr * getAttributeNodeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const = 0; + + /** + * Adds a new attribute. + * + * If an attribute with that local name and namespace URI is already present + * in the element, it is replaced by the new one. + * + * @param newAttr The DOMAttr node to add to the attribute list. + * @return If the newAttr attribute replaces an existing + * attribute with the same local name and namespace URI, + * the replaced DOMAttr node is + * returned, otherwise null is returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if newAttr was created from a + * different document than the one that created the element. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + *
INUSE_ATTRIBUTE_ERR: Raised if newAttr is already an + * attribute of another DOMElement object. The DOM user must + * explicitly clone DOMAttr nodes to re-use them in other + * elements. + * @since DOM Level 2 + */ + virtual DOMAttr * setAttributeNodeNS(DOMAttr *newAttr) = 0; + + /** + * Returns a DOMNodeList of all the DOMElements + * with a given local name and namespace URI in the order in which they + * would be encountered in a preorder traversal of the + * DOMDocument tree, starting from this node. + * + * @param namespaceURI The namespace URI of + * the elements to match on. The special value "*" matches all + * namespaces. + * @param localName The local name of the + * elements to match on. The special value "*" matches all local names. + * @return A new DOMNodeList object containing all the matched + * DOMElements. + * @since DOM Level 2 + */ + virtual DOMNodeList * getElementsByTagNameNS(const XMLCh *namespaceURI, + const XMLCh *localName) const = 0; + + /** + * Returns true when an attribute with a given name is + * specified on this element or has a default value, false + * otherwise. + * @param name The name of the attribute to look for. + * @return true if an attribute with the given name is + * specified on this element or has a default value, false + * otherwise. + * @since DOM Level 2 + */ + virtual bool hasAttribute(const XMLCh *name) const = 0; + + /** + * Returns true when an attribute with a given local name and + * namespace URI is specified on this element or has a default value, + * false otherwise. HTML-only DOM implementations do not + * need to implement this method. + * @param namespaceURI The namespace URI of the attribute to look for. + * @param localName The local name of the attribute to look for. + * @return true if an attribute with the given local name + * and namespace URI is specified or has a default value on this + * element, false otherwise. + * @since DOM Level 2 + */ + virtual bool hasAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const = 0; + //@} + + /** @name Functions introduced in DOM Level 3 */ + //@{ + + /** + * If the parameter isId is true, this method declares the specified + * attribute to be a user-determined ID attribute. + * This affects the value of DOMAttr::isId and the behavior of + * DOMDocument::getElementById, but does not change any schema that + * may be in use, in particular this does not affect the DOMAttr::getSchemaTypeInfo + * of the specified DOMAttr node. Use the value false for the parameter isId + * to undeclare an attribute for being a user-determined ID attribute. + * To specify an DOMAttr by local name and namespace URI, use the + * setIdAttributeNS method. + * + * @param name The name of the DOMAttr. + * @param isId Whether the attribute is of type ID. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * NOT_FOUND_ERR: Raised if the specified node is not an DOMAttr + * of this element. + * + * @since DOM Level 3 + */ + virtual void setIdAttribute(const XMLCh* name, bool isId) = 0; + + + /** + * If the parameter isId is true, this method declares the specified + * attribute to be a user-determined ID attribute. + * This affects the value of DOMAttr::isId and the behavior of + * DOMDocument::getElementById, but does not change any schema that + * may be in use, in particular this does not affect the DOMAttr::getSchemaTypeInfo + * of the specified DOMAttr node. Use the value false for the parameter isId + * to undeclare an attribute for being a user-determined ID attribute. + * + * @param namespaceURI The namespace URI of the DOMAttr. + * @param localName The local name of the DOMAttr. + * @param isId Whether the attribute is of type ID. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * NOT_FOUND_ERR: Raised if the specified node is not an DOMAttr of this element. + * + * @since DOM Level 3 + */ + virtual void setIdAttributeNS(const XMLCh* namespaceURI, const XMLCh* localName, bool isId) = 0; + + + + /** + * If the parameter isId is true, this method declares the specified + * attribute to be a user-determined ID attribute. + * This affects the value of DOMAttr::isId and the behavior of + * DOMDocument::getElementById, but does not change any schema that + * may be in use, in particular this does not affect the DOMAttr::getSchemaTypeInfo + * of the specified DOMAttr node. Use the value false for the parameter isId + * to undeclare an attribute for being a user-determined ID attribute. + * + * @param idAttr The DOMAttr node. + * @param isId Whether the attribute is of type ID. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * NOT_FOUND_ERR: Raised if the specified node is not an DOMAttr of this element. + * + * @since DOM Level 3 + */ + virtual void setIdAttributeNode(const DOMAttr *idAttr, bool isId) = 0; + + + + /** + * Returns the type information associated with this element. + * + * @return the DOMTypeInfo associated with this element + * @since DOM level 3 + */ + virtual const DOMTypeInfo* getSchemaTypeInfo() const = 0; + + //@} + + // ----------------------------------------------------------------------- + // DOMElementTraversal interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in the ElementTraversal specification (http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/)*/ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * The first child of type DOMElement. + * + * @return The DOMElement object that is the first element node + * among the child nodes of this node, or null if there is none. + */ + virtual DOMElement * getFirstElementChild() const = 0; + + /** + * The last child of type DOMElement. + * + * @return The DOMElement object that is the last element node + * among the child nodes of this node, or null if there is none. + */ + virtual DOMElement * getLastElementChild() const = 0; + + /** + * The previous sibling node of type DOMElement. + * + * @return The DOMElement object that is the previous sibling element node + * in document order, or null if there is none. + */ + virtual DOMElement * getPreviousElementSibling() const = 0; + + /** + * The next sibling node of type DOMElement. + * + * @return The DOMElement object that is the next sibling element node + * in document order, or null if there is none. + */ + virtual DOMElement * getNextElementSibling() const = 0; + + /** + * The number of child nodes that are of type DOMElement. + * + * Note: the count is computed every time this function is invoked + * + * @return The number of DOMElement objects that are direct children + * of this object (nested elements are not counted), or 0 if there is none. + * + */ + virtual XMLSize_t getChildElementCount() const = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + + diff --git a/include/xercesc/dom/DOMEntity.hpp b/include/xercesc/dom/DOMEntity.hpp new file mode 100644 index 0000000..2a33a38 --- /dev/null +++ b/include/xercesc/dom/DOMEntity.hpp @@ -0,0 +1,170 @@ +/* + * 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: DOMEntity.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMENTITY_HPP) +#define XERCESC_INCLUDE_GUARD_DOMENTITY_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This interface represents an entity, either parsed or unparsed, in an XML + * document. Note that this models the entity itself not the entity + * declaration. DOMEntity declaration modeling has been left for a + * later Level of the DOM specification. + *

The nodeName attribute that is inherited from + * DOMNode contains the name of the entity. + *

An XML processor may choose to completely expand entities before the + * structure model is passed to the DOM; in this case there will be no + * DOMEntityReference nodes in the document tree. + *

XML does not mandate that a non-validating XML processor read and + * process entity declarations made in the external subset or declared in + * external parameter entities. This means that parsed entities declared in + * the external subset need not be expanded by some classes of applications, + * and that the replacement value of the entity may not be available. When + * the replacement value is available, the corresponding DOMEntity + * node's child list represents the structure of that replacement text. + * Otherwise, the child list is empty. + *

The DOM Level 2 does not support editing DOMEntity nodes; if a + * user wants to make changes to the contents of an DOMEntity, + * every related DOMEntityReference node has to be replaced in the + * structure model by a clone of the DOMEntity's contents, and + * then the desired changes must be made to each of those clones instead. + * DOMEntity nodes and all their descendants are readonly. + *

An DOMEntity node does not have any parent.If the entity + * contains an unbound namespace prefix, the namespaceURI of + * the corresponding node in the DOMEntity node subtree is + * null. The same is true for DOMEntityReference + * nodes that refer to this entity, when they are created using the + * createEntityReference method of the DOMDocument + * interface. The DOM Level 2 does not support any mechanism to resolve + * namespace prefixes. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMEntity: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMEntity() {} + DOMEntity(const DOMEntity &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMEntity & operator = (const DOMEntity &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMEntity() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMEntity interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * The public identifier associated with the entity, if specified. + * + * If the public identifier was not specified, this is null. + * + * @since DOM Level 1 + */ + virtual const XMLCh * getPublicId() const = 0; + + /** + * The system identifier associated with the entity, if specified. + * + * If the system identifier was not specified, this is null. + * + * @since DOM Level 1 + */ + virtual const XMLCh * getSystemId() const = 0; + + /** + * For unparsed entities, the name of the notation for the entity. + * + * For parsed entities, this is null. + * + * @since DOM Level 1 + */ + virtual const XMLCh * getNotationName() const = 0; + //@} + + /** @name Functions introduced in DOM Level 3. */ + //@{ + + /** + * An attribute specifying the encoding used for this entity at the time of parsing, + * when it is an external parsed entity. This is null if it an entity + * from the internal subset or if it is not known. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getInputEncoding() const = 0; + + /** + * An attribute specifying, as part of the text declaration, the encoding + * of this entity, when it is an external parsed entity. This is + * null otherwise. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getXmlEncoding() const = 0; + + /** + * An attribute specifying, as part of the text declaration, the version + * number of this entity, when it is an external parsed entity. This is + * null otherwise. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getXmlVersion() const = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/DOMEntityReference.hpp b/include/xercesc/dom/DOMEntityReference.hpp new file mode 100644 index 0000000..7dc89c3 --- /dev/null +++ b/include/xercesc/dom/DOMEntityReference.hpp @@ -0,0 +1,96 @@ +/* + * 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: DOMEntityReference.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMENTITYREFERENCE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMENTITYREFERENCE_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * DOMEntityReference objects may be inserted into the structure + * model when an entity reference is in the source document, or when the + * user wishes to insert an entity reference. Note that character references + * and references to predefined entities are considered to be expanded by + * the HTML or XML processor so that characters are represented by their + * Unicode equivalent rather than by an entity reference. Moreover, the XML + * processor may completely expand references to entities while building the + * structure model, instead of providing DOMEntityReference + * objects. If it does provide such objects, then for a given + * DOMEntityReference node, it may be that there is no + * DOMEntity node representing the referenced entity. If such an + * DOMEntity exists, then the subtree of the + * DOMEntityReference node is in general a copy of the + * DOMEntity node subtree. However, this may not be true when an + * entity contains an unbound namespace prefix. In such a case, because the + * namespace prefix resolution depends on where the entity reference is, the + * descendants of the DOMEntityReference node may be bound to + * different namespace URIs. + *

As for DOMEntity nodes, DOMEntityReference nodes and + * all their descendants are readonly. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * + * @since DOM Level 1 + */ + +class CDOM_EXPORT DOMEntityReference: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMEntityReference() {} + DOMEntityReference(const DOMEntityReference &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMEntityReference & operator = (const DOMEntityReference &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMEntityReference() {}; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMError.hpp b/include/xercesc/dom/DOMError.hpp new file mode 100644 index 0000000..76bb676 --- /dev/null +++ b/include/xercesc/dom/DOMError.hpp @@ -0,0 +1,173 @@ +/* + * 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: DOMError.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMERROR_HPP) +#define XERCESC_INCLUDE_GUARD_DOMERROR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMLocator; + + +/** + * DOMError is an interface that describes an error. + * + * @see DOMErrorHandler#handleError + * @since DOM Level 3 + */ + +class CDOM_EXPORT DOMError +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMError() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMError(const DOMError &); + DOMError & operator = (const DOMError &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMError() {}; + //@} + + // ----------------------------------------------------------------------- + // Class types + // ----------------------------------------------------------------------- + /** @name Public constants */ + //@{ + /** + * The severity of the error described by the DOMError. + * + *

DOM_SEVERITY_ERROR: + * The severity of the error described by the DOMError is error. + * A DOM_SEVERITY_ERROR may not cause the processing to stop if the error can + * be recovered, unless DOMErrorHandler::handleError() returns false.

+ * + *

DOM_SEVERITY_FATAL_ERROR + * The severity of the error described by the DOMError is fatal error. + * A DOM_SEVERITY_FATAL_ERROR will cause the normal processing to stop. The return + * value of DOMErrorHandler::handleError() is ignored unless the + * implementation chooses to continue, in which case the behavior becomes undefined.

+ * + *

DOM_SEVERITY_WARNING + * The severity of the error described by the DOMError is warning. + * A DOM_SEVERITY_WARNING will not cause the processing to stop, unless + * DOMErrorHandler::handleError() returns false.

+ * + * @since DOM Level 3 + */ + enum ErrorSeverity + { + DOM_SEVERITY_WARNING = 1, + DOM_SEVERITY_ERROR = 2, + DOM_SEVERITY_FATAL_ERROR = 3 + }; + //@} + + + // ----------------------------------------------------------------------- + // Virtual DOMError interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Get the severity of the error + * + * @see setSeverity + * @since DOM Level 3 + */ + virtual ErrorSeverity getSeverity() const = 0; + + /** + * Get the message describing the error that occured. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getMessage() const = 0; + + /** + * Get the location of the error + * + * @since DOM Level 3 + */ + virtual DOMLocator* getLocation() const = 0; + + /** + * The related platform dependent exception if any. + * + * @since DOM Level 3 + */ + virtual void* getRelatedException() const = 0; + + /** + * A XMLCh* indicating which related data is expected in + * relatedData. Users should refer to the specification of the error + * in order to find its XMLCh* type and relatedData + * definitions if any. + * + * Note: As an example, DOMDocument::normalizeDocument() does generate + * warnings when the "split-cdata-sections" parameter is in use. Therefore, the + * method generates a DOM_SEVERITY_WARNING with type "cdata-sections-splitted" + * and the first DOMCDATASection node in document order resulting from the split + * is returned by the relatedData attribute. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getType() const = 0; + + /** + * The related DOMError::getType dependent data if any. + * + * @since DOM Level 3 + */ + virtual void* getRelatedData() const = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMErrorHandler.hpp b/include/xercesc/dom/DOMErrorHandler.hpp new file mode 100644 index 0000000..880a9c0 --- /dev/null +++ b/include/xercesc/dom/DOMErrorHandler.hpp @@ -0,0 +1,107 @@ +/* + * 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: DOMErrorHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMERRORHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMERRORHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMError; + +/** + * Basic interface for DOM error handlers. + * + *

DOMErrorHandler is a callback interface that the DOM implementation + * can call when reporting errors that happens while processing XML data, or + * when doing some other processing (e.g. validating a document).

+ * + *

The application that is using the DOM implementation is expected to + * implement this interface.

+ * + * @see DOMLSParser#getDomConfig + * @since DOM Level 3 + */ + +class CDOM_EXPORT DOMErrorHandler +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMErrorHandler() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMErrorHandler(const DOMErrorHandler &); + DOMErrorHandler & operator = (const DOMErrorHandler &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMErrorHandler() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMErrorHandler interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * This method is called on the error handler when an error occurs. + * If an exception is thrown from this method, it is considered to be equivalent of returning true. + * + * @param domError The error object that describes the error, this object + * may be reused by the DOM implementation across multiple + * calls to the handleError method. + * @return If the handleError method returns true the DOM + * implementation should continue as if the error didn't happen + * when possible, if the method returns false then the + * DOM implementation should stop the current processing when + * possible. + * + * @since DOM Level 3 + */ + virtual bool handleError(const DOMError& domError) = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMException.cpp b/include/xercesc/dom/DOMException.cpp new file mode 100644 index 0000000..5f1f57f --- /dev/null +++ b/include/xercesc/dom/DOMException.cpp @@ -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: DOMException.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include +#include +#include +#include +#include +#include "impl/DOMImplementationImpl.hpp" + +#include "DOMException.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Destructor and Constructor +// --------------------------------------------------------------------------- +DOMException::~DOMException() +{ + if (msg && fMsgOwned) + fMemoryManager->deallocate((void*)msg); +} + +DOMException::DOMException() +:code(0) +,msg(0) +,fMemoryManager(0) +,fMsgOwned(false) +{ +} + +DOMException::DOMException(short exCode, + short messageCode, + MemoryManager* const memoryManager) +:code(exCode) +,fMemoryManager(0) +,fMsgOwned(true) +{ + if (memoryManager) + fMemoryManager = memoryManager->getExceptionMemoryManager(); + + const XMLSize_t msgSize = 2047; + XMLCh errText[msgSize + 1]; + + // load the text + if(messageCode==0) + messageCode=XMLDOMMsg::DOMEXCEPTION_ERRX+exCode; + + msg = XMLString::replicate + ( + DOMImplementationImpl::getMsgLoader4DOM()->loadMsg(messageCode, errText, msgSize) ? errText : XMLUni::fgDefErrMsg + , fMemoryManager + ); +} + +DOMException::DOMException(const DOMException &other) +:code(other.code) +,msg(0) +,fMemoryManager(other.fMemoryManager) +,fMsgOwned(other.fMsgOwned) +{ + if (other.msg) + msg = other.fMsgOwned? XMLString::replicate(other.msg, other.fMemoryManager) : other.msg; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/DOMException.hpp b/include/xercesc/dom/DOMException.hpp new file mode 100644 index 0000000..142f8df --- /dev/null +++ b/include/xercesc/dom/DOMException.hpp @@ -0,0 +1,257 @@ +/* + * 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: DOMException.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * DOM operations only raise exceptions in "exceptional" circumstances, i.e., + * when an operation is impossible to perform (either for logical reasons, + * because data is lost, or because the implementation has become unstable). + * In general, DOM methods return specific error values in ordinary + * processing situations, such as out-of-bound errors when using + * DOMNodeList. + *

Implementations should raise other exceptions under other circumstances. + * For example, implementations should raise an implementation-dependent + * exception if a null argument is passed. + *

Some languages and object systems do not support the concept of + * exceptions. For such systems, error conditions may be indicated using + * native error reporting mechanisms. For some bindings, for example, + * methods may return error codes similar to those listed in the + * corresponding method descriptions. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + * @since DOM Level 1 + */ + +class MemoryManager; + +class CDOM_EXPORT DOMException { +public: + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * ExceptionCode + * + *

INDEX_SIZE_ERR: + * If index or size is negative, or greater than the allowed value.

+ * + *

DOMSTRING_SIZE_ERR: + * If the specified range of text does not fit into a DOMString.

+ * + *

HIERARCHY_REQUEST_ERR: + * If any node is inserted somewhere it doesn't belong.

+ * + *

WRONG_DOCUMENT_ERR: + * If a node is used in a different document than the one that created it + * (that doesn't support it).

+ * + *

INVALID_CHARACTER_ERR: + * If an invalid or illegal character is specified, such as in a name. See + * production 2 in the XML specification for the definition of a legal + * character, and production 5 for the definition of a legal name + * character.

+ * + *

NO_DATA_ALLOWED_ERR: + * If data is specified for a node which does not support data.

+ * + *

NO_MODIFICATION_ALLOWED_ERR: + * If an attempt is made to modify an object where modifications are not + * allowed.

+ * + *

NOT_FOUND_ERR: + * If an attempt is made to reference a node in a context where it does + * not exist.

+ * + *

NOT_SUPPORTED_ERR: + * If the implementation does not support the requested type of object or + * operation.

+ * + *

INUSE_ATTRIBUTE_ERR: + * If an attempt is made to add an attribute that is already in use + * elsewhere.

+ * + * The above are since DOM Level 1 + * @since DOM Level 1 + * + *

INVALID_STATE_ERR: + * If an attempt is made to use an object that is not, or is no longer, + * usable.

+ * + *

SYNTAX_ERR: + * If an invalid or illegal string is specified.

+ * + *

INVALID_MODIFICATION_ERR: + * If an attempt is made to modify the type of the underlying object.

+ * + *

NAMESPACE_ERR: + * If an attempt is made to create or change an object in a way which is + * incorrect with regard to namespaces.

+ * + *

INVALID_ACCESS_ERR: + * If a parameter or an operation is not supported by the underlying + * object. + * + * The above are since DOM Level 2 + * @since DOM Level 2 + * + *

VALIDATION_ERR: + * If a call to a method such as insertBefore or + * removeChild would make the Node invalid + * with respect to "partial validity", this exception would be raised + * and the operation would not be done. + * + *

TYPE_MISMATCH_ERR: + * If the type of an object is incompatible with the expected type of + * the parameter associated to the object, this exception would be raised. + * + * The above is since DOM Level 3 + * @since DOM Level 3 + */ + enum ExceptionCode { + INDEX_SIZE_ERR = 1, + DOMSTRING_SIZE_ERR = 2, + HIERARCHY_REQUEST_ERR = 3, + WRONG_DOCUMENT_ERR = 4, + INVALID_CHARACTER_ERR = 5, + NO_DATA_ALLOWED_ERR = 6, + NO_MODIFICATION_ALLOWED_ERR = 7, + NOT_FOUND_ERR = 8, + NOT_SUPPORTED_ERR = 9, + INUSE_ATTRIBUTE_ERR = 10, + INVALID_STATE_ERR = 11, + SYNTAX_ERR = 12, + INVALID_MODIFICATION_ERR = 13, + NAMESPACE_ERR = 14, + INVALID_ACCESS_ERR = 15, + VALIDATION_ERR = 16, + TYPE_MISMATCH_ERR = 17 + }; + //@} + +public: + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + /** + * Default constructor for DOMException. + * + */ + DOMException(); + + /** + * Constructor which takes an error code and an optional message code. + * + * @param code The error code which indicates the exception + * @param messageCode The string containing the error message + * @param memoryManager The memory manager used to (de)allocate memory + */ + DOMException(short code, + short messageCode = 0, + MemoryManager* const memoryManager = XMLPlatformUtils::fgMemoryManager); + + /** + * Copy constructor. + * + * @param other The object to be copied. + */ + DOMException(const DOMException &other); + + //@} + + // ----------------------------------------------------------------------- + // Destructors + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + /** + * Destructor for DOMException. + * + */ + virtual ~DOMException(); + //@} + + +public: + // ----------------------------------------------------------------------- + // Getter + // ----------------------------------------------------------------------- + inline const XMLCh* getMessage() const; + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public variables */ + //@{ + /** + * A code value, from the set defined by the ExceptionCode enum, + * indicating the type of error that occured. + */ + short code; + + /** + * A string value. Applications may use this field to hold an error + * message. The field value is not set by the DOM implementation, + * meaning that the string will be empty when an exception is first + * thrown. + */ + const XMLCh *msg; + //@} + +protected: + MemoryManager* fMemoryManager; + +private: + + /** + * A boolean value. + * If the message is provided by the applications, it is not + * adopted. + * If the message is resolved by the DOM implementation, it is + * owned. + */ + bool fMsgOwned; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMException & operator = (const DOMException &); +}; + +inline const XMLCh* DOMException::getMessage() const +{ + return msg; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMImplementation.hpp b/include/xercesc/dom/DOMImplementation.hpp new file mode 100644 index 0000000..79ef386 --- /dev/null +++ b/include/xercesc/dom/DOMImplementation.hpp @@ -0,0 +1,249 @@ +/* + * 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: DOMImplementation.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATION_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMDocument; +class DOMDocumentType; + +/** + * The DOMImplementation interface provides a number of methods + * for performing operations that are independent of any particular instance + * of the document object model. + */ + +class CDOM_EXPORT DOMImplementation : public DOMImplementationLS +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMImplementation() {}; // no plain constructor + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMImplementation(const DOMImplementation &); // no copy constructor. + DOMImplementation & operator = (const DOMImplementation &); // No Assignment + //@} + + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMImplementation() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMImplementation interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + /** + * Test if the DOM implementation implements a specific feature. + * @param feature The name of the feature to test (case-insensitive). The + * values used by DOM features are defined throughout the DOM Level 2 + * specifications and listed in the section. The name must be an XML + * name. To avoid possible conflicts, as a convention, names referring + * to features defined outside the DOM specification should be made + * unique. + * @param version This is the version number of the feature to test. In + * Level 2, the string can be either "2.0" or "1.0". If the version is + * not specified, supporting any version of the feature causes the + * method to return true. + * @return true if the feature is implemented in the + * specified version, false otherwise. + * @since DOM Level 1 + */ + virtual bool hasFeature(const XMLCh *feature, const XMLCh *version) const = 0; + //@} + + // ----------------------------------------------------------------------- + // Functions introduced in DOM Level 2 + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + /** + * Creates an empty DOMDocumentType node. Entity declarations + * and notations are not made available. Entity reference expansions and + * default attribute additions do not occur. It is expected that a + * future version of the DOM will provide a way for populating a + * DOMDocumentType. + * @param qualifiedName The qualified name of the document type to be + * created. + * @param publicId The external subset public identifier. + * @param systemId The external subset system identifier. + * @return A new DOMDocumentType node with + * ownerDocument set to null. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + *
NAMESPACE_ERR: Raised if the qualifiedName is + * malformed. + *
NOT_SUPPORTED_ERR: May be raised by DOM implementations which do + * not support the "XML" feature, if they choose not to + * support this method. Other features introduced in the future, by + * the DOM WG or in extensions defined by other groups, may also + * demand support for this method; please consult the definition of + * the feature to see if it requires this method. + * @since DOM Level 2 + */ + virtual DOMDocumentType *createDocumentType(const XMLCh *qualifiedName, + const XMLCh *publicId, + const XMLCh *systemId) = 0; + + /** + * Creates a DOMDocument object of the specified type with its document + * element. + * @param namespaceURI The namespace URI of the document element to + * create. + * @param qualifiedName The qualified name of the document element to be + * created. + * @param doctype The type of document to be created or null. + * When doctype is not null, its + * ownerDocument attribute is set to the document + * being created. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + * @return A new DOMDocument object. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + *
NAMESPACE_ERR: Raised if the qualifiedName is + * malformed, if the qualifiedName has a prefix and the + * namespaceURI is null, or if the + * qualifiedName has a prefix that is "xml" and the + * namespaceURI is different from " + * http://www.w3.org/XML/1998/namespace" , or if the DOM + * implementation does not support the "XML" feature but + * a non-null namespace URI was provided, since namespaces were + * defined by XML. + *
WRONG_DOCUMENT_ERR: Raised if doctype has already + * been used with a different document or was created from a different + * implementation. + *
NOT_SUPPORTED_ERR: May be raised by DOM implementations which do + * not support the "XML" feature, if they choose not to support this + * method. Other features introduced in the future, by the DOM WG or + * in extensions defined by other groups, may also demand support for + * this method; please consult the definition of the feature to see if + * it requires this method. + * @since DOM Level 2 + */ + + virtual DOMDocument *createDocument(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + DOMDocumentType *doctype, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) = 0; + + //@} + // ----------------------------------------------------------------------- + // Functions introduced in DOM Level 3 + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * This method returns a specialized object which implements the specialized APIs + * of the specified feature and version, as specified in DOM Features. + * This method also allow the implementation to provide specialized objects which + * do not support the DOMImplementation interface. + * + * @param feature The name of the feature requested (case-insensitive). + * Note that any plus sign "+" prepended to the name of the feature will + * be ignored since it is not significant in the context of this method. + * @param version This is the version number of the feature to test. + * @return Returns an object which implements the specialized APIs of the specified + * feature and version, if any, or null if there is no object which implements + * interfaces associated with that feature. + * @since DOM Level 3 + */ + virtual void* getFeature(const XMLCh* feature, const XMLCh* version) const = 0; + + //@} + + // ----------------------------------------------------------------------- + // Non-standard extension + // ----------------------------------------------------------------------- + /** @name Non-standard extension */ + //@{ + /** + * Non-standard extension + * + * Create a completely empty document that has neither a root element or a doctype node. + */ + virtual DOMDocument *createDocument(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) = 0; + + /** + * Non-standard extension + * + * Factory method for getting a DOMImplementation object. + * The DOM implementation retains ownership of the returned object. + * Application code should NOT delete it. + */ + static DOMImplementation *getImplementation(); + + /** + * Non-standard extension + * + * Load the default error text message for DOMException. + * @param msgToLoad The DOM ExceptionCode id to be processed + * @param toFill The buffer that will hold the output on return. The + * size of this buffer should at least be 'maxChars + 1'. + * @param maxChars The maximum number of output characters that can be + * accepted. If the result will not fit, it is an error. + * @return true if the message is successfully loaded + */ + static bool loadDOMExceptionMsg + ( + const short msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars + ); + + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMImplementationLS.hpp b/include/xercesc/dom/DOMImplementationLS.hpp new file mode 100644 index 0000000..acd09a2 --- /dev/null +++ b/include/xercesc/dom/DOMImplementationLS.hpp @@ -0,0 +1,183 @@ +/* + * 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: DOMImplementationLS.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONLS_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONLS_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMLSParser; +class DOMLSSerializer; +class DOMLSInput; +class DOMLSOutput; +class MemoryManager; +class XMLGrammarPool; + +/** + *

DOMImplementationLS contains the factory methods for + * creating Load and Save objects.

+ * + *

An object that implements DOMImplementationLS is obtained by doing a + * binding specific cast from DOMImplementation to DOMImplementationLS. + * Implementations supporting the Load and Save feature must implement the + * DOMImplementationLS interface on whatever object implements the + * DOMImplementation interface.

+ * + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMImplementationLS +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMImplementationLS() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMImplementationLS(const DOMImplementationLS &); + DOMImplementationLS & operator = (const DOMImplementationLS &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMImplementationLS() {}; + //@} + + // ----------------------------------------------------------------------- + // Public constants + // ----------------------------------------------------------------------- + /** @name Public constants */ + //@{ + /** + * Create a synchronous or an asynchronous DOMLSParser. + * @see createLSParser(const DOMImplementationLSMode mode, const XMLCh* const schemaType) + * @since DOM Level 3 + * + */ + enum DOMImplementationLSMode + { + MODE_SYNCHRONOUS = 1, + MODE_ASYNCHRONOUS = 2 + }; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMImplementationLS interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Factory create methods + // ----------------------------------------------------------------------- + /** + * Create a new DOMLSParser. The newly constructed parser may then be configured + * by means of its DOMConfiguration object, and used to parse documents by + * means of its parse method. + * + * @param mode The mode argument is either MODE_SYNCHRONOUS + * or MODE_ASYNCHRONOUS, if mode is MODE_SYNCHRONOUS + * then the DOMLSParser that is created will operate in synchronous + * mode, if it's MODE_ASYNCHRONOUS then the DOMLSParser + * that is created will operate in asynchronous mode. + * @param schemaType An absolute URI representing the type of the schema + * language used during the load of a DOMDocument using the newly + * created DOMLSParser. Note that no lexical checking is done on + * the absolute URI. In order to create a DOMLSParser for any kind + * of schema types (i.e. the DOMLSParser will be free to use any + * schema found), use the value NULL. + * Note: For W3C XML Schema [XML Schema Part 1], applications must use + * the value "http://www.w3.org/2001/XMLSchema". For XML DTD [XML 1.0], + * applications must use the value "http://www.w3.org/TR/REC-xml". + * Other Schema languages are outside the scope of the W3C and therefore should + * recommend an absolute URI in order to use this method. + * @param manager Pointer to the memory manager to be used to allocate objects. + * @param gramPool The collection of cached grammars. + * @return The newly created DOMLSParser object. This + * DOMLSParser is either synchronous or asynchronous depending + * on the value of the mode argument. + * @exception DOMException NOT_SUPPORTED_ERR: Raised if the requested mode + * or schema type is not supported. + * + * @see DOMLSParser + * @since DOM Level 3 + */ + virtual DOMLSParser* createLSParser(const DOMImplementationLSMode mode, + const XMLCh* const schemaType, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager, + XMLGrammarPool* const gramPool = 0) = 0; + + + /** + * Create a new DOMLSSerializer. DOMLSSerializer is used to serialize a DOM tree + * back into an XML document. + * + * @return The newly created DOMLSSerializer object. + * + * @see DOMLSSerializer + * @since DOM Level 3 + */ + virtual DOMLSSerializer* createLSSerializer(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) = 0; + + /** + * Create a new "empty" DOMLSInput. + * + * @return The newly created DOMLSInput object. + * + * @see DOMLSInput + * @since DOM Level 3 + */ + virtual DOMLSInput* createLSInput(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) = 0; + + /** + * Create a new "empty" LSOutput. + * + * @return The newly created LSOutput object. + * + * @see LSOutput + * @since DOM Level 3 + */ + virtual DOMLSOutput* createLSOutput(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) = 0; + //@} +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMImplementationList.hpp b/include/xercesc/dom/DOMImplementationList.hpp new file mode 100644 index 0000000..45990e9 --- /dev/null +++ b/include/xercesc/dom/DOMImplementationList.hpp @@ -0,0 +1,124 @@ +/* + * 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: DOMImplementationList.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONLIST_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONLIST_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMImplementation; + + +/** + * The DOMImplementationList interface provides the abstraction of an ordered + * collection of DOM implementations, without defining or constraining how this collection + * is implemented. The items in the DOMImplementationList are accessible via + * an integral index, starting from 0. + */ + +class CDOM_EXPORT DOMImplementationList { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMImplementationList() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMImplementationList(const DOMImplementationList &); + DOMImplementationList & operator = (const DOMImplementationList &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMImplementationList() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMImplementationList interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the index item in the collection. + * + * If index is greater than or equal to the number of DOMImplementation in + * the list, this returns null. + * + * @param index Index into the collection. + * @return The DOMImplementation at the indexth position in the + * DOMImplementationList, or null if that is not a valid + * index. + * @since DOM Level 3 + */ + virtual DOMImplementation *item(XMLSize_t index) const = 0; + + /** + * Returns the number of DOMImplementation in the list. + * + * The range of valid child node indices is 0 to length-1 inclusive. + * @since DOM Level 3 + */ + virtual XMLSize_t getLength() const = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this list is no longer in use + * and that the implementation may relinquish any resources associated with it and + * its associated children. + * + * Access to a released object will lead to unexpected result. + * + */ + virtual void release() = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMImplementationRegistry.hpp b/include/xercesc/dom/DOMImplementationRegistry.hpp new file mode 100644 index 0000000..b151cf1 --- /dev/null +++ b/include/xercesc/dom/DOMImplementationRegistry.hpp @@ -0,0 +1,101 @@ +/* + * 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: DOMImplementationRegistry.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONREGISTRY_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONREGISTRY_HPP + + /** + * This class holds the list of registered DOMImplementations. Implementation + * or application can register DOMImplementationSource to the registry, and + * then can query DOMImplementation based on a list of requested features. + * + *

This provides an application with an implementation independent starting + * point. + * + * @see DOMImplementation + * @see DOMImplementationList + * @see DOMImplementationSource + * @since DOM Level 3 + */ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMImplementation; +class DOMImplementationSource; +class DOMImplementationList; + +class CDOM_EXPORT DOMImplementationRegistry +{ +public: + // ----------------------------------------------------------------------- + // Static DOMImplementationRegistry interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * Return the first registered implementation that has the desired features, + * or null if none is found. + * + * @param features A string that specifies which features are required. + * This is a space separated list in which each feature is + * specified by its name optionally followed by a space + * and a version number. + * This is something like: "XML 1.0 Traversal 2.0" + * @return An implementation that has the desired features, or + * null if this source has none. + * @since DOM Level 3 + */ + static DOMImplementation* getDOMImplementation(const XMLCh* features); + + /** + * Return the list of registered implementation that have the desired features. + * + * @param features A string that specifies which features are required. + * This is a space separated list in which each feature is + * specified by its name optionally followed by a space + * and a version number. + * This is something like: "XML 1.0 Traversal 2.0" + * @return A DOMImplementationList object that contains the DOMImplementation + * that have the desired features + * @since DOM Level 3 + */ + static DOMImplementationList* getDOMImplementationList(const XMLCh* features); + + /** + * Register an implementation. + * + * @param source A DOMImplementation Source object to be added to the registry. + * The registry does NOT adopt the source object. Users still own it. + * @since DOM Level 3 + */ + static void addSource(DOMImplementationSource* source); + //@} + +private: + DOMImplementationRegistry(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMImplementationSource.hpp b/include/xercesc/dom/DOMImplementationSource.hpp new file mode 100644 index 0000000..21cc7b6 --- /dev/null +++ b/include/xercesc/dom/DOMImplementationSource.hpp @@ -0,0 +1,112 @@ +/* + * 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: DOMImplementationSource.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONSOURCE_HPP + + /** + * This interface permits a DOM implementer to supply one or more + * implementations, based upon requested features and versions. Each implemented + * DOMImplementationSource object is listed in the + * binding-specific list of available sources so that its + * DOMImplementation objects are made available. + * + * @since DOM Level 3 + */ +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMImplementation; +class DOMImplementationList; + +class CDOM_EXPORT DOMImplementationSource +{ +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMImplementationSource() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMImplementationSource(const DOMImplementationSource &); + DOMImplementationSource & operator = (const DOMImplementationSource &); + //@} + + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMImplementationSource() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMImplementationSource interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * A method to request the first DOM implementation that supports the specified features. + * + * @param features A string that specifies which features are required. + * This is a space separated list in which each feature is specified + * by its name optionally followed by a space and a version number. + * This is something like: "XML 1.0 Traversal 2.0" + * @return An implementation that has the desired features, or + * null if this source has none. + * @since DOM Level 3 + */ + virtual DOMImplementation* getDOMImplementation(const XMLCh* features) const = 0; + + /** + * A method to request a list of DOM implementations that support the specified features and versions, + * + * @param features A string that specifies which features are required. + * This is a space separated list in which each feature is specified + * by its name optionally followed by a space and a version number. + * This is something like: "XML 1.0 Traversal 2.0" + * @return A list of DOM implementations that support the desired features + * @since DOM Level 3 + */ + virtual DOMImplementationList* getDOMImplementationList(const XMLCh* features) const = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSException.cpp b/include/xercesc/dom/DOMLSException.cpp new file mode 100644 index 0000000..0e3df1c --- /dev/null +++ b/include/xercesc/dom/DOMLSException.cpp @@ -0,0 +1,49 @@ +/* + * 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: DOMLSException.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMLSException.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMLSException::DOMLSException() +: DOMException() +{ +} + +DOMLSException::DOMLSException(short exCode, + short messageCode, + MemoryManager* const memoryManager) +: DOMException(exCode, messageCode?messageCode:XMLDOMMsg::DOMLSEXCEPTION_ERRX+exCode-DOMLSException::PARSE_ERR+1, memoryManager) +{ +} + +DOMLSException::DOMLSException(const DOMLSException &other) +: DOMException(other) +{ +} + + +DOMLSException::~DOMLSException() +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/DOMLSException.hpp b/include/xercesc/dom/DOMLSException.hpp new file mode 100644 index 0000000..14d9cab --- /dev/null +++ b/include/xercesc/dom/DOMLSException.hpp @@ -0,0 +1,123 @@ +/* + * 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: DOMLSException.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSEXCEPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * Parser or write operations may throw an LSException if the processing is stopped. + * The processing can be stopped due to a DOMError with a severity of + * DOMError::DOM_SEVERITY_FATAL_ERROR or a non recovered DOMError::DOM_SEVERITY_ERROR, + * or if DOMErrorHandler::handleError() returned false. + *

Note: As suggested in the definition of the constants in the DOMError + * interface, a DOM implementation may choose to continue after a fatal error, but the + * resulting DOM tree is then implementation dependent. + *

See also the + * Document Object Model (DOM) Level 3 Load and Save Specification. + * @since DOM Level 3 + */ + +class MemoryManager; + +class CDOM_EXPORT DOMLSException : public DOMException { +public: + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Contants */ + //@{ + /** + * ExceptionCode + * + *

PARSE_ERR: + * If an attempt was made to load a document, or an XML Fragment, using DOMLSParser + * and the processing has been stopped.

+ * + *

SERIALIZE_ERR: + * If an attempt was made to serialize a Node using LSSerializer and the processing + * has been stopped.

+ * + * @since DOM Level 3 + */ + enum LSExceptionCode { + PARSE_ERR = 81, + SERIALIZE_ERR = 82 + }; + //@} + + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + /** + * Default constructor for DOMLSException. + * + */ + DOMLSException(); + + /** + * Constructor which takes an error code and a message. + * + * @param code The error code which indicates the exception + * @param messageCode The string containing the error message + * @param memoryManager The memory manager used to (de)allocate memory + */ + DOMLSException(short code, + short messageCode, + MemoryManager* const memoryManager); + + /** + * Copy constructor. + * + * @param other The object to be copied. + */ + DOMLSException(const DOMLSException &other); + + //@} + + // ----------------------------------------------------------------------- + // Destructors + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + /** + * Destructor for DOMLSException. + * + */ + virtual ~DOMLSException(); + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMLSException & operator = (const DOMLSException &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSInput.hpp b/include/xercesc/dom/DOMLSInput.hpp new file mode 100644 index 0000000..a73a6ea --- /dev/null +++ b/include/xercesc/dom/DOMLSInput.hpp @@ -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: DOMLSInput.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSINPUT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSINPUT_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class InputSource; + + +/** + * This interface represents a single input source for an XML entity. + * + *

This interface allows an application to encapsulate information about + * an input source in a single object, which may include a public identifier, + * a system identifier, a byte stream (possibly with a specified encoding), + * and/or a character stream.

+ * + *

There are two places that the application will deliver this input source + * to the parser: as the argument to the parse method, or as the return value + * of the DOMLSResourceResolver.resolveResource method.

+ * + *

The DOMLSParser will use the DOMLSInput object to determine how to + * read XML input. If there is a character stream available, the parser will + * read that stream directly; if not, the parser will use a byte stream, if + * available; if neither a character stream nor a byte stream is available, + * the parser will attempt to open a URI connection to the resource identified + * by the system identifier.

+ * + *

A DOMLSInput object belongs to the application: the parser shall + * never modify it in any way (it may modify a copy if necessary).

+ * + * @see DOMLSParser#parse + * @see DOMLSResourceResolver#resolveResource + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMLSInput +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSInput() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSInput(const DOMLSInput &); + DOMLSInput & operator = (const DOMLSInput &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSInput() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLSInput interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * String data to parse. If provided, this will always be treated as a sequence of 16-bit units (UTF-16 encoded characters). + * It is not a requirement to have an XML declaration when using stringData. If an XML declaration is present, the value of + * the encoding attribute will be ignored. + * + */ + virtual const XMLCh* getStringData() const = 0; + + /** + * Returns the byte stream for this input source. + * + * @see InputSource + */ + virtual InputSource* getByteStream() const = 0; + + /** + * An input source can be set to force the parser to assume a particular + * encoding for the data that input source reprsents, via the setEncoding() + * method. This method returns name of the encoding that is to be forced. + * If the encoding has never been forced, it returns a null pointer. + * + * @return The forced encoding, or null if none was supplied. + * @see #setEncoding + * @since DOM Level 3 + */ + virtual const XMLCh* getEncoding() const = 0; + + + /** + * Get the public identifier for this input source. + * + * @return The public identifier, or null if none was supplied. + * @see #setPublicId + * @since DOM Level 3 + */ + virtual const XMLCh* getPublicId() const = 0; + + + /** + * Get the system identifier for this input source. + * + *

If the system ID is a URL, it will be fully resolved.

+ * + * @return The system identifier. + * @see #setSystemId + * @since DOM Level 3 + */ + virtual const XMLCh* getSystemId() const = 0; + + + /** + * Get the base URI to be used for resolving relative URIs to absolute + * URIs. If the baseURI is itself a relative URI, the behavior is + * implementation dependent. + * + * @return The base URI. + * @see #setBaseURI + * @since DOM Level 3 + */ + virtual const XMLCh* getBaseURI() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + // ----------------------------------------------------------------------- + /** + * Sets the UTF-16 string for this input source. + * + */ + virtual void setStringData(const XMLCh* data) = 0; + + /** + * Sets the byte stream for this input source. + * + * @see BinInputStream + */ + virtual void setByteStream(InputSource* stream) = 0; + + /** + * Set the encoding which will be required for use with the XML text read + * via a stream opened by this input source. + * + *

This is usually not set, allowing the encoding to be sensed in the + * usual XML way. However, in some cases, the encoding in the file is known + * to be incorrect because of intermediate transcoding, for instance + * encapsulation within a MIME document. + * + * @param encodingStr The name of the encoding to force. + * @since DOM Level 3 + */ + virtual void setEncoding(const XMLCh* const encodingStr) = 0; + + + /** + * Set the public identifier for this input source. + * + *

The public identifier is always optional: if the application writer + * includes one, it will be provided as part of the location information.

+ * + * @param publicId The public identifier as a string. + * @see #getPublicId + * @since DOM Level 3 + */ + virtual void setPublicId(const XMLCh* const publicId) = 0; + + /** + * Set the system identifier for this input source. + * + *

The system id is always required. The public id may be used to map + * to another system id, but the system id must always be present as a fall + * back.

+ * + *

If the system ID is a URL, it must be fully resolved.

+ * + * @param systemId The system identifier as a string. + * @see #getSystemId + * @since DOM Level 3 + */ + virtual void setSystemId(const XMLCh* const systemId) = 0; + + /** + * Set the base URI to be used for resolving relative URIs to absolute + * URIs. If the baseURI is itself a relative URI, the behavior is + * implementation dependent. + * + * @param baseURI The base URI. + * @see #getBaseURI + * @since DOM Level 3 + */ + virtual void setBaseURI(const XMLCh* const baseURI) = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + + /** + * Indicates if the parser should issue fatal error if this input source + * is not found. If set to false, the parser issue warning message instead. + * + * @param flag True if the parser should issue fatal error if this input source is not found. + * If set to false, the parser issue warning message instead. (Default: true) + * + * @see #getIssueFatalErrorIfNotFound + */ + virtual void setIssueFatalErrorIfNotFound(bool flag) = 0; + + + /** + * Get the flag that indicates if the parser should issue fatal error if this input source + * is not found. + * + * @return True if the parser should issue fatal error if this input source is not found. + * False if the parser issue warning message instead. + * @see #setIssueFatalErrorIfNotFound + */ + virtual bool getIssueFatalErrorIfNotFound() const = 0; + + /** + * Called to indicate that this DOMLSInput is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSOutput.hpp b/include/xercesc/dom/DOMLSOutput.hpp new file mode 100644 index 0000000..ab86288 --- /dev/null +++ b/include/xercesc/dom/DOMLSOutput.hpp @@ -0,0 +1,169 @@ +/* + * 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: DOMLSOutput.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSOUTPUT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSOUTPUT_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class XMLFormatTarget; + + +/** + * This interface represents an output destination for data. + * + * @see XMLFormatTarget + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMLSOutput +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSOutput() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSOutput(const DOMLSOutput &); + DOMLSOutput & operator = (const DOMLSOutput &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSOutput() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLSOutput interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the byte stream for this input source. + * + * @see InputSource + */ + virtual XMLFormatTarget* getByteStream() const = 0; + + /** + * An input source can be set to force the parser to assume a particular + * encoding for the data that input source reprsents, via the setEncoding() + * method. This method returns name of the encoding that is to be forced. + * If the encoding has never been forced, it returns a null pointer. + * + * @return The forced encoding, or null if none was supplied. + * @see #setEncoding + * @since DOM Level 3 + */ + virtual const XMLCh* getEncoding() const = 0; + + /** + * Get the system identifier for this input source. + * + *

If the system ID is a URL, it will be fully resolved.

+ * + * @return The system identifier. + * @see #setSystemId + * @since DOM Level 3 + */ + virtual const XMLCh* getSystemId() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Sets the byte stream for this input source. + * + * @see BinInputStream + */ + virtual void setByteStream(XMLFormatTarget* stream) = 0; + + /** + * Set the encoding which will be required for use with the XML text read + * via a stream opened by this input source. + * + *

This is usually not set, allowing the encoding to be sensed in the + * usual XML way. However, in some cases, the encoding in the file is known + * to be incorrect because of intermediate transcoding, for instance + * encapsulation within a MIME document. + * + * @param encodingStr The name of the encoding to force. + * @since DOM Level 3 + */ + virtual void setEncoding(const XMLCh* const encodingStr) = 0; + + /** + * Set the system identifier for this input source. + * + *

The system id is always required. The public id may be used to map + * to another system id, but the system id must always be present as a fall + * back.

+ * + *

If the system ID is a URL, it must be fully resolved.

+ * + * @param systemId The system identifier as a string. + * @see #getSystemId + * @since DOM Level 3 + */ + virtual void setSystemId(const XMLCh* const systemId) = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this DOMLSOutput is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSParser.hpp b/include/xercesc/dom/DOMLSParser.hpp new file mode 100644 index 0000000..fcfc839 --- /dev/null +++ b/include/xercesc/dom/DOMLSParser.hpp @@ -0,0 +1,766 @@ +/* + * 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: DOMLSParser.hpp 832686 2009-11-04 08:55:59Z borisk $ + * + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSPARSER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSPARSER_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMErrorHandler; +class DOMLSInput; +class DOMNode; +class DOMDocument; + +/** + * DOMLSParser provides an API for parsing XML documents and building the + * corresponding DOM document tree. A DOMLSParser instance is obtained from + * the DOMImplementationLS interface by invoking its createLSParser method. + * + * @since DOM Level 3 + * + */ +class CDOM_EXPORT DOMLSParser +{ +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSParser() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSParser(const DOMLSParser &); + DOMLSParser & operator = (const DOMLSParser &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSParser() {}; + //@} + + // ----------------------------------------------------------------------- + // Class types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * A set of possible actions for the parseWithContext method. + * + *

ACTION_APPEND_AS_CHILDREN: + * Append the result of the parse operation as children of the context node. + * For this action to work, the context node must be a DOMElement + * or a DOMDocumentFragment.

+ * + *

ACTION_INSERT_AFTER: + * Insert the result of the parse operation as the immediately following sibling + * of the context node. For this action to work the context node's parent must + * be a DOMElement or a DOMDocumentFragment.

+ * + *

ACTION_INSERT_BEFORE: + * Insert the result of the parse operation as the immediately preceding sibling + * of the context node. For this action to work the context node's parent must + * be a DOMElement or a DOMDocumentFragment.

+ * + *

ACTION_REPLACE: + * Replace the context node with the result of the parse operation. For this + * action to work, the context node must have a parent, and the parent must be + * a DOMElement or a DOMDocumentFragment.

+ * + *

ACTION_REPLACE_CHILDREN: + * Replace all the children of the context node with the result of the parse + * operation. For this action to work, the context node must be a DOMElement, + * a DOMDocument, or a DOMDocumentFragment.

+ * + * @see parseWithContext(...) + * @since DOM Level 3 + */ + enum ActionType + { + ACTION_APPEND_AS_CHILDREN = 1, + ACTION_REPLACE_CHILDREN = 2, + ACTION_INSERT_BEFORE = 3, + ACTION_INSERT_AFTER = 4, + ACTION_REPLACE = 5 + }; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLSParser interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** + * Get a pointer to the DOMConfiguration object used when parsing + * an input source. + * This DOMConfiguration is specific to the parse operation. + * No parameter values from this DOMConfiguration object are passed + * automatically to the DOMConfiguration object on the + * DOMDocument that is created, or used, by the parse operation. + * The DOM application is responsible for passing any needed parameter values + * from this DOMConfiguration object to the DOMConfiguration + * object referenced by the DOMDocument object. + * + * In addition to the parameters recognized in on the DOMConfiguration + * interface defined in [DOM Level 3 Core], the DOMConfiguration objects + * for DOMLSParser add or modify the following parameters: + * + * "charset-overrides-xml-encoding" + * true [optional] (default) + * If a higher level protocol such as HTTP [IETF RFC 2616] provides an + * indication of the character encoding of the input stream being processed, + * that will override any encoding specified in the XML declaration or the + * Text declaration (see also section 4.3.3, "Character Encoding in Entities", + * in [XML 1.0]). Explicitly setting an encoding in the DOMLSInput + * overrides any encoding from the protocol. + * false [required] + * The parser ignores any character set encoding information from higher-level + * protocols. + * + * "disallow-doctype" + * true [optional] + * Throw a fatal "doctype-not-allowed" error if a doctype node is found while + * parsing the document. This is useful when dealing with things like SOAP + * envelopes where doctype nodes are not allowed. + * false [required] (default) + * Allow doctype nodes in the document. + * + * "ignore-unknown-character-denormalizations" + * true [required] (default) + * If, while verifying full normalization when [XML 1.1] is supported, a + * processor encounters characters for which it cannot determine the normalization + * properties, then the processor will ignore any possible denormalizations + * caused by these characters. + * This parameter is ignored for [XML 1.0]. + * false [optional] + * Report an fatal "unknown-character-denormalization" error if a character + * is encountered for which the processor cannot determine the normalization + * properties. + * + * "infoset" + * See the definition of DOMConfiguration for a description of this parameter. + * Unlike in [DOM Level 3 Core], this parameter will default to true for DOMLSParser. + * + * "namespaces" + * true [required] (default) + * Perform the namespace processing as defined in [XML Namespaces] and + * [XML Namespaces 1.1]. + * false [optional] + * Do not perform the namespace processing. + * + * "resource-resolver" [required] + * A pointer to a DOMLSResourceResolver object, or NULL. If the value of this parameter + * is not null when an external resource (such as an external XML entity or an XML schema + * location) is encountered, the implementation will request that the DOMLSResourceResolver + * referenced in this parameter resolves the resource. + * + * "supported-media-types-only" + * true [optional] + * Check that the media type of the parsed resource is a supported media type. If + * an unsupported media type is encountered, a fatal error of type "unsupported-media-type" + * will be raised. The media types defined in [IETF RFC 3023] must always be accepted. + * false [required] (default) + * Accept any media type. + * + * "validate" + * See the definition of DOMConfiguration for a description of this parameter. + * Unlike in [DOM Level 3 Core], the processing of the internal subset is always accomplished, even + * if this parameter is set to false. + * + * "validate-if-schema" + * See the definition of DOMConfiguration for a description of this parameter. + * Unlike in [DOM Level 3 Core], the processing of the internal subset is always accomplished, even + * if this parameter is set to false. + * + * "well-formed" + * See the definition of DOMConfiguration for a description of this parameter. + * Unlike in [DOM Level 3 Core], this parameter cannot be set to false. + * + * In addition to these, Xerces adds these non standard parameters: + * + * "http://apache.org/xml/properties/entity-resolver" + * A pointer to a XMLEntityResolver object, or NULL. If the value of this parameter + * is not null when an external resource (such as an external XML entity or an XML schema + * location) is encountered, the implementation will request that the XMLEntityResolver + * referenced in this parameter resolves the resource. + * + * "http://apache.org/xml/properties/schema/external-schemaLocation" + * A string holding a set of [namespaceUri schemaLocation] entries that will be treated as + * the content of the attribute xsi:schemaLocation of the root element + * + * "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation" + * A string holding the schemaLocation for the empty namespace URI that will be treated as + * the content of the attribute xsi:noNamespaceSchemaLocation of the root element + * + * "http://apache.org/xml/properties/security-manager" + * A pointer to a SecurityManager object that will control how many entity references will be + * expanded during parsing + * + * "http://apache.org/xml/properties/scannerName" + * A string holding the type of scanner used while parsing. The valid names are: + *
    + *
  • IGXMLScanner: the default one, capable of both XMLSchema and DTD validation
  • + *
  • SGXMLScanner: a scanner that can only perform XMLSchema validation
  • + *
  • DGXMLScanner: a scanner that can only perform DTD validation
  • + *
  • WFXMLScanner: a scanner that cannot perform any type validation, only well-formedness
  • + *
+ * + * "http://apache.org/xml/properties/parser-use-DOMDocument-from-Implementation" + * A string holding the capabilities of the DOM implementation to be used to create the DOMDocument + * resulting from the parse operation. For instance, "LS" or "Core" + * + * "http://apache.org/xml/features/validation/schema" + * true + * Enable XMLSchema validation (note that also namespace processing should be enabled) + * false (default) + * Don't perform XMLSchema validation + * + * "http://apache.org/xml/features/validation/schema-full-checking" + * true + * Turn on full XMLSchema checking (e.g. Unique Particle Attribution) + * false (default) + * Don't perform full XMLSchema checking + * + * "http://apache.org/xml/features/validating/load-schema" + * true (default) + * Allow the parser to load schemas that are not in the grammar pool + * false + * Schemas that are not in the grammar pool are ignored + * + * "http://apache.org/xml/features/dom/user-adopts-DOMDocument" + * true + * The DOMDocument objects returned by parse will be owned by the caller + * false (default) + * The DOMDocument objects returned by parse will be owned by this DOMLSParser + * and deleted when released + * + * "http://apache.org/xml/features/nonvalidating/load-external-dtd" + * true (default) + * Allow the parser to load external DTDs + * false + * References to external DTDs will be ignored + * + * "http://apache.org/xml/features/continue-after-fatal-error" + * true + * Parsing should try to continue even if a fatal error has been triggered, trying to generate a DOM tree + * from a non well-formed XML + * false (default) + * Violation of XML rules will abort parsing + * + * "http://apache.org/xml/features/validation-error-as-fatal" + * true + * Validation errors are treated as fatal errors, and abort parsing (unless "continue-after-fatal-error" + * has been specified) + * false (default) + * Validation errors are normal errors + * + * "http://apache.org/xml/features/validation/cache-grammarFromParse" + * true + * XMLSchemas referenced by an XML file are cached in order to be reused by other parse operations + * false (default) + * XMLSchemas loaded during a parse operation will be discarded before the next one + * + * "http://apache.org/xml/features/validation/use-cachedGrammarInParse" + * true + * During this parse operation, reuse the XMLSchemas found in the cache + * false (default) + * Don't reuse the XMLSchemas found in the cache + * + * "http://apache.org/xml/features/calculate-src-ofs" + * true + * During parsing update the position in the source stream + * false (default) + * Don't waste time computing the position in the source stream + * + * "http://apache.org/xml/features/standard-uri-conformant" + * true + * Require that every URL being resolved is made of valid URL characters only + * false (default) + * Allow invalid URL characters in URL (e.g. spaces) + * + * "http://apache.org/xml/features/dom-has-psvi-info" + * true + * Add schema informations to DOMElement and DOMAttr nodes in the output DOM tree + * false (default) + * Don't store schema informations in the output DOM tree + * + * "http://apache.org/xml/features/generate-synthetic-annotations" + * true + * Create annotation objects in the representation of the loaded XMLSchemas + * false (default) + * Discard annotations found in the loaded XMLSchemas + * + * "http://apache.org/xml/features/validate-annotations" + * true + * Check that annotations are valid according to their XMLSchema definition + * false (default) + * Don't validate annotations + * + * "http://apache.org/xml/features/validation/identity-constraint-checking" + * true (default) + * Enforce identity constraints specified in the XMLSchema + * false + * Don't enforce identity constraints + * + * "http://apache.org/xml/features/validation/ignoreCachedDTD" + * true + * Don't reuse DTDs found in the cache, even if use-cachedGrammarInParse is true + * false (default) + * Reuse DTDs found in the cache, if use-cachedGrammarInParse is true + * + * "http://apache.org/xml/features/schema/ignore-annotations" + * true + * Don't process annotations found in an XMLSchema + * false (default) + * Process the annotations found in an XMLSchema + * + * "http://apache.org/xml/features/disable-default-entity-resolution" + * true + * Entities will be resolved only by a resolver installed by the user + * false (default) + * If the entity resolver has not been installed, or it refuses to resolve the given entity, the + * parser will try to locate it himself + * + * "http://apache.org/xml/features/validation/schema/skip-dtd-validation" + * true + * If XMLSchema validation is true, DTD validation will not be performed + * false (default) + * If a DTD is found, it will be used to validate the XML + * + * @return The pointer to the configuration object. + * @since DOM Level 3 + */ + virtual DOMConfiguration* getDomConfig() = 0; + + /** + * Get a const pointer to the application filter + * + * This method returns the installed application filter. If no filter + * has been installed, then it will be a zero pointer. + * + * @return A const pointer to the installed application filter + * @since DOM Level 3 + */ + virtual const DOMLSParserFilter* getFilter() const = 0; + + /** + * Return whether the parser is asynchronous + * + * @return true if the DOMLSParser is asynchronous, + * false if it is synchronous + * @since DOM Level 3 + */ + virtual bool getAsync() const = 0; + + /** + * Return whether the parser is busy parsing + * + * @return true if the DOMLSParser is currently busy + * loading a document, otherwise false. + * @since DOM Level 3 + */ + virtual bool getBusy() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Set the application filter + * + * When the application provides a filter, the parser will call out to + * the filter at the completion of the construction of each DOMElement + * node. The filter implementation can choose to remove the element from the + * document being constructed or to terminate the parse early. + * The filter is invoked after the operations requested by the DOMConfiguration + * parameters have been applied. For example, if "validate" is set to true, + * the validation is done before invoking the filter. + * + * Any previously set filter is merely dropped, since the parser + * does not own them. + * + * @param filter A const pointer to the user supplied application + * filter. + * + * @see #getFilter + * @since DOM Level 3 + */ + virtual void setFilter(DOMLSParserFilter* const filter) = 0; + + // ----------------------------------------------------------------------- + // Parsing methods + // ----------------------------------------------------------------------- + /** + * Parse an XML document from a resource identified by a DOMLSInput. + * + * The parser owns the returned DOMDocument. It will be deleted + * when the parser is released. + * + * @param source The DOMLSInput from which the source of the document + * is to be read. + * @return If the DOMLSParser is a synchronous DOMLSParser + * the newly created and populated DOMDocument is returned. + * If the DOMLSParser is asynchronous then NULL + * is returned since the document object may not yet be constructed when + * this method returns. + * @exception DOMException INVALID_STATE_ERR: Raised if the DOMLSParser::busy + * attribute is true. + * @exception DOMLSException PARSE_ERR: Starting from Xerces-C++ 4.0.0 this exception is + * raised if the DOMLSParser was unable + * to load the XML document. DOM applications should + * attach a DOMErrorHandler using the + * parameter "error-handler" if they wish to get details + * on the error. + * + * @see DOMLSInput#DOMLSInput + * @see DOMConfiguration + * @see resetDocumentPool + * @since DOM Level 3 + */ + virtual DOMDocument* parse(const DOMLSInput* source) = 0; + + /** + * Parse an XML document from a location identified by a URI reference [IETF RFC 2396]. + * If the URI contains a fragment identifier (see section 4.1 in [IETF RFC 2396]), + * the behavior is not defined by this specification, future versions of this + * specification may define the behavior. + * + * The parser owns the returned DOMDocument. It will be deleted + * when the parser is released. + * + * @param uri The location of the XML document to be read (in Unicode) + * @return If the DOMLSParser is a synchronous DOMLSParser + * the newly created and populated DOMDocument is returned. + * If the DOMLSParser is asynchronous then NULL + * is returned since the document object is not yet parsed when this method returns. + * @exception DOMException INVALID_STATE_ERR: Raised if the DOMLSParser::busy + * attribute is true. + * @exception DOMLSException PARSE_ERR: Starting from Xerces-C++ 4.0.0 this exception is + * raised if the DOMLSParser was unable + * to load the XML document. DOM applications should + * attach a DOMErrorHandler using the + * parameter "error-handler" if they wish to get details + * on the error. + * + * @see #parse(DOMLSInput,...) + * @see resetDocumentPool + * @since DOM Level 3 + */ + virtual DOMDocument* parseURI(const XMLCh* const uri) = 0; + + /** + * Parse an XML document from a location identified by a URI reference [IETF RFC 2396]. + * If the URI contains a fragment identifier (see section 4.1 in [IETF RFC 2396]), + * the behavior is not defined by this specification, future versions of this + * specification may define the behavior. + * + * The parser owns the returned DOMDocument. It will be deleted + * when the parser is released. + * + * @param uri The location of the XML document to be read (in the local code page) + * @return If the DOMLSParser is a synchronous DOMLSParser + * the newly created and populated DOMDocument is returned. + * If the DOMLSParser is asynchronous then NULL + * is returned since the document object is not yet parsed when this method returns. + * @exception DOMException INVALID_STATE_ERR: Raised if the DOMLSParser::busy + * attribute is true. + * @exception DOMLSException PARSE_ERR: Starting from Xerces-C++ 4.0.0 this exception is + * raised if the DOMLSParser was unable + * to load the XML document. DOM applications should + * attach a DOMErrorHandler using the + * parameter "error-handler" if they wish to get details + * on the error. + * + * @see #parse(DOMLSInput,...) + * @see resetDocumentPool + * @since DOM Level 3 + */ + virtual DOMDocument* parseURI(const char* const uri) = 0; + + /** + * Parse an XML fragment from a resource identified by a DOMLSInput + * and insert the content into an existing document at the position specified + * with the context and action arguments. When parsing the input stream, the + * context node (or its parent, depending on where the result will be inserted) + * is used for resolving unbound namespace prefixes. The context node's + * ownerDocument node (or the node itself if the node of type + * DOCUMENT_NODE) is used to resolve default attributes and entity + * references. + * As the new data is inserted into the document, at least one mutation event + * is fired per new immediate child or sibling of the context node. + * If the context node is a DOMDocument node and the action is + * ACTION_REPLACE_CHILDREN, then the document that is passed as + * the context node will be changed such that its xmlEncoding, + * documentURI, xmlVersion, inputEncoding, + * xmlStandalone, and all other such attributes are set to what they + * would be set to if the input source was parsed using DOMLSParser::parse(). + * This method is always synchronous, even if the DOMLSParser is + * asynchronous (DOMLSParser::getAsync() returns true). + * If an error occurs while parsing, the caller is notified through the ErrorHandler + * instance associated with the "error-handler" parameter of the DOMConfiguration. + * When calling parseWithContext, the values of the following configuration + * parameters will be ignored and their default values will always be used instead: + * "validate", + * "validate-if-schema" + * "element-content-whitespace". + * Other parameters will be treated normally, and the parser is expected to call + * the DOMLSParserFilter just as if a whole document was parsed. + * + * @param source The DOMLSInput from which the source document is + * to be read. The source document must be an XML fragment, i.e. + * anything except a complete XML document (except in the case where + * the context node of type DOCUMENT_NODE, and the action is + * ACTION_REPLACE_CHILDREN), a DOCTYPE + * (internal subset), entity declaration(s), notation declaration(s), + * or XML or text declaration(s). + * @param contextNode The node that is used as the context for the data that is being + * parsed. This node must be a DOMDocument node, a + * DOMDocumentFragment node, or a node of a type that + * is allowed as a child of an DOMElement node, e.g. + * it cannot be an DOMAttribute node. + * @param action This parameter describes which action should be taken between the new + * set of nodes being inserted and the existing children of the context node. + * The set of possible actions is defined in ACTION_TYPES above. + * @return Return the node that is the result of the parse operation. If the result is more + * than one top-level node, the first one is returned. + * + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if the content cannot replace, be inserted before, after, + * or as a child of the context node (see also DOMNode::insertBefore + * or DOMNode::replaceChild in [DOM Level 3 Core]). + * NOT_SUPPORTED_ERR: Raised if the DOMLSParser doesn't support this method, + * or if the context node is of type DOMDocument and the DOM + * implementation doesn't support the replacement of the DOMDocumentType + * child or DOMElement child. + * NO_MODIFICATION_ALLOWED_ERR: Raised if the context node is a read only node and the content + * is being appended to its child list, or if the parent node of + * the context node is read only node and the content is being + * inserted in its child list. + * INVALID_STATE_ERR: Raised if the DOMLSParser::getBusy() returns true. + * + * @exception DOMLSException PARSE_ERR: Raised if the DOMLSParser was unable to load + * the XML fragment. DOM applications should attach a + * DOMErrorHandler using the parameter "error-handler" + * if they wish to get details on the error. + * @since DOM Level 3 + */ + virtual DOMNode* parseWithContext(const DOMLSInput* source, DOMNode* contextNode, const ActionType action) = 0; + + /** + * Abort the loading of the document that is currently being loaded by the DOMLSParser. + * If the DOMLSParser is currently not busy, a call to this method does nothing. + * + * Note: invoking this method will remove the installed DOMLSParserFilter filter + * + * @since DOM Level 3 + */ + virtual void abort() = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this DOMLSParser is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + + /** Reset the documents vector pool and release all the associated memory + * back to the system. + * + * When parsing a document using a DOM parser, all memory allocated + * for a DOM tree is associated to the DOM document. + * + * If you do multiple parse using the same DOM parser instance, then + * multiple DOM documents will be generated and saved in a vector pool. + * All these documents (and thus all the allocated memory) + * won't be deleted until the parser instance is destroyed. + * + * If you don't need these DOM documents anymore and don't want to + * destroy the DOM parser instance at this moment, then you can call this method + * to reset the document vector pool and release all the allocated memory + * back to the system. + * + * It is an error to call this method if you are in the middle of a + * parse (e.g. in the mid of a progressive parse). + * + * @exception IOException An exception from the parser if this function + * is called when a parse is in progress. + * + */ + virtual void resetDocumentPool() = 0; + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the DOMLSInput parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * @param source A const reference to the DOMLSInput object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no chaching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see DOMLSInput#DOMLSInput + */ + virtual Grammar* loadGrammar(const DOMLSInput* source, + const Grammar::GrammarType grammarType, + const bool toCache = false) = 0; + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag is + * enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no chaching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false) = 0; + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag is + * enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no chaching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false) = 0; + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + virtual Grammar* getGrammar(const XMLCh* const nameSpaceKey) const = 0; + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + virtual Grammar* getRootGrammar() const = 0; + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + virtual const XMLCh* getURIText(unsigned int uriId) const = 0; + + /** + * Clear the cached grammar pool + */ + virtual void resetCachedGrammarPool() = 0; + + /** + * Returns the current src offset within the input source. + * + * @return offset within the input source + */ + virtual XMLFilePos getSrcOffset() const = 0; + + //@} + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSParserFilter.hpp b/include/xercesc/dom/DOMLSParserFilter.hpp new file mode 100644 index 0000000..0621322 --- /dev/null +++ b/include/xercesc/dom/DOMLSParserFilter.hpp @@ -0,0 +1,164 @@ +/* + * 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: DOMLSParserFilter.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSPARSERFILTER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSPARSERFILTER_HPP + + /** + * + * DOMLSParserFilter.hpp: interface for the DOMLSParserFilter class. + * + * DOMLSParserFilter provide applications the ability to examine nodes + * as they are being created during the parse process. + * + * DOMLSParserFilter lets the application decide what nodes should be + * in the output DOM tree or not. + * + * @since DOM Level 3 + */ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMElement; +class DOMNode; + +class CDOM_EXPORT DOMLSParserFilter { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSParserFilter() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSParserFilter(const DOMLSParserFilter &); + DOMLSParserFilter & operator = (const DOMLSParserFilter &); + //@} + + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSParserFilter() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Contants */ + //@{ + /** + * Constants returned by acceptNode. + * + *

FILTER_ACCEPT: + * Accept the node.

+ * + *

FILTER_REJECT: + * Reject the node and its children.

+ * + *

FILTER_SKIP: + * Skip this single node. The children of this node will still be considered.

+ * + *

FILTER_INTERRUPT: + * Interrupt the normal processing of the document.

+ * + * @since DOM Level 3 + */ + enum FilterAction {FILTER_ACCEPT = 1, + FILTER_REJECT = 2, + FILTER_SKIP = 3, + FILTER_INTERRUPT = 4}; + + // ----------------------------------------------------------------------- + // Virtual DOMLSParserFilter interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * This method will be called by the parser at the completion of the parsing of each node. + * The node and all of its descendants will exist and be complete. The parent node will also exist, + * although it may be incomplete, i.e. it may have additional children that have not yet been parsed. + * Attribute nodes are never passed to this function. + * From within this method, the new node may be freely modified - children may be added or removed, + * text nodes modified, etc. The state of the rest of the document outside this node is not defined, + * and the affect of any attempt to navigate to, or to modify any other part of the document is undefined. + * For validating parsers, the checks are made on the original document, before any modification by the + * filter. No validity checks are made on any document modifications made by the filter. + * If this new node is rejected, the parser might reuse the new node and any of its descendants. + * + * @param node The newly constructed element. At the time this method is called, the element is complete - + * it has all of its children (and their children, recursively) and attributes, and is attached + * as a child to its parent. + * @return One of the FilterAction enum + */ + virtual FilterAction acceptNode(DOMNode* node) = 0; + + /** + * The parser will call this method after each DOMElement start tag has been scanned, + * but before the remainder of the DOMElement is processed. The intent is to allow the element, + * including any children, to be efficiently skipped. Note that only element nodes are passed to the + * startElement function. + * The element node passed to startElement for filtering will include all of the attributes, but none + * of the children nodes. The DOMElement may not yet be in place in the document being + * constructed (it may not have a parent node.) + * A startElement filter function may access or change the attributes for the DOMElement. + * Changing namespace declarations will have no effect on namespace resolution by the parser. + * + * @param node The newly encountered element. At the time this method is called, the element is incomplete - + * it will have its attributes, but no children. + * @return One of the FilterAction enum + */ + virtual FilterAction startElement(DOMElement* node) = 0; + + /** + * Tells the DOMLSParser what types of nodes to show to the method DOMLSParserFilter::acceptNode. + * If a node is not shown to the filter using this attribute, it is automatically included in the DOM document being built. + * See DOMNodeFilter for definition of the constants. The constants SHOW_ATTRIBUTE, SHOW_DOCUMENT, + * SHOW_DOCUMENT_TYPE, SHOW_NOTATION, SHOW_ENTITY, and SHOW_DOCUMENT_FRAGMENT are meaningless here. + * Those nodes will never be passed to DOMLSParserFilter::acceptNode. + * + * @return The constants of what types of nodes to show. + * @since DOM Level 3 + */ + virtual DOMNodeFilter::ShowType getWhatToShow() const = 0; + + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSResourceResolver.hpp b/include/xercesc/dom/DOMLSResourceResolver.hpp new file mode 100644 index 0000000..24792d3 --- /dev/null +++ b/include/xercesc/dom/DOMLSResourceResolver.hpp @@ -0,0 +1,143 @@ +/* + * 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: DOMLSResourceResolver.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSRESOURCERESOLVER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSRESOURCERESOLVER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMLSInput; + +/** + * DOMLSResourceResolver provides a way for applications to redirect references + * to external entities. + * + *

Applications needing to implement customized handling for external + * entities must implement this interface and register their implementation + * by setting the entityResolver attribute of the DOMLSParser.

+ * + *

The DOMLSParser will then allow the application to intercept any + * external entities (including the external DTD subset and external parameter + * entities) before including them.

+ * + *

Many DOM applications will not need to implement this interface, but it + * will be especially useful for applications that build XML documents from + * databases or other specialized input sources, or for applications that use + * URNs.

+ * + * @see DOMLSParser#getDomConfig + * @see DOMLSInput#DOMLSInput + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMLSResourceResolver +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSResourceResolver() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSResourceResolver(const DOMLSResourceResolver &); + DOMLSResourceResolver & operator = (const DOMLSResourceResolver &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSResourceResolver() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLSResourceResolver interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * Allow the application to resolve external resources. + * + * The DOMLSParser will call this method before opening any external resource, + * including the external DTD subset, external entities referenced within the DTD, and + * external entities referenced within the document element (however, the top-level + * document entity is not passed to this method). The application may then request that + * the DOMLSParser resolve the external resource itself, that it use an + * alternative URI, or that it use an entirely different input source. + * + * Application writers can use this method to redirect external system identifiers to + * secure and/or local URI, to look up public identifiers in a catalogue, or to read + * an entity from a database or other input source (including, for example, a dialog box). + * + * The returned DOMLSInput is owned by the DOMLSParser which is + * responsible to clean up the memory. + * + * @param resourceType The type of the resource being resolved. For XML [XML 1.0] resources + * (i.e. entities), applications must use the value "http://www.w3.org/TR/REC-xml". + * For XML Schema [XML Schema Part 1], applications must use the value + * "http://www.w3.org/2001/XMLSchema". Other types of resources are outside + * the scope of this specification and therefore should recommend an absolute + * URI in order to use this method. + * @param namespaceUri The namespace of the resource being resolved, e.g. the target namespace + * of the XML Schema [XML Schema Part 1] when resolving XML Schema resources. + * @param publicId The public identifier of the external entity being referenced, or null + * if no public identifier was supplied or if the resource is not an entity. + * @param systemId The system identifier, a URI reference [IETF RFC 2396], of the external + * resource being referenced, or null if no system identifier was supplied. + * @param baseURI The absolute base URI of the resource being parsed, or null if + * there is no base URI. + * @return A DOMLSInput object describing the new input source, + * or null to request that the parser open a regular + * URI connection to the resource. + * The returned DOMLSInput is owned by the DOMLSParser which is + * responsible to clean up the memory. + * @see DOMLSInput#DOMLSInput + * @since DOM Level 3 + */ + virtual DOMLSInput* resolveResource( const XMLCh* const resourceType + , const XMLCh* const namespaceUri + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLCh* const baseURI) = 0; + + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSSerializer.hpp b/include/xercesc/dom/DOMLSSerializer.hpp new file mode 100644 index 0000000..96aadd4 --- /dev/null +++ b/include/xercesc/dom/DOMLSSerializer.hpp @@ -0,0 +1,547 @@ +/* + * 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: DOMLSSerializer.hpp 883665 2009-11-24 11:41:38Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSSERIALIZER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSSERIALIZER_HPP + +/** + * + * DOMLSSerializer provides an API for serializing (writing) a DOM document out in + * an XML document. The XML data is written to an output stream, the type of + * which depends on the specific language bindings in use. During + * serialization of XML data, namespace fixup is done when possible. + *

DOMLSSerializer accepts any node type for serialization. For + * nodes of type Document or Entity, well formed + * XML will be created if possible. The serialized output for these node + * types is either as a Document or an External Entity, respectively, and is + * acceptable input for an XML parser. For all other types of nodes the + * serialized form is not specified, but should be something useful to a + * human for debugging or diagnostic purposes. Note: rigorously designing an + * external (source) form for stand-alone node types that don't already have + * one defined in seems a bit much to take on here. + *

Within a Document or Entity being serialized, Nodes are processed as + * follows Documents are written including an XML declaration and a DTD + * subset, if one exists in the DOM. Writing a document node serializes the + * entire document. Entity nodes, when written directly by + * write defined in the DOMLSSerializer interface, + * output the entity expansion but no namespace fixup is done. The resulting + * output will be valid as an external entity. Entity References nodes are + * serializes as an entity reference of the form + * "&entityName;") in the output. Child nodes (the + * expansion) of the entity reference are ignored. CDATA sections + * containing content characters that can not be represented in the + * specified output encoding are handled according to the + * "split-cdata-sections" feature.If the feature is true, CDATA + * sections are split, and the unrepresentable characters are serialized as + * numeric character references in ordinary content. The exact position and + * number of splits is not specified. If the feature is false, + * unrepresentable characters in a CDATA section are reported as errors. The + * error is not recoverable - there is no mechanism for supplying + * alternative characters and continuing with the serialization. All other + * node types (DOMElement, DOMText, etc.) are serialized to their corresponding + * XML source form. + *

Within the character data of a document (outside of markup), any + * characters that cannot be represented directly are replaced with + * character references. Occurrences of '<' and '&' are replaced by + * the predefined entities &lt; and &amp. The other predefined + * entities (&gt, &apos, etc.) are not used; these characters can be + * included directly. Any character that can not be represented directly in + * the output character encoding is serialized as a numeric character + * reference. + *

Attributes not containing quotes are serialized in quotes. Attributes + * containing quotes but no apostrophes are serialized in apostrophes + * (single quotes). Attributes containing both forms of quotes are + * serialized in quotes, with quotes within the value represented by the + * predefined entity &quot;. Any character that can not be represented + * directly in the output character encoding is serialized as a numeric + * character reference. + *

Within markup, but outside of attributes, any occurrence of a character + * that cannot be represented in the output character encoding is reported + * as an error. An example would be serializing the element + * <LaCañada/> with the encoding="us-ascii". + *

When requested by setting the normalize-characters feature + * on DOMLSSerializer, all data to be serialized, both markup and + * character data, is W3C Text normalized according to the rules defined in + * . The W3C Text normalization process affects only the data as it is being + * written; it does not alter the DOM's view of the document after + * serialization has completed. + *

Namespaces are fixed up during serialization, the serialization process + * will verify that namespace declarations, namespace prefixes and the + * namespace URIs associated with Elements and Attributes are consistent. If + * inconsistencies are found, the serialized form of the document will be + * altered to remove them. The algorithm used for doing the namespace fixup + * while seralizing a document is a combination of the algorithms used for + * lookupNamespaceURI and lookupPrefix. previous paragraph to be + * defined closer here. + *

Any changes made affect only the namespace prefixes and declarations + * appearing in the serialized data. The DOM's view of the document is not + * altered by the serialization operation, and does not reflect any changes + * made to namespace declarations or prefixes in the serialized output. + *

While serializing a document the serializer will write out + * non-specified values (such as attributes whose specified is + * false) if the output-default-values feature is + * set to true. If the output-default-values flag + * is set to false and the use-abstract-schema + * feature is set to true the abstract schema will be used to + * determine if a value is specified or not, if + * use-abstract-schema is not set the specified + * flag on attribute nodes is used to determine if attribute values should + * be written out. + *

Ref to Core spec (1.1.9, XML namespaces, 5th paragraph) entity ref + * description about warning about unbound entity refs. Entity refs are + * always serialized as &foo;, also mention this in the load part of + * this spec. + *

When serializing a document the DOMLSSerializer checks to see if the document + * element in the document is a DOM Level 1 element or a DOM Level 2 (or + * higher) element (this check is done by looking at the localName of the + * root element). If the root element is a DOM Level 1 element then the + * DOMLSSerializer will issue an error if a DOM Level 2 (or higher) element is + * found while serializing. Likewise if the document element is a DOM Level + * 2 (or higher) element and the DOMLSSerializer sees a DOM Level 1 element an + * error is issued. Mixing DOM Level 1 elements with DOM Level 2 (or higher) + * is not supported. + *

DOMLSSerializers have a number of named features that can be + * queried or set. The name of DOMLSSerializer features must be valid + * XML names. Implementation specific features (extensions) should choose an + * implementation dependent prefix to avoid name collisions. + *

Here is a list of properties that must be recognized by all + * implementations. + *

+ *
"normalize-characters"
+ *
+ *
+ *
true
+ *
[ + * optional] (default) Perform the W3C Text Normalization of the characters + * in document as they are written out. Only the characters being written + * are (potentially) altered. The DOM document itself is unchanged.
+ *
+ * false
+ *
[required] do not perform character normalization.
+ *
+ *
+ * "split-cdata-sections"
+ *
+ *
+ *
true
+ *
[required] (default) + * Split CDATA sections containing the CDATA section termination marker + * ']]>' or characters that can not be represented in the output + * encoding, and output the characters using numeric character references. + * If a CDATA section is split a warning is issued.
+ *
false
+ *
[ + * required] Signal an error if a CDATASection contains an + * unrepresentable character.
+ *
+ *
"validation"
+ *
+ *
+ *
true
+ *
[ + * optional] Use the abstract schema to validate the document as it is being + * serialized. If validation errors are found the error handler is notified + * about the error. Setting this state will also set the feature + * use-abstract-schema to true.
+ *
false
+ *
[ + * required] (default) Don't validate the document as it is being + * serialized.
+ *
+ *
"expand-entity-references"
+ *
+ *
+ *
true
+ *
[ + * optional] Expand EntityReference nodes when serializing.
+ *
+ * false
+ *
[required] (default) Serialize all + * EntityReference nodes as XML entity references.
+ *
+ *
+ * "whitespace-in-element-content"
+ *
+ *
+ *
true
+ *
[required] ( + * default) Output all white spaces in the document.
+ *
false
+ *
[ + * optional] Only output white space that is not within element content. The + * implementation is expected to use the + * isWhitespaceInElementContent flag on Text nodes + * to determine if a text node should be written out or not.
+ *
+ *
+ * "discard-default-content"
+ *
+ *
+ *
true
+ *
[required] (default + * ) Use whatever information available to the implementation (i.e. XML + * schema, DTD, the specified flag on Attr nodes, + * and so on) to decide what attributes and content should be serialized or + * not. Note that the specified flag on Attr nodes + * in itself is not always reliable, it is only reliable when it is set to + * false since the only case where it can be set to + * false is if the attribute was created by a Level 1 + * implementation.
+ *
false
+ *
[required] Output all attributes and + * all content.
+ *
+ *
"format-canonical"
+ *
+ *
+ *
true
+ *
[optional] + * This formatting writes the document according to the rules specified in . + * Setting this feature to true will set the feature "format-pretty-print" + * to false.
+ *
false
+ *
[required] (default) Don't canonicalize the + * output.
+ *
+ *
"format-pretty-print"
+ *
+ *
+ *
true
+ *
[optional] + * Formatting the output by adding whitespace to produce a pretty-printed, + * indented, human-readable form. The exact form of the transformations is + * not specified by this specification. Setting this feature to true will + * set the feature "format-canonical" to false.
+ *
false
+ *
[required] + * (default) Don't pretty-print the result.
+ *
+ *
"http://apache.org/xml/features/dom/byte-order-mark"
+ *
+ *
+ *
false
+ *
[optional] + * (default) Setting this feature to true will output the correct BOM for the specified + * encoding.
+ *
true
+ *
[required] + * Don't generate a BOM.
+ *
+ *
"http://apache.org/xml/features/pretty-print/space-first-level-elements"
+ *
+ *
+ *
true
+ *
[optional] + * (default) Setting this feature to true will add an extra line feed between the elements + * that are children of the document root.
+ *
false
+ *
[required] + * Don't add the extra line feed.
+ *
+ *
+ *

See also the Document Object Model (DOM) Level 3 Load and Save Specification. + * + * @since DOM Level 3 + */ + + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMLSOutput; + +class CDOM_EXPORT DOMLSSerializer +{ +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSSerializer() {}; + //@} +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSSerializer(const DOMLSSerializer &); + DOMLSSerializer & operator = (const DOMLSSerializer &); + //@} + + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSSerializer() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLSSerializer interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Feature methods + // ----------------------------------------------------------------------- + /** + * The DOMConfiguration object used by the LSSerializer when serializing a DOM node. + * + * In addition to the parameters recognized in on the DOMConfiguration + * interface defined in [DOM Level 3 Core], the DOMConfiguration objects + * for DOMLSSerializer add or modify the following parameters: + * + * "canonical-form" + * true [optional] + * Writes the document according to the rules specified in [Canonical XML]. In addition to + * the behavior described in "canonical-form" [DOM Level 3 Core], setting this parameter to + * true will set the parameters "format-pretty-print", "discard-default-content", and + * "xml-declaration", to false. Setting one of those parameters to true will set this + * parameter to false. Serializing an XML 1.1 document when "canonical-form" is true will + * generate a fatal error. + * false [required] (default) + * Do not canonicalize the output. + * + * "discard-default-content" + * true [required] (default) + * Use the DOMAttr::getSpecified attribute to decide what attributes should be discarded. + * Note that some implementations might use whatever information available to the implementation + * (i.e. XML schema, DTD, the DOMAttr::getSpecified attribute, and so on) to determine what + * attributes and content to discard if this parameter is set to true. + * false [required] + * Keep all attributes and all content. + * + * "format-pretty-print" + * true [optional] + * Formatting the output by adding whitespace to produce a pretty-printed, indented, + * human-readable form. The exact form of the transformations is not specified by this specification. + * Pretty-printing changes the content of the document and may affect the validity of the document, + * validating implementations should preserve validity. + * false [required] (default) + * Don't pretty-print the result. + * + * "ignore-unknown-character-denormalizations" + * true [required] (default) + * If, while verifying full normalization when [XML 1.1] is supported, a character is encountered + * for which the normalization properties cannot be determined, then raise a "unknown-character-denormalization" + * warning (instead of raising an error, if this parameter is not set) and ignore any possible + * denormalizations caused by these characters. + * false [optional] + * Report a fatal error if a character is encountered for which the processor cannot determine the + * normalization properties. + * + * "normalize-characters" + * This parameter is equivalent to the one defined by DOMConfiguration in [DOM Level 3 Core]. + * Unlike in the Core, the default value for this parameter is true. While DOM implementations are not + * required to support fully normalizing the characters in the document according to appendix E of [XML 1.1], + * this parameter must be activated by default if supported. + * + * "xml-declaration" + * true [required] (default) + * If a DOMDocument, DOMElement, or DOMEntity node is serialized, the XML declaration, or text declaration, + * should be included. The version (DOMDocument::xmlVersion if the document is a Level 3 document and the + * version is non-null, otherwise use the value "1.0"), and the output encoding (see DOMLSSerializer::write + * for details on how to find the output encoding) are specified in the serialized XML declaration. + * false [required] + * Do not serialize the XML and text declarations. Report a "xml-declaration-needed" warning if this will + * cause problems (i.e. the serialized data is of an XML version other than [XML 1.0], or an encoding would + * be needed to be able to re-parse the serialized data). + * + * "error-handler" + * Contains a DOMErrorHandler object. If an error is encountered in the document, the implementation will call back + * the DOMErrorHandler registered using this parameter. The implementation may provide a default DOMErrorHandler + * object. When called, DOMError::relatedData will contain the closest node to where the error occurred. + * If the implementation is unable to determine the node where the error occurs, DOMError::relatedData will contain + * the DOMDocument node. Mutations to the document from within an error handler will result in implementation + * dependent behavior. + * + * @return The pointer to the configuration object. + * @since DOM Level 3 + */ + virtual DOMConfiguration* getDomConfig() = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * The end-of-line sequence of characters to be used in the XML being + * written out. The only permitted values are these: + *

+ *
null
+ *
+ * Use a default end-of-line sequence. DOM implementations should choose + * the default to match the usual convention for text files in the + * environment being used. Implementations must choose a default + * sequence that matches one of those allowed by 2.11 "End-of-Line + * Handling". However, Xerces-C++ always uses LF when this + * property is set to null since otherwise automatic + * translation of LF to CR-LF on Windows for text files would + * result in such files containing CR-CR-LF. If you need Windows-style + * end of line sequences in your output, consider writing to a file + * opened in text mode or explicitly set this property to CR-LF.
+ *
CR
+ *
The carriage-return character (\#xD).
+ *
CR-LF
+ *
The + * carriage-return and line-feed characters (\#xD \#xA).
+ *
LF
+ *
The line-feed + * character (\#xA).
+ *
+ *
The default value for this attribute is null. + * + * @param newLine The end-of-line sequence of characters to be used. + * @see getNewLine + * @since DOM Level 3 + */ + virtual void setNewLine(const XMLCh* const newLine) = 0; + + /** + * When the application provides a filter, the serializer will call out + * to the filter before serializing each Node. Attribute nodes are never + * passed to the filter. The filter implementation can choose to remove + * the node from the stream or to terminate the serialization early. + * + * @param filter The writer filter to be used. + * @see getFilter + * @since DOM Level 3 + */ + virtual void setFilter(DOMLSSerializerFilter *filter) = 0; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Return the end-of-line sequence of characters to be used in the XML being + * written out. + * + * @return The end-of-line sequence of characters to be used. + * @see setNewLine + * @since DOM Level 3 + */ + virtual const XMLCh* getNewLine() const = 0; + + /** + * Return the WriterFilter used. + * + * @return The writer filter used. + * @see setFilter + * @since DOM Level 3 + */ + virtual DOMLSSerializerFilter* getFilter() const = 0; + + // ----------------------------------------------------------------------- + // Write methods + // ----------------------------------------------------------------------- + /** + * Write out the specified node as described above in the description of + * DOMLSSerializer. Writing a Document or Entity node produces a + * serialized form that is well formed XML. Writing other node types + * produces a fragment of text in a form that is not fully defined by + * this document, but that should be useful to a human for debugging or + * diagnostic purposes. + * + * @param nodeToWrite The Document or Entity node to + * be written. For other node types, something sensible should be + * written, but the exact serialized form is not specified. + * @param destination The destination for the data to be written. + * @return Returns true if node was + * successfully serialized and false in case a failure + * occured and the failure wasn't canceled by the error handler. + * @since DOM Level 3 + */ + virtual bool write(const DOMNode* nodeToWrite, + DOMLSOutput* const destination) = 0; + + /** + * Write out the specified node as described above in the description of + * DOMLSSerializer. Writing a Document or Entity node produces a + * serialized form that is well formed XML. Writing other node types + * produces a fragment of text in a form that is not fully defined by + * this document, but that should be useful to a human for debugging or + * diagnostic purposes. + * + * @param nodeToWrite The Document or Entity node to + * be written. For other node types, something sensible should be + * written, but the exact serialized form is not specified. + * @param uri The destination for the data to be written. + * @return Returns true if node was + * successfully serialized and false in case a failure + * occured and the failure wasn't canceled by the error handler. + * @since DOM Level 3 + */ + virtual bool writeToURI(const DOMNode* nodeToWrite, + const XMLCh* uri) = 0; + /** + * Serialize the specified node as described above in the description of + * DOMLSSerializer. The result of serializing the node is + * returned as a string. Writing a Document or Entity node produces a + * serialized form that is well formed XML. Writing other node types + * produces a fragment of text in a form that is not fully defined by + * this document, but that should be useful to a human for debugging or + * diagnostic purposes. + * + * @param nodeToWrite The node to be written. + * @param manager The memory manager to be used to allocate the result string. + * If NULL is used, the memory manager used to construct the serializer will + * be used. + * @return Returns the serialized data, or null in case a + * failure occured and the failure wasn't canceled by the error + * handler. The returned string is always in UTF-16. + * The encoding information available in DOMLSSerializer is ignored in writeToString(). + * @since DOM Level 3 + */ + virtual XMLCh* writeToString(const DOMNode* nodeToWrite, MemoryManager* manager = NULL) = 0; + + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this Writer is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} + + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLSSerializerFilter.hpp b/include/xercesc/dom/DOMLSSerializerFilter.hpp new file mode 100644 index 0000000..0bd9bc7 --- /dev/null +++ b/include/xercesc/dom/DOMLSSerializerFilter.hpp @@ -0,0 +1,107 @@ +/* + * 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: DOMLSSerializerFilter.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSSERIALIZERFILTER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSSERIALIZERFILTER_HPP + +/** + * + * DOMLSSerializerFilter.hpp: interface for the DOMLSSerializerFilter class. + * + * DOMLSSerializerFilter provide applications the ability to examine nodes + * as they are being serialized. + * + * DOMLSSerializerFilter lets the application decide what nodes should be + * serialized or not. + * + * The DOMDocument, DOMDocumentType, DOMNotation, and DOMEntity nodes are not passed + * to the filter. + * + * @since DOM Level 3 + */ + + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMLSSerializerFilter : public DOMNodeFilter { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLSSerializerFilter() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLSSerializerFilter(const DOMLSSerializerFilter &); + DOMLSSerializerFilter & operator = (const DOMLSSerializerFilter &); + //@} + + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLSSerializerFilter() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLSSerializerFilter interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * Interface from DOMNodeFilter, + * to be implemented by implementation (derived class) + */ + virtual FilterAction acceptNode(const DOMNode* node) const = 0; + + /** + * Tells the DOMLSSerializer what types of nodes to show to the filter. + * See DOMNodeFilter for definition of the constants. + * The constant SHOW_ATTRIBUTE is meaningless here, attribute nodes will + * never be passed to a DOMLSSerializerFilter. + * + * @return The constants of what types of nodes to show. + * @since DOM Level 3 + */ + virtual ShowType getWhatToShow() const =0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMLocator.hpp b/include/xercesc/dom/DOMLocator.hpp new file mode 100644 index 0000000..abbcd8e --- /dev/null +++ b/include/xercesc/dom/DOMLocator.hpp @@ -0,0 +1,135 @@ +/* + * 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: DOMLocator.hpp 676853 2008-07-15 09:58:05Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLOCATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLOCATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; + + +/** + * DOMLocator is an interface that describes a location. (e.g. where an error + * occured). + * + * @see DOMError#DOMError + * @since DOM Level 3 + */ + +class CDOM_EXPORT DOMLocator +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMLocator() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMLocator(const DOMLocator &); + DOMLocator & operator = (const DOMLocator &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMLocator() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMLocator interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Get the line number where the error occured, or 0 if there is + * no line number available. + * + * @since DOM Level 3 + */ + virtual XMLFileLoc getLineNumber() const = 0; + + /** + * Get the column number where the error occured, or 0 if there + * is no column number available. + * + * @since DOM Level 3 + */ + virtual XMLFileLoc getColumnNumber() const = 0; + + /** + * Get the byte offset into the input source, or ~(XMLFilePos(0)) if + * there is no byte offset available. + * + * @since DOM Level 3 + */ + virtual XMLFilePos getByteOffset() const = 0; + + /** + * Get the UTF-16 offset into the input source, or ~(XMLFilePos(0)) if + * there is no UTF-16 offset available. + * + * @since DOM Level 3 + */ + virtual XMLFilePos getUtf16Offset() const = 0; + + /** + * Get the DOMNode where the error occured, or null if there + * is no node available. + * + * @since DOM Level 3 + */ + virtual DOMNode* getRelatedNode() const = 0; + + /** + * Get the URI where the error occured, or null if there is no + * URI available. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getURI() const = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMMemoryManager.hpp b/include/xercesc/dom/DOMMemoryManager.hpp new file mode 100644 index 0000000..c1dd83c --- /dev/null +++ b/include/xercesc/dom/DOMMemoryManager.hpp @@ -0,0 +1,160 @@ +/* + * 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. + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMMEMORYMANAGER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMMEMORYMANAGER_HPP + +//------------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------------ + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * The DOMMemoryManager interface exposes the memory allocation-related + * functionalities of a DOMDocument + */ + +class CDOM_EXPORT DOMMemoryManager +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMMemoryManager() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMMemoryManager(const DOMMemoryManager &); + DOMMemoryManager & operator = (const DOMMemoryManager &); + //@} + +public: + + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMMemoryManager() {}; + //@} + + // ----------------------------------------------------------------------- + // data types + // ----------------------------------------------------------------------- + enum NodeObjectType { + ATTR_OBJECT = 0, + ATTR_NS_OBJECT = 1, + CDATA_SECTION_OBJECT = 2, + COMMENT_OBJECT = 3, + DOCUMENT_FRAGMENT_OBJECT = 4, + DOCUMENT_TYPE_OBJECT = 5, + ELEMENT_OBJECT = 6, + ELEMENT_NS_OBJECT = 7, + ENTITY_OBJECT = 8, + ENTITY_REFERENCE_OBJECT = 9, + NOTATION_OBJECT = 10, + PROCESSING_INSTRUCTION_OBJECT = 11, + TEXT_OBJECT = 12 + }; + + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the size of the chunks of memory allocated by the memory manager + * + * @return the dimension of the chunks of memory allocated by the memory manager + */ + virtual XMLSize_t getMemoryAllocationBlockSize() const = 0; + + //@} + + //@{ + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Set the size of the chunks of memory allocated by the memory manager + * + * @param size the new size of the chunks; it must be greater than 4KB + */ + virtual void setMemoryAllocationBlockSize(XMLSize_t size) = 0; + //@} + + //@{ + // ----------------------------------------------------------------------- + // Operations + // ----------------------------------------------------------------------- + /** + * Allocate a memory block of the requested size from the managed pool + * + * @param amount the size of the new memory block + * + * @return the pointer to the newly allocated block + */ + virtual void* allocate(XMLSize_t amount) = 0; + + /** + * Allocate a memory block of the requested size from the managed pool of DOM objects + * + * @param amount the size of the new memory block + * @param type the type of the DOM object that will be stored in the block + * + * @return the pointer to the newly allocated block + */ + virtual void* allocate(XMLSize_t amount, DOMMemoryManager::NodeObjectType type) = 0; + + /** + * Release a DOM object and place its memory back in the pool + * + * @param object the pointer to the DOM node + * @param type the type of the DOM object + */ + virtual void release(DOMNode* object, DOMMemoryManager::NodeObjectType type) = 0; + + /** + * Allocate a memory block from the mnaged pool and copy the provided string + * + * @param src the string to be copied + * + * @return the pointer to the newly allocated block + */ + virtual XMLCh* cloneString(const XMLCh *src) = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DOMMemoryManager.hpp + */ diff --git a/include/xercesc/dom/DOMNamedNodeMap.hpp b/include/xercesc/dom/DOMNamedNodeMap.hpp new file mode 100644 index 0000000..2d23f27 --- /dev/null +++ b/include/xercesc/dom/DOMNamedNodeMap.hpp @@ -0,0 +1,245 @@ +/* + * 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: DOMNamedNodeMap.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNAMEDNODEMAP_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNAMEDNODEMAP_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; + +/** + * DOMNamedNodeMaps are used to + * represent collections of nodes that can be accessed by name. + * + * Note that DOMNamedNodeMap does not inherit from DOMNodeList; + * DOMNamedNodeMaps are not maintained in any particular order. + * Nodes contained in a DOMNamedNodeMap may + * also be accessed by an ordinal index, but this is simply to allow + * convenient enumeration of the contents, and + * does not imply that the DOM specifies an order to these Nodes. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMNamedNodeMap { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMNamedNodeMap() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMNamedNodeMap(const DOMNamedNodeMap &); + DOMNamedNodeMap & operator = (const DOMNamedNodeMap &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMNamedNodeMap() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMNamedNodeMap interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Adds a node using its nodeName attribute. + * + *
As the nodeName attribute is used to derive the name + * which the node must be stored under, multiple nodes of certain types + * (those that have a "special" string value) cannot be stored as the names + * would clash. This is seen as preferable to allowing nodes to be aliased. + * @param arg A node to store in a named node map. The node will later be + * accessible using the value of the nodeName attribute of + * the node. If a node with that name is already present in the map, it + * is replaced by the new one. + * @return If the new DOMNode replaces an existing node the + * replaced DOMNode is returned, + * otherwise null is returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if arg was created from a + * different document than the one that created the + * DOMNamedNodeMap. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this + * DOMNamedNodeMap is readonly. + *
INUSE_ATTRIBUTE_ERR: Raised if arg is an + * DOMAttr that is already an attribute of another + * DOMElement object. The DOM user must explicitly clone + * DOMAttr nodes to re-use them in other elements. + * @since DOM Level 1 + */ + virtual DOMNode *setNamedItem(DOMNode *arg) = 0; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the indexth item in the map. + * + * If index + * is greater than or equal to the number of nodes in the map, this returns + * null. + * @param index Index into the map. + * @return The node at the indexth position in the + * DOMNamedNodeMap, or null if that is not a valid + * index. + * @since DOM Level 1 + */ + virtual DOMNode *item(XMLSize_t index) const = 0; + + /** + * Retrieves a node specified by name. + * + * @param name The nodeName of a node to retrieve. + * @return A DOMNode (of any type) with the specified nodeName, or + * null if it does not identify any node in + * the map. + * @since DOM Level 1 + */ + virtual DOMNode *getNamedItem(const XMLCh *name) const = 0; + + /** + * The number of nodes in the map. + * + * The range of valid child node indices is + * 0 to length-1 inclusive. + * @since DOM Level 1 + */ + virtual XMLSize_t getLength() const = 0; + + // ----------------------------------------------------------------------- + // Node methods + // ----------------------------------------------------------------------- + /** + * Removes a node specified by name. + * + * If the removed node is an + * DOMAttr with a default value it is immediately replaced. + * @param name The nodeName of a node to remove. + * @return The node removed from the map if a node with such a name exists. + * @exception DOMException + * NOT_FOUND_ERR: Raised if there is no node named name in + * the map. + *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this DOMNamedNodeMap + * is readonly. + * @since DOM Level 1 + */ + virtual DOMNode *removeNamedItem(const XMLCh *name) = 0; + //@} + + /** @name Functions introduced in DOM Level 2 */ + //@{ + /** + * Retrieves a node specified by local name and namespace URI. + * + * @param namespaceURI The namespace URI of + * the node to retrieve. + * @param localName The local name of the node to retrieve. + * @return A DOMNode (of any type) with the specified + * local name and namespace URI, or null if they do not + * identify any node in the map. + * @since DOM Level 2 + */ + virtual DOMNode *getNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName) const = 0; + + /** + * Adds a node using its namespaceURI and localName. + * + * @param arg A node to store in a named node map. The node will later be + * accessible using the value of the namespaceURI and + * localName attribute of the node. If a node with those + * namespace URI and local name is already present in the map, it is + * replaced by the new one. + * @return If the new DOMNode replaces an existing node the + * replaced DOMNode is returned, + * otherwise null is returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if arg was created from a + * different document than the one that created the + * DOMNamedNodeMap. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this + * DOMNamedNodeMap is readonly. + *
INUSE_ATTRIBUTE_ERR: Raised if arg is an + * DOMAttr that is already an attribute of another + * DOMElement object. The DOM user must explicitly clone + * DOMAttr nodes to re-use them in other elements. + * @since DOM Level 2 + */ + virtual DOMNode *setNamedItemNS(DOMNode *arg) = 0; + + /** + * Removes a node specified by local name and namespace URI. + * + * @param namespaceURI The namespace URI of + * the node to remove. + * @param localName The local name of the + * node to remove. When this DOMNamedNodeMap contains the + * attributes attached to an element, as returned by the attributes + * attribute of the DOMNode interface, if the removed + * attribute is known to have a default value, an attribute + * immediately appears containing the default value + * as well as the corresponding namespace URI, local name, and prefix. + * @return The node removed from the map if a node with such a local name + * and namespace URI exists. + * @exception DOMException + * NOT_FOUND_ERR: Raised if there is no node named name in + * the map. + *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this DOMNamedNodeMap + * is readonly. + * @since DOM Level 2 + */ + virtual DOMNode *removeNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName) = 0; + //@} + +}; + +#define GetDOMNamedNodeMapMemoryManager GET_INDIRECT_MM(fOwnerNode) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMNode.hpp b/include/xercesc/dom/DOMNode.hpp new file mode 100644 index 0000000..0cf0f99 --- /dev/null +++ b/include/xercesc/dom/DOMNode.hpp @@ -0,0 +1,922 @@ +/* + * 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: DOMNode.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMDocument; +class DOMNamedNodeMap; +class DOMNodeList; +class DOMUserDataHandler; + +/** + * The DOMNode interface is the primary datatype for the entire + * Document Object Model. It represents a single node in the document tree. + * While all objects implementing the DOMNode interface expose + * methods for dealing with children, not all objects implementing the + * DOMNode interface may have children. For example, + * DOMText nodes may not have children, and adding children to + * such nodes results in a DOMException being raised. + *

The attributes nodeName, nodeValue and + * attributes are included as a mechanism to get at node + * information without casting down to the specific derived interface. In + * cases where there is no obvious mapping of these attributes for a + * specific nodeType (e.g., nodeValue for an + * DOMElement or attributes for a DOMComment + * ), this returns null. Note that the specialized interfaces + * may contain additional and more convenient mechanisms to get and set the + * relevant information. + *

The values of nodeName, + * nodeValue, and attributes vary according to the + * node type as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
InterfacenodeNamenodeValueattributes
DOMAttrname of attributevalue of attributenull
DOMCDATASection"\#cdata-section"content of the CDATA Sectionnull
DOMComment"\#comment"content of the commentnull
DOMDocument"\#document"nullnull
DOMDocumentFragment"\#document-fragment"nullnull
DOMDocumentTypedocument type namenullnull
DOMElementtag namenullNamedNodeMap
DOMEntityentity namenullnull
DOMEntityReferencename of entity referencednullnull
DOMNotationnotation namenullnull
DOMProcessingInstructiontargetentire content excluding the targetnull
DOMText"\#text"content of the text nodenull
+ *

See also the Document Object Model (DOM) Level 2 Core Specification. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMNode() {} + DOMNode(const DOMNode &) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMNode & operator = (const DOMNode &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMNode() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * NodeType + * + * @since DOM Level 1 + */ + enum NodeType { + ELEMENT_NODE = 1, + ATTRIBUTE_NODE = 2, + TEXT_NODE = 3, + CDATA_SECTION_NODE = 4, + ENTITY_REFERENCE_NODE = 5, + ENTITY_NODE = 6, + PROCESSING_INSTRUCTION_NODE = 7, + COMMENT_NODE = 8, + DOCUMENT_NODE = 9, + DOCUMENT_TYPE_NODE = 10, + DOCUMENT_FRAGMENT_NODE = 11, + NOTATION_NODE = 12 + }; + + /** + * DocumentPosition: + * + *

DOCUMENT_POSITION_CONTAINED_BY: + * The node is contained by the reference node. A node which is contained is always following, too.

+ *

DOCUMENT_POSITION_CONTAINS: + * The node contains the reference node. A node which contains is always preceding, too.

+ *

DOCUMENT_POSITION_DISCONNECTED: + * The two nodes are disconnected. Order between disconnected nodes is always implementation-specific.

+ *

DOCUMENT_POSITION_FOLLOWING: + * The node follows the reference node.

+ *

DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: + * The determination of preceding versus following is implementation-specific.

+ *

DOCUMENT_POSITION_PRECEDING: + * The second node precedes the reference node.

+ * + * @since DOM Level 3 + */ + enum DocumentPosition { + DOCUMENT_POSITION_DISCONNECTED = 0x01, + DOCUMENT_POSITION_PRECEDING = 0x02, + DOCUMENT_POSITION_FOLLOWING = 0x04, + DOCUMENT_POSITION_CONTAINS = 0x08, + DOCUMENT_POSITION_CONTAINED_BY = 0x10, + DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20 + }; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMNode interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * The name of this node, depending on its type; see the table above. + * @since DOM Level 1 + */ + virtual const XMLCh * getNodeName() const = 0; + + /** + * Gets the value of this node, depending on its type. + * + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + * @since DOM Level 1 + */ + virtual const XMLCh * getNodeValue() const = 0; + + /** + * An enum value representing the type of the underlying object. + * @since DOM Level 1 + */ + virtual NodeType getNodeType() const = 0; + + /** + * Gets the parent of this node. + * + * All nodes, except DOMDocument, + * DOMDocumentFragment, and DOMAttr may have a parent. + * However, if a node has just been created and not yet added to the tree, + * or if it has been removed from the tree, a null DOMNode + * is returned. + * @since DOM Level 1 + */ + virtual DOMNode *getParentNode() const = 0; + + /** + * Gets a DOMNodeList that contains all children of this node. + * + * If there + * are no children, this is a DOMNodeList containing no nodes. + * The content of the returned DOMNodeList is "live" in the sense + * that, for instance, changes to the children of the node object that + * it was created from are immediately reflected in the nodes returned by + * the DOMNodeList accessors; it is not a static snapshot of the + * content of the node. This is true for every DOMNodeList, + * including the ones returned by the getElementsByTagName + * method. + * @since DOM Level 1 + */ + virtual DOMNodeList *getChildNodes() const = 0; + /** + * Gets the first child of this node. + * + * If there is no such node, this returns null. + * @since DOM Level 1 + */ + virtual DOMNode *getFirstChild() const = 0; + + /** + * Gets the last child of this node. + * + * If there is no such node, this returns null. + * @since DOM Level 1 + */ + virtual DOMNode *getLastChild() const = 0; + + /** + * Gets the node immediately preceding this node. + * + * If there is no such node, this returns null. + * @since DOM Level 1 + */ + virtual DOMNode *getPreviousSibling() const = 0; + + /** + * Gets the node immediately following this node. + * + * If there is no such node, this returns null. + * @since DOM Level 1 + */ + virtual DOMNode *getNextSibling() const = 0; + + /** + * Gets a DOMNamedNodeMap containing the attributes of this node (if it + * is an DOMElement) or null otherwise. + * @since DOM Level 1 + */ + virtual DOMNamedNodeMap *getAttributes() const = 0; + + /** + * Gets the DOMDocument object associated with this node. + * + * This is also + * the DOMDocument object used to create new nodes. When this + * node is a DOMDocument or a DOMDocumentType + * which is not used with any DOMDocument yet, this is + * null. + * + * @since DOM Level 1 + */ + virtual DOMDocument *getOwnerDocument() const = 0; + + // ----------------------------------------------------------------------- + // Node methods + // ----------------------------------------------------------------------- + /** + * Returns a duplicate of this node. + * + * This function serves as a generic copy constructor for nodes. + * + * The duplicate node has no parent ( + * parentNode returns null.). + *
Cloning an DOMElement copies all attributes and their + * values, including those generated by the XML processor to represent + * defaulted attributes, but this method does not copy any text it contains + * unless it is a deep clone, since the text is contained in a child + * DOMText node. Cloning any other type of node simply returns a + * copy of this node. + * @param deep If true, recursively clone the subtree under the + * specified node; if false, clone only the node itself (and + * its attributes, if it is an DOMElement). + * @return The duplicate node. + * @since DOM Level 1 + */ + virtual DOMNode * cloneNode(bool deep) const = 0; + + /** + * Inserts the node newChild before the existing child node + * refChild. + * + * If refChild is null, + * insert newChild at the end of the list of children. + *
If newChild is a DOMDocumentFragment object, + * all of its children are inserted, in the same order, before + * refChild. If the newChild is already in the + * tree, it is first removed. Note that a DOMNode that + * has never been assigned to refer to an actual node is == null. + * @param newChild The node to insert. + * @param refChild The reference node, i.e., the node before which the new + * node must be inserted. + * @return The node being inserted. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not + * allow children of the type of the newChild node, or if + * the node to insert is one of this node's ancestors. + *
WRONG_DOCUMENT_ERR: Raised if newChild was created + * from a different document than the one that created this node. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node or the node being + * inserted is readonly. + *
NOT_FOUND_ERR: Raised if refChild is not a child of + * this node. + * @since DOM Level 1 + */ + virtual DOMNode *insertBefore(DOMNode *newChild, + DOMNode *refChild) = 0; + + + /** + * Replaces the child node oldChild with newChild + * in the list of children, and returns the oldChild node. + * + * If newChild is a DOMDocumentFragment object, + * oldChild is replaced by all of the DOMDocumentFragment + * children, which are inserted in the same order. + * + * If the newChild is already in the tree, it is first removed. + * @param newChild The new node to put in the child list. + * @param oldChild The node being replaced in the list. + * @return The node replaced. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not + * allow children of the type of the newChild node, or it + * the node to put in is one of this node's ancestors. + *
WRONG_DOCUMENT_ERR: Raised if newChild was created + * from a different document than the one that created this node. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node or the new node is readonly. + *
NOT_FOUND_ERR: Raised if oldChild is not a child of + * this node. + * @since DOM Level 1 + */ + virtual DOMNode *replaceChild(DOMNode *newChild, + DOMNode *oldChild) = 0; + /** + * Removes the child node indicated by oldChild from the list + * of children, and returns it. + * + * @param oldChild The node being removed. + * @return The node removed. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + *
NOT_FOUND_ERR: Raised if oldChild is not a child of + * this node. + * @since DOM Level 1 + */ + virtual DOMNode *removeChild(DOMNode *oldChild) = 0; + + /** + * Adds the node newChild to the end of the list of children of + * this node. + * + * If the newChild is already in the tree, it is + * first removed. + * @param newChild The node to add.If it is a DOMDocumentFragment + * object, the entire contents of the document fragment are moved into + * the child list of this node + * @return The node added. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not + * allow children of the type of the newChild node, or if + * the node to append is one of this node's ancestors. + *
WRONG_DOCUMENT_ERR: Raised if newChild was created + * from a different document than the one that created this node. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node or the node being + * appended is readonly. + * @since DOM Level 1 + */ + virtual DOMNode *appendChild(DOMNode *newChild) = 0; + + // ----------------------------------------------------------------------- + // Query methods + // ----------------------------------------------------------------------- + /** + * This is a convenience method to allow easy determination of whether a + * node has any children. + * + * @return true if the node has any children, + * false if the node has no children. + * @since DOM Level 1 + */ + virtual bool hasChildNodes() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Sets the value of the node. + * + * Any node which can have a nodeValue will + * also accept requests to set it to a string. The exact response to + * this varies from node to node -- Attribute, for example, stores + * its values in its children and has to replace them with a new Text + * holding the replacement value. + * + * For most types of Node, value is null and attempting to set it + * will throw DOMException(NO_MODIFICATION_ALLOWED_ERR). This will + * also be thrown if the node is read-only. + * @see #getNodeValue + * @since DOM Level 1 + */ + virtual void setNodeValue(const XMLCh *nodeValue) = 0; + //@} + + /** @name Functions introduced in DOM Level 2. */ + //@{ + /** + * Puts all DOMText + * nodes in the full depth of the sub-tree underneath this DOMNode, + * including attribute nodes, into a "normal" form where only markup (e.g., + * tags, comments, processing instructions, CDATA sections, and entity + * references) separates DOMText + * nodes, i.e., there are neither adjacent DOMText + * nodes nor empty DOMText + * nodes. This can be used to ensure that the DOM view of a document is the + * same as if it were saved and re-loaded, and is useful when operations + * (such as XPointer lookups) that depend on a particular document tree + * structure are to be used. + *

Note: In cases where the document contains DOMCDATASections, + * the normalize operation alone may not be sufficient, since XPointers do + * not differentiate between DOMText + * nodes and DOMCDATASection + * nodes.

+ * + * @since DOM Level 2 + */ + virtual void normalize() = 0; + + /** + * Tests whether the DOM implementation implements a specific + * feature and that feature is supported by this node. + * + * @param feature The string of the feature to test. This is the same + * name as what can be passed to the method hasFeature on + * DOMImplementation. + * @param version This is the version number of the feature to test. In + * Level 2, version 1, this is the string "2.0". If the version is not + * specified, supporting any version of the feature will cause the + * method to return true. + * @return Returns true if the specified feature is supported + * on this node, false otherwise. + * @since DOM Level 2 + */ + virtual bool isSupported(const XMLCh *feature, + const XMLCh *version) const = 0; + + /** + * Get the namespace URI of + * this node, or null if it is unspecified. + *

+ * This is not a computed value that is the result of a namespace lookup + * based on an examination of the namespace declarations in scope. It is + * merely the namespace URI given at creation time. + *

+ * For nodes of any type other than ELEMENT_NODE and + * ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, + * such as createElement from the DOMDocument + * interface, this is always null. + * + * @since DOM Level 2 + */ + virtual const XMLCh * getNamespaceURI() const = 0; + + /** + * Get the namespace prefix + * of this node, or null if it is unspecified. + * + * @since DOM Level 2 + */ + virtual const XMLCh * getPrefix() const = 0; + + /** + * Returns the local part of the qualified name of this node. + *

+ * For nodes created with a DOM Level 1 method, such as + * createElement from the DOMDocument interface, + * it is null. + * + * @since DOM Level 2 + */ + virtual const XMLCh * getLocalName() const = 0; + + /** + * Set the namespace prefix of this node. + *

+ * Note that setting this attribute, when permitted, changes + * the nodeName attribute, which holds the qualified + * name, as well as the tagName and name + * attributes of the DOMElement and DOMAttr + * interfaces, when applicable. + *

+ * Note also that changing the prefix of an + * attribute, that is known to have a default value, does not make a new + * attribute with the default value and the original prefix appear, since the + * namespaceURI and localName do not change. + * + * + * @param prefix The prefix of this node. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified prefix contains + * an illegal character. + *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + *
+ * NAMESPACE_ERR: Raised if the specified prefix is + * malformed, if the namespaceURI of this node is + * null, if the specified prefix is "xml" and the + * namespaceURI of this node is different from + * "http://www.w3.org/XML/1998/namespace", if this node is an attribute + * and the specified prefix is "xmlns" and the + * namespaceURI of this node is different from + * "http://www.w3.org/2000/xmlns/", or if this node is an attribute and + * the qualifiedName of this node is "xmlns". + * @since DOM Level 2 + */ + virtual void setPrefix(const XMLCh * prefix) = 0; + + /** + * Returns whether this node (if it is an element) has any attributes. + * @return true if this node has any attributes, + * false otherwise. + * @since DOM Level 2 + */ + virtual bool hasAttributes() const = 0; + //@} + + /** @name Functions introduced in DOM Level 3. */ + //@{ + /** + * Returns whether this node is the same node as the given one. + *
This method provides a way to determine whether two + * DOMNode references returned by the implementation reference + * the same object. When two DOMNode references are references + * to the same object, even if through a proxy, the references may be + * used completely interchangeably, such that all attributes have the + * same values and calling the same DOM method on either reference + * always has exactly the same effect. + * + * @param other The node to test against. + * @return Returns true if the nodes are the same, + * false otherwise. + * @since DOM Level 3 + */ + virtual bool isSameNode(const DOMNode* other) const = 0; + + /** + * Tests whether two nodes are equal. + *
This method tests for equality of nodes, not sameness (i.e., + * whether the two nodes are pointers to the same object) which can be + * tested with DOMNode::isSameNode. All nodes that are the same + * will also be equal, though the reverse may not be true. + *
Two nodes are equal if and only if the following conditions are + * satisfied: The two nodes are of the same type.The following string + * attributes are equal: nodeName, localName, + * namespaceURI, prefix, nodeValue + * , baseURI. This is: they are both null, or + * they have the same length and are character for character identical. + * The attributes DOMNamedNodeMaps are equal. + * This is: they are both null, or they have the same + * length and for each node that exists in one map there is a node that + * exists in the other map and is equal, although not necessarily at the + * same index.The childNodes DOMNodeLists are + * equal. This is: they are both null, or they have the + * same length and contain equal nodes at the same index. This is true + * for DOMAttr nodes as for any other type of node. Note that + * normalization can affect equality; to avoid this, nodes should be + * normalized before being compared. + *
For two DOMDocumentType nodes to be equal, the following + * conditions must also be satisfied: The following string attributes + * are equal: publicId, systemId, + * internalSubset.The entities + * DOMNamedNodeMaps are equal.The notations + * DOMNamedNodeMaps are equal. + *
On the other hand, the following do not affect equality: the + * ownerDocument attribute, the specified + * attribute for DOMAttr nodes, the + * isWhitespaceInElementContent attribute for + * DOMText nodes, as well as any user data or event listeners + * registered on the nodes. + * + * @param arg The node to compare equality with. + * @return If the nodes, and possibly subtrees are equal, + * true otherwise false. + * @since DOM Level 3 + */ + virtual bool isEqualNode(const DOMNode* arg) const = 0; + + + /** + * Associate an object to a key on this node. The object can later be + * retrieved from this node by calling getUserData with the + * same key. + * + * Deletion of the user data remains the responsibility of the + * application program; it will not be automatically deleted when + * the nodes themselves are reclaimed. + * + * Both the parameter data and the returned object are + * void pointer, it is applications' responsibility to keep track of + * their original type. Casting them to the wrong type may result + * unexpected behavior. + * + * @param key The key to associate the object to. + * @param data The object to associate to the given key, or + * null to remove any existing association to that key. + * @param handler The handler to associate to that key, or + * null. + * @return Returns the void* object previously associated to + * the given key on this node, or null if there was none. + * @see #getUserData + * + * @since DOM Level 3 + */ + virtual void* setUserData(const XMLCh* key, + void* data, + DOMUserDataHandler* handler) = 0; + + /** + * Retrieves the object associated to a key on a this node. The object + * must first have been set to this node by calling + * setUserData with the same key. + * + * @param key The key the object is associated to. + * @return Returns the void* associated to the given key + * on this node, or null if there was none. + * @see #setUserData + * @since DOM Level 3 + */ + virtual void* getUserData(const XMLCh* key) const = 0; + + + /** + * The absolute base URI of this node or null if undefined. + * This value is computed according to . However, when the + * DOMDocument supports the feature "HTML" , the base URI is + * computed using first the value of the href attribute of the HTML BASE + * element if any, and the value of the documentURI + * attribute from the DOMDocument interface otherwise. + * + *
When the node is an DOMElement, a DOMDocument + * or a a DOMProcessingInstruction, this attribute represents + * the properties [base URI] defined in . When the node is a + * DOMNotation, an DOMEntity, or an + * DOMEntityReference, this attribute represents the + * properties [declaration base URI]. + * @since DOM Level 3 + */ + virtual const XMLCh* getBaseURI() const = 0; + + /** + * Compares the reference node, i.e. the node on which this method is being called, + * with a node, i.e. the one passed as a parameter, with regard to their position + * in the document and according to the document order. + * + * @param other The node to compare against this node. + * @return Returns how the given node is positioned relatively to this + * node. + * @since DOM Level 3 + */ + virtual short compareDocumentPosition(const DOMNode* other) const = 0; + + /** + * This attribute returns the text content of this node and its + * descendants. No serialization is performed, the returned string + * does not contain any markup. No whitespace normalization is + * performed and the returned string does not contain the white + * spaces in element content. + * + *
The string returned is made of the text content of this node + * depending on its type, as defined below: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Node typeContent
+ * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE, + * DOCUMENT_FRAGMENT_NODEconcatenation of the textContent + * attribute value of every child node, excluding COMMENT_NODE and + * PROCESSING_INSTRUCTION_NODE nodes
ATTRIBUTE_NODE, TEXT_NODE, + * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE + * nodeValue
DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE + * null
+ * @exception DOMException + * DOMSTRING_SIZE_ERR: Raised when it would return more characters than + * fit in a DOMString variable on the implementation + * platform. + * @see #setTextContent + * @since DOM Level 3 + */ + virtual const XMLCh* getTextContent() const = 0; + + /** + * This attribute removes any possible children this node may have and, if the + * new string is not empty or null, replaced by a single DOMText + * node containing the string this attribute is set to. No parsing is + * performed, the input string is taken as pure textual content. + * + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + * @see #getTextContent + * @since DOM Level 3 + */ + virtual void setTextContent(const XMLCh* textContent) = 0; + + /** + * Look up the prefix associated to the given namespace URI, starting from this node. + * The default namespace declarations are ignored by this method. + * + * @param namespaceURI The namespace URI to look for. + * @return Returns an associated namespace prefix if found, + * null if none is found. If more + * than one prefix are associated to the namespace prefix, the + * returned namespace prefix is implementation dependent. + * @since DOM Level 3 + */ + virtual const XMLCh* lookupPrefix(const XMLCh* namespaceURI) const = 0; + + /** + * This method checks if the specified namespaceURI is the + * default namespace or not. + * + * @param namespaceURI The namespace URI to look for. + * @return true if the specified namespaceURI + * is the default namespace, false otherwise. + * @since DOM Level 3 + */ + virtual bool isDefaultNamespace(const XMLCh* namespaceURI) const = 0; + + /** + * Look up the namespace URI associated to the given prefix, starting from + * this node. + * + * @param prefix The prefix to look for. If this parameter is + * null, the method will return the default namespace URI + * if any. + * @return Returns the associated namespace URI or null if + * none is found. + * @since DOM Level 3 + */ + virtual const XMLCh* lookupNamespaceURI(const XMLCh* prefix) const = 0; + + /** + * This method makes available a DOMNode's specialized interface + * + * @param feature The name of the feature requested (case-insensitive). + * @param version The version of the feature requested. + * @return Returns an alternate DOMNode which implements the + * specialized APIs of the specified feature, if any, or + * null if there is no alternate DOMNode which + * implements interfaces associated with that feature. Any alternate + * DOMNode returned by this method must delegate to the + * primary core DOMNode and not return results inconsistent + * with the primary core DOMNode such as key, + * attributes, childNodes, etc. + * @since DOM Level 3 + */ + virtual void* getFeature(const XMLCh* feature, const XMLCh* version) const = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this Node (and its associated children) is no longer in use + * and that the implementation may relinquish any resources associated with it and + * its associated children. + * + * If this is a document, any nodes it owns (created by DOMDocument::createXXXX()) + * are also released. + * + * Access to a released object will lead to unexpected result. + * + * @exception DOMException + * INVALID_ACCESS_ERR: Raised if this Node has a parent and thus should not be released yet. + */ + virtual void release() = 0; + //@} +#if defined(XML_DOMREFCOUNT_EXPERIMENTAL) + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * This is custom function which can be implemented by classes deriving + * from DOMNode for implementing reference counting on DOMNodes. Any + * implementation which has memory management model which involves + * disposing of nodes immediately after being used can override this + * function to do that job. + */ + virtual void decRefCount() {} + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * This is custom function which can be implemented by classes deriving + * from DOMNode for implementing reference counting on DOMNodes. + */ + virtual void incRefCount() {} + //@} +#endif +}; + +/*** + * Utilities macros for getting memory manager within DOM +***/ +#define GET_OWNER_DOCUMENT(ptr) \ + ((DOMDocumentImpl*)(ptr->getOwnerDocument())) + +#define GET_DIRECT_MM(ptr) \ + (ptr ? ((DOMDocumentImpl*)ptr)->getMemoryManager() : XMLPlatformUtils::fgMemoryManager) + +#define GET_INDIRECT_MM(ptr) \ + (!ptr ? XMLPlatformUtils::fgMemoryManager : \ + GET_OWNER_DOCUMENT(ptr) ? GET_OWNER_DOCUMENT(ptr)->getMemoryManager() : \ + XMLPlatformUtils::fgMemoryManager) + +/*** + * For DOMNode and its derivatives +***/ +#define GetDOMNodeMemoryManager GET_INDIRECT_MM(this) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMNodeFilter.hpp b/include/xercesc/dom/DOMNodeFilter.hpp new file mode 100644 index 0000000..55d1d31 --- /dev/null +++ b/include/xercesc/dom/DOMNodeFilter.hpp @@ -0,0 +1,221 @@ +/* + * 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: DOMNodeFilter.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODEFILTER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODEFILTER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * Filters are objects that know how to "filter out" nodes. If a + * DOMNodeIterator or DOMTreeWalker is given a + * DOMNodeFilter, it applies the filter before it returns the next + * node. If the filter says to accept the node, the traversal logic returns + * it; otherwise, traversal looks for the next node and pretends that the + * node that was rejected was not there. + *

The DOM does not provide any filters. DOMNodeFilter is just an + * interface that users can implement to provide their own filters. + *

DOMNodeFilters do not need to know how to traverse from node + * to node, nor do they need to know anything about the data structure that + * is being traversed. This makes it very easy to write filters, since the + * only thing they have to know how to do is evaluate a single node. One + * filter may be used with a number of different kinds of traversals, + * encouraging code reuse. + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * @since DOM Level 2 + */ + +class CDOM_EXPORT DOMNodeFilter +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMNodeFilter() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMNodeFilter(const DOMNodeFilter &); + DOMNodeFilter & operator = (const DOMNodeFilter &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMNodeFilter() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * Constants returned by acceptNode. + * + *

FILTER_ACCEPT: + * Accept the node. Navigation methods defined for + * DOMNodeIterator or DOMTreeWalker will return this + * node.

+ * + *

FILTER_REJECT: + * Reject the node. Navigation methods defined for + * DOMNodeIterator or DOMTreeWalker will not return + * this node. For DOMTreeWalker, the children of this node + * will also be rejected. DOMNodeIterators treat this as a + * synonym for FILTER_SKIP.

+ * + *

FILTER_SKIP: + * Skip this single node. Navigation methods defined for + * DOMNodeIterator or DOMTreeWalker will not return + * this node. For both DOMNodeIterator and + * DOMTreeWalker, the children of this node will still be + * considered.

+ * + * @since DOM Level 2 + */ + enum FilterAction {FILTER_ACCEPT = 1, + FILTER_REJECT = 2, + FILTER_SKIP = 3}; + + /** + * Constants for whatToShow + * + *

SHOW_ALL: + * Show all DOMNode(s).

+ * + *

SHOW_ELEMENT: + * Show DOMElement nodes.

+ * + *

SHOW_ATTRIBUTE: + * Show DOMAttr nodes. This is meaningful only when creating an + * DOMNodeIterator or DOMTreeWalker with an + * attribute node as its root; in this case, it means that + * the attribute node will appear in the first position of the iteration + * or traversal. Since attributes are never children of other nodes, + * they do not appear when traversing over the document tree.

+ * + *

SHOW_TEXT: + * Show DOMText nodes.

+ * + *

SHOW_CDATA_SECTION: + * Show DOMCDATASection nodes.

+ * + *

SHOW_ENTITY_REFERENCE: + * Show DOMEntityReference nodes.

+ * + *

SHOW_ENTITY: + * Show DOMEntity nodes. This is meaningful only when creating + * an DOMNodeIterator or DOMTreeWalker with an + * DOMEntity node as its root; in this case, it + * means that the DOMEntity node will appear in the first + * position of the traversal. Since entities are not part of the + * document tree, they do not appear when traversing over the document + * tree.

+ * + *

SHOW_PROCESSING_INSTRUCTION: + * Show DOMProcessingInstruction nodes.

+ * + *

SHOW_COMMENT: + * Show DOMComment nodes.

+ * + *

SHOW_DOCUMENT: + * Show DOMDocument nodes.

+ * + *

SHOW_DOCUMENT_TYPE: + * Show DOMDocumentType nodes.

+ * + *

SHOW_DOCUMENT_FRAGMENT: + * Show DOMDocumentFragment nodes.

+ * + *

SHOW_NOTATION: + * Show DOMNotation nodes. This is meaningful only when creating + * an DOMNodeIterator or DOMTreeWalker with a + * DOMNotation node as its root; in this case, it + * means that the DOMNotation node will appear in the first + * position of the traversal. Since notations are not part of the + * document tree, they do not appear when traversing over the document + * tree.

+ * + * @since DOM Level 2 + */ + enum ShowTypeMasks { + SHOW_ALL = 0x0000FFFF, + SHOW_ELEMENT = 0x00000001, + SHOW_ATTRIBUTE = 0x00000002, + SHOW_TEXT = 0x00000004, + SHOW_CDATA_SECTION = 0x00000008, + SHOW_ENTITY_REFERENCE = 0x00000010, + SHOW_ENTITY = 0x00000020, + SHOW_PROCESSING_INSTRUCTION = 0x00000040, + SHOW_COMMENT = 0x00000080, + SHOW_DOCUMENT = 0x00000100, + SHOW_DOCUMENT_TYPE = 0x00000200, + SHOW_DOCUMENT_FRAGMENT = 0x00000400, + SHOW_NOTATION = 0x00000800 + }; + + typedef unsigned long ShowType; + + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMNodeFilter interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + /** + * Test whether a specified node is visible in the logical view of a + * DOMTreeWalker or DOMNodeIterator. This function + * will be called by the implementation of DOMTreeWalker and + * DOMNodeIterator; it is not normally called directly from + * user code. (Though you could do so if you wanted to use the same + * filter to guide your own application logic.) + * @param node The node to check to see if it passes the filter or not. + * @return A constant to determine whether the node is accepted, + * rejected, or skipped, as defined above. + * @since DOM Level 2 + */ + virtual FilterAction acceptNode (const DOMNode* node) const =0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMNodeIterator.hpp b/include/xercesc/dom/DOMNodeIterator.hpp new file mode 100644 index 0000000..44b29a9 --- /dev/null +++ b/include/xercesc/dom/DOMNodeIterator.hpp @@ -0,0 +1,196 @@ +/* + * 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: DOMNodeIterator.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODEITERATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODEITERATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * DOMNodeIterators are used to step through a set of nodes, e.g. + * the set of nodes in a DOMNodeList, the document subtree + * governed by a particular DOMNode, the results of a query, or + * any other set of nodes. The set of nodes to be iterated is determined by + * the implementation of the DOMNodeIterator. DOM Level 2 + * specifies a single DOMNodeIterator implementation for + * document-order traversal of a document subtree. Instances of these + * DOMNodeIterators are created by calling + * DOMDocumentTraversal.createNodeIterator(). + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * @since DOM Level 2 + */ +class CDOM_EXPORT DOMNodeIterator +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMNodeIterator() {} + DOMNodeIterator(const DOMNodeIterator &) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMNodeIterator & operator = (const DOMNodeIterator &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMNodeIterator() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMNodeFilter interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * The root node of the DOMNodeIterator, as specified + * when it was created. + * @since DOM Level 2 + */ + virtual DOMNode* getRoot() = 0; + /** + * Return which node types are presented via the iterator. + * This attribute determines which node types are presented via the + * DOMNodeIterator. The available set of constants is defined + * in the DOMNodeFilter interface. Nodes not accepted by + * whatToShow will be skipped, but their children may still + * be considered. Note that this skip takes precedence over the filter, + * if any. + * @since DOM Level 2 + * + */ + virtual DOMNodeFilter::ShowType getWhatToShow() = 0; + + /** + * The DOMNodeFilter used to screen nodes. + * + * @since DOM Level 2 + */ + virtual DOMNodeFilter* getFilter() = 0; + + /** + * Return the expandEntityReferences flag. + * The value of this flag determines whether the children of entity + * reference nodes are visible to the DOMNodeIterator. If + * false, these children and their descendants will be rejected. Note + * that this rejection takes precedence over whatToShow and + * the filter. Also note that this is currently the only situation where + * DOMNodeIterators may reject a complete subtree rather than + * skipping individual nodes. + *
+ *
To produce a view of the document that has entity references + * expanded and does not expose the entity reference node itself, use + * the whatToShow flags to hide the entity reference node + * and set expandEntityReferences to true when creating the + * DOMNodeIterator. To produce a view of the document that has + * entity reference nodes but no entity expansion, use the + * whatToShow flags to show the entity reference node and + * set expandEntityReferences to false. + * + * @since DOM Level 2 + */ + virtual bool getExpandEntityReferences() = 0; + + // ----------------------------------------------------------------------- + // Query methods + // ----------------------------------------------------------------------- + /** + * Returns the next node in the set and advances the position of the + * DOMNodeIterator in the set. After a + * DOMNodeIterator is created, the first call to + * nextNode() returns the first node in the set. + * @return The next DOMNode in the set being iterated over, or + * null if there are no more members in that set. + * @exception DOMException + * INVALID_STATE_ERR: Raised if this method is called after the + * detach method was invoked. + * @since DOM Level 2 + */ + virtual DOMNode* nextNode() = 0; + + /** + * Returns the previous node in the set and moves the position of the + * DOMNodeIterator backwards in the set. + * @return The previous DOMNode in the set being iterated over, + * or null if there are no more members in that set. + * @exception DOMException + * INVALID_STATE_ERR: Raised if this method is called after the + * detach method was invoked. + * @since DOM Level 2 + */ + virtual DOMNode* previousNode() = 0; + + /** + * Detaches the DOMNodeIterator from the set which it iterated + * over, releasing any computational resources and placing the + * DOMNodeIterator in the INVALID state. After + * detach has been invoked, calls to nextNode + * or previousNode will raise the exception + * INVALID_STATE_ERR. + * @since DOM Level 2 + */ + virtual void detach() = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this NodeIterator is no longer in use + * and that the implementation may relinquish any resources associated with it. + * (release() will call detach() where appropriate) + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} +}; + +#define GetDOMNodeIteratorMemoryManager GET_DIRECT_MM(fDocument) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMNodeList.hpp b/include/xercesc/dom/DOMNodeList.hpp new file mode 100644 index 0000000..a8cfc78 --- /dev/null +++ b/include/xercesc/dom/DOMNodeList.hpp @@ -0,0 +1,112 @@ +/* + * 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: DOMNodeList.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODELIST_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODELIST_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; + + +/** + * The DOMNodeList interface provides the abstraction of an ordered + * collection of nodes. DOMNodeLists are created by DOMDocument::getElementsByTagName(), + * DOMNode::getChildNodes(), + * + *

The items in the DOMNodeList are accessible via an integral + * index, starting from 0. + * + * DOMNodeLists are "live", in that any changes to the document tree are immediately + * reflected in any DOMNodeLists that may have been created for that tree. + */ + +class CDOM_EXPORT DOMNodeList { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMNodeList() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMNodeList(const DOMNodeList &); + DOMNodeList & operator = (const DOMNodeList &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMNodeList() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMNodeList interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the index item in the collection. + * + * If index is greater than or equal to the number of nodes in + * the list, this returns null. + * + * @param index Index into the collection. + * @return The node at the indexth position in the + * DOMNodeList, or null if that is not a valid + * index. + * @since DOM Level 1 + */ + virtual DOMNode *item(XMLSize_t index) const = 0; + + /** + * Returns the number of nodes in the list. + * + * The range of valid child node indices is 0 to length-1 inclusive. + * @since DOM Level 1 + */ + virtual XMLSize_t getLength() const = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMNotation.hpp b/include/xercesc/dom/DOMNotation.hpp new file mode 100644 index 0000000..919c7e9 --- /dev/null +++ b/include/xercesc/dom/DOMNotation.hpp @@ -0,0 +1,114 @@ +/* + * 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: DOMNotation.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNOTATION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNOTATION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * This interface represents a notation declared in the DTD. A notation either + * declares, by name, the format of an unparsed entity (see section 4.7 of + * the XML 1.0 specification), or is used for formal declaration of + * Processing Instruction targets (see section 2.6 of the XML 1.0 + * specification). The nodeName attribute inherited from + * DOMNode is set to the declared name of the notation. + *

The DOM Level 1 does not support editing DOMNotation nodes; + * they are therefore readonly. + *

A DOMNotation node does not have any parent. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMNotation: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMNotation() {} + DOMNotation(const DOMNotation &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMNotation & operator = (const DOMNotation &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMNotation() {}; + //@} + + + // ----------------------------------------------------------------------- + // Virtual DOMNotation interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Get the public identifier of this notation. + * + * If the public identifier was not + * specified, this is null. + * @return Returns the public identifier of the notation + * @since DOM Level 1 + */ + virtual const XMLCh *getPublicId() const = 0; + + /** + * Get the system identifier of this notation. + * + * If the system identifier was not + * specified, this is null. + * @return Returns the system identifier of the notation + * @since DOM Level 1 + */ + virtual const XMLCh *getSystemId() const = 0; + + + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMPSVITypeInfo.hpp b/include/xercesc/dom/DOMPSVITypeInfo.hpp new file mode 100644 index 0000000..8ccd1fb --- /dev/null +++ b/include/xercesc/dom/DOMPSVITypeInfo.hpp @@ -0,0 +1,118 @@ +/* + * 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. + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMPSVITYPEINFO_HPP) +#define XERCESC_INCLUDE_GUARD_DOMPSVITYPEINFO_HPP + +//------------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------------ +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * The DOMPSVITypeInfo interface represent the PSVI info used by + * DOMElement or DOMAttr nodes, specified in the + * schemas associated with the document. + */ +class CDOM_EXPORT DOMPSVITypeInfo +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMPSVITypeInfo() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMPSVITypeInfo(const DOMPSVITypeInfo &); + DOMPSVITypeInfo & operator = (const DOMPSVITypeInfo &); + //@} + +public: + + enum PSVIProperty + { + PSVI_Validity + , PSVI_Validation_Attempted + , PSVI_Type_Definition_Type + , PSVI_Type_Definition_Name + , PSVI_Type_Definition_Namespace + , PSVI_Type_Definition_Anonymous + , PSVI_Nil + , PSVI_Member_Type_Definition_Name + , PSVI_Member_Type_Definition_Namespace + , PSVI_Member_Type_Definition_Anonymous + , PSVI_Schema_Default + , PSVI_Schema_Normalized_Value + , PSVI_Schema_Specified + }; + + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMPSVITypeInfo() {}; + //@} + + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the string value of the specified PSVI property associated to a + * DOMElement or DOMAttr, or null if not available. + * + * + * @return the string value of the specified PSVI property associated to a + * DOMElement or DOMAttr, or null if not available. + */ + virtual const XMLCh* getStringProperty(PSVIProperty prop) const = 0; + + /** + * Returns the numeric value of the specified PSVI property associated to a + * DOMElement or DOMAttr, or null if not available. + * + * + * @return the numeric value of the specified PSVI property associated to a + * DOMElement or DOMAttr, or null if not available. + */ + virtual int getNumericProperty(PSVIProperty prop) const = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DOMPSVITypeInfo.hpp + */ diff --git a/include/xercesc/dom/DOMProcessingInstruction.hpp b/include/xercesc/dom/DOMProcessingInstruction.hpp new file mode 100644 index 0000000..269416c --- /dev/null +++ b/include/xercesc/dom/DOMProcessingInstruction.hpp @@ -0,0 +1,121 @@ +/* + * 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: DOMProcessingInstruction.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMPROCESSINGINSTRUCTION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMPROCESSINGINSTRUCTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * The DOMProcessingInstruction interface represents a "processing + * instruction", used in XML as a way to keep processor-specific information + * in the text of the document. + * + * @since DOM Level 1 + */ +class CDOM_EXPORT DOMProcessingInstruction: public DOMNode { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMProcessingInstruction() {} + DOMProcessingInstruction(const DOMProcessingInstruction &other) : DOMNode(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMProcessingInstruction & operator = (const DOMProcessingInstruction &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMProcessingInstruction() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMProcessingInstruction interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * The target of this processing instruction. + * + * XML defines this as being the + * first token following the markup that begins the processing instruction. + * + * @since DOM Level 1 + */ + virtual const XMLCh * getTarget() const = 0; + + /** + * The content of this processing instruction. + * + * This is from the first non + * white space character after the target to the character immediately + * preceding the ?>. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + * @since DOM Level 1 + */ + virtual const XMLCh * getData() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Sets the content of this processing instruction. + * + * This is from the first non + * white space character after the target to the character immediately + * preceding the ?>. + * @param data The string containing the processing instruction + * @since DOM Level 1 + */ + virtual void setData(const XMLCh * data) = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/DOMRange.hpp b/include/xercesc/dom/DOMRange.hpp new file mode 100644 index 0000000..f0cdec5 --- /dev/null +++ b/include/xercesc/dom/DOMRange.hpp @@ -0,0 +1,530 @@ +/* + * 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: DOMRange.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMRANGE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMRANGE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMNode; +class DOMDocumentFragment; + +/** + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * @since DOM Level 2 + */ +class CDOM_EXPORT DOMRange { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMRange() {} + DOMRange(const DOMRange &) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMRange & operator = (const DOMRange &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMRange() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * Constants CompareHow. + * + *

START_TO_START: + * Compare start boundary-point of sourceRange to start + * boundary-point of Range on which compareBoundaryPoints + * is invoked.

+ * + *

START_TO_END: + * Compare start boundary-point of sourceRange to end + * boundary-point of Range on which compareBoundaryPoints + * is invoked.

+ * + *

END_TO_END: + * Compare end boundary-point of sourceRange to end + * boundary-point of Range on which compareBoundaryPoints + * is invoked.

+ * + *

END_TO_START: + * Compare end boundary-point of sourceRange to start + * boundary-point of Range on which compareBoundaryPoints + * is invoked.

+ * + * @since DOM Level 2 + */ + enum CompareHow { + START_TO_START = 0, + START_TO_END = 1, + END_TO_END = 2, + END_TO_START = 3 + }; + + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMRange interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * DOMNode within which the Range begins + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual DOMNode* getStartContainer() const = 0; + + /** + * Offset within the starting node of the Range. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual XMLSize_t getStartOffset() const = 0; + + /** + * DOMNode within which the Range ends + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual DOMNode* getEndContainer() const = 0; + + /** + * Offset within the ending node of the Range. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual XMLSize_t getEndOffset() const = 0; + + /** + * TRUE if the Range is collapsed + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual bool getCollapsed() const = 0; + + /** + * The deepest common ancestor container of the Range's two + * boundary-points. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual const DOMNode* getCommonAncestorContainer() const = 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * Sets the attributes describing the start of the Range. + * @param refNode The refNode value. This parameter must be + * different from null. + * @param offset The startOffset value. + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor + * of refNode is an DOMEntity, DOMNotation, or DOMDocumentType + * node. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if offset is negative or greater + * than the number of child units in refNode. Child units + * are 16-bit units if refNode is a type of DOMCharacterData + * node (e.g., a DOMText or DOMComment node) or a DOMProcessingInstruction + * node. Child units are Nodes in all other cases. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void setStart(const DOMNode *refNode, XMLSize_t offset) = 0; + + /** + * Sets the attributes describing the end of a Range. + * @param refNode The refNode value. This parameter must be + * different from null. + * @param offset The endOffset value. + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor + * of refNode is an DOMEntity, DOMNotation, or DOMDocumentType + * node. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if offset is negative or greater + * than the number of child units in refNode. Child units + * are 16-bit units if refNode is a type of DOMCharacterData + * node (e.g., a DOMText or DOMComment node) or a DOMProcessingInstruction + * node. Child units are Nodes in all other cases. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void setEnd(const DOMNode *refNode, XMLSize_t offset) = 0; + + /** + * Sets the start position to be before a node + * @param refNode Range starts before refNode + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if the root container of + * refNode is not an DOMAttr, DOMDocument, or DOMDocumentFragment + * node or if refNode is a DOMDocument, DOMDocumentFragment, + * DOMAttr, DOMEntity, or DOMNotation node. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void setStartBefore(const DOMNode *refNode) = 0; + + /** + * Sets the start position to be after a node + * @param refNode Range starts after refNode + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if the root container of + * refNode is not an DOMAttr, DOMDocument, or DOMDocumentFragment + * node or if refNode is a DOMDocument, DOMDocumentFragment, + * DOMAttr, DOMEntity, or DOMNotation node. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void setStartAfter(const DOMNode *refNode) = 0; + + /** + * Sets the end position to be before a node. + * @param refNode Range ends before refNode + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if the root container of + * refNode is not an DOMAttr, DOMDocument, or DOMDocumentFragment + * node or if refNode is a DOMDocument, DOMDocumentFragment, + * DOMAttr, DOMEntity, or DOMNotation node. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void setEndBefore(const DOMNode *refNode) = 0; + + /** + * Sets the end of a Range to be after a node + * @param refNode Range ends after refNode. + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if the root container of + * refNode is not a DOMAttr, DOMDocument or DOMDocumentFragment + * node or if refNode is a DOMDocument, DOMDocumentFragment, + * DOMAttr, DOMEntity, or DOMNotation node. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void setEndAfter(const DOMNode *refNode) = 0; + + // ----------------------------------------------------------------------- + // Misc methods + // ----------------------------------------------------------------------- + /** + * Collapse a Range onto one of its boundary-points + * @param toStart If TRUE, collapses the Range onto its start; if FALSE, + * collapses it onto its end. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual void collapse(bool toStart) = 0; + + /** + * Select a node and its contents + * @param refNode The node to select. + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode + * is an DOMEntity, DOMNotation or DOMDocumentType node or if + * refNode is a DOMDocument, DOMDocumentFragment, DOMAttr, DOMEntity, + * or DOMNotation node. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void selectNode(const DOMNode *refNode) = 0; + + /** + * Select the contents within a node + * @param refNode DOMNode to select from + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor + * of refNode is an DOMEntity, DOMNotation or DOMDocumentType node. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + *
WRONG_DOCUMENT_ERR: Raised if refNode was created + * from a different document than the one that created this range. + * + * @since DOM Level 2 + */ + virtual void selectNodeContents(const DOMNode *refNode) = 0; + + /** + * Compare the boundary-points of two Ranges in a document. + * @param how A code representing the type of comparison, as defined + * above. + * @param sourceRange The Range on which this current + * Range is compared to. + * @return -1, 0 or 1 depending on whether the corresponding + * boundary-point of the Range is respectively before, equal to, or + * after the corresponding boundary-point of sourceRange. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the same + * DOMDocument or DOMDocumentFragment. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + * + * @since DOM Level 2 + */ + virtual short compareBoundaryPoints(CompareHow how, const DOMRange* sourceRange) const = 0; + + /** + * Removes the contents of a Range from the containing document or + * document fragment without returning a reference to the removed + * content. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the content of + * the Range is read-only or any of the nodes that contain any of the + * content of the Range are read-only. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + * + * @since DOM Level 2 + */ + virtual void deleteContents() = 0; + + /** + * Moves the contents of a Range from the containing document or document + * fragment to a new DOMDocumentFragment. + * @return A DOMDocumentFragment containing the extracted contents. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the content of + * the Range is read-only or any of the nodes which contain any of the + * content of the Range are read-only. + *
HIERARCHY_REQUEST_ERR: Raised if a DOMDocumentType node would be + * extracted into the new DOMDocumentFragment. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + * + * @since DOM Level 2 + */ + virtual DOMDocumentFragment* extractContents() = 0; + + /** + * Duplicates the contents of a Range + * @return A DOMDocumentFragment that contains content equivalent to this + * Range. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if a DOMDocumentType node would be + * extracted into the new DOMDocumentFragment. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + * + * @since DOM Level 2 + */ + virtual DOMDocumentFragment* cloneContents() const = 0; + + /** + * Inserts a node into the DOMDocument or DOMDocumentFragment at the start of + * the Range. If the container is a DOMText node, this will be split at the + * start of the Range (as if the DOMText node's splitText method was + * performed at the insertion point) and the insertion will occur + * between the two resulting DOMText nodes. Adjacent DOMText nodes will not be + * automatically merged. If the node to be inserted is a + * DOMDocumentFragment node, the children will be inserted rather than the + * DOMDocumentFragment node itself. + * @param newNode The node to insert at the start of the Range + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of the + * start of the Range is read-only. + *
WRONG_DOCUMENT_ERR: Raised if newNode and the + * container of the start of the Range were not created from the same + * document. + *
HIERARCHY_REQUEST_ERR: Raised if the container of the start of + * the Range is of a type that does not allow children of the type of + * newNode or if newNode is an ancestor of + * the container. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + * @exception DOMRangeException + * INVALID_NODE_TYPE_ERR: Raised if newNode is an DOMAttr, + * DOMEntity, DOMNotation, or DOMDocument node. + * + * @since DOM Level 2 + */ + virtual void insertNode(DOMNode *newNode) = 0; + + /** + * Reparents the contents of the Range to the given node and inserts the + * node at the position of the start of the Range. + * @param newParent The node to surround the contents with. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of + * either boundary-point of the Range is read-only. + *
WRONG_DOCUMENT_ERR: Raised if newParent and the + * container of the start of the Range were not created from the same + * document. + *
HIERARCHY_REQUEST_ERR: Raised if the container of the start of + * the Range is of a type that does not allow children of the type of + * newParent or if newParent is an ancestor + * of the container or if node would end up with a child + * node of a type not allowed by the type of node. + *
INVALID_STATE_ERR: Raised if detach() has already + * been invoked on this object. + * @exception DOMRangeException + * BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a + * non-text node. + *
INVALID_NODE_TYPE_ERR: Raised if node is an DOMAttr, + * DOMEntity, DOMDocumentType, DOMNotation, DOMDocument, or DOMDocumentFragment node. + * + * @since DOM Level 2 + */ + virtual void surroundContents(DOMNode *newParent) = 0; + + /** + * Produces a new Range whose boundary-points are equal to the + * boundary-points of the Range. + * @return The duplicated Range. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual DOMRange* cloneRange() const = 0; + + /** + * Returns the contents of a Range as a string. This string contains only + * the data characters, not any markup. + * @return The contents of the Range. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual const XMLCh* toString() const = 0; + + /** + * Called to indicate that the Range is no longer in use and that the + * implementation may relinquish any resources associated with this + * Range. Subsequent calls to any methods or attribute getters on this + * Range will result in a DOMException being thrown with an + * error code of INVALID_STATE_ERR. + * @exception DOMException + * INVALID_STATE_ERR: Raised if detach() has already been + * invoked on this object. + * + * @since DOM Level 2 + */ + virtual void detach() = 0; + + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this Range is no longer in use + * and that the implementation may relinquish any resources associated with it. + * (release() will call detach() where appropriate) + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMRangeException.cpp b/include/xercesc/dom/DOMRangeException.cpp new file mode 100644 index 0000000..28a8249 --- /dev/null +++ b/include/xercesc/dom/DOMRangeException.cpp @@ -0,0 +1,52 @@ +/* + * 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: DOMRangeException.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMRangeException.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +DOMRangeException::DOMRangeException() +: DOMException() +{ +} + + +DOMRangeException::DOMRangeException(short exCode, + short messageCode, + MemoryManager* const memoryManager) +: DOMException(exCode, messageCode?messageCode:XMLDOMMsg::DOMRANGEEXCEPTION_ERRX+exCode-DOMRangeException::BAD_BOUNDARYPOINTS_ERR+1, memoryManager) +{ +} + + +DOMRangeException::DOMRangeException(const DOMRangeException &other) +: DOMException(other) +{ +} + + +DOMRangeException::~DOMRangeException() +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/DOMRangeException.hpp b/include/xercesc/dom/DOMRangeException.hpp new file mode 100644 index 0000000..c4d05f8 --- /dev/null +++ b/include/xercesc/dom/DOMRangeException.hpp @@ -0,0 +1,114 @@ +/* + * 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: DOMRangeException.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMRANGEEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMRANGEEXCEPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Range operations may throw a DOMRangeException as specified in + * their method descriptions. + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * @since DOM Level 2 + */ + +class CDOM_EXPORT DOMRangeException : public DOMException { +public: + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * Enumerators for DOM Range Exceptions + * + *

BAD_BOUNDARYPOINTS_ERR: + * If the boundary-points of a Range do not meet specific requirements.

+ * + *

INVALID_NODE_TYPE_ERR: + * If the container of an boundary-point of a Range is being set to either + * a node of an invalid type or a node with an ancestor of an invalid + * type.

+ * + * @since DOM Level 2 + */ + enum RangeExceptionCode { + BAD_BOUNDARYPOINTS_ERR = 111, + INVALID_NODE_TYPE_ERR = 112 + }; + //@} + +public: + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + /** + * Default constructor for DOMRangeException. + * + */ + DOMRangeException(); + + /** + * Constructor which takes an error code and a message. + * + * @param code The error code which indicates the exception + * @param messageCode The string containing the error message + * @param memoryManager The memory manager used to (de)allocate memory + */ + DOMRangeException(short code, + short messageCode, + MemoryManager* const memoryManager); + + /** + * Copy constructor. + * + * @param other The object to be copied. + */ + DOMRangeException(const DOMRangeException &other); + //@} + + // ----------------------------------------------------------------------- + // Destructors + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + /** + * Destructor for DOMRangeException. + * + */ + virtual ~DOMRangeException(); + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMRangeException & operator = (const DOMRangeException &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMStringList.hpp b/include/xercesc/dom/DOMStringList.hpp new file mode 100644 index 0000000..e594566 --- /dev/null +++ b/include/xercesc/dom/DOMStringList.hpp @@ -0,0 +1,131 @@ +/* + * 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: DOMStringList.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMSTRINGLIST_HPP) +#define XERCESC_INCLUDE_GUARD_DOMSTRINGLIST_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * The DOMStringList interface provides the abstraction of an ordered + * collection of strings, without defining or constraining how this collection + * is implemented. The items in the DOMStringList are accessible via + * an integral index, starting from 0. + */ + +class CDOM_EXPORT DOMStringList { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMStringList() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMStringList(const DOMStringList &); + DOMStringList & operator = (const DOMStringList &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMStringList() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMStringList interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns the index item in the collection. + * + * If index is greater than or equal to the number of strings in + * the list, this returns null. + * + * @param index Index into the collection. + * @return The string at the indexth position in the + * DOMStringList, or null if that is not a valid + * index. + * @since DOM Level 3 + */ + virtual const XMLCh *item(XMLSize_t index) const = 0; + + /** + * Returns the number of strings in the list. + * + * The range of valid child node indices is 0 to length-1 inclusive. + * + * @since DOM Level 3 + */ + virtual XMLSize_t getLength() const = 0; + + /** + * Test if a string is part of this DOMStringList + * + * @return true if the string has been found, false otherwise. + * + * @since DOM Level 3 + */ + virtual bool contains(const XMLCh*) const = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this list is no longer in use + * and that the implementation may relinquish any resources associated with it and + * its associated children. + * + * Access to a released object will lead to unexpected result. + * + */ + virtual void release() = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMText.hpp b/include/xercesc/dom/DOMText.hpp new file mode 100644 index 0000000..9bc3053 --- /dev/null +++ b/include/xercesc/dom/DOMText.hpp @@ -0,0 +1,182 @@ +/* + * 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: DOMText.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMTEXT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMTEXT_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * The DOMText interface inherits from DOMCharacterData + * and represents the textual content (termed character data in XML) of an + * DOMElement or DOMAttr. If there is no markup inside + * an element's content, the text is contained in a single object + * implementing the DOMText interface that is the only child of + * the element. If there is markup, it is parsed into the information items + * (elements, comments, etc.) and DOMText nodes that form the list + * of children of the element. + *

When a document is first made available via the DOM, there is only one + * DOMText node for each block of text. Users may create adjacent + * DOMText nodes that represent the contents of a given element + * without any intervening markup, but should be aware that there is no way + * to represent the separations between these nodes in XML or HTML, so they + * will not (in general) persist between DOM editing sessions. The + * normalize() method on DOMNode merges any such + * adjacent DOMText objects into a single node for each block of + * text. + *

See also the Document Object Model (DOM) Level 2 Core Specification. + */ +class CDOM_EXPORT DOMText: public DOMCharacterData { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMText() {} + DOMText(const DOMText &other) : DOMCharacterData(other) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented operators */ + //@{ + DOMText & operator = (const DOMText &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMText() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMText interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 1 */ + //@{ + /** + * Breaks this node into two nodes at the specified offset, + * keeping both in the tree as siblings. After being split, this node + * will contain all the content up to the offset point. A + * new node of the same type, which contains all the content at and + * after the offset point, is returned. If the original + * node had a parent node, the new node is inserted as the next sibling + * of the original node. When the offset is equal to the + * length of this node, the new node has no data. + * @param offset The 16-bit unit offset at which to split, starting from + * 0. + * @return The new node, of the same type as this node. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater + * than the number of 16-bit units in data. + *
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 1 + */ + virtual DOMText *splitText(XMLSize_t offset) = 0; + //@} + + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * Returns whether this text node contains element content whitespace, + * often abusively called "ignorable whitespace". The text node is determined + * to contain whitespace in element content during the load of the document + * or if validation occurs while using DOMDocument::normalizeDocument(). + * + * @since DOM Level 3 + */ + virtual bool getIsElementContentWhitespace() const = 0; + + /** + * Returns all text of DOMText nodes logically-adjacent text + * nodes to this node, concatenated in document order. + * + * @since DOM Level 3 + */ + virtual const XMLCh* getWholeText() const = 0; + + /** + * Substitutes the a specified text for the text of the current node and + * all logically-adjacent text nodes. + * + *
This method returns the node in the hierarchy which received the + * replacement text, which is null if the text was empty or is the + * current node if the current node is not read-only or otherwise is a + * new node of the same type as the current node inserted at the site of + * the replacement. All logically-adjacent text nodes are removed + * including the current node unless it was the recipient of the + * replacement text. + *
Where the nodes to be removed are read-only descendants of an + * DOMEntityReference, the DOMEntityReference must + * be removed instead of the read-only nodes. If any + * DOMEntityReference to be removed has descendants that are + * not DOMEntityReference, DOMText, or + * DOMCDATASection nodes, the replaceWholeText + * method must fail before performing any modification of the document, + * raising a DOMException with the code + * NO_MODIFICATION_ALLOWED_ERR. + * + * @param content The content of the replacing DOMText node. + * @return The DOMText node created with the specified content. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if one of the DOMText + * nodes being replaced is readonly. + * @since DOM Level 3 + */ + virtual DOMText* replaceWholeText(const XMLCh* content) = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard extension + // ----------------------------------------------------------------------- + /** @name Non-standard extension */ + //@{ + /** + * Non-standard extension + * + * Return true if this node contains ignorable whitespaces only. + * @return True if this node contains ignorable whitespaces only. + */ + virtual bool isIgnorableWhitespace() const = 0; + //@} + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/DOMTreeWalker.hpp b/include/xercesc/dom/DOMTreeWalker.hpp new file mode 100644 index 0000000..9f22fbe --- /dev/null +++ b/include/xercesc/dom/DOMTreeWalker.hpp @@ -0,0 +1,276 @@ +/* + * 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: DOMTreeWalker.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMTREEWALKER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMTREEWALKER_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * DOMTreeWalker objects are used to navigate a document tree or + * subtree using the view of the document defined by their + * whatToShow flags and filter (if any). Any function which + * performs navigation using a DOMTreeWalker will automatically + * support any view defined by a DOMTreeWalker. + *

Omitting nodes from the logical view of a subtree can result in a + * structure that is substantially different from the same subtree in the + * complete, unfiltered document. Nodes that are siblings in the + * DOMTreeWalker view may be children of different, widely + * separated nodes in the original view. For instance, consider a + * DOMNodeFilter that skips all nodes except for DOMText nodes and + * the root node of a document. In the logical view that results, all text + * nodes will be siblings and appear as direct children of the root node, no + * matter how deeply nested the structure of the original document. + *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. + * + * @since DOM Level 2 + */ +class CDOM_EXPORT DOMTreeWalker { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMTreeWalker() {} + DOMTreeWalker(const DOMTreeWalker &) {} + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMTreeWalker & operator = (const DOMTreeWalker &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMTreeWalker() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMTreeWalker interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 2 */ + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** + * The root node of the DOMTreeWalker, as specified + * when it was created. + * + * @since DOM Level 2 + */ + virtual DOMNode* getRoot() = 0; + /** + * This attribute determines which node types are presented via the + * DOMTreeWalker. The available set of constants is defined in + * the DOMNodeFilter interface. Nodes not accepted by + * whatToShow will be skipped, but their children may still + * be considered. Note that this skip takes precedence over the filter, + * if any. + * + * @since DOM Level 2 + */ + virtual DOMNodeFilter::ShowType getWhatToShow()= 0; + + /** + * Return The filter used to screen nodes. + * + * @since DOM Level 2 + */ + virtual DOMNodeFilter* getFilter()= 0; + + /** + * The value of this flag determines whether the children of entity + * reference nodes are visible to the DOMTreeWalker. If false, + * these children and their descendants will be rejected. Note that + * this rejection takes precedence over whatToShow and the + * filter, if any. + *
To produce a view of the document that has entity references + * expanded and does not expose the entity reference node itself, use + * the whatToShow flags to hide the entity reference node + * and set expandEntityReferences to true when creating the + * DOMTreeWalker. To produce a view of the document that has + * entity reference nodes but no entity expansion, use the + * whatToShow flags to show the entity reference node and + * set expandEntityReferences to false. + * + * @since DOM Level 2 + */ + virtual bool getExpandEntityReferences()= 0; + + /** + * Return the node at which the DOMTreeWalker is currently positioned. + * + * @since DOM Level 2 + */ + virtual DOMNode* getCurrentNode()= 0; + + // ----------------------------------------------------------------------- + // Query methods + // ----------------------------------------------------------------------- + /** + * Moves to and returns the closest visible ancestor node of the current + * node. If the search for parentNode attempts to step + * upward from the DOMTreeWalker's root node, or + * if it fails to find a visible ancestor node, this method retains the + * current position and returns null. + * @return The new parent node, or null if the current node + * has no parent in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* parentNode()= 0; + + /** + * Moves the DOMTreeWalker to the first visible child of the + * current node, and returns the new node. If the current node has no + * visible children, returns null, and retains the current + * node. + * @return The new node, or null if the current node has no + * visible children in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* firstChild()= 0; + + /** + * Moves the DOMTreeWalker to the last visible child of the + * current node, and returns the new node. If the current node has no + * visible children, returns null, and retains the current + * node. + * @return The new node, or null if the current node has no + * children in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* lastChild()= 0; + + /** + * Moves the DOMTreeWalker to the previous sibling of the + * current node, and returns the new node. If the current node has no + * visible previous sibling, returns null, and retains the + * current node. + * @return The new node, or null if the current node has no + * previous sibling. in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* previousSibling()= 0; + + /** + * Moves the DOMTreeWalker to the next sibling of the current + * node, and returns the new node. If the current node has no visible + * next sibling, returns null, and retains the current node. + * @return The new node, or null if the current node has no + * next sibling. in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* nextSibling()= 0; + + /** + * Moves the DOMTreeWalker to the previous visible node in + * document order relative to the current node, and returns the new + * node. If the current node has no previous node, or if the search for + * previousNode attempts to step upward from the + * DOMTreeWalker's root node, returns + * null, and retains the current node. + * @return The new node, or null if the current node has no + * previous node in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* previousNode()= 0; + + /** + * Moves the DOMTreeWalker to the next visible node in document + * order relative to the current node, and returns the new node. If the + * current node has no next node, or if the search for nextNode attempts + * to step upward from the DOMTreeWalker's root + * node, returns null, and retains the current node. + * @return The new node, or null if the current node has no + * next node in the DOMTreeWalker's logical view. + * + * @since DOM Level 2 + */ + virtual DOMNode* nextNode()= 0; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** + * The node at which the DOMTreeWalker is currently positioned. + *
Alterations to the DOM tree may cause the current node to no longer + * be accepted by the DOMTreeWalker's associated filter. + * currentNode may also be explicitly set to any node, + * whether or not it is within the subtree specified by the + * root node or would be accepted by the filter and + * whatToShow flags. Further traversal occurs relative to + * currentNode even if it is not part of the current view, + * by applying the filters in the requested direction; if no traversal + * is possible, currentNode is not changed. + * @exception DOMException + * NOT_SUPPORTED_ERR: Raised if an attempt is made to set + * currentNode to null. + * + * @since DOM Level 2 + */ + virtual void setCurrentNode(DOMNode* currentNode)= 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this TreeWalker is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} +}; + +#define GetDOMTreeWalkerMemoryManager GET_INDIRECT_MM(fCurrentNode) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMTypeInfo.hpp b/include/xercesc/dom/DOMTypeInfo.hpp new file mode 100644 index 0000000..4e22b8d --- /dev/null +++ b/include/xercesc/dom/DOMTypeInfo.hpp @@ -0,0 +1,196 @@ +/* + * 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. + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMTYPEINFO_HPP) +#define XERCESC_INCLUDE_GUARD_DOMTYPEINFO_HPP + +//------------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------------ +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * The DOMTypeInfo interface represent a type used by + * DOMElement or DOMAttr nodes, specified in the + * schemas associated with the document. The type is a pair of a namespace URI + * and name properties, and depends on the document's schema. + */ +class CDOM_EXPORT DOMTypeInfo +{ +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMTypeInfo() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMTypeInfo(const DOMTypeInfo &); + DOMTypeInfo & operator = (const DOMTypeInfo &); + //@} + +public: + + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMTypeInfo() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Contants */ + //@{ + /** + * These are the available values for the derivationMethod parameter used by the + * method DOMTypeInfo::isDerivedFrom(). It is a set of possible types + * of derivation, and the values represent bit positions. If a bit in the derivationMethod + * parameter is set to 1, the corresponding type of derivation will be taken into account + * when evaluating the derivation between the reference type definition and the other type + * definition. When using the isDerivedFrom method, combining all of them in the + * derivationMethod parameter is equivalent to invoking the method for each of them separately + * and combining the results with the OR boolean function. This specification only defines + * the type of derivation for XML Schema. + * + * In addition to the types of derivation listed below, please note that: + * - any type derives from xsd:anyType. + * - any simple type derives from xsd:anySimpleType by restriction. + * - any complex type does not derive from xsd:anySimpleType by restriction. + * + *

DERIVATION_EXTENSION: + * If the document's schema is an XML Schema [XML Schema Part 1], this constant represents the + * derivation by extension. The reference type definition is derived by extension from the other + * type definition if the other type definition can be reached recursively following the + * {base type definition} property from the reference type definition, and at least one of the + * derivation methods involved is an extension.

+ * + *

DERIVATION_LIST: + * If the document's schema is an XML Schema [XML Schema Part 1], this constant represents the list. + * The reference type definition is derived by list from the other type definition if there exists + * two type definitions T1 and T2 such as the reference type definition is derived from T1 by + * DERIVATION_RESTRICTION or DERIVATION_EXTENSION, T2 is derived from the other type definition by + * DERIVATION_RESTRICTION, T1 has {variety} list, and T2 is the {item type definition}. Note that + * T1 could be the same as the reference type definition, and T2 could be the same as the other + * type definition.

+ * + *

DERIVATION_RESTRICTION: + * If the document's schema is an XML Schema [XML Schema Part 1], this constant represents the + * derivation by restriction if complex types are involved, or a restriction if simple types are + * involved. + * The reference type definition is derived by restriction from the other type definition if the + * other type definition is the same as the reference type definition, or if the other type definition + * can be reached recursively following the {base type definition} property from the reference type + * definition, and all the derivation methods involved are restriction.

+ * + *

DERIVATION_UNION: + * If the document's schema is an XML Schema [XML Schema Part 1], this constant represents the union + * if simple types are involved. + * The reference type definition is derived by union from the other type definition if there exists + * two type definitions T1 and T2 such as the reference type definition is derived from T1 by + * DERIVATION_RESTRICTION or DERIVATION_EXTENSION, T2 is derived from the other type definition by + * DERIVATION_RESTRICTION, T1 has {variety} union, and one of the {member type definitions} is T2. + * Note that T1 could be the same as the reference type definition, and T2 could be the same as the + * other type definition.

+ * + * @since DOM Level 3 + * + */ + enum DerivationMethods { + DERIVATION_RESTRICTION = 0x001, + DERIVATION_EXTENSION = 0x002, + DERIVATION_UNION = 0x004, + DERIVATION_LIST = 0x008 + }; + //@} + + //@{ + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * Returns The name of a type declared for the associated DOMElement + * or DOMAttr, or null if unknown. + * + * @return The name of a type declared for the associated DOMElement + * or DOMAttribute, or null if unknown. + * @since DOM level 3 + */ + virtual const XMLCh* getTypeName() const = 0; + + /** + * The namespace of the type declared for the associated DOMElement + * or DOMAttr or null if the DOMElement does not have + * declaration or if no namespace information is available. + * + * @return The namespace of the type declared for the associated DOMElement + * or DOMAttr or null if the DOMElement does not have + * declaration or if no namespace information is available. + * @since DOM level 3 + */ + virtual const XMLCh* getTypeNamespace() const = 0; + //@} + + //@{ + /** + * This method returns if there is a derivation between the reference type definition, + * i.e. the DOMTypeInfo on which the method is being called, and the other type definition, + * i.e. the one passed as parameters. + * + * @param typeNamespaceArg The namespace of the other type definition. + * @param typeNameArg The name of the other type definition. + * @param derivationMethod The type of derivation and conditions applied between two types, + * as described in the list of constants provided in this interface. + * @return If the document's schema is a DTD or no schema is associated with the document, + * this method will always return false. + * If the document's schema is an XML Schema, the method will true if the reference + * type definition is derived from the other type definition according to the derivation + * parameter. If the value of the parameter is 0 (no bit is set to 1 for the + * derivationMethod parameter), the method will return true if the other type definition + * can be reached by recursing any combination of {base type definition}, + * {item type definition}, or {member type definitions} from the reference type definition. + * @since DOM level 3 + */ + virtual bool isDerivedFrom(const XMLCh* typeNamespaceArg, + const XMLCh* typeNameArg, + DerivationMethods derivationMethod) const = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DOMTypeInfo.hpp + */ diff --git a/include/xercesc/dom/DOMUserDataHandler.hpp b/include/xercesc/dom/DOMUserDataHandler.hpp new file mode 100644 index 0000000..74c24dd --- /dev/null +++ b/include/xercesc/dom/DOMUserDataHandler.hpp @@ -0,0 +1,140 @@ +/* + * 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: DOMUserDataHandler.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMUSERDATAHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMUSERDATAHANDLER_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * When associating an object to a key on a node using setUserData + * the application can provide a handler that gets called when the node the + * object is associated to is being cloned or imported. This can be used by + * the application to implement various behaviors regarding the data it + * associates to the DOM nodes. This interface defines that handler. + * + *

See also the Document Object Model (DOM) Level 3 Core Specification. + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMUserDataHandler { +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMUserDataHandler() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMUserDataHandler(const DOMUserDataHandler &); + DOMUserDataHandler & operator = (const DOMUserDataHandler &); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMUserDataHandler() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * Operation Type + * + *

NODE_CLONED: + * The node is cloned.

+ * + *

NODE_IMPORTED + * The node is imported.

+ * + *

NODE_DELETED + * The node is deleted.

+ * + *

NODE_RENAMED + * The node is renamed. + * + *

NODE_ADOPTED + * The node is adopted. + * + * @since DOM Level 3 + */ + enum DOMOperationType { + NODE_CLONED = 1, + NODE_IMPORTED = 2, + NODE_DELETED = 3, + NODE_RENAMED = 4, + NODE_ADOPTED = 5 + }; + //@} + + + // ----------------------------------------------------------------------- + // Virtual DOMUserDataHandler interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * This method is called whenever the node for which this handler is + * registered is imported or cloned. + * + * @param operation Specifies the type of operation that is being + * performed on the node. + * @param key Specifies the key for which this handler is being called. + * @param data Specifies the data for which this handler is being called. + * @param src Specifies the node being cloned, adopted, imported, or renamed. + * This is null when the node is being deleted. + * @param dst Specifies the node newly created if any, or null. + * + * @since DOM Level 3 + */ + virtual void handle(DOMOperationType operation, + const XMLCh* const key, + void* data, + const DOMNode* src, + DOMNode* dst) = 0; + + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/DOMXPathEvaluator.hpp b/include/xercesc/dom/DOMXPathEvaluator.hpp new file mode 100644 index 0000000..b491c7e --- /dev/null +++ b/include/xercesc/dom/DOMXPathEvaluator.hpp @@ -0,0 +1,180 @@ +/* + * 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: DOMXPathEvaluator.hpp 698579 2008-09-24 14:13:08Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHEVALUATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHEVALUATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMXPathNSResolver; +class DOMXPathExpression; +class DOMNode; + +/** + * The evaluation of XPath expressions is provided by DOMXPathEvaluator. + * In a DOM implementation which supports the XPath feature, the DOMXPathEvaluator + * interface will be implemented on the same object which implements the Document interface permitting + * it to be obtained by casting or by using the DOM Level 3 getFeature method. In this case the + * implementation obtained from the Document supports the XPath DOM module and is compatible + * with the XPath 1.0 specification. + * Evaluation of expressions with specialized extension functions or variables may not + * work in all implementations and is, therefore, not portable. XPathEvaluator implementations + * may be available from other sources that could provide specific support for specialized extension + * functions or variables as would be defined by other specifications. + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMXPathEvaluator +{ + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMXPathEvaluator() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMXPathEvaluator(const DOMXPathEvaluator &); + DOMXPathEvaluator& operator = (const DOMXPathEvaluator&); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMXPathEvaluator() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMXPathEvaluator interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + + /** + * Creates a parsed XPath expression with resolved namespaces. This is useful + * when an expression will be reused in an application since it makes it + * possible to compile the expression string into a more efficient internal + * form and preresolve all namespace prefixes which occur within the expression. + * @param expression of type XMLCh - The XPath expression string to be parsed. + * @param resolver of type XPathNSResolver - The resolver permits + * translation of all prefixes, including the xml namespace prefix, within the XPath expression + * into appropriate namespace URIs. If this is specified as null, any namespace + * prefix within the expression will result in DOMException being thrown with the + * code NAMESPACE_ERR. + * @return DOMXPathExpression The compiled form of the XPath expression. + * @exception DOMXPathException + * INVALID_EXPRESSION_ERR: Raised if the expression is not legal according to the + * rules of the DOMXPathEvaluator. + * @exception DOMException + * NAMESPACE_ERR: Raised if the expression contains namespace prefixes which cannot + * be resolved by the specified XPathNSResolver. + * @since DOM Level 3 + */ + virtual DOMXPathExpression* createExpression(const XMLCh *expression, + const DOMXPathNSResolver *resolver) = 0; + + + /** Adapts any DOM node to resolve namespaces so that an XPath expression can be + * easily evaluated relative to the context of the node where it appeared within + * the document. This adapter works like the DOM Level 3 method lookupNamespaceURI + * on nodes in resolving the namespaceURI from a given prefix using the current + * information available in the node's hierarchy at the time lookupNamespaceURI + * is called. also correctly resolving the implicit xml prefix. + * @param nodeResolver of type DOMNode The node to be used as a context + * for namespace resolution. If this parameter is null, an unpopulated + * DOMXPathNSResolver is returned, which can be populated using the + * Xerces-C extension DOMXPathNSResolver::addNamespaceBinding(). + * @return DOMXPathNSResolver The object which resolves namespaces + * with respect to the definitions in scope for the specified node. + */ + virtual DOMXPathNSResolver* createNSResolver(const DOMNode *nodeResolver) = 0; + + + /** + * Evaluates an XPath expression string and returns a result of the specified + * type if possible. + * @param expression of type XMLCh The XPath expression string to be parsed + * and evaluated. + * @param contextNode of type DOMNode The context is context node + * for the evaluation + * of this XPath expression. If the DOMXPathEvaluator was obtained by + * casting the DOMDocument then this must be owned by the same + * document and must be a DOMDocument, DOMElement, + * DOMAttribute, DOMText, DOMCDATASection, + * DOMComment, DOMProcessingInstruction, or + * XPathNamespace node. If the context node is a DOMText or + * a DOMCDATASection, then the context is interpreted as the whole + * logical text node as seen by XPath, unless the node is empty in which case it + * may not serve as the XPath context. + * @param resolver of type XPathNSResolver The resolver permits + * translation of all prefixes, including the xml namespace prefix, within + * the XPath expression into appropriate namespace URIs. If this is specified + * as null, any namespace prefix within the expression will result in + * DOMException being thrown with the code NAMESPACE_ERR. + * @param type - If a specific type is specified, then + * the result will be returned as the corresponding type. This must be one + * of the codes of the DOMXPathResult interface. + * @param result of type DOMXPathResult* - The result specifies a specific result object + * which may be reused and returned by this method. If this is specified as + * null or the implementation does not reuse the specified result, a new result + * object will be constructed and returned. + * @return DOMXPathResult* The result of the evaluation of the XPath expression. + * @exception DOMXPathException + * INVALID_EXPRESSION_ERR: Raised if the expression is not legal + * according to the rules of the DOMXPathEvaluator + * TYPE_ERR: Raised if the result cannot be converted to return the specified type. + * @exception DOMException + * NAMESPACE_ERR: Raised if the expression contains namespace prefixes + * which cannot be resolved by the specified XPathNSResolver. + * WRONG_DOCUMENT_ERR: The DOMNode is from a document that is not supported + * by this DOMXPathEvaluator. + * NOT_SUPPORTED_ERR: The DOMNode is not a type permitted as an XPath context + * node or the request type is not permitted by this DOMXPathEvaluator. + */ + virtual DOMXPathResult* evaluate(const XMLCh *expression, + const DOMNode *contextNode, + const DOMXPathNSResolver *resolver, + DOMXPathResult::ResultType type, + DOMXPathResult* result) = 0; + + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMXPathException.cpp b/include/xercesc/dom/DOMXPathException.cpp new file mode 100644 index 0000000..8e4877e --- /dev/null +++ b/include/xercesc/dom/DOMXPathException.cpp @@ -0,0 +1,52 @@ +/* + * 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. + */ + + +#include "DOMXPathException.hpp" +#include +#include +#include +#include "impl/DOMImplementationImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +DOMXPathException::DOMXPathException() +: DOMException() +{ +} + + +DOMXPathException::DOMXPathException(short exCode, + short messageCode, + MemoryManager* const memoryManager) +: DOMException(exCode, messageCode?messageCode:XMLDOMMsg::DOMXPATHEXCEPTION_ERRX+exCode-DOMXPathException::INVALID_EXPRESSION_ERR+1, memoryManager) +{ +} + + +DOMXPathException::DOMXPathException(const DOMXPathException &other) +: DOMException(other) +{ +} + + +DOMXPathException::~DOMXPathException() +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/DOMXPathException.hpp b/include/xercesc/dom/DOMXPathException.hpp new file mode 100644 index 0000000..3ad187e --- /dev/null +++ b/include/xercesc/dom/DOMXPathException.hpp @@ -0,0 +1,105 @@ +/* + * 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: DOMXPathException.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHEXCEPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMXPathException : public DOMException +{ +public: + //@{ + /** + * ExceptionCode + *
INVALID_EXPRESSION_ERR The expression has a syntax error or otherwise + * is not a legal expression according to the rules of the specific + * DOMXPathEvaluator or contains specialized extension functions + * or variables not supported by this implementation. + *
TYPE_ERR The expression cannot be converted to return the specified type. + *
NO_RESULT_ERROR There is no current result in the result object. + */ + enum ExceptionCode { + INVALID_EXPRESSION_ERR = 51, + TYPE_ERR = 52, + NO_RESULT_ERROR = 53 + }; + //@} + +public: + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + /** + * Default constructor for DOMXPathException. + * + */ + DOMXPathException(); + + /** + * Constructor which takes an error code and a message. + * + * @param code The error code which indicates the exception + * @param messageCode The string containing the error message + * @param memoryManager The memory manager used to (de)allocate memory + */ + DOMXPathException(short code, + short messageCode = 0, + MemoryManager* const memoryManager = XMLPlatformUtils::fgMemoryManager); + + /** + * Copy constructor. + * + * @param other The object to be copied. + */ + DOMXPathException(const DOMXPathException &other); + + //@} + + // ----------------------------------------------------------------------- + // Destructors + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + /** + * Destructor for DOMXPathException. + * + */ + virtual ~DOMXPathException(); + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMXPathException& operator = (const DOMXPathException&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMXPathExpression.hpp b/include/xercesc/dom/DOMXPathExpression.hpp new file mode 100644 index 0000000..0bf34b2 --- /dev/null +++ b/include/xercesc/dom/DOMXPathExpression.hpp @@ -0,0 +1,129 @@ +/* + * 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: DOMXPathExpression.hpp 698579 2008-09-24 14:13:08Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHEXPRESSION_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHEXPRESSION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMNode; + +/** + * The DOMXPathExpression interface represents a parsed and resolved XPath expression. + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMXPathExpression +{ + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMXPathExpression() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMXPathExpression(const DOMXPathExpression &); + DOMXPathExpression& operator = (const DOMXPathExpression&); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMXPathExpression() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMXPathExpression interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + + /** + * Evaluates this XPath expression and returns a result. + * @param contextNode of type DOMNode The context is context + * node for the evaluation of this XPath expression. + * If the XPathEvaluator was obtained by casting the Document then this must + * be owned by the same document and must be a DOMDocument, DOMElement, + * DOMAttribute, DOMText, DOMCDATASection, + * DOMComment, DOMProcessingInstruction, or + * XPathNamespace. If the context node is a DOMText or a + * DOMCDATASection, then the context is interpreted as the whole logical + * text node as seen by XPath, unless the node is empty in which case it may not + * serve as the XPath context. + * @param type If a specific type is specified, then the result + * will be coerced to return the specified type relying on XPath conversions and fail + * if the desired coercion is not possible. This must be one of the type codes of DOMXPathResult. + * @param result of type DOMXPathResult* The result specifies a specific result object which + * may be reused and returned by this method. If this is specified as nullor the + * implementation does not reuse the specified result, a new result object will be constructed + * and returned. + * @return DOMXPathResult* The result of the evaluation of the XPath expression. + * @exception DOMXPathException + * TYPE_ERR: Raised if the result cannot be converted to return the specified type. + * @exception DOMException + * WRONG_DOCUMENT_ERR: The DOMNode is from a document that is not supported by + * the XPathEvaluator that created this DOMXPathExpression. + * NOT_SUPPORTED_ERR: The DOMNode is not a type permitted as an XPath context node or the + * request type is not permitted by this DOMXPathExpression. + */ + + virtual DOMXPathResult* evaluate(const DOMNode *contextNode, + DOMXPathResult::ResultType type, + DOMXPathResult* result) const = 0; + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this DOMXPathExpression is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMXPathNSResolver.hpp b/include/xercesc/dom/DOMXPathNSResolver.hpp new file mode 100644 index 0000000..b12d5a8 --- /dev/null +++ b/include/xercesc/dom/DOMXPathNSResolver.hpp @@ -0,0 +1,130 @@ +/* + * 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: DOMXPathNSResolver.hpp 698579 2008-09-24 14:13:08Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHNSRESOLVER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHNSRESOLVER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN +/** + * The DOMXPathNSResolver interface permit prefix strings + * in the expression to be properly bound to namespaceURI strings. + * DOMXPathEvaluator can construct an implementation of + * DOMXPathNSResolver from a node, or the interface may be + * implemented by any application. + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMXPathNSResolver +{ + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMXPathNSResolver() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMXPathNSResolver(const DOMXPathNSResolver &); + DOMXPathNSResolver& operator = (const DOMXPathNSResolver&); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMXPathNSResolver() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMDocument interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + + /** Look up the namespace URI associated to the given namespace prefix. + * + * @param prefix of type XMLCh - The prefix to look for. An empty or + * null string denotes the default namespace. + * @return the associated namespace URI or null if none is found. + */ + virtual const XMLCh* lookupNamespaceURI(const XMLCh* prefix) const = 0; + //@} + + + // ----------------------------------------------------------------------- + // Non-standard extension + // ----------------------------------------------------------------------- + /** @name Non-standard extension */ + //@{ + + /** + * Non-standard extension + * + * XPath2 implementations require a reverse lookup in the static context. + * Look up the prefix associated with the namespace URI + * @param URI of type XMLCh - The namespace to look for. + * @return the associated prefix which can be an empty string if this + * is a default namespace or null if none is found. + */ + virtual const XMLCh* lookupPrefix(const XMLCh* URI) const = 0; + + /** + * Non-standard extension + * + * Associate the given namespace prefix to the namespace URI. + * @param prefix of type XMLCh - The namespace prefix to bind. An empty + * or null string denotes the default namespace. + * @param uri of type XMLCh - The associated namespace URI. If this + * argument is null or an empty string then the existing binding for this + * prefix is removed. + */ + virtual void addNamespaceBinding(const XMLCh* prefix, const XMLCh* uri) = 0; + + /** + * Called to indicate that this object (and its associated children) is no longer in use + * and that the implementation may relinquish any resources associated with it and + * its associated children. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMXPathNamespace.hpp b/include/xercesc/dom/DOMXPathNamespace.hpp new file mode 100644 index 0000000..ae62341 --- /dev/null +++ b/include/xercesc/dom/DOMXPathNamespace.hpp @@ -0,0 +1,115 @@ +/* + * 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: DOMXPathNamespace.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHNAMESPACE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHNAMESPACE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMElement; + +/** + * The DOMXPathNamespace interface is returned by DOMXPathResult + * interfaces to represent the XPath namespace node type that DOM lacks. There is no + * public constructor for this node type. Attempts to place it into a hierarchy or a + * NamedNodeMap result in a DOMException with the code HIERARCHY_REQUEST_ERR. This node + * is read only, so methods or setting of attributes that would mutate the node result + * in a DOMException with the code NO_MODIFICATION_ALLOWED_ERR. + * The core specification describes attributes of the DOMNode interface that + * are different for different node types but does not describe XPATH_NAMESPACE_NODE, + * so here is a description of those attributes for this node type. All attributes of + * DOMNode not described in this section have a null or false value. + * ownerDocument matches the ownerDocument of the ownerElement even if the element is later adopted. + * nodeName is always the string "#namespace". + * prefix is the prefix of the namespace represented by the node. + * localName is the same as prefix. + * nodeType is equal to XPATH_NAMESPACE_NODE. + * namespaceURI is the namespace URI of the namespace represented by the node. + * nodeValue is the same as namespaceURI. + * adoptNode, cloneNode, and importNode fail on this node type by raising a DOMException with the code NOT_SUPPORTED_ERR. + * Note: In future versions of the XPath specification, the definition of a namespace node may + * be changed incompatibly, in which case incompatible changes to field values may be required to + * implement versions beyond XPath 1.0. + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMXPathNamespace : public DOMNode +{ + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMXPathNamespace() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMXPathNamespace(const DOMXPathNamespace &); + DOMXPathNamespace& operator = (const DOMXPathNamespace&); + //@} + +public: + + + enum XPathNodeType { + XPATH_NAMESPACE_NODE = 13 + }; + + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMXPathNamespace() {}; + //@} + + // ----------------------------------------------------------------------- + // Virtual DOMXPathNamespace interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + /** + * The DOMElement on which the namespace was in scope when + * it was requested. This does not change on a returned namespace node + * even if the document changes such that the namespace goes out of + * scope on that element and this node is no longer found there by XPath. + * @since DOM Level 3 + */ + virtual DOMElement *getOwnerElement() const = 0; + + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/DOMXPathResult.hpp b/include/xercesc/dom/DOMXPathResult.hpp new file mode 100644 index 0000000..2e35eb3 --- /dev/null +++ b/include/xercesc/dom/DOMXPathResult.hpp @@ -0,0 +1,351 @@ +/* + * 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: DOMXPathResult.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHRESULT_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHRESULT_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMXPathNSResolver; +class DOMXPathExpression; +class DOMTypeInfo; +class DOMNode; + +/** + * The DOMXPathResult interface represents the result of the + * evaluation of an XPath 1.0 or XPath 2.0 expression within the context + * of a particular node. Since evaluation of an XPath expression can result + * in various result types, this object makes it possible to discover and + * manipulate the type and value of the result. + * + * Note that some function signatures were changed compared to the + * DOM Level 3 in order to accommodate XPath 2.0. + * + * @since DOM Level 3 + */ +class CDOM_EXPORT DOMXPathResult +{ + +protected: + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Hidden constructors */ + //@{ + DOMXPathResult() {}; + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + /** @name Unimplemented constructors and operators */ + //@{ + DOMXPathResult(const DOMXPathResult &); + DOMXPathResult& operator = (const DOMXPathResult&); + //@} + +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~DOMXPathResult() {}; + //@} + + // ----------------------------------------------------------------------- + // Class Types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + *

ANY_TYPE + *
[XPath 1.0] This code does not represent a specific type. An evaluation of an XPath + * expression will never produce this type. If this type is requested, then + * the evaluation returns whatever type naturally results from evaluation + * of the expression. + * If the natural result is a node set when ANY_TYPE was requested, then + * UNORDERED_NODE_ITERATOR_TYPE is always the resulting type. Any other + * representation of a node set must be explicitly requested. + *

ANY_UNORDERED_NODE_TYPE + *
[XPath 1.0] The result is a node set as defined by XPath 1.0 and will be accessed + * as a single node, which may be null if the node set is empty. Document + * modification does not invalidate the node, but may mean that the result + * node no longer corresponds to the current document. This is a convenience + * that permits optimization since the implementation can stop once any node + * in the resulting set has been found. + * If there is more than one node in the actual result, the single node + * returned might not be the first in document order. + *

BOOLEAN_TYPE + *
[XPath 1.0] The result is a boolean as defined by XPath 1.0. Document modification + * does not invalidate the boolean, but may mean that reevaluation would not + * yield the same boolean. + *

FIRST_ORDERED_NODE_TYPE + *
[XPath 1.0] The result is a node set as defined by XPath 1.0 and will be accessed + * as a single node, which may be null if the node set is empty. Document + * modification does not invalidate the node, but may mean that the result + * node no longer corresponds to the current document. This is a convenience + * that permits optimization since the implementation can stop once the first + * node in document order of the resulting set has been found. + * If there are more than one node in the actual result, the single node + * returned will be the first in document order. + *

NUMBER_TYPE + *
[XPath 1.0] The result is a number as defined by XPath 1.0. Document modification does + * not invalidate the number, but may mean that reevaluation would not yield the + * same number. + *

ORDERED_NODE_ITERATOR_TYPE + *
[XPath 1.0] The result is a node set as defined by XPath 1.0 that will be accessed + * iteratively, which will produce document-ordered nodes. Document modification + * invalidates the iteration. + *

ORDERED_NODE_SNAPSHOT_TYPE + *
[XPath 1.0] The result is a node set as defined by XPath 1.0 that will be accessed as a + * snapshot list of nodes that will be in original document order. Document + * modification does not invalidate the snapshot but may mean that reevaluation would + * not yield the same snapshot and nodes in the snapshot may have been altered, moved, + * or removed from the document. + *

STRING_TYPE + *
[XPath 1.0] The result is a string as defined by XPath 1.0. Document modification does not + * invalidate the string, but may mean that the string no longer corresponds to the + * current document. + *

UNORDERED_NODE_ITERATOR_TYPE + *
[XPath 1.0] The result is a node set as defined by XPath 1.0 that will be accessed iteratively, + * which may not produce nodes in a particular order. Document modification invalidates the iteration. + * This is the default type returned if the result is a node set and ANY_TYPE is requested. + *

UNORDERED_NODE_SNAPSHOT_TYPE + *
[XPath 1.0] The result is a node set as defined by XPath 1.0 that will be accessed as a + * snapshot list of nodes that may not be in a particular order. Document modification + * does not invalidate the snapshot but may mean that reevaluation would not yield the same + * snapshot and nodes in the snapshot may have been altered, moved, or removed from the document. + *

FIRST_RESULT_TYPE + *
[XPath 2.0] The result is a sequence as defined by XPath 2.0 and will be accessed + * as a single current value or there will be no current value if the sequence + * is empty. Document modification does not invalidate the value, but may mean + * that the result no longer corresponds to the current document. This is a + * convenience that permits optimization since the implementation can stop once + * the first item in the resulting sequence has been found. If there is more + * than one item in the actual result, the single item returned might not be + * the first in document order. + *

ITERATOR_RESULT_TYPE + *
[XPath 2.0] The result is a sequence as defined by XPath 2.0 that will be accessed + * iteratively. Document modification invalidates the iteration. + *

SNAPSHOT_RESULT_TYPE + *
[XPath 2.0] The result is a sequence as defined by XPath 2.0 that will be accessed + * as a snapshot list of values. Document modification does not invalidate the + * snapshot but may mean that reevaluation would not yield the same snapshot + * and any items in the snapshot may have been altered, moved, or removed from + * the document. + */ + enum ResultType { + /* XPath 1.0 */ + ANY_TYPE = 0, + NUMBER_TYPE = 1, + STRING_TYPE = 2, + BOOLEAN_TYPE = 3, + UNORDERED_NODE_ITERATOR_TYPE = 4, + ORDERED_NODE_ITERATOR_TYPE = 5, + UNORDERED_NODE_SNAPSHOT_TYPE = 6, + ORDERED_NODE_SNAPSHOT_TYPE = 7, + ANY_UNORDERED_NODE_TYPE = 8, + FIRST_ORDERED_NODE_TYPE = 9, + /* XPath 2.0 */ + FIRST_RESULT_TYPE = 100, + ITERATOR_RESULT_TYPE = 101, + SNAPSHOT_RESULT_TYPE = 102 + }; + //@} + + + // ----------------------------------------------------------------------- + // Virtual DOMXPathResult interface + // ----------------------------------------------------------------------- + /** @name Functions introduced in DOM Level 3 */ + //@{ + + /** + * Returns the result type of this result + * @return ResultType + * A code representing the type of this result, as defined by the type constants. + */ + virtual ResultType getResultType() const = 0; + + /** + * Returns the DOM type info of the current result node or value + * (XPath 2 only). + * @return typeInfo of type TypeInfo, readonly + */ + virtual const DOMTypeInfo *getTypeInfo() const = 0; + + /** + * Returns true if the result has a current result and the value is a + * node (XPath 2 only). This function is necessary to distinguish + * between a string value and a node of type string as returned by + * the getTypeInfo() function. + * @return isNode of type boolean, readonly + */ + virtual bool isNode() const = 0; + + /** + * Returns the boolean value of this result + * @return booleanValue of type boolean + * The value of this boolean result. + * @exception DOMXPathException + * TYPE_ERR: raised if ResultType is not BOOLEAN_TYPE (XPath 1.0) or + * if current result cannot be properly converted to boolean (XPath 2.0). + *
+ * NO_RESULT_ERROR: raised if there is no current result in the result object (XPath 2.0). + */ + virtual bool getBooleanValue() const = 0; + + /** + * Returns the integer value of this result (XPath 2 only). + * @return integerValue of type int + * The value of this integer result. + * @exception DOMXPathException + * TYPE_ERR: raised if current result cannot be properly converted to + * int (XPath 2.0). + *
+ * NO_RESULT_ERROR: raised if there is no current result in the result object (XPath 2.0). + */ + virtual int getIntegerValue() const = 0; + + /** + * Returns the number value of this result + * @return numberValue + * The value of this number result. If the native double type of the DOM + * binding does not directly support the exact IEEE 754 result of the XPath + * expression, then it is up to the definition of the binding to specify how + * the XPath number is converted to the native binding number. + * @exception DOMXPathException + * TYPE_ERR: raised if ResultType is not NUMBER_TYPE (XPath 1.0) or + * if current result cannot be properly converted to double (XPath 2.0). + *
+ * NO_RESULT_ERROR: raised if there is no current result in the result object (XPath 2.0). + */ + virtual double getNumberValue() const = 0; + + /** + * Returns the string value of this result + * @return stringValue + * The value of this string result. + * @exception DOMXPathException + * TYPE_ERR: raised if ResultType is not STRING_TYPE (XPath 1.0) or + * if current result cannot be properly converted to string (XPath 2.0). + *
+ * NO_RESULT_ERROR: raised if there is no current result in the result object (XPath 2.0). + */ + virtual const XMLCh* getStringValue() const = 0; + + /** + * Returns the node value of this result + * @return nodeValue + * The value of this node result, which may be null. + * @exception DOMXPathException + * TYPE_ERR: raised if ResultType is not ANY_UNORDERED_NODE_TYPE, + * FIRST_ORDERED_NODE_TYPE, UNORDERED_NODE_ITERATOR_TYPE, + * ORDERED_NODE_ITERATOR_TYPE, UNORDERED_NODE_SNAPSHOT_TYPE, or + * ORDERED_NODE_SNAPSHOT_TYPE (XPath 1.0) or if current result is + * not a node (XPath 2.0). + *
+ * NO_RESULT_ERROR: raised if there is no current result in the result + * object. + */ + virtual DOMNode* getNodeValue() const = 0; + + /** + * Iterates and returns true if the current result is the next item from the + * sequence or false if there are no more items. + * @return boolean True if the current result is the next item from the sequence + * or false if there are no more items. + * @exception XPathException + * TYPE_ERR: raised if ResultType is not UNORDERED_NODE_ITERATOR_TYPE or + * ORDERED_NODE_ITERATOR_TYPE (XPath 1.0) or if ResultType is not + * ITERATOR_RESULT_TYPE (XPath 2.0). + * @exception DOMException + * INVALID_STATE_ERR: The document has been mutated since the result was returned. + */ + virtual bool iterateNext() = 0; + + /** + * Signifies that the iterator has become invalid. + * @return invalidIteratorState + * True if ResultType is UNORDERED_NODE_ITERATOR_TYPE or + * ORDERED_NODE_ITERATOR_TYPE (XPath 1.0) or ITERATOR_RESULT_TYPE (XPath 2.0) + * and the document has been modified since this result was returned. + * @exception XPathException + * TYPE_ERR: raised if ResultType is not UNORDERED_NODE_ITERATOR_TYPE or + * ORDERED_NODE_ITERATOR_TYPE (XPath 1.0) or if ResultType is not + * ITERATOR_RESULT_TYPE (XPath 2.0). + */ + virtual bool getInvalidIteratorState() const = 0; + + /** + * Sets the current result to the indexth item in the snapshot collection. If + * index is greater than or equal to the number of items in the list, this method + * returns false. Unlike the iterator result, the snapshot does not become + * invalid, but may not correspond to the current document if it is mutated. + * @param index of type XMLSize_t - Index into the snapshot collection. + * @return boolean True if the current result is the next item from the sequence + * or false if there are no more items. + * @exception XPathException + * TYPE_ERR: raised if ResultType is not UNORDERED_NODE_SNAPSHOT_TYPE or + * ORDERED_NODE_SNAPSHOT_TYPE (XPath 1.0) or if ResultType is not + * SNAPSHOT_RESULT_TYPE (XPath 2.0). + */ + virtual bool snapshotItem(XMLSize_t index) = 0; + + /** + * The number of items in the result snapshot. Valid values for snapshotItem + * indices are 0 to snapshotLength-1 inclusive. + * @return snapshotLength of type XMLSize_t + * @exception XPathException + * TYPE_ERR: raised if ResultType is not UNORDERED_NODE_SNAPSHOT_TYPE or + * ORDERED_NODE_SNAPSHOT_TYPE (XPath 1.0) or if ResultType is not + * SNAPSHOT_RESULT_TYPE (XPath 2.0). + */ + virtual XMLSize_t getSnapshotLength() const = 0; + + //@} + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + /** + * Called to indicate that this DOMXPathResult is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + virtual void release() = 0; + //@} +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/StDOMNode.hpp b/include/xercesc/dom/StDOMNode.hpp new file mode 100644 index 0000000..c28248a --- /dev/null +++ b/include/xercesc/dom/StDOMNode.hpp @@ -0,0 +1,95 @@ +/* + * 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: StDOMNode.hpp 570480 2007-08-28 16:36:34Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_STDOMNODE_HPP) +#define XERCESC_INCLUDE_GUARD_STDOMNODE_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/* This class is a smart pointer implementation over DOMNode interface and +** classes derived from it. It takes care of reference counting automatically. +** Reference counting is optional so use of this class is experimental. +*/ +template class StDOMNode { + T* m_node; + + static inline void INCREFCOUNT(T *x) { if (x != (T*)0) x->incRefCount(); } + static inline void DECREFCOUNT(T *x) { if (x != (T*)0) x->decRefCount(); } + +public: + inline StDOMNode(T* node = (T*)0) : m_node(node) { INCREFCOUNT(m_node); } + inline StDOMNode(const StDOMNode& stNode) : m_node(stNode.m_node) { INCREFCOUNT(m_node); } + inline ~StDOMNode() { DECREFCOUNT(m_node); } + + inline T* operator= (T *node) + { + if (m_node != node) { + DECREFCOUNT(m_node); + m_node = node; + INCREFCOUNT(m_node); + } + return (m_node); + } + + inline bool operator!= (T* node) const { return (m_node != node); } + inline bool operator== (T* node) const { return (m_node == node); } + + inline T& operator* () { return (*m_node); } + inline const T& operator* () const { return (*m_node); } + inline T* operator-> () const { return (m_node); } + inline operator T*() const { return (m_node); } + inline void ClearNode() { operator=((T*)(0)); } +}; + +#if defined(XML_DOMREFCOUNT_EXPERIMENTAL) + typedef StDOMNode DOMNodeSPtr; +#else + typedef DOMNode* DOMNodeSPtr; +#endif + +/* StDOMNode is a smart pointer implementation over DOMNode interface and +** classes derived from it. It takes care of reference counting automatically. +** Reference counting is optional so use of this class is experimental. +*/ +#if defined(XML_DOMREFCOUNT_EXPERIMENTAL) + typedef StDOMNode DOMAttrSPtr; +#else + typedef DOMAttr* DOMAttrSPtr; +#endif + +/* StDOMNode is a smart pointer implementation over DOMNode interface and +** classes derived from it. It takes care of reference counting automatically. +** Reference counting is optional so use of this class is experimental. +*/ +#if defined(XML_DOMREFCOUNT_EXPERIMENTAL) + typedef StDOMNode DOMElementSPtr; +#else + typedef DOMElement* DOMElementSPtr; +#endif + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/impl/DOMAttrImpl.cpp b/include/xercesc/dom/impl/DOMAttrImpl.cpp new file mode 100644 index 0000000..7bd1409 --- /dev/null +++ b/include/xercesc/dom/impl/DOMAttrImpl.cpp @@ -0,0 +1,362 @@ +/* + * 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: DOMAttrImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#include +#include + +#include "DOMAttrImpl.hpp" +#include "DOMStringPool.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" +#include "DOMTypeInfoImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +DOMAttrImpl::DOMAttrImpl(DOMDocument *ownerDoc, const XMLCh *aName) + : fNode(ownerDoc), fParent (ownerDoc), fSchemaType(0) +{ + DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc; + fName = docImpl->getPooledString(aName); + fNode.isSpecified(true); +} + +DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool /*deep*/) + : DOMAttr(other) + , fNode(other.fNode) + , fParent (other.fParent) + , fName(other.fName) + , fSchemaType(other.fSchemaType) +{ + if (other.fNode.isSpecified()) + fNode.isSpecified(true); + else + fNode.isSpecified(false); + + if (other.fNode.isIdAttr()) + { + fNode.isIdAttr(true); + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + doc->getNodeIDMap()->add(this); + } + + fParent.cloneChildren(&other); +} + + +DOMAttrImpl::~DOMAttrImpl() { +} + + +DOMNode * DOMAttrImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (fParent.fOwnerDocument, DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMAttrImpl::getNodeName() const{ + return fName; +} + +DOMNode::NodeType DOMAttrImpl::getNodeType() const { + return DOMNode::ATTRIBUTE_NODE; +} + + +const XMLCh * DOMAttrImpl::getName() const { + return fName; +} + + +const XMLCh * DOMAttrImpl::getNodeValue() const +{ + return getValue(); +} + + +bool DOMAttrImpl::getSpecified() const +{ + return fNode.isSpecified(); +} + + + + +const XMLCh * DOMAttrImpl::getValue() const +{ + if (fParent.fFirstChild == 0) { + return XMLUni::fgZeroLenString; // return ""; + } + + // Simple case where attribute value is just a single text node + DOMNode *node = castToChildImpl(fParent.fFirstChild)->nextSibling; + if (node == 0 && fParent.fFirstChild->getNodeType() == DOMNode::TEXT_NODE) { + return fParent.fFirstChild->getNodeValue(); + } + + // + // Complicated case where attribute value is a DOM tree + // + // According to the spec, the child nodes of the Attr node may be either + // Text or EntityReference nodes. + // + // The parser will not create such thing, this is for those created by users. + // + // In such case, we have to visit each child to retrieve the text + // + + DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; + + XMLBuffer buf(1023, doc->getMemoryManager()); + for (node = fParent.fFirstChild; node != 0; node = castToChildImpl(node)->nextSibling) + getTextValue(node, buf); + + return doc->getPooledString(buf.getRawBuffer()); +} + +void DOMAttrImpl::getTextValue(DOMNode* node, XMLBuffer& buf) const +{ + if (node->getNodeType() == DOMNode::TEXT_NODE) + buf.append(node->getNodeValue()); + else if (node->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) + { + for (node = node->getFirstChild(); node != 0; node = castToChildImpl(node)->nextSibling) + { + getTextValue(node, buf); + } + } + + return; +} + + +void DOMAttrImpl::setNodeValue(const XMLCh *val) +{ + setValue(val); +} + + + +void DOMAttrImpl::setSpecified(bool arg) +{ + fNode.isSpecified(arg); +} + + + +void DOMAttrImpl::setValue(const XMLCh *val) +{ + if (fNode.isReadOnly()) + { + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + + // If this attribute was of type ID and in the map, take it out, + // then put it back in with the new name. For now, we don't worry + // about what happens if the new name conflicts + // + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + if (fNode.isIdAttr()) + doc->getNodeIDMap()->remove(this); + + DOMNode *kid; + while ((kid = fParent.fFirstChild) != 0) // Remove existing kids + { + DOMNode* node = removeChild(kid); + if (node) + node->release(); + } + + if (val != 0) // Create and add the new one + fParent.appendChildFast(doc->createTextNode(val)); + fNode.isSpecified(true); + fParent.changed(); + + if (fNode.isIdAttr()) + doc->getNodeIDMap()->add(this); + +} + +void DOMAttrImpl::setValueFast(const XMLCh *val) +{ + if (val != 0) + fParent.appendChildFast(fParent.fOwnerDocument->createTextNode(val)); + + fNode.isSpecified (true); +} + + + +//Introduced in DOM Level 2 + +DOMElement *DOMAttrImpl::getOwnerElement() const +{ + // if we have an owner, ownerNode is our ownerElement, otherwise it's + // our ownerDocument and we don't have an ownerElement + return (DOMElement *) (fNode.isOwned() ? fNode.fOwnerNode : 0); +} + + +//internal use by parser only +void DOMAttrImpl::setOwnerElement(DOMElement *ownerElem) +{ + fNode.fOwnerNode = ownerElem; + // revisit. Is this backwards? isOwned(true)? + fNode.isOwned(false); +} + + +//For DOM Level 3 + +void DOMAttrImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fParent.release(); + doc->release(this, DOMMemoryManager::ATTR_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + + +bool DOMAttrImpl::isId() const { + return fNode.isIdAttr(); +} + + +DOMNode* DOMAttrImpl::rename(const XMLCh* namespaceURI, const XMLCh* name) +{ + DOMElement* el = getOwnerElement(); + DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; + + if (el) + el->removeAttributeNode(this); + + if (!namespaceURI || !*namespaceURI) { + fName = doc->getPooledString(name); + + if (el) + el->setAttributeNode(this); + + // and fire user data NODE_RENAMED event + castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this); + + return this; + } + else { + + // create a new AttrNS + DOMAttr* newAttr = doc->createAttributeNS(namespaceURI, name); + + // transfer the userData + doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newAttr)); + + // move children to new node + DOMNode* child = getFirstChild(); + while (child) { + removeChild(child); + newAttr->appendChild(child); + child = getFirstChild(); + } + + // reattach attr to element + if (el) + el->setAttributeNodeNS(newAttr); + + // and fire user data NODE_RENAMED event + castToNodeImpl(newAttr)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newAttr); + + return newAttr; + } +} + +const DOMTypeInfo *DOMAttrImpl::getSchemaTypeInfo() const +{ + if(!fSchemaType) + return &DOMTypeInfoImpl::g_DtdNotValidatedAttribute; + + return fSchemaType; +} + + +void DOMAttrImpl::setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo) +{ + fSchemaType = typeInfo; +} + +bool DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const +{ + // check for '+DOMPSVITypeInfo' + if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfacePSVITypeInfo)) + return true; + return fNode.isSupported (feature, version); +} + +void* DOMAttrImpl::getFeature(const XMLCh* feature, const XMLCh* version) const +{ + if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo)) + return (DOMPSVITypeInfo*)fSchemaType; + return fNode.getFeature(feature, version); +} + + DOMNode* DOMAttrImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } + DOMNamedNodeMap* DOMAttrImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMAttrImpl::getChildNodes() const {return fParent.getChildNodes (); } + DOMNode* DOMAttrImpl::getFirstChild() const {return fParent.getFirstChild (); } + DOMNode* DOMAttrImpl::getLastChild() const {return fParent.getLastChild (); } + const XMLCh* DOMAttrImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMAttrImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMAttrImpl::getNextSibling() const {return fNode.getNextSibling (); } + DOMDocument* DOMAttrImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } + const XMLCh* DOMAttrImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMAttrImpl::getParentNode() const {return fNode.getParentNode (); } + DOMNode* DOMAttrImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } + bool DOMAttrImpl::hasChildNodes() const {return fParent.hasChildNodes (); } + DOMNode* DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fParent.insertBefore (newChild, refChild); } + void DOMAttrImpl::normalize() {fParent.normalize (); } + DOMNode* DOMAttrImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } + DOMNode* DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fParent.replaceChild (newChild, oldChild); } + void DOMAttrImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMAttrImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMAttrImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMAttrImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg); } + void* DOMAttrImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMAttrImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + const XMLCh* DOMAttrImpl::getBaseURI() const {return fNode.getBaseURI(); } + short DOMAttrImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMAttrImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMAttrImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMAttrImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMAttrImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMAttrImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMAttrImpl.hpp b/include/xercesc/dom/impl/DOMAttrImpl.hpp new file mode 100644 index 0000000..e4fc0fa --- /dev/null +++ b/include/xercesc/dom/impl/DOMAttrImpl.hpp @@ -0,0 +1,137 @@ +/* + * 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: DOMAttrImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMATTRIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMATTRIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include +#include "DOMParentNode.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include +#include +#include "DOMNodeIDMap.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMElementImpl; +class DOMTypeInfoImpl; + +class CDOM_EXPORT DOMAttrImpl: public DOMAttr { + +public: + DOMNodeImpl fNode; + DOMParentNode fParent; + const XMLCh *fName; + +protected: + const DOMTypeInfoImpl *fSchemaType; + +public: + DOMAttrImpl(DOMDocument *ownerDocument, const XMLCh *aName); + DOMAttrImpl(const DOMAttrImpl &other, bool deep=false); + virtual ~DOMAttrImpl(); + +public: + // Add all functions that are pure virtual in DOMNODE + DOMNODE_FUNCTIONS; + +public: + virtual const XMLCh * getName() const; + virtual bool getSpecified() const; + virtual const XMLCh * getValue() const; + virtual void setSpecified(bool arg); + virtual void setValue(const XMLCh * value); + virtual DOMElement * getOwnerElement() const; + virtual bool isId() const; + virtual const DOMTypeInfo* getSchemaTypeInfo() const; + + void setOwnerElement(DOMElement *ownerElem); //internal use only + + // helper function for DOM Level 3 renameNode + virtual DOMNode* rename(const XMLCh* namespaceURI, const XMLCh* name); + + //helper function for DOM Level 3 TypeInfo + virtual void setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo); + + // helper method that sets this attr to an idnode and places it into the document map + virtual void addAttrToIDNodeMap(); + + // helper to remove this attr from from the id map if it is in there + virtual void removeAttrFromIDNodeMap(); + +public: + // Set attribute value fast. Assumptions: + // + // - node is not read-only + // - no ID management is performed + // - this attribute does not have a value + // + virtual void setValueFast (const XMLCh * value); + +protected: + void getTextValue(DOMNode* node, XMLBuffer& buf) const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMAttrImpl& operator=(const DOMAttrImpl&); +}; + +inline void DOMAttrImpl::removeAttrFromIDNodeMap() +{ + if (fNode.isIdAttr()) { + ((DOMDocumentImpl *)fParent.fOwnerDocument)->getNodeIDMap()->remove(this); + fNode.isIdAttr(false); + } +} + +inline void DOMAttrImpl::addAttrToIDNodeMap() +{ + if (fNode.isIdAttr()) + return; + + fNode.isIdAttr(true); + + // REVIST For now, we don't worry about what happens if the new + // name conflicts as per setValue + DOMDocumentImpl *doc = (DOMDocumentImpl *)(fParent.fOwnerDocument); + + if (doc->fNodeIDMap == 0) + doc->fNodeIDMap = new (doc) DOMNodeIDMap(500, doc); + + doc->getNodeIDMap()->add(this); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMAttrMapImpl.cpp b/include/xercesc/dom/impl/DOMAttrMapImpl.cpp new file mode 100644 index 0000000..6ae5e51 --- /dev/null +++ b/include/xercesc/dom/impl/DOMAttrMapImpl.cpp @@ -0,0 +1,494 @@ +/* + * 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: DOMAttrMapImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#include "DOMCasts.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMNodeVector.hpp" +#include "DOMAttrMapImpl.hpp" +#include "DOMAttrImpl.hpp" +#include "DOMElementImpl.hpp" + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod) +{ + this->fOwnerNode=ownerNod; + this->fNodes = 0; + hasDefaults(false); +} + +DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod, const DOMAttrMapImpl *defaults) +{ + this->fOwnerNode=ownerNod; + this->fNodes = 0; + hasDefaults(false); + if (defaults != 0) + { + if (defaults->getLength() > 0) + { + hasDefaults(true); + cloneContent(defaults); + } + } +} + +DOMAttrMapImpl::~DOMAttrMapImpl() +{ +} + +void DOMAttrMapImpl::cloneContent(const DOMAttrMapImpl *srcmap) +{ + if ((srcmap != 0) && (srcmap->fNodes != 0)) + { + if (fNodes != 0) + fNodes->reset(); + else + { + XMLSize_t size = srcmap->fNodes->size(); + if(size > 0) { + DOMDocumentImpl *doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument(); + fNodes = new (doc) DOMNodeVector(doc, size); + } + } + + for (XMLSize_t i = 0; i < srcmap->fNodes->size(); i++) + { + DOMNode *n = srcmap->fNodes->elementAt(i); + DOMNode *clone = n->cloneNode(true); + castToNodeImpl(clone)->isSpecified(castToNodeImpl(n)->isSpecified()); + castToNodeImpl(clone)->fOwnerNode = fOwnerNode; + castToNodeImpl(clone)->isOwned(true); + fNodes->addElement(clone); + } + } +} + +DOMAttrMapImpl *DOMAttrMapImpl::cloneAttrMap(DOMNode *ownerNode_p) +{ + DOMAttrMapImpl *newmap = new (castToNodeImpl(ownerNode_p)->getOwnerDocument()) DOMAttrMapImpl(ownerNode_p); + newmap->cloneContent(this); + // newmap->attrDefaults = this->attrDefaults; // revisit + return newmap; +} + +void DOMAttrMapImpl::setReadOnly(bool readOnl, bool deep) +{ + // this->fReadOnly=readOnl; + if(deep && fNodes!=0) + { + XMLSize_t sz = fNodes->size(); + for (XMLSize_t i=0; ielementAt(i))->setReadOnly(readOnl, deep); + } + } +} + +bool DOMAttrMapImpl::readOnly() { + return castToNodeImpl(fOwnerNode)->isReadOnly(); +} + +int DOMAttrMapImpl::findNamePoint(const XMLCh *name) const +{ + // Binary search + int i=0; + if(fNodes!=0) + { + int first=0,last=(int)fNodes->size()-1; + + while(first<=last) + { + i=(first+last)/2; + int test = XMLString::compareString(name, fNodes->elementAt(i)->getNodeName()); + if(test==0) + return i; // Name found + else if(test<0) + last=i-1; + else + first=i+1; + } + if(first>i) i=first; + } + /******************** + // Linear search + int i = 0; + if (fNodes != 0) + for (i = 0; i < fNodes.size(); ++i) + { + int test = name.compareTo(((NodeImpl *) (fNodes.elementAt(i))).getNodeName()); + if (test == 0) + return i; + else + if (test < 0) + { + break; // Found insertpoint + } + } + + *******************/ + return -1 - i; // not-found has to be encoded. +} + +DOMNode * DOMAttrMapImpl::getNamedItem(const XMLCh *name) const +{ + int i=findNamePoint(name); + return (i<0) ? 0 : fNodes->elementAt(i); +} + +DOMNode *DOMAttrMapImpl::setNamedItem(DOMNode *arg) +{ + if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + DOMDocument *doc = fOwnerNode->getOwnerDocument(); + DOMNodeImpl *argImpl = castToNodeImpl(arg); + if(argImpl->getOwnerDocument() != doc) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNamedNodeMapMemoryManager); + if (this->readOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode)) + throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); + + argImpl->fOwnerNode = fOwnerNode; + argImpl->isOwned(true); + int i=findNamePoint(arg->getNodeName()); + DOMNode * previous=0; + if(i>=0) + { + previous = fNodes->elementAt(i); + fNodes->setElementAt(arg,i); + } + else + { + i=-1-i; // Insert point (may be end of list) + if(0==fNodes) + { + fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc); + } + fNodes->insertElementAt(arg,i); + } + if (previous != 0) { + castToNodeImpl(previous)->fOwnerNode = doc; + castToNodeImpl(previous)->isOwned(false); + } + + return previous; +} + +//Introduced in DOM Level 2 + +int DOMAttrMapImpl::findNamePoint(const XMLCh *namespaceURI, + const XMLCh *localName) const +{ + if (fNodes == 0) + return -1; + // This is a linear search through the same fNodes Vector. + // The Vector is sorted on the DOM Level 1 nodename. + // The DOM Level 2 NS keys are namespaceURI and Localname, + // so we must linear search thru it. + // In addition, to get this to work with fNodes without any namespace + // (namespaceURI and localNames are both 0) we then use the nodeName + // as a secondary key. + const XMLSize_t len = fNodes -> size(); + for (XMLSize_t i = 0; i < len; ++i) { + DOMNode *node = fNodes -> elementAt(i); + const XMLCh * nNamespaceURI = node->getNamespaceURI(); + const XMLCh * nLocalName = node->getLocalName(); + if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match + continue; + else { + if (XMLString::equals(localName, nLocalName) + || + (nLocalName == 0 && XMLString::equals(localName, node->getNodeName()))) + return (int)i; + } + } + return -1; //not found +} + +DOMNode *DOMAttrMapImpl::getNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName) const +{ + int i = findNamePoint(namespaceURI, localName); + return i < 0 ? 0 : fNodes -> elementAt(i); +} + +DOMNode *DOMAttrMapImpl::setNamedItemNS(DOMNode* arg) +{ + if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + DOMDocument *doc = fOwnerNode->getOwnerDocument(); + DOMNodeImpl *argImpl = castToNodeImpl(arg); + if (argImpl->getOwnerDocument() != doc) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager); + if (this->readOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + if (argImpl->isOwned()) + throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); + + argImpl->fOwnerNode = fOwnerNode; + argImpl->isOwned(true); + int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName()); + DOMNode *previous=0; + if(i>=0) { + previous = fNodes->elementAt(i); + fNodes->setElementAt(arg,i); + } else { + i=findNamePoint(arg->getNodeName()); // Insert point (may be end of list) + if (i<0) + i = -1 - i; + if(0==fNodes) + fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc); + fNodes->insertElementAt(arg,i); + } + if (previous != 0) { + castToNodeImpl(previous)->fOwnerNode = doc; + castToNodeImpl(previous)->isOwned(false); + } + + return previous; +} + +DOMNode *DOMAttrMapImpl::removeNamedItem(const XMLCh *name) +{ + if (this->readOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + int i=findNamePoint(name); + DOMNode *removed = 0; + + if(i<0) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + removed = fNodes->elementAt(i); + fNodes->removeElementAt(i); + castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument(); + castToNodeImpl(removed)->isOwned(false); + + // Replace it if it had a default value + // (DOM spec level 1 - Element Interface) + if (hasDefaults() && (removed != 0)) + { + DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes(); + DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItem(name)); + if (attr != 0) + { + DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); + setNamedItem(newAttr); + } + } + + return removed; +} + +DOMNode *DOMAttrMapImpl::removeNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) +{ + if (this->readOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + int i = findNamePoint(namespaceURI, localName); + if (i < 0) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + DOMNode * removed = fNodes -> elementAt(i); + fNodes -> removeElementAt(i); //remove n from nodes + castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument(); + castToNodeImpl(removed)->isOwned(false); + + // Replace it if it had a default value + // (DOM spec level 2 - Element Interface) + + if (hasDefaults() && (removed != 0)) + { + DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes(); + DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItemNS(namespaceURI, localName)); + if (attr != 0) + { + DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); + setNamedItemNS(newAttr); + } + } + + return removed; +} + +// remove the name using index +// avoid calling findNamePoint again if the index is already known +DOMNode * DOMAttrMapImpl::removeNamedItemAt(XMLSize_t index) +{ + if (this->readOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + DOMNode *removed = item(index); + if(!removed) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + fNodes->removeElementAt(index); + castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument(); + castToNodeImpl(removed)->isOwned(false); + + // Replace it if it had a default value + // (DOM spec level 1 - Element Interface) + if (hasDefaults() && (removed != 0)) + { + DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes(); + + const XMLCh* localName = removed->getLocalName(); + DOMAttr* attr = 0; + if (localName) + attr = (DOMAttr*)(defAttrs->getNamedItemNS(removed->getNamespaceURI(), localName)); + else + attr = (DOMAttr*)(defAttrs->getNamedItem(((DOMAttr*)removed)->getName())); + + if (attr != 0) + { + DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); + setNamedItem(newAttr); + } + } + + return removed; +} + +/** + * Get this AttributeMap in sync with the given "defaults" map. + * @param defaults The default attributes map to sync with. + */ +void DOMAttrMapImpl::reconcileDefaultAttributes(const DOMAttrMapImpl* defaults) { + + // remove any existing default + XMLSize_t nsize = getLength(); + for (XMLSize_t i = nsize; i > 0; i--) { + DOMAttr* attr = (DOMAttr*)item(i-1); + if (!attr->getSpecified()) { + removeNamedItemAt(i-1); + } + } + + hasDefaults(false); + + // add the new defaults + if (defaults) { + hasDefaults(true); + + if (nsize == 0) { + cloneContent(defaults); + } + else { + XMLSize_t dsize = defaults->getLength(); + for (XMLSize_t n = 0; n < dsize; n++) { + DOMAttr* attr = (DOMAttr*)defaults->item(n); + + DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); + setNamedItemNS(newAttr); + DOMAttrImpl* newAttrImpl = (DOMAttrImpl*) newAttr; + newAttrImpl->setSpecified(false); + } + } + } +} // reconcileDefaults() + + +/** + * Move specified attributes from the given map to this one + */ +void DOMAttrMapImpl::moveSpecifiedAttributes(DOMAttrMapImpl* srcmap) { + XMLSize_t nsize = srcmap->getLength(); + + for (XMLSize_t i = nsize; i > 0; i--) { + DOMAttr* attr = (DOMAttr*)srcmap->item(i-1); + if (attr->getSpecified()) { + srcmap->removeNamedItemAt(i-1); + } + + if (attr->getLocalName()) + setNamedItemNS(attr); + else + setNamedItem(attr); + } +} // moveSpecifiedAttributes(AttributeMap):void + +XMLSize_t DOMAttrMapImpl::getLength() const +{ + return (fNodes != 0) ? fNodes->size() : 0; +} + +DOMNode * DOMAttrMapImpl::item(XMLSize_t index) const +{ + return (fNodes != 0 && index < fNodes->size()) ? + fNodes->elementAt(index) : 0; +} + +void DOMAttrMapImpl::setNamedItemFast(DOMNode *arg) +{ + DOMNodeImpl *argImpl = castToNodeImpl(arg); + + argImpl->fOwnerNode = fOwnerNode; + argImpl->isOwned(true); + int i = findNamePoint(arg->getNodeName()); + + if(i >= 0) + fNodes->setElementAt(arg, i); + else + { + i= -1 -i; + fNodes->insertElementAt(arg, i); + } +} + +void DOMAttrMapImpl::setNamedItemNSFast(DOMNode* arg) +{ + DOMNodeImpl *argImpl = castToNodeImpl(arg); + + argImpl->fOwnerNode = fOwnerNode; + argImpl->isOwned(true); + int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName()); + + if(i >= 0) + { + fNodes->setElementAt(arg,i); + } + else + { + i = findNamePoint(arg->getNodeName()); + + if (i < 0) + i = -1 - i; + + fNodes->insertElementAt(arg,i); + } +} + +void DOMAttrMapImpl::reserve (XMLSize_t n) +{ + if (fNodes == 0) + { + DOMDocumentImpl* doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument(); + fNodes = new (doc) DOMNodeVector(doc, n); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMAttrMapImpl.hpp b/include/xercesc/dom/impl/DOMAttrMapImpl.hpp new file mode 100644 index 0000000..2d22543 --- /dev/null +++ b/include/xercesc/dom/impl/DOMAttrMapImpl.hpp @@ -0,0 +1,125 @@ +/* + * 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: DOMAttrMapImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMATTRMAPIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMATTRMAPIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMNode; +class DOMNodeVector; + +class CDOM_EXPORT DOMAttrMapImpl : public DOMNamedNodeMap +{ +protected: + DOMNodeVector* fNodes; + DOMNode* fOwnerNode; // the node this map belongs to + bool attrDefaults; + + virtual void cloneContent(const DOMAttrMapImpl *srcmap); + + bool readOnly(); // revisit. Look at owner node read-only. + +public: + DOMAttrMapImpl(DOMNode *ownerNod); + + // revisit. This "copy" constructor is used for cloning an Element with Attributes, + // and for setting up default attributes. It's probably not right + // for one or the other or both. + DOMAttrMapImpl(DOMNode *ownerNod, const DOMAttrMapImpl *defaults); + DOMAttrMapImpl(); + + virtual ~DOMAttrMapImpl(); + virtual DOMAttrMapImpl *cloneAttrMap(DOMNode *ownerNode); + virtual bool hasDefaults(); + virtual void hasDefaults(bool value); + virtual int findNamePoint(const XMLCh *name) const; + virtual int findNamePoint(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual DOMNode* removeNamedItemAt(XMLSize_t index); + virtual void setReadOnly(bool readOnly, bool deep); + + + virtual XMLSize_t getLength() const; + virtual DOMNode* item(XMLSize_t index) const; + + virtual DOMNode* getNamedItem(const XMLCh *name) const; + virtual DOMNode* setNamedItem(DOMNode *arg); + virtual DOMNode* removeNamedItem(const XMLCh *name); + + virtual DOMNode* getNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual DOMNode* setNamedItemNS(DOMNode *arg); + virtual DOMNode* removeNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName); + + // Fast versions of the above functions which bypass validity checks. + // It also assumes that fNode is not 0 (call reserve) and that there + // is no previous node with this name. These are used in parsing. + // + void setNamedItemFast(DOMNode *arg); + void setNamedItemNSFast(DOMNode *arg); + + // Tries to reserve space for the specified number of elements. + // Currently only works on newly-created instances (fNodes == 0). + // + void reserve (XMLSize_t); + + void reconcileDefaultAttributes(const DOMAttrMapImpl* defaults); + void moveSpecifiedAttributes(DOMAttrMapImpl* srcmap); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMAttrMapImpl(const DOMAttrMapImpl &); + DOMAttrMapImpl & operator = (const DOMAttrMapImpl &); +}; + +// --------------------------------------------------------------------------- +// DOMAttrMapImpl: Getters & Setters +// --------------------------------------------------------------------------- + +inline bool DOMAttrMapImpl::hasDefaults() +{ + return attrDefaults; +} + +inline void DOMAttrMapImpl::hasDefaults(bool value) +{ + attrDefaults = value; +} + +XERCES_CPP_NAMESPACE_END + + +#endif diff --git a/include/xercesc/dom/impl/DOMAttrNSImpl.cpp b/include/xercesc/dom/impl/DOMAttrNSImpl.cpp new file mode 100644 index 0000000..4402d0d --- /dev/null +++ b/include/xercesc/dom/impl/DOMAttrNSImpl.cpp @@ -0,0 +1,247 @@ +/* + * 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: DOMAttrNSImpl.cpp 901107 2010-01-20 08:45:02Z borisk $ + */ + +#include +#include "DOMAttrNSImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include +#include +#include + +#include "assert.h" + +XERCES_CPP_NAMESPACE_BEGIN + +DOMAttrNSImpl::DOMAttrNSImpl(DOMDocument *ownerDoc, const XMLCh *nam) : +DOMAttrImpl(ownerDoc, nam) +{ + this->fNamespaceURI=0; //DOM Level 2 + this->fLocalName=0; //DOM Level 2 + this->fPrefix=0; +} + +//Introduced in DOM Level 2 +DOMAttrNSImpl::DOMAttrNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *qualifiedName) : +DOMAttrImpl(ownerDoc, qualifiedName) +{ + setName(namespaceURI, qualifiedName); +} + +DOMAttrNSImpl:: +DOMAttrNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *prefix, + const XMLCh *localName, + const XMLCh *qualifiedName) + : DOMAttrImpl(ownerDoc, qualifiedName) +{ + DOMDocumentImpl* docImpl = (DOMDocumentImpl*)fParent.fOwnerDocument; + + if (prefix == 0 || *prefix == 0) + { + fPrefix = 0; + fLocalName = fName; + } + else + { + fPrefix = docImpl->getPooledString(prefix); + fLocalName = docImpl->getPooledString(localName); + } + + // DOM Level 3: namespace URI is never empty string. + // + const XMLCh * URI = DOMNodeImpl::mapPrefix + ( + fPrefix, + (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI, + DOMNode::ATTRIBUTE_NODE + ); + this -> fNamespaceURI = (URI == 0) ? 0 : docImpl->getPooledString(URI); +} + +DOMAttrNSImpl::DOMAttrNSImpl(const DOMAttrNSImpl &other, bool deep) : +DOMAttrImpl(other, deep) +{ + this->fNamespaceURI = other.fNamespaceURI; //DOM Level 2 + this->fLocalName = other.fLocalName; //DOM Level 2 + this->fPrefix = other.fPrefix; +} + +DOMNode * DOMAttrNSImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ATTR_NS_OBJECT) DOMAttrNSImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + +const XMLCh * DOMAttrNSImpl::getNamespaceURI() const +{ + return fNamespaceURI; +} + +const XMLCh * DOMAttrNSImpl::getPrefix() const +{ + return fPrefix; +} + +const XMLCh * DOMAttrNSImpl::getLocalName() const +{ + return fLocalName; +} + +void DOMAttrNSImpl::setPrefix(const XMLCh *prefix) +{ + const XMLCh * xmlns = DOMNodeImpl::getXmlnsString(); + + if (fNode.isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + if (fNamespaceURI == 0 || fNamespaceURI[0] == chNull || XMLString::equals(fLocalName, xmlns)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + if (prefix == 0 || prefix[0] == chNull) { + fName = fLocalName; + fPrefix = 0; + return; + } + + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + + if (!doc->isXMLName(prefix)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, GetDOMNodeMemoryManager); + + const XMLCh * xml = DOMNodeImpl::getXmlString(); + const XMLCh * xmlURI = DOMNodeImpl::getXmlURIString(); + const XMLCh * xmlnsURI = DOMNodeImpl::getXmlnsURIString(); + + if ((XMLString::equals(prefix, xml) && + !XMLString::equals(fNamespaceURI, xmlURI)) + || (XMLString::equals(prefix, xmlns) && + !XMLString::equals(fNamespaceURI, xmlnsURI))) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + if (XMLString::indexOf(prefix, chColon) != -1) { + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + } + + this-> fPrefix = doc->getPooledString(prefix); + + XMLSize_t prefixLen = XMLString::stringLen(prefix); + XMLSize_t newQualifiedNameLen = prefixLen+1+XMLString::stringLen(fLocalName); + XMLCh* newName; + XMLCh temp[256]; + if (newQualifiedNameLen >= 255) + newName = (XMLCh*) doc->getMemoryManager()->allocate + ( + newQualifiedNameLen * sizeof(XMLCh) + );//new XMLCh[newQualifiedNameLen]; + else + newName = temp; + + // newName = prefix + chColon + fLocalName; + XMLString::copyString(newName, prefix); + newName[prefixLen] = chColon; + XMLString::copyString(&newName[prefixLen+1], fLocalName); + + fName = doc->getPooledString(newName); + + if (newQualifiedNameLen >= 255) + doc->getMemoryManager()->deallocate(newName);//delete[] newName; + +} + +void DOMAttrNSImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fParent.release(); + doc->release(this, DOMMemoryManager::ATTR_NS_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + + +DOMNode* DOMAttrNSImpl::rename(const XMLCh* namespaceURI, const XMLCh* name) +{ + DOMElement* el = getOwnerElement(); + if (el) + el->removeAttributeNode(this); + + setName(namespaceURI, name); + + if (el) + el->setAttributeNodeNS(this); + + return this; +} + +void DOMAttrNSImpl::setName(const XMLCh* namespaceURI, const XMLCh* qualifiedName) +{ + DOMDocumentImpl* ownerDoc = (DOMDocumentImpl *)fParent.fOwnerDocument; + const XMLCh * xmlns = DOMNodeImpl::getXmlnsString(); + const XMLCh * xmlnsURI = DOMNodeImpl::getXmlnsURIString(); + this->fName = ownerDoc->getPooledString(qualifiedName); + + int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); + if (index < 0) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + bool xmlnsAlone = false; //true if attribute name is "xmlns" + if (index == 0) + { //qualifiedName contains no ':' + if (XMLString::equals(this->fName, xmlns)) { + if (!XMLString::equals(namespaceURI, xmlnsURI)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + xmlnsAlone = true; + } + fPrefix = 0; + fLocalName = fName; + } + else + { + fPrefix = ownerDoc->getPooledNString(fName, index); + fLocalName = ownerDoc->getPooledString(fName+index+1); + + // Before we carry on, we should check if the prefix or localName are valid XMLName + if (!ownerDoc->isXMLName(fPrefix) || !ownerDoc->isXMLName(fLocalName)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + } + + // DOM Level 3: namespace URI is never empty string. + const XMLCh * URI = xmlnsAlone ? xmlnsURI + : DOMNodeImpl::mapPrefix + ( + fPrefix, + (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI, + DOMNode::ATTRIBUTE_NODE + ); + this -> fNamespaceURI = (URI == 0) ? 0 : ownerDoc->getPooledString(URI); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMAttrNSImpl.hpp b/include/xercesc/dom/impl/DOMAttrNSImpl.hpp new file mode 100644 index 0000000..64470e6 --- /dev/null +++ b/include/xercesc/dom/impl/DOMAttrNSImpl.hpp @@ -0,0 +1,85 @@ +/* + * 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: DOMAttrNSImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMATTRNSIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMATTRNSIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include "DOMAttrImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMAttrNSImpl: public DOMAttrImpl { +protected: + //Introduced in DOM Level 2 + const XMLCh * fNamespaceURI; //namespace URI of this node + const XMLCh * fLocalName; //local part of qualified name + const XMLCh * fPrefix; // prefix part of qualified name + // revisit - can return local part + // by pointing into the qualified (L1) name. + +public: + DOMAttrNSImpl(DOMDocument *ownerDoc, const XMLCh *name); + DOMAttrNSImpl(DOMDocument *ownerDoc, //DOM Level 2 + const XMLCh *namespaceURI, const XMLCh *qualifiedName); + DOMAttrNSImpl(const DOMAttrNSImpl &other, bool deep=false); + + // Fast construction without any checks for name validity. Used in + // parsing. Note that if prefix is not specified and localName is + // 'xmlns', this constructor expects proper namespaceURI. + // + DOMAttrNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *prefix, // Null or empty - no prefix. + const XMLCh *localName, + const XMLCh *qualifiedName); + + virtual DOMNode * cloneNode(bool deep) const; + //Introduced in DOM Level 2 + virtual const XMLCh * getNamespaceURI() const; + virtual const XMLCh * getPrefix() const; + virtual const XMLCh * getLocalName() const; + virtual void setPrefix(const XMLCh *prefix); + virtual void release(); + + // helper function for DOM Level 3 renameNode + virtual DOMNode* rename(const XMLCh* namespaceURI, const XMLCh* name); + void setName(const XMLCh* namespaceURI, const XMLCh* name); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMAttrNSImpl & operator = (const DOMAttrNSImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMCDATASectionImpl.cpp b/include/xercesc/dom/impl/DOMCDATASectionImpl.cpp new file mode 100644 index 0000000..42c2e3a --- /dev/null +++ b/include/xercesc/dom/impl/DOMCDATASectionImpl.cpp @@ -0,0 +1,321 @@ +/* + * 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: DOMCDATASectionImpl.cpp 1027995 2010-10-27 15:09:39Z amassari $ + */ + +#include "DOMCDATASectionImpl.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMRangeImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" +#include "DOMStringPool.hpp" +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMCDATASectionImpl::DOMCDATASectionImpl(DOMDocument *ownerDoc, + const XMLCh *dat) + : fNode(ownerDoc), fCharacterData(ownerDoc, dat) +{ + fNode.setIsLeafNode(true); +} + +DOMCDATASectionImpl:: +DOMCDATASectionImpl(DOMDocument *ownerDoc, const XMLCh* data, XMLSize_t n) + : fNode(ownerDoc), fCharacterData(ownerDoc, data, n) +{ + fNode.setIsLeafNode(true); +} + +DOMCDATASectionImpl::DOMCDATASectionImpl(const DOMCDATASectionImpl &other, bool /*deep*/) + : DOMCDATASection(other), + fNode(*castToNodeImpl(&other)), + fChild(*castToChildImpl(&other)), + fCharacterData(other.fCharacterData) +{ + // revisit. Something nees to make "deep" work. +} + + +DOMCDATASectionImpl::~DOMCDATASectionImpl() +{ +} + + +DOMNode *DOMCDATASectionImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (this->getOwnerDocument(), DOMMemoryManager::CDATA_SECTION_OBJECT) DOMCDATASectionImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMCDATASectionImpl::getNodeName() const { + static const XMLCh gcdata_section[] = {chPound, chLatin_c, chLatin_d, chLatin_a, chLatin_t, chLatin_a, + chDash, chLatin_s, chLatin_e, chLatin_c, chLatin_t, chLatin_i, chLatin_o, chLatin_n, 0}; + return gcdata_section; +} + + +DOMNode::NodeType DOMCDATASectionImpl::getNodeType() const { + return DOMNode::CDATA_SECTION_NODE; +} + + +bool DOMCDATASectionImpl::isIgnorableWhitespace() const +{ + return fNode.ignorableWhitespace(); +} + + +// +// splitText. revist - factor into a common function for use +// here and in DOMTextImpl +// +DOMText *DOMCDATASectionImpl::splitText(XMLSize_t offset) +{ + if (fNode.isReadOnly()) + { + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + XMLSize_t len = fCharacterData.fDataBuf->getLen(); + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager); + + DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument(); + DOMText *newText = + doc->createCDATASection(this->substringData(offset, len - offset)); + + DOMNode *parent = getParentNode(); + if (parent != 0) + parent->insertBefore(newText, getNextSibling()); + + fCharacterData.fDataBuf->chop(offset); + + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateSplitInfo( this, newText, offset); + } + } + } + } + + return newText; +} + + +bool DOMCDATASectionImpl::getIsElementContentWhitespace() const +{ + return isIgnorableWhitespace(); +} + +const XMLCh* DOMCDATASectionImpl::getWholeText() const +{ + DOMDocument *doc = getOwnerDocument(); + if (!doc) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager); + return 0; + } + DOMNode* root=doc->getDocumentElement(); + DOMTreeWalker* pWalker=doc->createTreeWalker(root!=NULL?root:(DOMNode*)this, DOMNodeFilter::SHOW_ALL, NULL, true); + pWalker->setCurrentNode((DOMNode*)this); + // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in + // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes. + DOMNode* prevNode; + while((prevNode=pWalker->previousNode())!=NULL) + { + if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + } + XMLBuffer buff(1023, GetDOMNodeMemoryManager); + DOMNode* nextNode; + while((nextNode=pWalker->nextNode())!=NULL) + { + if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + if(nextNode->getNodeType()==TEXT_NODE || nextNode->getNodeType()==CDATA_SECTION_NODE) + buff.append(nextNode->getNodeValue()); + } + pWalker->release(); + + XMLCh* wholeString = (XMLCh*)((DOMDocumentImpl*)doc)->allocate((buff.getLen()+1) * sizeof(XMLCh)); + XMLString::copyString(wholeString, buff.getRawBuffer()); + return wholeString; +} + +DOMText* DOMCDATASectionImpl::replaceWholeText(const XMLCh* newText) +{ + DOMDocument *doc = getOwnerDocument(); + DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true); + pWalker->setCurrentNode((DOMNode*)this); + // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in + // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes. + DOMNode* pFirstTextNode=this; + DOMNode* prevNode; + while((prevNode=pWalker->previousNode())!=NULL) + { + if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + pFirstTextNode=prevNode; + } + // before doing any change we need to check if we are going to remove an entity reference that doesn't contain just text + DOMNode* pCurrentNode=pWalker->getCurrentNode(); + DOMNode* nextNode; + while((nextNode=pWalker->nextNode())!=NULL) + { + if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + if(nextNode->getNodeType()==ENTITY_REFERENCE_NODE) + { + DOMTreeWalker* pInnerWalker=doc->createTreeWalker(nextNode, DOMNodeFilter::SHOW_ALL, NULL, true); + while(pInnerWalker->nextNode()) + { + short nodeType=pInnerWalker->getCurrentNode()->getNodeType(); + if(nodeType!=ENTITY_REFERENCE_NODE && nodeType!=TEXT_NODE && nodeType!=CDATA_SECTION_NODE) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + pInnerWalker->release(); + } + } + DOMText* retVal=NULL; + // if the first node in the chain is a text node, replace its content, otherwise create a new node + if(newText && *newText) + { + if(!castToNodeImpl(pFirstTextNode)->isReadOnly() && (pFirstTextNode->getNodeType()==TEXT_NODE || pFirstTextNode->getNodeType()==CDATA_SECTION_NODE)) + { + pFirstTextNode->setNodeValue(newText); + retVal=(DOMText*)pFirstTextNode; + } + else + { + if(getNodeType()==TEXT_NODE) + retVal=doc->createTextNode(newText); + else + retVal=doc->createCDATASection(newText); + pFirstTextNode->getParentNode()->insertBefore(retVal, pFirstTextNode); + } + } + // now delete all the following text nodes + pWalker->setCurrentNode(pCurrentNode); + while((nextNode=pWalker->nextNode())!=NULL) + { + if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + if(nextNode!=retVal) + { + // keep the tree walker valid + pWalker->previousNode(); + nextNode->getParentNode()->removeChild(nextNode); + nextNode->release(); + } + } + pWalker->release(); + return retVal; +} + + +void DOMCDATASectionImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); + + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fCharacterData.releaseBuffer(); + doc->release(this, DOMMemoryManager::CDATA_SECTION_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + + +// +// Delegation stubs for other DOM_Node inherited functions. +// + DOMNode* DOMCDATASectionImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); } + DOMNamedNodeMap* DOMCDATASectionImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMCDATASectionImpl::getChildNodes() const {return fNode.getChildNodes (); } + DOMNode* DOMCDATASectionImpl::getFirstChild() const {return fNode.getFirstChild (); } + DOMNode* DOMCDATASectionImpl::getLastChild() const {return fNode.getLastChild (); } + const XMLCh* DOMCDATASectionImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMCDATASectionImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMCDATASectionImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMCDATASectionImpl::getNodeValue() const {return fCharacterData.getNodeValue (); } + DOMDocument* DOMCDATASectionImpl::getOwnerDocument() const {return fNode.getOwnerDocument(); } + const XMLCh* DOMCDATASectionImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMCDATASectionImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMCDATASectionImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMCDATASectionImpl::hasChildNodes() const {return fNode.hasChildNodes (); } + DOMNode* DOMCDATASectionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fNode.insertBefore (newChild, refChild); } + void DOMCDATASectionImpl::normalize() {fNode.normalize (); } + DOMNode* DOMCDATASectionImpl::removeChild(DOMNode *oldChild) {return fNode.removeChild (oldChild); } + DOMNode* DOMCDATASectionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fNode.replaceChild (newChild, oldChild); } + bool DOMCDATASectionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMCDATASectionImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMCDATASectionImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMCDATASectionImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMCDATASectionImpl::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); } + void* DOMCDATASectionImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMCDATASectionImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + const XMLCh* DOMCDATASectionImpl::getBaseURI() const {return fNode.getBaseURI(); } + short DOMCDATASectionImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMCDATASectionImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMCDATASectionImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMCDATASectionImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMCDATASectionImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMCDATASectionImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMCDATASectionImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + + + +// +// Delegation of CharacerData functions. +// + + + const XMLCh* DOMCDATASectionImpl::getData() const {return fCharacterData.getData();} + XMLSize_t DOMCDATASectionImpl::getLength() const {return fCharacterData.getLength();} + const XMLCh* DOMCDATASectionImpl::substringData(XMLSize_t offset, XMLSize_t count) const + {return fCharacterData.substringData(this, offset, count);} + void DOMCDATASectionImpl::appendData(const XMLCh *arg) {fCharacterData.appendData(this, arg);} + void DOMCDATASectionImpl::insertData(XMLSize_t offset, const XMLCh *arg) + {fCharacterData.insertData(this, offset, arg);} + void DOMCDATASectionImpl::deleteData(XMLSize_t offset, XMLSize_t count) + {fCharacterData.deleteData(this, offset, count);} + void DOMCDATASectionImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg) + {fCharacterData.replaceData(this, offset, count, arg);} + void DOMCDATASectionImpl::setData(const XMLCh *data) {fCharacterData.setData(this, data);} + void DOMCDATASectionImpl::setNodeValue(const XMLCh *nodeValue) {fCharacterData.setNodeValue (this, nodeValue); } + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMCDATASectionImpl.hpp b/include/xercesc/dom/impl/DOMCDATASectionImpl.hpp new file mode 100644 index 0000000..b8711ae --- /dev/null +++ b/include/xercesc/dom/impl/DOMCDATASectionImpl.hpp @@ -0,0 +1,98 @@ +/* + * 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: DOMCDATASectionImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCDATASECTIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCDATASECTIONIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include +#include +#include "DOMNodeImpl.hpp" +#include "DOMChildNode.hpp" +#include "DOMParentNode.hpp" +#include "DOMCharacterDataImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMCDATASectionImpl: public DOMCDATASection { +protected: + DOMNodeImpl fNode; + DOMChildNode fChild; + DOMCharacterDataImpl fCharacterData; + + +public: + DOMCDATASectionImpl(DOMDocument *ownerDoc, const XMLCh* data); + DOMCDATASectionImpl(DOMDocument *ownerDoc, const XMLCh* data, XMLSize_t n); + DOMCDATASectionImpl(const DOMCDATASectionImpl &other, bool deep = false); + + virtual ~DOMCDATASectionImpl(); + + // Functions inherited from TEXT + virtual DOMText* splitText(XMLSize_t offset); + // DOM Level 3 + virtual bool getIsElementContentWhitespace() const; + virtual const XMLCh* getWholeText() const; + virtual DOMText* replaceWholeText(const XMLCh* content); + + // non-standard extension + virtual bool isIgnorableWhitespace() const; + + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + // Functions introduced by DOMCharacterData + virtual const XMLCh* getData() const; + virtual XMLSize_t getLength() const; + virtual const XMLCh* substringData(XMLSize_t offset, + XMLSize_t count) const; + virtual void appendData(const XMLCh *arg); + virtual void insertData(XMLSize_t offset, const XMLCh *arg); + virtual void deleteData(XMLSize_t offset, + XMLSize_t count); + virtual void replaceData(XMLSize_t offset, + XMLSize_t count, + const XMLCh *arg); + virtual void setData(const XMLCh *data); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMCDATASectionImpl & operator = (const DOMCDATASectionImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMCasts.hpp b/include/xercesc/dom/impl/DOMCasts.hpp new file mode 100644 index 0000000..6350278 --- /dev/null +++ b/include/xercesc/dom/impl/DOMCasts.hpp @@ -0,0 +1,146 @@ +/* + * 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: DOMCasts.hpp 673975 2008-07-04 09:23:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCASTS_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCASTS_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +// +// Define inline casting functions to convert from +// (DOMNode *) to DOMParentNode or DOMChildNode *. +// +// This requires knowledge of the structure of the fields of +// for all node types. There are three categories - +// +// Nodetypes that can have children and can be a child themselves. +// e.g. Elements +// +// Object +// DOMNodeImpl fNode; +// DOMParentNode fParent; +// DOMChildNode fChild; +// ... // other fields, depending on node type. +// +// Nodetypes that can not have children, e.g. TEXT +// +// Object +// DOMNodeImpl fNode; +// DOMChildNode fChild; +// ... // other fields, depending on node type +// +// Nodetypes that can not be a child of other nodes, but that can +// have children (are a parent) e.g. ATTR +// Object +// DOMNodeImpl fNode; +// DOMParentNode fParent +// ... // other fields, depending on node type +// +// The casting functions make these assumptions: +// 1. The cast is possible. Using code will not attempt to +// cast to something that does not exist, such as the child +// part of an ATTR +// +// 2. The nodes belong to this implementation. +// +// Some of the casts use the LEAFNODE flag in the common fNode part to +// determine whether an fParent field exists, and thus the +// position of the fChild part within the node. +// +// These functions also cast off const. It was either do that, or make +// a second overloaded set that took and returned const arguements. +// + +// +// Note that using offsetof, or taking the offset of an object member at +// a 0 address, is now undefined in C++. And gcc now warns about this behavior. +// This is because doing do so is unreliable for some types of objects. +// See: http://gcc.gnu.org/ml/gcc/2004-06/msg00227.html +// : http://gcc.gnu.org/ml/gcc-bugs/2000-03/msg00805.html +// The casting code below works around gcc's warnings by using a dummy +// pointer, which the compiler cannot tell is null. The defeats the warning, +// but also masks the potential problem. +// The gcc option -Wno-invalid-offsetof may also be used to turn off this warning. +// + +#include "DOMElementImpl.hpp" +#include "DOMTextImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +static inline DOMNodeImpl *castToNodeImpl(const DOMNode *p) +{ + DOMElementImpl *pE = (DOMElementImpl *)p; + return &(pE->fNode); +} + + +static inline DOMParentNode *castToParentImpl(const DOMNode *p) { + DOMElementImpl *pE = (DOMElementImpl *)p; + return &(pE->fParent); +} + + +static inline DOMChildNode *castToChildImpl(const DOMNode *p) { + DOMElementImpl *pE = (DOMElementImpl *)p; + if (pE->fNode.isLeafNode()) { + DOMTextImpl *pT = (DOMTextImpl *)p; + return &(pT->fChild); + } + return &(pE->fChild); +} + + +static inline DOMNode *castToNode(const DOMParentNode *p ) { + DOMElementImpl* dummy = 0; + XMLSize_t parentOffset = (char *)&(dummy->fParent) - (char *)dummy; + char *retPtr = (char *)p - parentOffset; + return (DOMNode *)retPtr; +} + +static inline DOMNode *castToNode(const DOMNodeImpl *p) { + DOMElementImpl* dummy = 0; + XMLSize_t nodeImplOffset = (char *)&(dummy->fNode) - (char *)dummy; + char *retPtr = (char *)p - nodeImplOffset; + return (DOMNode *)retPtr; +} + + +static inline DOMNodeImpl *castToNodeImpl(const DOMParentNode *p) +{ + DOMElementImpl* dummy = 0; + XMLSize_t nodeImplOffset = (char *)&(dummy->fNode) - (char *)dummy; + XMLSize_t parentOffset = (char *)&(dummy->fParent) - (char *)dummy; + char *retPtr = (char *)p - parentOffset + nodeImplOffset; + return (DOMNodeImpl *)retPtr; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMCharacterDataImpl.cpp b/include/xercesc/dom/impl/DOMCharacterDataImpl.cpp new file mode 100644 index 0000000..bf093ca --- /dev/null +++ b/include/xercesc/dom/impl/DOMCharacterDataImpl.cpp @@ -0,0 +1,318 @@ +/* + * 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: DOMCharacterDataImpl.cpp 678766 2008-07-22 14:00:16Z borisk $ + */ + +#include "DOMCharacterDataImpl.hpp" +#include +#include +#include "DOMRangeImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" +#include "DOMStringPool.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMCharacterDataImpl::DOMCharacterDataImpl(DOMDocument *doc, const XMLCh *dat) +{ + fDoc = (DOMDocumentImpl*)doc; + + XMLSize_t len=XMLString::stringLen(dat); + fDataBuf = fDoc->popBuffer(len+1); + if (!fDataBuf) + fDataBuf = new (fDoc) DOMBuffer(fDoc, len+15); + fDataBuf->set(dat, len); +} + +DOMCharacterDataImpl:: +DOMCharacterDataImpl(DOMDocument *doc, const XMLCh* dat, XMLSize_t len) +{ + fDoc = (DOMDocumentImpl*)doc; + + fDataBuf = fDoc->popBuffer(len+1); + + if (!fDataBuf) + fDataBuf = new (fDoc) DOMBuffer(fDoc, len+15); + + fDataBuf->set(dat, len); +} + +DOMCharacterDataImpl::DOMCharacterDataImpl(const DOMCharacterDataImpl &other) +{ + fDoc = (DOMDocumentImpl*)other.fDoc; + + XMLSize_t len=other.getLength(); + fDataBuf = fDoc->popBuffer(len+1); + if (!fDataBuf) + fDataBuf = new (fDoc) DOMBuffer(fDoc, len+15); + fDataBuf->set(other.fDataBuf->getRawBuffer(), len); +} + + +DOMCharacterDataImpl::~DOMCharacterDataImpl() { +} + + +const XMLCh * DOMCharacterDataImpl::getNodeValue() const +{ + return fDataBuf->getRawBuffer(); +} + + +void DOMCharacterDataImpl::setNodeValue(const DOMNode *node, const XMLCh *value) +{ + if (castToNodeImpl(node)->isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMCharacterDataImplMemoryManager); + fDataBuf->set(value); + + DOMDocumentImpl *doc = (DOMDocumentImpl *)node->getOwnerDocument(); + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->receiveReplacedText((DOMNode*)node); + } + } + } + } +} + + +void DOMCharacterDataImpl::appendData(const DOMNode *node, const XMLCh *dat) +{ + if(castToNodeImpl(node)->isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + fDataBuf->append(dat); +} + +void DOMCharacterDataImpl::appendData(const DOMNode *node, const XMLCh *dat, XMLSize_t n) +{ + if(castToNodeImpl(node)->isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + fDataBuf->append(dat, n); +} + +void DOMCharacterDataImpl::deleteData(const DOMNode *node, XMLSize_t offset, XMLSize_t count) +{ + if (castToNodeImpl(node)->isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + // Note: the C++ XMLCh * operation throws the correct DOMExceptions + // when parameter values are bad. + // + + XMLSize_t len = this->fDataBuf->getLen(); + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + + + // Cap the value of delLength to avoid trouble with overflows + // in the following length computations. + if (count > len) + count = len; + + // If the length of data to be deleted would extend off the end + // of the string, cut it back to stop at the end of string. + if (offset + count >= len) + count = len - offset; + + XMLSize_t newLen = len - count; + + XMLCh* newString; + XMLCh temp[4096]; + if (newLen >= 4095) + newString = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate + ( + (newLen+1) * sizeof(XMLCh) + );//new XMLCh[newLen+1]; + else + newString = temp; + + XMLString::copyNString(newString, fDataBuf->getRawBuffer(), offset); + XMLString::copyString(newString+offset, fDataBuf->getRawBuffer()+offset+count); + + fDataBuf->set(newString); + + if (newLen >= 4095) + XMLPlatformUtils::fgMemoryManager->deallocate(newString);//delete[] newString; + + // We don't delete the old string (doesn't work), or alter + // the old string (may be shared) + // It just hangs around, possibly orphaned. + + DOMDocumentImpl *doc = (DOMDocumentImpl *)node->getOwnerDocument(); + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateRangeForDeletedText( (DOMNode*)node, offset, count); + } + } + } + } +} + + + +const XMLCh *DOMCharacterDataImpl::getData() const +{ + return fDataBuf->getRawBuffer(); +} + + +// +// getCharDataLength - return the length of the character data string. +// +XMLSize_t DOMCharacterDataImpl::getLength() const +{ + return fDataBuf->getLen(); +} + + + +void DOMCharacterDataImpl::insertData(const DOMNode *node, XMLSize_t offset, const XMLCh *dat) +{ + if (castToNodeImpl(node)->isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + // Note: the C++ XMLCh * operation throws the correct DOMExceptions + // when parameter values are bad. + // + + XMLSize_t len = fDataBuf->getLen(); + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + XMLSize_t datLen = XMLString::stringLen(dat); + + XMLSize_t newLen = len + datLen; + + XMLCh* newString; + XMLCh temp[4096]; + if (newLen >= 4095) + newString = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate + ( + (newLen + 1) * sizeof(XMLCh) + );//new XMLCh[newLen+1]; + else + newString = temp; + + XMLString::copyNString(newString, fDataBuf->getRawBuffer(), offset); + XMLString::copyNString(newString+offset, dat, datLen); + XMLString::copyString(newString+offset+datLen, fDataBuf->getRawBuffer()+offset); + + fDataBuf->set(newString); + + if (newLen >= 4095) + XMLPlatformUtils::fgMemoryManager->deallocate(newString);//delete[] newString; + + DOMDocumentImpl *doc = (DOMDocumentImpl *)node->getOwnerDocument(); + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateRangeForInsertedText( (DOMNode*)node, offset, datLen); + } + } + } + } +} + + + +void DOMCharacterDataImpl::replaceData(const DOMNode *node, XMLSize_t offset, XMLSize_t count, + const XMLCh *dat) +{ + if (castToNodeImpl(node)->isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + deleteData(node, offset, count); + insertData(node, offset, dat); +} + + + + +void DOMCharacterDataImpl::setData(const DOMNode *node, const XMLCh *arg) +{ + setNodeValue(node, arg); +} + + + + + +const XMLCh * DOMCharacterDataImpl::substringData(const DOMNode *node, XMLSize_t offset, + XMLSize_t count) const +{ + + // Note: the C++ XMLCh * operation throws the correct DOMExceptions + // when parameter values are bad. + // + + + XMLSize_t len = fDataBuf->getLen(); + + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMCharacterDataImplMemoryManager); + + DOMDocumentImpl *doc = (DOMDocumentImpl *)node->getOwnerDocument(); + + XMLCh* newString; + XMLCh temp[4096]; + if (len >= 4095) + newString = (XMLCh*) doc->getMemoryManager()->allocate + ( + (len + 1) * sizeof(XMLCh) + );//new XMLCh[len+1]; + else + newString = temp; + + XMLString::copyNString(newString, fDataBuf->getRawBuffer()+offset, count); + newString[count] = chNull; + + const XMLCh* retString = doc->getPooledString(newString); + + if (len >= 4095) + doc->getMemoryManager()->deallocate(newString);//delete[] newString; + + return retString; + +} + + +void DOMCharacterDataImpl::releaseBuffer() { + fDoc->releaseBuffer(fDataBuf); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMCharacterDataImpl.hpp b/include/xercesc/dom/impl/DOMCharacterDataImpl.hpp new file mode 100644 index 0000000..64bdf5e --- /dev/null +++ b/include/xercesc/dom/impl/DOMCharacterDataImpl.hpp @@ -0,0 +1,89 @@ +/* + * 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: DOMCharacterDataImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCHARACTERDATAIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCHARACTERDATAIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; +class DOMDocument; +class DOMDocumentImpl; +class DOMBuffer; + +// Instances of DOMCharacterDataImpl appear as members of node types +// that implement the DOMCharacterData interfaces. +// Operations in those classes are delegated to this class. +// +class CDOM_EXPORT DOMCharacterDataImpl +{ +public: + DOMBuffer* fDataBuf; + // for the buffer bid + DOMDocumentImpl* fDoc; + +public: + DOMCharacterDataImpl(DOMDocument *doc, const XMLCh *dat); + DOMCharacterDataImpl(DOMDocument *doc, const XMLCh* data, XMLSize_t n); + DOMCharacterDataImpl(const DOMCharacterDataImpl &other); + ~DOMCharacterDataImpl(); + const XMLCh * getNodeValue() const; + void setNodeValue(const XMLCh * value); + void appendData(const DOMNode *node, const XMLCh *data); + void appendData(const DOMNode *node, const XMLCh *data, XMLSize_t n); + void deleteData(const DOMNode *node, XMLSize_t offset, XMLSize_t count); + const XMLCh* getData() const; + XMLSize_t getLength() const; + void insertData(const DOMNode *node, XMLSize_t offset, const XMLCh * data); + void replaceData(const DOMNode *node, XMLSize_t offset, XMLSize_t count, const XMLCh * data); + void setData(const DOMNode *node, const XMLCh * arg); + void setNodeValue(const DOMNode *node, const XMLCh *value); + + + const XMLCh* substringData(const DOMNode *node, XMLSize_t offset, XMLSize_t count) const; + void releaseBuffer(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMCharacterDataImpl & operator = (const DOMCharacterDataImpl &); +}; + +#define GetDOMCharacterDataImplMemoryManager GET_DIRECT_MM(fDoc) + +XERCES_CPP_NAMESPACE_END + + +#endif diff --git a/include/xercesc/dom/impl/DOMChildNode.cpp b/include/xercesc/dom/impl/DOMChildNode.cpp new file mode 100644 index 0000000..0ed42f6 --- /dev/null +++ b/include/xercesc/dom/impl/DOMChildNode.cpp @@ -0,0 +1,78 @@ +/* + * 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: DOMChildNode.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// This class only adds the ability to have siblings + +#include +#include "DOMNodeImpl.hpp" +#include "DOMChildNode.hpp" +#include "DOMCasts.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +DOMChildNode::DOMChildNode() +{ + this->previousSibling = 0; + this->nextSibling = 0; +} + +// This only makes a shallow copy, cloneChildren must also be called for a +// deep clone +DOMChildNode::DOMChildNode(const DOMChildNode &) +{ + // Need to break the association w/ original siblings and parent + this->previousSibling = 0; + this->nextSibling = 0; +} + +DOMChildNode::~DOMChildNode() { +} + + +DOMNode * DOMChildNode::getNextSibling() const { + return nextSibling; +} + +// +// Note: for getParentNode and getPreviousSibling(), below, an +// extra paramter "thisNode" is required. This is because there +// is no way to cast from a DOMChildNode pointer back to the +// DOMNodeImpl that it is part of. Our "this" may or may not +// be preceded by a fParent in the object layout, and there's no +// practical way to tell, so we just take an extra parameter instead. + +DOMNode * DOMChildNode::getParentNode(const DOMNode *thisNode) const +{ + // if we have an owner, ownerNode is our parent, otherwise it's + // our ownerDocument and we don't have a parent + DOMNodeImpl *thisNodeImpl = castToNodeImpl(thisNode); + return thisNodeImpl->isOwned() ? thisNodeImpl->fOwnerNode : 0; +} + +DOMNode * DOMChildNode::getPreviousSibling(const DOMNode *thisNode) const { + // if we are the firstChild, previousSibling actually refers to our + // parent's lastChild, but we hide that + return castToNodeImpl(thisNode)->isFirstChild() ? 0 : previousSibling; +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/dom/impl/DOMChildNode.hpp b/include/xercesc/dom/impl/DOMChildNode.hpp new file mode 100644 index 0000000..e7c1812 --- /dev/null +++ b/include/xercesc/dom/impl/DOMChildNode.hpp @@ -0,0 +1,72 @@ +/* + * 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: DOMChildNode.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCHILDNODE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCHILDNODE_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +/** + * ChildNode adds to NodeImpl the capability of being a child, this is having + * siblings. + **/ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMDocument; +class DOMNode; + + +class CDOM_EXPORT DOMChildNode { + +public: + DOMNode *previousSibling; + DOMNode *nextSibling; + + DOMChildNode(); + DOMChildNode(const DOMChildNode &other); + ~DOMChildNode(); + + DOMNode * getNextSibling() const; + DOMNode * getParentNode(const DOMNode *thisNode) const; + DOMNode * getPreviousSibling(const DOMNode *thisNode) const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMChildNode & operator = (const DOMChildNode &); +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMCommentImpl.cpp b/include/xercesc/dom/impl/DOMCommentImpl.cpp new file mode 100644 index 0000000..b8fa540 --- /dev/null +++ b/include/xercesc/dom/impl/DOMCommentImpl.cpp @@ -0,0 +1,189 @@ +/* + * 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: DOMCommentImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ + +#include "DOMCommentImpl.hpp" +#include "DOMCharacterDataImpl.hpp" +#include "DOMStringPool.hpp" +#include "DOMCasts.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMRangeImpl.hpp" +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMCommentImpl::DOMCommentImpl(DOMDocument *ownerDoc, const XMLCh *dat) + : fNode(ownerDoc), fCharacterData(ownerDoc, dat) +{ + fNode.setIsLeafNode(true); +} + + +DOMCommentImpl::DOMCommentImpl(const DOMCommentImpl &other, bool) + + : fNode(other.fNode), + fChild(other.fChild), + fCharacterData(other.fCharacterData) +{ + fNode.setIsLeafNode(true); +} + + +DOMCommentImpl::~DOMCommentImpl() { +} + + + +DOMNode * DOMCommentImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (getOwnerDocument(), DOMMemoryManager::COMMENT_OBJECT) DOMCommentImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMCommentImpl::getNodeName() const { + static const XMLCh gComment[] = + {chPound, chLatin_c, chLatin_o, chLatin_m, chLatin_m, chLatin_e,chLatin_n, chLatin_t, 0}; + return gComment; +} + +DOMNode::NodeType DOMCommentImpl::getNodeType() const { + return DOMNode::COMMENT_NODE; +} + +void DOMCommentImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fCharacterData.releaseBuffer(); + doc->release(this, DOMMemoryManager::COMMENT_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + + +// Non standard extension for the range to work +DOMComment *DOMCommentImpl::splitText(XMLSize_t offset) +{ + if (fNode.isReadOnly()) + { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + XMLSize_t len = fCharacterData.fDataBuf->getLen(); + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager); + + DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument(); + DOMComment *newText = + doc->createComment(this->substringData(offset, len - offset)); + + DOMNode *parent = getParentNode(); + if (parent != 0) + parent->insertBefore(newText, getNextSibling()); + + fCharacterData.fDataBuf->chop(offset); + + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateSplitInfo( this, newText, offset); + } + } + } + } + + return newText; +} + + + DOMNode* DOMCommentImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); } + DOMNamedNodeMap* DOMCommentImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMCommentImpl::getChildNodes() const {return fNode.getChildNodes (); } + DOMNode* DOMCommentImpl::getFirstChild() const {return fNode.getFirstChild (); } + DOMNode* DOMCommentImpl::getLastChild() const {return fNode.getLastChild (); } + const XMLCh* DOMCommentImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMCommentImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMCommentImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMCommentImpl::getNodeValue() const {return fCharacterData.getNodeValue (); } + DOMDocument* DOMCommentImpl::getOwnerDocument() const {return fNode.getOwnerDocument (); } + const XMLCh* DOMCommentImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMCommentImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMCommentImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMCommentImpl::hasChildNodes() const {return fNode.hasChildNodes (); } + DOMNode* DOMCommentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fNode.insertBefore (newChild, refChild); } + void DOMCommentImpl::normalize() {fNode.normalize (); } + DOMNode* DOMCommentImpl::removeChild(DOMNode *oldChild) {return fNode.removeChild (oldChild); } + DOMNode* DOMCommentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fNode.replaceChild (newChild, oldChild); } + bool DOMCommentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMCommentImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMCommentImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMCommentImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMCommentImpl::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); } + void* DOMCommentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMCommentImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + const XMLCh* DOMCommentImpl::getBaseURI() const {return fNode.getBaseURI(); } + short DOMCommentImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMCommentImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMCommentImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMCommentImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMCommentImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMCommentImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMCommentImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + + + +// +// Delegation of CharacerData functions. +// + + + const XMLCh* DOMCommentImpl::getData() const {return fCharacterData.getData();} + XMLSize_t DOMCommentImpl::getLength() const {return fCharacterData.getLength();} + const XMLCh* DOMCommentImpl::substringData(XMLSize_t offset, XMLSize_t count) const + {return fCharacterData.substringData(this, offset, count);} + void DOMCommentImpl::appendData(const XMLCh *arg) {fCharacterData.appendData(this, arg);} + void DOMCommentImpl::insertData(XMLSize_t offset, const XMLCh *arg) + {fCharacterData.insertData(this, offset, arg);} + void DOMCommentImpl::deleteData(XMLSize_t offset, XMLSize_t count) + {fCharacterData.deleteData(this, offset, count);} + void DOMCommentImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg) + {fCharacterData.replaceData(this, offset, count, arg);} + void DOMCommentImpl::setData(const XMLCh *data) {fCharacterData.setData(this, data);} + void DOMCommentImpl::setNodeValue(const XMLCh *nodeValue) {fCharacterData.setNodeValue (this, nodeValue); } + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMCommentImpl.hpp b/include/xercesc/dom/impl/DOMCommentImpl.hpp new file mode 100644 index 0000000..e3cc62c --- /dev/null +++ b/include/xercesc/dom/impl/DOMCommentImpl.hpp @@ -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: DOMCommentImpl.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCOMMENTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCOMMENTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include +#include + +#include "DOMNodeImpl.hpp" +#include "DOMChildNode.hpp" +#include "DOMCharacterDataImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMCommentImpl: public DOMComment { +public: + DOMNodeImpl fNode; + DOMChildNode fChild; + DOMCharacterDataImpl fCharacterData; + +public: + DOMCommentImpl(DOMDocument *, const XMLCh *); + DOMCommentImpl(const DOMCommentImpl &other, bool deep); + virtual ~DOMCommentImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + // Functions from DOMCharacterData + virtual void appendData(const XMLCh *data); + virtual void deleteData(XMLSize_t offset, XMLSize_t count); + virtual const XMLCh * getData() const; + virtual XMLSize_t getLength() const; + virtual void insertData(XMLSize_t offset, const XMLCh * data); + virtual void replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh * data); + virtual void setData(const XMLCh * arg); + virtual const XMLCh * substringData(XMLSize_t offset, XMLSize_t count) const; + + // Non standard extension for the range to work + DOMComment* splitText(XMLSize_t offset); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMCommentImpl & operator = (const DOMCommentImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/impl/DOMConfigurationImpl.cpp b/include/xercesc/dom/impl/DOMConfigurationImpl.cpp new file mode 100644 index 0000000..fa4fb87 --- /dev/null +++ b/include/xercesc/dom/impl/DOMConfigurationImpl.cpp @@ -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. + */ + +#include "DOMConfigurationImpl.hpp" +#include "DOMStringListImpl.hpp" +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +const unsigned short DOMConfigurationImpl::fDEFAULT_VALUES = 0x2596; + +DOMConfigurationImpl::DOMConfigurationImpl(MemoryManager* const manager): featureValues(fDEFAULT_VALUES), + fErrorHandler(0), fSchemaType(0), fSchemaLocation(0), + fSupportedParameters(0), fMemoryManager(manager) +{ + fSupportedParameters=new (fMemoryManager) DOMStringListImpl(17, fMemoryManager); + fSupportedParameters->add(XMLUni::fgDOMErrorHandler); + fSupportedParameters->add(XMLUni::fgDOMSchemaType); + fSupportedParameters->add(XMLUni::fgDOMSchemaLocation); + fSupportedParameters->add(XMLUni::fgDOMCanonicalForm); + fSupportedParameters->add(XMLUni::fgDOMCDATASections); + fSupportedParameters->add(XMLUni::fgDOMComments); + fSupportedParameters->add(XMLUni::fgDOMDatatypeNormalization); + fSupportedParameters->add(XMLUni::fgDOMWRTDiscardDefaultContent); + fSupportedParameters->add(XMLUni::fgDOMEntities); + fSupportedParameters->add(XMLUni::fgDOMInfoset); + fSupportedParameters->add(XMLUni::fgDOMNamespaces); + fSupportedParameters->add(XMLUni::fgDOMNamespaceDeclarations); + fSupportedParameters->add(XMLUni::fgDOMNormalizeCharacters); + fSupportedParameters->add(XMLUni::fgDOMSplitCDATASections); + fSupportedParameters->add(XMLUni::fgDOMValidate); + fSupportedParameters->add(XMLUni::fgDOMValidateIfSchema); + fSupportedParameters->add(XMLUni::fgDOMElementContentWhitespace); +} + +DOMConfigurationImpl::~DOMConfigurationImpl() { + delete fSupportedParameters; +} + +void DOMConfigurationImpl::setParameter(const XMLCh* name, const void* value) { + if(!canSetParameter(name, value)) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager); + } + + if(XMLString::compareIStringASCII(name, XMLUni::fgDOMErrorHandler)==0) { + fErrorHandler = (DOMErrorHandler*)value; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaType)==0) { + fSchemaType = (XMLCh*)value; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaLocation)==0) { + fSchemaLocation = (XMLCh*)value; + } else { // canSetParameter above should take care of this case + throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager); + } + +} + +void DOMConfigurationImpl::setParameter(const XMLCh* name, bool value) { + if(!canSetParameter(name, value)) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager); + } + + DOMConfigurationFeature whichFlag = getFeatureFlag(name); + if(value) { + featureValues |= whichFlag; + } else { + featureValues &= ~whichFlag; + } + +} + +// -------------------------------------- +// Getter Methods +// -------------------------------------- + +const void* DOMConfigurationImpl::getParameter(const XMLCh* name) const { + DOMConfigurationFeature whichFlag; + try { + whichFlag = getFeatureFlag(name); + if(featureValues & whichFlag) { + return (void*)true; + } else { + return (void*)false; + } + } catch (DOMException&) { + // must not be a boolean parameter + if(XMLString::compareIStringASCII(name, XMLUni::fgDOMErrorHandler)==0) { + return fErrorHandler; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaType)==0) { + return fSchemaType; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaLocation)==0) { + return fSchemaLocation; + } else { + throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager); + } + } + +} + +// ----------------------------------------- +// Query Methods +// ----------------------------------------- + +bool DOMConfigurationImpl::canSetParameter(const XMLCh* name, const void* /*value*/) const { + + /** + * canSetParameter(name, value) returns false in two conditions: + * 1) if a [required] feature has no supporting code, then return false in + * both the true and false outcomes (This is in order to be either fully + * spec compliant, or not at all) + * 2) if an [optional] feature has no supporting code, then return false + **/ + + if(XMLString::compareIStringASCII(name, XMLUni::fgDOMErrorHandler)==0) { + return true; // required // + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaType)==0) { + return false; // optional // + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaLocation)==0) { + return false; // optional // + } + return false; +} + +bool DOMConfigurationImpl::canSetParameter(const XMLCh* name, bool booleanValue) const { + /** + * canSetParameter(name, value) returns false in two conditions: + * 1) if a [required] feature has no supporting code, then return false in + * both the true and false outcomes (This is in order to be either fully + * spec compliant, or not at all) + * 2) if an [optional] feature has no supporting code, then return false + **/ + + DOMConfigurationFeature whichFlag = getFeatureFlag(name); + switch (whichFlag) { + case FEATURE_CANONICAL_FORM: + if(booleanValue) return false; // optional // + else return true; // required // + case FEATURE_CDATA_SECTIONS: + return true; + case FEATURE_COMMENTS: + return true; + case FEATURE_DATATYPE_NORMALIZATION: + if(booleanValue) return false; // required // + else return true; // required // + case FEATURE_DISCARD_DEFAULT_CONTENT: + if(booleanValue) return false; // required // + else return true; // required // + case FEATURE_ENTITIES: + if(booleanValue) return true; // required // + else return true; // required // + case FEATURE_INFOSET: + if(booleanValue) return false; // required // + else return true; // no effect// + case FEATURE_NAMESPACES: + return true; + case FEATURE_NAMESPACE_DECLARATIONS: + if(booleanValue) return true; // optional // + else return false; // required // + case FEATURE_NORMALIZE_CHARACTERS: + if(booleanValue) return false; // optional // + else return true; // required // + case FEATURE_SPLIT_CDATA_SECTIONS: + //we dont report an error in the false case so we cant claim we do it + if(booleanValue) return false; // required // + else return false; // required // + case FEATURE_VALIDATE: + if(booleanValue) return false; // optional // + else return true; // required // + case FEATURE_VALIDATE_IF_SCHEMA: + if(booleanValue) return false; // optional // + else return true; // required // + + case FEATURE_ELEMENT_CONTENT_WHITESPACE: + if(booleanValue) return true; // required // + else return false; // optional // + } + // should never be here + return false; +} + +const DOMStringList* DOMConfigurationImpl::getParameterNames() const +{ + return fSupportedParameters; +} + +// ------------------------------------------- +// Impl methods +// ------------------------------------------- + +DOMConfigurationImpl::DOMConfigurationFeature DOMConfigurationImpl::getFeatureFlag(const XMLCh* name) const { + if(XMLString::compareIStringASCII(name, XMLUni::fgDOMCanonicalForm)==0) { + return FEATURE_CANONICAL_FORM; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCDATASections )==0) { + return FEATURE_CDATA_SECTIONS; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMComments)==0) { + return FEATURE_COMMENTS; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMDatatypeNormalization)==0) { + return FEATURE_DATATYPE_NORMALIZATION; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMWRTDiscardDefaultContent)==0) { + return FEATURE_DISCARD_DEFAULT_CONTENT; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMEntities)==0) { + return FEATURE_ENTITIES; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMInfoset)==0) { + return FEATURE_INFOSET; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaces)==0) { + return FEATURE_NAMESPACES; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaceDeclarations)==0) { + return FEATURE_NAMESPACE_DECLARATIONS; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNormalizeCharacters)==0) { + return FEATURE_NORMALIZE_CHARACTERS; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSplitCDATASections)==0) { + return FEATURE_SPLIT_CDATA_SECTIONS; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMValidate)==0) { + return FEATURE_VALIDATE; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMValidateIfSchema)==0) { + return FEATURE_VALIDATE_IF_SCHEMA; + } else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMElementContentWhitespace)==0) { + return FEATURE_ELEMENT_CONTENT_WHITESPACE; + } else { + throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager); + } + +} + +DOMErrorHandler* DOMConfigurationImpl::getErrorHandler() const { + return fErrorHandler; +} + +const XMLCh* DOMConfigurationImpl::getSchemaType() const { + return fSchemaType; +} + +const XMLCh* DOMConfigurationImpl::getSchemaLocation() const { + return fSchemaLocation; +} + +void DOMConfigurationImpl::setErrorHandler(DOMErrorHandler *erHandler) { + fErrorHandler = erHandler; +} + +void DOMConfigurationImpl::setSchemaType(const XMLCh* st) { + fSchemaType = st; +} + +void DOMConfigurationImpl::setSchemaLocation(const XMLCh* sl) { + fSchemaLocation = sl; +} + + +XERCES_CPP_NAMESPACE_END + + +/** + * End of file DOMConfigurationImpl.cpp + */ diff --git a/include/xercesc/dom/impl/DOMConfigurationImpl.hpp b/include/xercesc/dom/impl/DOMConfigurationImpl.hpp new file mode 100644 index 0000000..91033a1 --- /dev/null +++ b/include/xercesc/dom/impl/DOMConfigurationImpl.hpp @@ -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. + */ + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#if !defined(XERCESC_INCLUDE_GUARD_DOMCONFIGURATIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMCONFIGURATIONIMPL_HPP + +//------------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------------ +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMDocumentImpl; +class DOMStringListImpl; + +class CDOM_EXPORT DOMConfigurationImpl : public DOMConfiguration +{ +private: + //unimplemented + DOMConfigurationImpl(const DOMConfiguration &); + DOMConfigurationImpl & operator = (const DOMConfiguration &); + + +public: + + //----------------------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------------------- + DOMConfigurationImpl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~DOMConfigurationImpl(); + + enum DOMConfigurationFeature { + FEATURE_CANONICAL_FORM = 0x0001, + FEATURE_CDATA_SECTIONS = 0x0002, + FEATURE_COMMENTS = 0x0004, + FEATURE_DATATYPE_NORMALIZATION = 0x0008, + FEATURE_DISCARD_DEFAULT_CONTENT = 0x0010, + FEATURE_ENTITIES = 0x0020, + FEATURE_INFOSET = 0x0040, + FEATURE_NAMESPACES = 0x0080, + FEATURE_NAMESPACE_DECLARATIONS = 0x0100, + FEATURE_NORMALIZE_CHARACTERS = 0x0200, + FEATURE_SPLIT_CDATA_SECTIONS = 0x0400, + FEATURE_VALIDATE = 0x0800, + FEATURE_VALIDATE_IF_SCHEMA = 0x1000, + FEATURE_ELEMENT_CONTENT_WHITESPACE = 0x2000 + }; + + unsigned short featureValues; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + virtual void setParameter(const XMLCh* name, const void* value); + virtual void setParameter(const XMLCh* name, bool value); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + virtual const void* getParameter(const XMLCh* name) const; + + + // ----------------------------------------------------------------------- + // Query methods + // ----------------------------------------------------------------------- + + virtual bool canSetParameter(const XMLCh* name, const void* value) const; + virtual bool canSetParameter(const XMLCh* name, bool value) const; + + virtual const DOMStringList* getParameterNames() const; + + // --------------------------------------------------------------------------- + // Impl specific methods + // --------------------------------------------------------------------------- + + /* specific get and set methods for non-boolean parameters + * */ + + DOMErrorHandler* getErrorHandler() const; + + const XMLCh* getSchemaType() const; + + const XMLCh* getSchemaLocation() const; + + void setErrorHandler(DOMErrorHandler *erHandler); + + void setSchemaType(const XMLCh* st); + + void setSchemaLocation(const XMLCh* sl); + + // The default values for the boolean parameters + // from CANONICAL_FORM to ELEMENT_CONTENT_WHITESPACE + // 10010110010110 = 0x2596 + static const unsigned short fDEFAULT_VALUES; + + +protected: + // implements a simple map between the name and its enum value + DOMConfigurationFeature getFeatureFlag(const XMLCh* name) const; + + // the error handler + DOMErrorHandler* fErrorHandler; + + // the schema type + const XMLCh* fSchemaType; + + // the schema location + const XMLCh* fSchemaLocation; + + // the list of supported parameters + DOMStringListImpl* fSupportedParameters; + + MemoryManager* fMemoryManager; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DOMConfigurationImpl.hpp + */ diff --git a/include/xercesc/dom/impl/DOMDeepNodeListImpl.cpp b/include/xercesc/dom/impl/DOMDeepNodeListImpl.cpp new file mode 100644 index 0000000..f48189f --- /dev/null +++ b/include/xercesc/dom/impl/DOMDeepNodeListImpl.cpp @@ -0,0 +1,219 @@ +/* + * 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: DOMDeepNodeListImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ + +#include "DOMDeepNodeListImpl.hpp" +#include "DOMElementImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" +#include "DOMNodeImpl.hpp" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +static const XMLCh kAstr[] = {chAsterisk, chNull}; + +DOMDeepNodeListImpl::DOMDeepNodeListImpl(const DOMNode *rootNode, + const XMLCh *tagName) + : fRootNode(rootNode) + , fChanges(0) + , fCurrentNode(0) + , fCurrentIndexPlus1(0) + , fNamespaceURI(0) + , fMatchAllURI(false) + , fMatchURIandTagname(false) +{ + fTagName = ((DOMDocumentImpl *)(castToNodeImpl(rootNode)->getOwnerDocument()))->getPooledString(tagName); + fMatchAll = XMLString::equals(fTagName, kAstr); +} + + +//DOM Level 2 +DOMDeepNodeListImpl::DOMDeepNodeListImpl(const DOMNode *rootNode, + const XMLCh *namespaceURI, + const XMLCh *localName) + : fRootNode(rootNode) + , fChanges(0) + , fCurrentNode(0) + , fCurrentIndexPlus1(0) + , fMatchAllURI(false) + , fMatchURIandTagname(true) +{ + DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(rootNode)->getOwnerDocument(); + + fTagName = doc->getPooledString(localName); + fMatchAll = XMLString::equals(fTagName, kAstr); + fMatchAllURI = XMLString::equals(namespaceURI, kAstr); + fNamespaceURI = doc->getPooledString(namespaceURI); +} + + +DOMDeepNodeListImpl::~DOMDeepNodeListImpl() +{ +} + +XMLSize_t DOMDeepNodeListImpl::getLength() const +{ + // Reset cache to beginning of list + item(0); + + // Preload all matching elements. (Stops when we run out of subtree!) + item(INT_MAX); + return fCurrentIndexPlus1; +} + + +DOMNode *DOMDeepNodeListImpl::item(XMLSize_t index) const +{ + return ((DOMDeepNodeListImpl*)this)->cacheItem(index); +} + +// Start from the first child and count forward, 0-based. index>length-1 +// should return 0. +// +// Attempts to do only work actually requested, cache work already +// done, and to flush that cache when the tree has changed. +// +// LIMITATION: ????? Unable to tell relevant tree-changes from +// irrelevant ones. Doing so in a really useful manner would seem +// to involve a tree-walk in its own right, or maintaining our data +// in a parallel tree. +DOMNode *DOMDeepNodeListImpl::cacheItem(XMLSize_t index) +{ + XMLSize_t currentIndexPlus1 = fCurrentIndexPlus1; + DOMNode *currentNode = fCurrentNode; + + if (castToParentImpl(fRootNode)->changes() != fChanges) + { + // Tree changed. Do it all from scratch! + currentIndexPlus1 = 0; + currentNode = (DOMNode *)fRootNode; + fChanges = castToParentImpl(fRootNode)->changes(); + } + else if (currentIndexPlus1 > index+1) + { + // Interested in something before cached node. Do it all from scratch! + currentIndexPlus1 = 0; + currentNode = (DOMNode *)fRootNode; + } + else if (index+1 == currentIndexPlus1) + { + // What luck! User is interested in cached node. + return currentNode; + } + + DOMNode *nextNode = 0; + +// revisit - ???? How efficient is this loop? ???? + + // Start at the place in the tree at which we're + // currently pointing and count off nodes until we + // reach the node of interest or the end of the tree. + while (currentIndexPlus1 < index+1 && currentNode != 0) + { + nextNode = nextMatchingElementAfter(currentNode); + if (nextNode == 0) + break; + currentNode = nextNode; + currentIndexPlus1++; + } + + fCurrentNode = currentNode; + fCurrentIndexPlus1 = currentIndexPlus1; + + // If we found a node at the requested index, make that the current node + if (nextNode != 0) + { + return currentNode; + } + + // If we didn't find a node at the requested index, return 0 + return 0; +} + + + +/* Iterative tree-walker. When you have a Parent link, there's often no +need to resort to recursion. NOTE THAT only Element nodes are matched +since we're specifically supporting getElementsByTagName(). +*/ +DOMNode *DOMDeepNodeListImpl::nextMatchingElementAfter(DOMNode *current) +{ + DOMNode *next; + while (current != 0) + { + // Look down to first child. + if (current->hasChildNodes()) + { + current = current->getFirstChild(); + } + // Look right to sibling (but not from root!) + else + { + if (current != fRootNode && 0 != (next = current->getNextSibling())) + { + current = next; + } + // Look up and right (but not past root!) + else + { + next = 0; + for (; + current != fRootNode; // Stop on return to starting point + current = current->getParentNode()) + { + next = current->getNextSibling(); + if (next != 0) + break; + } + current = next; + } + } + + // Have we found an Element with the right tagName? + // ("*" matches anything.) + if (current != 0 && current != fRootNode && + current->getNodeType() == DOMNode::ELEMENT_NODE) { + DOMElement *currElement = (DOMElement *)current; + + if (!fMatchURIandTagname) { //DOM Level 1 + if (fMatchAll || + XMLString::equals(currElement->getTagName(), fTagName)) + return current; + } else { //DOM Level 2 + if (!fMatchAllURI && + !XMLString::equals(current->getNamespaceURI(), fNamespaceURI)) + continue; + + if (fMatchAll || + XMLString::equals(current->getLocalName(), fTagName)) + return current; + } + } + + // Otherwise continue walking the tree + } + // Fell out of tree-walk; no more instances found + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMDeepNodeListImpl.hpp b/include/xercesc/dom/impl/DOMDeepNodeListImpl.hpp new file mode 100644 index 0000000..ea67066 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDeepNodeListImpl.hpp @@ -0,0 +1,80 @@ +/* + * 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: DOMDeepNodeListImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDEEPNODELISTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDEEPNODELISTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; + + +class CDOM_EXPORT DOMDeepNodeListImpl: public DOMNodeList { +protected: + const DOMNode* fRootNode; + const XMLCh* fTagName; + bool fMatchAll; + int fChanges; + DOMNode* fCurrentNode; + XMLSize_t fCurrentIndexPlus1; + + //DOM Level 2 + const XMLCh* fNamespaceURI; + bool fMatchAllURI; + bool fMatchURIandTagname; //match both namespaceURI and tagName + +public: + DOMDeepNodeListImpl(const DOMNode *rootNode, const XMLCh *tagName); + DOMDeepNodeListImpl(const DOMNode *rootNode, //DOM Level 2 + const XMLCh *namespaceURI, + const XMLCh *localName); + virtual ~DOMDeepNodeListImpl(); + virtual XMLSize_t getLength() const; + virtual DOMNode* item(XMLSize_t index) const; + DOMNode* cacheItem(XMLSize_t index); + +protected: + DOMNode* nextMatchingElementAfter(DOMNode *current); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMDeepNodeListImpl(const DOMDeepNodeListImpl &); + DOMDeepNodeListImpl & operator = (const DOMDeepNodeListImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMDeepNodeListPool.c b/include/xercesc/dom/impl/DOMDeepNodeListPool.c new file mode 100644 index 0000000..618c7c3 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDeepNodeListPool.c @@ -0,0 +1,428 @@ +/* + * 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: DOMDeepNodeListPool.c 883368 2009-11-23 15:28:19Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Include +// --------------------------------------------------------------------------- +#include +#if defined(XERCES_TMPLSINC) +#include +#endif + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + + +// --------------------------------------------------------------------------- +// DOMDeepNodeListPool: Constructors and Destructor +// --------------------------------------------------------------------------- +template +DOMDeepNodeListPool::DOMDeepNodeListPool( const XMLSize_t modulus + , const bool adoptElems + , const XMLSize_t initSize) : + fAdoptedElems(adoptElems) + , fBucketList(0) + , fHashModulus(modulus) + , fIdPtrs(0) + , fIdPtrsCount(initSize) + , fIdCounter(0) + , fMemoryManager(XMLPlatformUtils::fgMemoryManager) +{ + initialize(modulus); + + // + // Allocate the initial id pointers array. We don't have to zero them + // out since the fIdCounter value tells us which ones are valid. The + // zeroth element is never used (and represents an invalid pool id.) + // + if (!fIdPtrsCount) + fIdPtrsCount = 256; + + fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount]; + fIdPtrs[0] = 0; +} + +template +DOMDeepNodeListPool::DOMDeepNodeListPool( const XMLSize_t modulus + , const bool adoptElems + , const THasher& hasher + , const XMLSize_t initSize) : + fAdoptedElems(adoptElems) + , fBucketList(0) + , fHashModulus(modulus) + , fIdPtrs(0) + , fIdPtrsCount(initSize) + , fIdCounter(0) + , fMemoryManager(XMLPlatformUtils::fgMemoryManager) + , fHasher(hasher) +{ + initialize(modulus); + + // + // Allocate the initial id pointers array. We don't have to zero them + // out since the fIdCounter value tells us which ones are valid. The + // zeroth element is never used (and represents an invalid pool id.) + // + if (!fIdPtrsCount) + fIdPtrsCount = 256; + + fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount]; + fIdPtrs[0] = 0; +} + +template +DOMDeepNodeListPool::DOMDeepNodeListPool( const XMLSize_t modulus + , const XMLSize_t initSize) : + fAdoptedElems(true) + , fBucketList(0) + , fHashModulus(modulus) + , fIdPtrs(0) + , fIdPtrsCount(initSize) + , fIdCounter(0) + , fMemoryManager(XMLPlatformUtils::fgMemoryManager) +{ + initialize(modulus); + + // + // Allocate the initial id pointers array. We don't have to zero them + // out since the fIdCounter value tells us which ones are valid. The + // zeroth element is never used (and represents an invalid pool id.) + // + if (!fIdPtrsCount) + fIdPtrsCount = 256; + + fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount]; + fIdPtrs[0] = 0; +} + +template +void DOMDeepNodeListPool::initialize(const XMLSize_t modulus) +{ + if (modulus == 0) + ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager); + + // Allocate the bucket list and zero them + fBucketList = (DOMDeepNodeListPoolTableBucketElem**) + fMemoryManager->allocate + ( + fHashModulus * sizeof(DOMDeepNodeListPoolTableBucketElem*) + );//new DOMDeepNodeListPoolTableBucketElem*[fHashModulus]; + for (XMLSize_t index = 0; index < fHashModulus; index++) + fBucketList[index] = 0; +} + +template +DOMDeepNodeListPool::~DOMDeepNodeListPool() +{ + removeAll(); + + // Then delete the bucket list & hasher & id pointers list + fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs; + fMemoryManager->deallocate(fBucketList);//delete [] fBucketList; +} + + +// --------------------------------------------------------------------------- +// DOMDeepNodeListPool: Element management +// --------------------------------------------------------------------------- +template +bool DOMDeepNodeListPool::isEmpty() const +{ + // Just check the bucket list for non-empty elements + for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) + { + if (fBucketList[buckInd] != 0) + return false; + } + return true; +} + +template +bool DOMDeepNodeListPool::containsKey( const void* const key1 + , const XMLCh* const key2 + , const XMLCh* const key3) const +{ + XMLSize_t hashVal; + const DOMDeepNodeListPoolTableBucketElem* findIt = findBucketElem(key1, key2, key3, hashVal); + return (findIt != 0); +} + +template +void DOMDeepNodeListPool::removeAll() +{ + if (fIdCounter == 0) return; + + // Clean up the buckets first + for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) + { + // Get the bucket list head for this entry + DOMDeepNodeListPoolTableBucketElem* curElem = fBucketList[buckInd]; + DOMDeepNodeListPoolTableBucketElem* nextElem; + while (curElem) + { + // Save the next element before we hose this one + nextElem = curElem->fNext; + + // If we adopted the data, then delete it too + // (Note: the userdata hash table instance has data type of void *. + // This will generate compiler warnings here on some platforms, but they + // can be ignored since fAdoptedElements is false. + if (fAdoptedElems) + delete curElem->fData; + + // Then delete the current element and move forward + fMemoryManager->deallocate(curElem->fKey2);//delete [] curElem->fKey2; + fMemoryManager->deallocate(curElem->fKey3);//delete [] curElem->fKey3; + + delete curElem; + curElem = nextElem; + } + + // Clean out this entry + fBucketList[buckInd] = 0; + } + + // Reset the id counter + fIdCounter = 0; +} + +template +void DOMDeepNodeListPool::cleanup() +{ + removeAll(); + + // Then delete the bucket list & hasher & id pointers list + fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs; + fMemoryManager->deallocate(fBucketList);//delete [] fBucketList; +} + + + +// --------------------------------------------------------------------------- +// DOMDeepNodeListPool: Getters +// --------------------------------------------------------------------------- +template +TVal* +DOMDeepNodeListPool::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) +{ + XMLSize_t hashVal; + DOMDeepNodeListPoolTableBucketElem* findIt = findBucketElem(key1, key2, key3, hashVal); + if (!findIt) + return 0; + return findIt->fData; +} + +template +const TVal* +DOMDeepNodeListPool::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) const +{ + XMLSize_t hashVal; + const DOMDeepNodeListPoolTableBucketElem* findIt = findBucketElem(key1, key2, key3, hashVal); + if (!findIt) + return 0; + return findIt->fData; +} + +template +TVal* +DOMDeepNodeListPool::getById(const XMLSize_t elemId) +{ + // If its either zero or beyond our current id, its an error + if (!elemId || (elemId > fIdCounter)) + ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager); + + return fIdPtrs[elemId]; +} + +template +const TVal* +DOMDeepNodeListPool::getById(const XMLSize_t elemId) const +{ + // If its either zero or beyond our current id, its an error + if (!elemId || (elemId > fIdCounter)) + ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager); + + return fIdPtrs[elemId]; +} + +// --------------------------------------------------------------------------- +// DOMDeepNodeListPool: Putters +// --------------------------------------------------------------------------- +template +XMLSize_t +DOMDeepNodeListPool::put(void* key1, XMLCh* key2, XMLCh* key3, TVal* const valueToAdopt) +{ + // First see if the key exists already + XMLSize_t hashVal; + DOMDeepNodeListPoolTableBucketElem* newBucket = findBucketElem(key1, key2, key3, hashVal); + + // + // If so,then update its value. If not, then we need to add it to + // the right bucket + // + if (newBucket) + { + if (fAdoptedElems) + delete newBucket->fData; + + fMemoryManager->deallocate(newBucket->fKey2);//delete[] newBucket->fKey2; + fMemoryManager->deallocate(newBucket->fKey3);//delete[] newBucket->fKey3; + + newBucket->fData = valueToAdopt; + newBucket->fKey1 = key1; + newBucket->fKey2 = XMLString::replicate(key2, fMemoryManager); + newBucket->fKey3 = XMLString::replicate(key3, fMemoryManager); + } + else + { + // Revisit: the gcc compiler 2.95.x is generating an + // internal compiler error message. So we use the default + // memory manager for now. +#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600) + newBucket = new DOMDeepNodeListPoolTableBucketElem + ( + key1 + , key2 + , key3 + , valueToAdopt + , fBucketList[hashVal] + , fMemoryManager + ); +#else + newBucket = new (fMemoryManager) DOMDeepNodeListPoolTableBucketElem + ( + key1 + , key2 + , key3 + , valueToAdopt + , fBucketList[hashVal] + , fMemoryManager + ); +#endif + fBucketList[hashVal] = newBucket; + } + + // + // Give this new one the next available id and add to the pointer list. + // Expand the list if that is now required. + // + if (fIdCounter + 1 == fIdPtrsCount) + { + // Create a new count 1.5 times larger and allocate a new array + XMLSize_t newCount = (XMLSize_t)(fIdPtrsCount * 1.5); + TVal** newArray = (TVal**) fMemoryManager->allocate + ( + newCount * sizeof(TVal*) + );//new TVal*[newCount]; + + // Copy over the old contents to the new array + memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TVal*)); + + // Ok, toss the old array and store the new data + fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs; + fIdPtrs = newArray; + fIdPtrsCount = newCount; + } + const XMLSize_t retId = ++fIdCounter; + fIdPtrs[retId] = valueToAdopt; + + // Return the id that we gave to this element + return retId; +} + +// --------------------------------------------------------------------------- +// DOMDeepNodeListPool: Private methods +// --------------------------------------------------------------------------- +template +DOMDeepNodeListPoolTableBucketElem* DOMDeepNodeListPool:: +findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal) +{ + // Hash the key + hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // Search that bucket for the key + DOMDeepNodeListPoolTableBucketElem* curElem = fBucketList[hashVal]; + while (curElem) + { + //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same + //but we need them to be treated as different keys in this case + if (fHasher.equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) { + if (!key2 || !curElem->fKey2) { + if (key2 || curElem->fKey2) { + curElem = curElem->fNext; + continue; + } + } + if (!key3 || !curElem->fKey3) { + if (key3 || curElem->fKey3) { + curElem = curElem->fNext; + continue; + } + } + + return curElem; + } + + curElem = curElem->fNext; + } + return 0; +} + +template +const DOMDeepNodeListPoolTableBucketElem* DOMDeepNodeListPool:: +findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal) const +{ + // Hash the key + hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // Search that bucket for the key + const DOMDeepNodeListPoolTableBucketElem* curElem = fBucketList[hashVal]; + while (curElem) + { + //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same + //but we need them to be treated as different keys in this case + if (fHasher.equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) { + if (!key2 || !curElem->fKey2) { + if (key2 || curElem->fKey2) { + curElem = curElem->fNext; + continue; + } + } + if (!key3 || !curElem->fKey3) { + if (key3 || curElem->fKey3) { + curElem = curElem->fNext; + continue; + } + } + return curElem; + } + + curElem = curElem->fNext; + } + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMDeepNodeListPool.hpp b/include/xercesc/dom/impl/DOMDeepNodeListPool.hpp new file mode 100644 index 0000000..ad609b6 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDeepNodeListPool.hpp @@ -0,0 +1,200 @@ +/* + * 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: DOMDeepNodeListPool.hpp 883368 2009-11-23 15:28:19Z amassari $ + */ + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDEEPNODELISTPOOL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDEEPNODELISTPOOL_HPP + + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This should really be a nested class, but some of the compilers we +// have to support cannot deal with that! +// +template +struct DOMDeepNodeListPoolTableBucketElem : public XMemory +{ + DOMDeepNodeListPoolTableBucketElem + ( + void* key1 + , XMLCh* key2 + , XMLCh* key3 + , TVal* const value + , DOMDeepNodeListPoolTableBucketElem* next + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ) : + fData(value) + , fNext(next) + , fKey1(key1) + , fKey2(0) + , fKey3(0) + { + if (key2) + fKey2 = XMLString::replicate(key2, manager); + + if (key3) + fKey3 = XMLString::replicate(key3, manager); + } + + TVal* fData; + DOMDeepNodeListPoolTableBucketElem* fNext; + void* fKey1; + XMLCh* fKey2; + XMLCh* fKey3; + + ~DOMDeepNodeListPoolTableBucketElem() {}; +}; + + +template +class DOMDeepNodeListPool +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DOMDeepNodeListPool + ( + const XMLSize_t modulus + , const XMLSize_t initSize = 128 + ); + + DOMDeepNodeListPool + ( + const XMLSize_t modulus + , const bool adoptElems + , const XMLSize_t initSize = 128 + ); + + DOMDeepNodeListPool + ( + const XMLSize_t modulus + , const bool adoptElems + , const THasher& hasher + , const XMLSize_t initSize = 128 + ); + + ~DOMDeepNodeListPool(); + + // ----------------------------------------------------------------------- + // Element management + // ----------------------------------------------------------------------- + bool isEmpty() const; + bool containsKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) const; + void removeAll(); + void cleanup(); + + + // ----------------------------------------------------------------------- + // Getters + // ----------------------------------------------------------------------- + TVal* getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3); + const TVal* getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) const; + + TVal* getById(const XMLSize_t elemId); + const TVal* getById(const XMLSize_t elemId) const; + + // ----------------------------------------------------------------------- + // Putters + // ----------------------------------------------------------------------- + XMLSize_t put(void* key1, XMLCh* key2, XMLCh* key3, TVal* const valueToAdopt); + +private: + + // ----------------------------------------------------------------------- + // Private methods + // ----------------------------------------------------------------------- + DOMDeepNodeListPoolTableBucketElem* findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal); + const DOMDeepNodeListPoolTableBucketElem* findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal) const; + void initialize(const XMLSize_t modulus); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMDeepNodeListPool(const DOMDeepNodeListPool &); + DOMDeepNodeListPool & operator = (const DOMDeepNodeListPool &); + + // ----------------------------------------------------------------------- + // Data members + // + // fAdoptedElems + // Indicates whether the values added are adopted or just referenced. + // If adopted, then they are deleted when they are removed from the + // hash table. + // + // fBucketList + // This is the array that contains the heads of all of the list + // buckets, one for each possible hash value. + // + // fHashModulus + // The modulus used for this hash table, to hash the keys. This is + // also the number of elements in the bucket list. + // + // fHash + // The hasher for the key1 data type. + // + // fIdPtrs + // fIdPtrsCount + // This is the array of pointers to the bucket elements in order of + // their assigned ids. So taking id N and referencing this array + // gives you the element with that id. The count field indicates + // the current size of this list. When fIdCounter+1 reaches this + // value the list must be expanded. + // + // fIdCounter + // This is used to give out unique ids to added elements. It starts + // at zero (which means empty), and is bumped up for each newly added + // element. So the first element is 1, the next is 2, etc... This + // means that this value is set to the top index of the fIdPtrs array. + // ----------------------------------------------------------------------- + bool fAdoptedElems; + DOMDeepNodeListPoolTableBucketElem** fBucketList; + XMLSize_t fHashModulus; + TVal** fIdPtrs; + XMLSize_t fIdPtrsCount; + XMLSize_t fIdCounter; + MemoryManager* fMemoryManager; + THasher fHasher; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp b/include/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp new file mode 100644 index 0000000..c96fec9 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp @@ -0,0 +1,137 @@ +/* + * 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: DOMDocumentFragmentImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMDocumentFragmentImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMDocumentFragmentImpl::DOMDocumentFragmentImpl(DOMDocument *masterDoc) + : fNode(masterDoc), fParent(masterDoc) +{ +} + + +DOMDocumentFragmentImpl::DOMDocumentFragmentImpl(const DOMDocumentFragmentImpl &other, + bool deep) + : fNode(other.fNode), fParent(other.fParent) +{ + if (deep) + castToParentImpl(this)->cloneChildren(&other); +} + + +DOMDocumentFragmentImpl::~DOMDocumentFragmentImpl() +{ +} + + + +DOMNode *DOMDocumentFragmentImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (castToNodeImpl(this)->getOwnerDocument(), DOMMemoryManager::DOCUMENT_FRAGMENT_OBJECT) DOMDocumentFragmentImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMDocumentFragmentImpl::getNodeName() const { + static const XMLCh name[] = {chPound, chLatin_d, chLatin_o, chLatin_c, chLatin_u, chLatin_m, + chLatin_e, chLatin_n, chLatin_t, chDash, + chLatin_f, chLatin_r, chLatin_a, chLatin_g, chLatin_m, chLatin_e, chLatin_n, chLatin_t, 0}; + return name; +} + + +DOMNode::NodeType DOMDocumentFragmentImpl::getNodeType() const { + return DOMNode::DOCUMENT_FRAGMENT_NODE; +} + + +void DOMDocumentFragmentImpl::setNodeValue(const XMLCh *x) +{ + fNode.setNodeValue(x); +} + + +void DOMDocumentFragmentImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fParent.release(); + doc->release(this, DOMMemoryManager::DOCUMENT_FRAGMENT_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +// +// Delegation stubs for inherited functions. +// + DOMNode* DOMDocumentFragmentImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } + DOMNamedNodeMap* DOMDocumentFragmentImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMDocumentFragmentImpl::getChildNodes() const {return fParent.getChildNodes (); } + DOMNode* DOMDocumentFragmentImpl::getFirstChild() const {return fParent.getFirstChild (); } + DOMNode* DOMDocumentFragmentImpl::getLastChild() const {return fParent.getLastChild (); } + const XMLCh* DOMDocumentFragmentImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMDocumentFragmentImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMDocumentFragmentImpl::getNextSibling() const {return fNode.getNextSibling (); } + const XMLCh* DOMDocumentFragmentImpl::getNodeValue() const {return fNode.getNodeValue (); } + DOMDocument* DOMDocumentFragmentImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } + const XMLCh* DOMDocumentFragmentImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMDocumentFragmentImpl::getParentNode() const {return fNode.getParentNode (); } + DOMNode* DOMDocumentFragmentImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } + bool DOMDocumentFragmentImpl::hasChildNodes() const {return fParent.hasChildNodes (); } + DOMNode* DOMDocumentFragmentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fParent.insertBefore (newChild, refChild); } + void DOMDocumentFragmentImpl::normalize() {fParent.normalize (); } + DOMNode* DOMDocumentFragmentImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } + DOMNode* DOMDocumentFragmentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fParent.replaceChild (newChild, oldChild); } + bool DOMDocumentFragmentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMDocumentFragmentImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMDocumentFragmentImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMDocumentFragmentImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMDocumentFragmentImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg); } + void* DOMDocumentFragmentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMDocumentFragmentImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + const XMLCh* DOMDocumentFragmentImpl::getBaseURI() const {return fNode.getBaseURI(); } + short DOMDocumentFragmentImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMDocumentFragmentImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMDocumentFragmentImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMDocumentFragmentImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMDocumentFragmentImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMDocumentFragmentImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMDocumentFragmentImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMDocumentFragmentImpl.hpp b/include/xercesc/dom/impl/DOMDocumentFragmentImpl.hpp new file mode 100644 index 0000000..2ff08d0 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDocumentFragmentImpl.hpp @@ -0,0 +1,69 @@ +/* + * 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: DOMDocumentFragmentImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTFRAGMENTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTFRAGMENTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include +#include "DOMParentNode.hpp" +#include "DOMNodeImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMDocumentFragmentImpl: public DOMDocumentFragment { +protected: + DOMNodeImpl fNode; + DOMParentNode fParent; + +protected: + DOMDocumentFragmentImpl(DOMDocument *); + DOMDocumentFragmentImpl(const DOMDocumentFragmentImpl &other, bool deep); + friend class DOMDocumentImpl; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMDocumentFragmentImpl & operator = (const DOMDocumentFragmentImpl &); + +public: + virtual ~DOMDocumentFragmentImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/impl/DOMDocumentImpl.cpp b/include/xercesc/dom/impl/DOMDocumentImpl.cpp new file mode 100644 index 0000000..c4ced06 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDocumentImpl.cpp @@ -0,0 +1,1509 @@ +/* + * 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: DOMDocumentImpl.cpp 932949 2010-04-11 17:40:33Z borisk $ + */ +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" +#include "DOMConfigurationImpl.hpp" +#include "DOMDocumentTypeImpl.hpp" +#include "DOMAttrImpl.hpp" +#include "DOMAttrNSImpl.hpp" +#include "DOMCDATASectionImpl.hpp" +#include "DOMCommentImpl.hpp" +#include "DOMDeepNodeListImpl.hpp" +#include "DOMDocumentFragmentImpl.hpp" +#include "DOMElementImpl.hpp" +#include "XSDElementNSImpl.hpp" +#include "DOMEntityImpl.hpp" +#include "DOMEntityReferenceImpl.hpp" +#include "DOMNormalizer.hpp" +#include "DOMNotationImpl.hpp" +#include "DOMProcessingInstructionImpl.hpp" +#include "DOMTextImpl.hpp" +#include "DOMTreeWalkerImpl.hpp" +#include "DOMNodeIteratorImpl.hpp" +#include "DOMNodeIDMap.hpp" +#include "DOMRangeImpl.hpp" +#include "DOMTypeInfoImpl.hpp" +#include "DOMXPathExpressionImpl.hpp" +#include "DOMXPathNSResolverImpl.hpp" + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// The chunk size to allocate from the system allocator. +static XMLSize_t kInitialHeapAllocSize = 0x4000; +static XMLSize_t kMaxHeapAllocSize = 0x80000; +static XMLSize_t kMaxSubAllocationSize = 0x0100; // Any request for more bytes + // than this will be handled by + // allocating directly with system. + +void XMLInitializer::initializeDOMHeap (XMLSize_t initialHeapAllocSize, + XMLSize_t maxHeapAllocSize, + XMLSize_t maxSubAllocationSize) +{ + kInitialHeapAllocSize = initialHeapAllocSize; + kMaxHeapAllocSize = maxHeapAllocSize; + kMaxSubAllocationSize = maxSubAllocationSize; +} + +// +// Constructors. Warning - be very careful with the ordering of initialization +// of the heap. Ordering depends on the order of declaration +// in the .hpp file, not on the order of initializers here +// in the constructor. The heap declaration can not be +// first - fNode and fParent must be first for the casting +// functions in DOMCasts to work correctly. This means that +// fNode and fParent constructors used here can not +// allocate. +// +DOMDocumentImpl::DOMDocumentImpl(DOMImplementation* domImpl, MemoryManager* const manager) + : fNode(this), + fParent(this), + fNodeIDMap(0), + fInputEncoding(0), + fXmlEncoding(0), + fXmlStandalone(false), + fXmlVersion(0), + fDocumentURI(0), + fDOMConfiguration(0), + fUserDataTableKeys(17, manager), + fUserDataTable(0), + fCurrentBlock(0), + fFreePtr(0), + fFreeBytesRemaining(0), + fHeapAllocSize(kInitialHeapAllocSize), + fRecycleNodePtr(0), + fRecycleBufferPtr(0), + fNodeListPool(0), + fDocType(0), + fDocElement(0), + fNameTableSize(257), + fNormalizer(0), + fRanges(0), + fNodeIterators(0), + fMemoryManager(manager), + fDOMImplementation(domImpl), + fChanges(0), + errorChecking(true) +{ + fNameTable = (DOMStringPoolEntry**)allocate ( + sizeof (DOMStringPoolEntry*) * fNameTableSize); + for (XMLSize_t i = 0; i < fNameTableSize; i++) + fNameTable[i] = 0; +} + + +//DOM Level 2 +DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI, + const XMLCh *qualifiedName, + DOMDocumentType *doctype, + DOMImplementation* domImpl, + MemoryManager* const manager) + : fNode(this), + fParent(this), + fNodeIDMap(0), + fInputEncoding(0), + fXmlEncoding(0), + fXmlStandalone(false), + fXmlVersion(0), + fDocumentURI(0), + fDOMConfiguration(0), + fUserDataTableKeys(17, manager), + fUserDataTable(0), + fCurrentBlock(0), + fFreePtr(0), + fFreeBytesRemaining(0), + fHeapAllocSize(kInitialHeapAllocSize), + fRecycleNodePtr(0), + fRecycleBufferPtr(0), + fNodeListPool(0), + fDocType(0), + fDocElement(0), + fNameTableSize(257), + fNormalizer(0), + fRanges(0), + fNodeIterators(0), + fMemoryManager(manager), + fDOMImplementation(domImpl), + fChanges(0), + errorChecking(true) +{ + fNameTable = (DOMStringPoolEntry**)allocate ( + sizeof (DOMStringPoolEntry*) * fNameTableSize); + for (XMLSize_t i = 0; i < fNameTableSize; i++) + fNameTable[i] = 0; + + try { + setDocumentType(doctype); + + if (qualifiedName) + appendChild(createElementNS(fNamespaceURI, qualifiedName)); //root element + else if (fNamespaceURI) + throw DOMException(DOMException::NAMESPACE_ERR, 0, getMemoryManager()); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) { + this->deleteHeap(); + throw; + } +} + +void DOMDocumentImpl::setDocumentType(DOMDocumentType *doctype) +{ + if (!doctype) + return; + + // New doctypes can be created either with the factory methods on DOMImplementation, in + // which case ownerDocument will be 0, or with methods on DocumentImpl, in which case + // ownerDocument will be set, but the DocType won't yet be a child of the document. + // + DOMDocument* doc = doctype->getOwnerDocument(); + if (doc != 0 && doc != this) + throw DOMException( //one doctype can belong to only one DOMDocumentImpl + DOMException::WRONG_DOCUMENT_ERR, 0, getMemoryManager()); + + DOMDocumentTypeImpl* doctypeImpl = (DOMDocumentTypeImpl*) doctype; + doctypeImpl->setOwnerDocument(this); + + // The doctype can not have any Entities or Notations yet, because they can not + // be created except through factory methods on a document. + + // revisit. What if this doctype is already a child of the document? + appendChild(doctype); + +} + +DOMDocumentImpl::~DOMDocumentImpl() +{ + // While DOMConfiguration is allocated on the Document's heap, itself + // it uses the memory manager directly. This means that while we cannot + // delete with operator delete, we need to call its d-tor. + // + if (fDOMConfiguration) + fDOMConfiguration->~DOMConfiguration (); + + // Clean up the fNodeListPool + if (fNodeListPool) + fNodeListPool->cleanup(); + + if (fRanges) + delete fRanges; //fRanges->cleanup(); + + if (fNodeIterators) + delete fNodeIterators;//fNodeIterators->cleanup(); + + if (fUserDataTable) + delete fUserDataTable;//fUserDataTable->cleanup(); + + if (fRecycleNodePtr) { + fRecycleNodePtr->deleteAllElements(); + delete fRecycleNodePtr; + } + + if (fRecycleBufferPtr) { + delete fRecycleBufferPtr; + } + + delete fNormalizer; + + // Delete the heap for this document. This uncerimoniously yanks the storage + // out from under all of the nodes in the document. Destructors are NOT called. + this->deleteHeap(); +} + + +DOMNode *DOMDocumentImpl::cloneNode(bool deep) const { + + // Note: the cloned document node goes on the same heap we live in. + DOMDocumentImpl *newdoc = new (fMemoryManager) DOMDocumentImpl(fDOMImplementation, fMemoryManager); + if(fXmlEncoding && *fXmlEncoding) + newdoc->setXmlEncoding(fXmlEncoding); + if(fXmlVersion && *fXmlVersion) + newdoc->setXmlVersion(fXmlVersion); + newdoc->setXmlStandalone(fXmlStandalone); + + // then the children by _importing_ them + if (deep) + for (DOMNode *n = this->getFirstChild(); n != 0; n = n->getNextSibling()) { + newdoc->appendChild(newdoc->importNode(n, true, true)); + } + + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newdoc); + return newdoc; +} + + +const XMLCh * DOMDocumentImpl::getNodeName() const { + static const XMLCh nam[] = // "#document" + {chPound, chLatin_d, chLatin_o, chLatin_c, chLatin_u, chLatin_m, chLatin_e, chLatin_n, chLatin_t, 0}; + return nam; +} + + +DOMNode::NodeType DOMDocumentImpl::getNodeType() const { + return DOMNode::DOCUMENT_NODE; +} + + +// even though ownerDocument refers to this in this implementation +// the DOM Level 2 spec says it must be 0, so make it appear so +DOMDocument * DOMDocumentImpl::getOwnerDocument() const { + return 0; +} + + +DOMAttr *DOMDocumentImpl::createAttribute(const XMLCh *nam) +{ + if(!nam || !isXMLName(nam)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); + return new (this, DOMMemoryManager::ATTR_OBJECT) DOMAttrImpl(this,nam); +} + + + +DOMCDATASection *DOMDocumentImpl::createCDATASection(const XMLCh *data) { + return new (this, DOMMemoryManager::CDATA_SECTION_OBJECT) DOMCDATASectionImpl(this,data); +} + + + +DOMComment *DOMDocumentImpl::createComment(const XMLCh *data) +{ + return new (this, DOMMemoryManager::COMMENT_OBJECT) DOMCommentImpl(this, data); +} + + + +DOMDocumentFragment *DOMDocumentImpl::createDocumentFragment() +{ + return new (this, DOMMemoryManager::DOCUMENT_FRAGMENT_OBJECT) DOMDocumentFragmentImpl(this); +} + + + +DOMDocumentType *DOMDocumentImpl::createDocumentType(const XMLCh *nam) +{ + if (!nam || !isXMLName(nam)) + throw DOMException( + DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager()); + + return new (this, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(this, nam, false); +} + + + +DOMDocumentType * + DOMDocumentImpl::createDocumentType(const XMLCh *qualifiedName, + const XMLCh *publicId, + const XMLCh *systemId) +{ + if (!qualifiedName || !isXMLName(qualifiedName)) + throw DOMException( + DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager()); + + return new (this, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(this, qualifiedName, publicId, systemId, false); +} + + + +DOMElement *DOMDocumentImpl::createElement(const XMLCh *tagName) +{ + if(!tagName || !isXMLName(tagName)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); + + return new (this, DOMMemoryManager::ELEMENT_OBJECT) DOMElementImpl(this,tagName); +} + + +DOMElement *DOMDocumentImpl::createElementNoCheck(const XMLCh *tagName) +{ + return new (this, DOMMemoryManager::ELEMENT_OBJECT) DOMElementImpl(this, tagName); +} + + + + +DOMEntity *DOMDocumentImpl::createEntity(const XMLCh *nam) +{ + if (!nam || !isXMLName(nam)) + throw DOMException( + DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager()); + + return new (this, DOMMemoryManager::ENTITY_OBJECT) DOMEntityImpl(this, nam); +} + + + +DOMEntityReference *DOMDocumentImpl::createEntityReference(const XMLCh *nam) +{ + if (!nam || !isXMLName(nam)) + throw DOMException( + DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager()); + + return new (this, DOMMemoryManager::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(this, nam); +} + +DOMEntityReference *DOMDocumentImpl::createEntityReferenceByParser(const XMLCh *nam) +{ + if (!nam || !isXMLName(nam)) + throw DOMException( + DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager()); + + return new (this, DOMMemoryManager::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(this, nam, false); +} + +DOMNotation *DOMDocumentImpl::createNotation(const XMLCh *nam) +{ + if (!nam || !isXMLName(nam)) + throw DOMException( + DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager()); + + return new (this, DOMMemoryManager::NOTATION_OBJECT) DOMNotationImpl(this, nam); +} + + + +DOMProcessingInstruction *DOMDocumentImpl::createProcessingInstruction( + const XMLCh *target, const XMLCh *data) +{ + if(!target || !isXMLName(target)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); + return new (this, DOMMemoryManager::PROCESSING_INSTRUCTION_OBJECT) DOMProcessingInstructionImpl(this,target,data); +} + + + + +DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data) +{ + return new (this, DOMMemoryManager::TEXT_OBJECT) DOMTextImpl(this,data); +} + + +DOMNodeIterator* DOMDocumentImpl::createNodeIterator ( + DOMNode *root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* filter, + bool entityReferenceExpansion) +{ + if (!root) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + return 0; + } + + DOMNodeIteratorImpl* nodeIterator = new (this) DOMNodeIteratorImpl(this, root, whatToShow, filter, entityReferenceExpansion); + + if (fNodeIterators == 0L) { + //fNodeIterators = new (this) NodeIterators(1, false); + fNodeIterators = new (fMemoryManager) NodeIterators(1, false, fMemoryManager); + } + fNodeIterators->addElement(nodeIterator); + + return nodeIterator; +} + + +NodeIterators* DOMDocumentImpl::getNodeIterators() const +{ + return fNodeIterators; +} + +void DOMDocumentImpl::removeNodeIterator(DOMNodeIteratorImpl* nodeIterator) +{ + if (fNodeIterators != 0) { + XMLSize_t sz = fNodeIterators->size(); + if (sz !=0) { + for (XMLSize_t i =0; ielementAt(i) == nodeIterator) { + fNodeIterators->removeElementAt(i); + break; + } + } + } + } +} + + +DOMXPathExpression* DOMDocumentImpl::createExpression(const XMLCh * expression, const DOMXPathNSResolver *resolver) +{ + return new (getMemoryManager()) DOMXPathExpressionImpl(expression, resolver, getMemoryManager()); +} + +DOMXPathNSResolver* DOMDocumentImpl::createNSResolver(const DOMNode *nodeResolver) +{ + return new (getMemoryManager()) DOMXPathNSResolverImpl(nodeResolver, getMemoryManager()); +} + +DOMXPathResult* DOMDocumentImpl::evaluate(const XMLCh *expression, + const DOMNode *contextNode, + const DOMXPathNSResolver *resolver, + DOMXPathResult::ResultType type, + DOMXPathResult* result) +{ + JanitorMemFunCall expr( + createExpression(expression, resolver), + &DOMXPathExpression::release); + return expr->evaluate(contextNode, type, result); +} + + + +DOMTreeWalker* DOMDocumentImpl::createTreeWalker ( + DOMNode *root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* filter, + bool entityReferenceExpansion) +{ + if (!root) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + return 0; + } + + return new (this) DOMTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion); +} + + + + +DOMDocumentType *DOMDocumentImpl::getDoctype() const +{ + return fDocType; +} + + + +DOMElement *DOMDocumentImpl::getDocumentElement() const +{ + return fDocElement; +} + + + +DOMNodeList *DOMDocumentImpl::getElementsByTagName(const XMLCh *tagname) const +{ + // cast off the const of this because we will update the fNodeListPool + return ((DOMDocumentImpl*)this)->getDeepNodeList(this,tagname); +} + + +DOMImplementation *DOMDocumentImpl::getImplementation() const { + + return fDOMImplementation; +} + + +DOMNode *DOMDocumentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) +{ + // Only one such child permitted + if( + (newChild->getNodeType() == DOMNode::ELEMENT_NODE && fDocElement!=0) + || + (newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE && fDocType!=0) + ) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, getMemoryManager()); + + // if the newChild is a documenttype node created from domimplementation, set the ownerDoc first + if ((newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) && !newChild->getOwnerDocument()) + ((DOMDocumentTypeImpl*)newChild)->setOwnerDocument(this); + + fParent.insertBefore(newChild,refChild); + + // If insert succeeded, cache the kid appropriately + if(newChild->getNodeType() == DOMNode::ELEMENT_NODE) + fDocElement=(DOMElement *)newChild; + else if(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) + fDocType=(DOMDocumentType *)newChild; + + return newChild; +} + + +DOMNode* DOMDocumentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) { + DOMDocumentType* tempDocType = fDocType; + DOMElement* tempDocElement = fDocElement; + + if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) + fDocType=0; + else if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE) + fDocElement=0; + + try { + insertBefore(newChild, oldChild); + // changed() already done. + + if((oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) + || (oldChild->getNodeType() == DOMNode::ELEMENT_NODE)) + return fParent.removeChild(oldChild); + else + return removeChild(oldChild); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + fDocType = tempDocType; + fDocElement = tempDocElement; + throw; + } +} + +bool DOMDocumentImpl::isXMLName(const XMLCh *s) +{ + // fXmlVersion points directly to the static constants + if (fXmlVersion==XMLUni::fgVersion1_1) + return XMLChar1_1::isValidName(s); + else + return XMLChar1_0::isValidName(s); +} + + + + +DOMNode *DOMDocumentImpl::removeChild(DOMNode *oldChild) +{ + fParent.removeChild(oldChild); + + // If remove succeeded, un-cache the kid appropriately + if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE) + fDocElement=0; + else if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) + fDocType=0; + + return oldChild; +} + + + +void DOMDocumentImpl::setNodeValue(const XMLCh *x) +{ + fNode.setNodeValue(x); +} + + +//Introduced in DOM Level 2 +DOMNode *DOMDocumentImpl::importNode(const DOMNode *source, bool deep) +{ + return importNode(source, deep, false); +} + + +DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI, + const XMLCh *qualifiedName) +{ + if(!qualifiedName || !isXMLName(qualifiedName)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); + + return new (this, DOMMemoryManager::ELEMENT_NS_OBJECT) DOMElementNSImpl(this, fNamespaceURI, qualifiedName); +} + +DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI, + const XMLCh *qualifiedName, + const XMLFileLoc lineNo, + const XMLFileLoc columnNo) +{ + if(!qualifiedName || !isXMLName(qualifiedName)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); + + return new (this) XSDElementNSImpl(this, fNamespaceURI, qualifiedName, lineNo, columnNo); +} + + +DOMAttr *DOMDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI, + const XMLCh *qualifiedName) +{ + if(!qualifiedName || !isXMLName(qualifiedName)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); + return new (this, DOMMemoryManager::ATTR_NS_OBJECT) DOMAttrNSImpl(this, fNamespaceURI, qualifiedName); +} + + +DOMNodeList *DOMDocumentImpl::getElementsByTagNameNS(const XMLCh *fNamespaceURI, + const XMLCh *fLocalName) const +{ + // cast off the const of this because we will update the fNodeListPool + return ((DOMDocumentImpl*)this)->getDeepNodeList(this, fNamespaceURI, fLocalName); +} + + +DOMElement *DOMDocumentImpl::getElementById(const XMLCh *elementId) const +{ + if (fNodeIDMap == 0) + return 0; + + DOMAttr *theAttr = fNodeIDMap->find(elementId); + if (theAttr == 0) + return 0; + + return theAttr->getOwnerElement(); +} + +const XMLCh* DOMDocumentImpl::getBaseURI() const +{ + return fDocumentURI; +} + +DOMRange* DOMDocumentImpl::createRange() +{ + + DOMRangeImpl* range = new (this) DOMRangeImpl(this, fMemoryManager); + + if (fRanges == 0L) { + //fRanges = new (this) Ranges(1, false); + fRanges = new (fMemoryManager) Ranges(1, false, fMemoryManager); // XMemory + } + fRanges->addElement(range); + return range; +} + +Ranges* DOMDocumentImpl::getRanges() const +{ + return fRanges; +} + +void DOMDocumentImpl::removeRange(DOMRangeImpl* range) +{ + if (fRanges != 0) { + XMLSize_t sz = fRanges->size(); + if (sz !=0) { + for (XMLSize_t i =0; ielementAt(i) == range) { + fRanges->removeElementAt(i); + break; + } + } + } + } +} + +/** Uses the kidOK lookup table to check whether the proposed + tree structure is legal. + + ????? It feels like there must be a more efficient solution, + but for the life of me I can't think what it would be. +*/ +bool DOMDocumentImpl::isKidOK(DOMNode *parent, DOMNode *child) +{ + static int kidOK[14]; + + if (kidOK[DOMNode::ATTRIBUTE_NODE] == 0) + { + kidOK[DOMNode::DOCUMENT_NODE] = + 1 << DOMNode::ELEMENT_NODE | + 1 << DOMNode::PROCESSING_INSTRUCTION_NODE | + 1 << DOMNode::COMMENT_NODE | + 1 << DOMNode::DOCUMENT_TYPE_NODE; + + kidOK[DOMNode::DOCUMENT_FRAGMENT_NODE] = + kidOK[DOMNode::ENTITY_NODE] = + kidOK[DOMNode::ENTITY_REFERENCE_NODE] = + kidOK[DOMNode::ELEMENT_NODE] = + 1 << DOMNode::ELEMENT_NODE | + 1 << DOMNode::PROCESSING_INSTRUCTION_NODE | + 1 << DOMNode::COMMENT_NODE | + 1 << DOMNode::TEXT_NODE | + 1 << DOMNode::CDATA_SECTION_NODE | + 1 << DOMNode::ENTITY_REFERENCE_NODE; + + kidOK[DOMNode::ATTRIBUTE_NODE] = + 1 << DOMNode::TEXT_NODE | + 1 << DOMNode::ENTITY_REFERENCE_NODE; + + kidOK[DOMNode::PROCESSING_INSTRUCTION_NODE] = + kidOK[DOMNode::COMMENT_NODE] = + kidOK[DOMNode::TEXT_NODE] = + kidOK[DOMNode::CDATA_SECTION_NODE] = + kidOK[DOMNode::NOTATION_NODE] = + 0; + } + int p=parent->getNodeType(); + int ch = child->getNodeType(); + return ((kidOK[p] & 1<getXmlVersion(), XMLUni::fgVersion1_1))? + XMLChar1_1::isAllSpaces(child->getNodeValue(), XMLString::stringLen(child->getNodeValue())): + XMLChar1_0::isAllSpaces(child->getNodeValue(), XMLString::stringLen(child->getNodeValue()))) + ); +} + +void DOMDocumentImpl::changed() +{ + fChanges++; +} + + +int DOMDocumentImpl::changes() const{ + return fChanges; +} + + + +// +// Delegation for functions inherited from DOMNode +// + DOMNode* DOMDocumentImpl::appendChild(DOMNode *newChild) {return insertBefore(newChild, 0); } + DOMNamedNodeMap* DOMDocumentImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMDocumentImpl::getChildNodes() const {return fParent.getChildNodes (); } + DOMNode* DOMDocumentImpl::getFirstChild() const {return fParent.getFirstChild (); } + DOMNode* DOMDocumentImpl::getLastChild() const {return fParent.getLastChild (); } + const XMLCh* DOMDocumentImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMDocumentImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMDocumentImpl::getNextSibling() const {return fNode.getNextSibling (); } + const XMLCh* DOMDocumentImpl::getNodeValue() const {return fNode.getNodeValue (); } + const XMLCh* DOMDocumentImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMDocumentImpl::getParentNode() const {return fNode.getParentNode (); } + DOMNode* DOMDocumentImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } + bool DOMDocumentImpl::hasChildNodes() const {return fParent.hasChildNodes (); } + void DOMDocumentImpl::normalize() {fParent.normalize (); } + void DOMDocumentImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMDocumentImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMDocumentImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other);} + bool DOMDocumentImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg);} + void* DOMDocumentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMDocumentImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + short DOMDocumentImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMDocumentImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMDocumentImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMDocumentImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMDocumentImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMDocumentImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + + + + +//----------------------------------------------------------------------- +// +// Per Document Heap and Heap Helper functions +// +// revisit - this stuff should be a class of its own, rather than +// just lying around naked in DocumentImpl. +// +//----------------------------------------------------------------------- + +XMLCh * DOMDocumentImpl::cloneString(const XMLCh *src) +{ + if (!src) return 0; + XMLSize_t len = XMLString::stringLen(src); + len = (len + 1) * sizeof(XMLCh); + len = (len % 4) + len; + XMLCh *newStr = (XMLCh *)this->allocate(len); + XMLString::copyString(newStr, src); + return newStr; +} + +XMLSize_t DOMDocumentImpl::getMemoryAllocationBlockSize() const +{ + return fHeapAllocSize; +} + +void DOMDocumentImpl::setMemoryAllocationBlockSize(XMLSize_t size) +{ + // the new size must be bigger than the maximum amount of each allocation + if(size>kMaxSubAllocationSize) + fHeapAllocSize=size; +} + +void* DOMDocumentImpl::allocate(XMLSize_t amount) +{ + // Align the request size so that suballocated blocks + // beyond this one will be maintained at the same alignment. + amount = XMLPlatformUtils::alignPointerForNewBlockAllocation(amount); + + // If the request is for a largish block, hand it off to the system + // allocator. The block still must be linked into the list of + // allocated blocks so that it will be deleted when the time comes. + if (amount > kMaxSubAllocationSize) + { + // The size of the header we add to our raw blocks + XMLSize_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *)); + + // Try to allocate the block + void* newBlock; + newBlock = fMemoryManager->allocate(sizeOfHeader + amount); + + // Link it into the list beyond current block, as current block + // is still being subdivided. If there is no current block + // then track that we have no bytes to further divide. + if (fCurrentBlock) + { + *(void **)newBlock = *(void **)fCurrentBlock; + *(void **)fCurrentBlock = newBlock; + } + else + { + *(void **)newBlock = 0; + fCurrentBlock = newBlock; + fFreePtr = 0; + fFreeBytesRemaining = 0; + } + + void *retPtr = (char*)newBlock + sizeOfHeader; + return retPtr; + } + + // It's a normal (sub-allocatable) request. + // Are we out of room in our current block? + if (amount > fFreeBytesRemaining) + { + // Request doesn't fit in the current block. + // The size of the header we add to our raw blocks + XMLSize_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *)); + + // Get a new block from the system allocator. + void* newBlock; + newBlock = fMemoryManager->allocate(fHeapAllocSize); + + *(void **)newBlock = fCurrentBlock; + fCurrentBlock = newBlock; + fFreePtr = (char *)newBlock + sizeOfHeader; + fFreeBytesRemaining = fHeapAllocSize - sizeOfHeader; + + if(fHeapAllocSizedeallocate(fCurrentBlock); + fCurrentBlock = nextBlock; + } +} + + +DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName) +{ + if(!fNodeListPool) { + fNodeListPool = new (this) DOMDeepNodeListPool(109, false); + } + + DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, tagName, 0); + if (!retList) { + XMLSize_t id = fNodeListPool->put((void*) rootNode, (XMLCh*) tagName, 0, new (this) DOMDeepNodeListImpl(rootNode, tagName)); + retList = fNodeListPool->getById(id); + } + + return retList; +} + + +DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, //DOM Level 2 + const XMLCh *namespaceURI, + const XMLCh *localName) +{ + if(!fNodeListPool) { + fNodeListPool = new (this) DOMDeepNodeListPool(109, false); + } + + DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, localName, namespaceURI); + if (!retList) { + // the pool will adopt the DOMDeepNodeListImpl + XMLSize_t id = fNodeListPool->put((void*) rootNode, (XMLCh*) localName, (XMLCh*) namespaceURI, new (this) DOMDeepNodeListImpl(rootNode, namespaceURI, localName)); + retList = fNodeListPool->getById(id); + } + + return retList; +} + + +//Introduced in DOM Level 3 +const XMLCh* DOMDocumentImpl::getInputEncoding() const { + return fInputEncoding; +} + +void DOMDocumentImpl::setInputEncoding(const XMLCh* actualEncoding){ + fInputEncoding = cloneString(actualEncoding); +} + +const XMLCh* DOMDocumentImpl::getXmlEncoding() const { + return fXmlEncoding; +} + +void DOMDocumentImpl::setXmlEncoding(const XMLCh* encoding){ + fXmlEncoding = cloneString(encoding); +} + +bool DOMDocumentImpl::getXmlStandalone() const{ + return fXmlStandalone; +} + +void DOMDocumentImpl::setXmlStandalone(bool standalone){ + fXmlStandalone = standalone; +} + +const XMLCh* DOMDocumentImpl::getXmlVersion() const { + return fXmlVersion; +} + +void DOMDocumentImpl::setXmlVersion(const XMLCh* version){ + + // store the static strings, so that comparisons will be faster + if(version==0) + fXmlVersion = 0; + else if(*version==0) + fXmlVersion = XMLUni::fgZeroLenString; + else if(XMLString::equals(version, XMLUni::fgVersion1_0)) + fXmlVersion = XMLUni::fgVersion1_0; + else if(XMLString::equals(version, XMLUni::fgVersion1_1)) + fXmlVersion = XMLUni::fgVersion1_1; + else + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); +} + +const XMLCh* DOMDocumentImpl::getDocumentURI() const +{ + return fDocumentURI; +} + +void DOMDocumentImpl::setDocumentURI(const XMLCh* documentURI){ + if (documentURI && *documentURI) { + XMLCh* temp = (XMLCh*) this->allocate((XMLString::stringLen(documentURI) + 9)*sizeof(XMLCh)); + XMLString::fixURI(documentURI, temp); + fDocumentURI = temp; + } + else + fDocumentURI = 0; +} + +bool DOMDocumentImpl::getStrictErrorChecking() const { + return getErrorChecking(); +} + +void DOMDocumentImpl::setStrictErrorChecking(bool strictErrorChecking) { + setErrorChecking(strictErrorChecking); +} + +DOMNode* DOMDocumentImpl::adoptNode(DOMNode* sourceNode) { + if(sourceNode->getOwnerDocument()!=this) + { + // cannot take ownership of a node created by another document, as it comes from its memory pool + // and would be delete when the original document is deleted + return 0; + } + // if the adopted node is already part of this document (i.e. the source and target document are the same), + // this method still has the effect of removing the source node from the child list of its parent, if any + switch(sourceNode->getNodeType()) + { + case DOCUMENT_NODE: + case DOCUMENT_TYPE_NODE: + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + case ATTRIBUTE_NODE: + { + DOMAttr* sourceAttr=(DOMAttr*)sourceNode; + DOMElement* sourceAttrElem=sourceAttr->getOwnerElement(); + if(sourceAttrElem) + sourceAttrElem->removeAttributeNode(sourceAttr); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_ADOPTED, sourceNode, sourceNode); + break; + } + default: + { + DOMNode* sourceNodeParent=sourceNode->getParentNode(); + if(sourceNodeParent) + sourceNodeParent->removeChild(sourceNode); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_ADOPTED, sourceNode, sourceNode); + } + } + return 0; +} + +void DOMDocumentImpl::normalizeDocument() { + + if(!fNormalizer) + fNormalizer = new (fMemoryManager) DOMNormalizer(fMemoryManager); + + fNormalizer->normalizeDocument(this); +} + +DOMConfiguration* DOMDocumentImpl::getDOMConfig() const { + if(!fDOMConfiguration) + ((DOMDocumentImpl*)this)->fDOMConfiguration = new ((DOMDocumentImpl*)this) DOMConfigurationImpl(fMemoryManager); + + return fDOMConfiguration; +} + +DOMNode *DOMDocumentImpl::importNode(const DOMNode *source, bool deep, bool cloningDoc) +{ + DOMNode *newnode=0; + bool oldErrorCheckingFlag = errorChecking; + + switch (source->getNodeType()) + { + case DOMNode::ELEMENT_NODE : + { + DOMElement *newelement; + if (source->getLocalName() == 0) + newelement = createElement(source->getNodeName()); + else + { + DOMElementNSImpl* nsElem = (DOMElementNSImpl*)createElementNS(source->getNamespaceURI(), source->getNodeName()); + DOMTypeInfoImpl* clonedTypeInfo=NULL; + // if the source has type informations, copy them + DOMPSVITypeInfo* sourcePSVI=(DOMPSVITypeInfo*)source->getFeature(XMLUni::fgXercescInterfacePSVITypeInfo, 0); + if(sourcePSVI && sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Schema_Specified)) + clonedTypeInfo=new (this) DOMTypeInfoImpl(this, sourcePSVI); + else + { + const DOMTypeInfo * typeInfo=((DOMElement*)source)->getSchemaTypeInfo(); + // copy it only if it has valid data + if(typeInfo && typeInfo->getTypeName()!=NULL) + clonedTypeInfo=new (this) DOMTypeInfoImpl(typeInfo->getTypeNamespace(), typeInfo->getTypeName()); + } + if(clonedTypeInfo) + nsElem->setSchemaTypeInfo(clonedTypeInfo); + newelement=nsElem; + } + DOMNamedNodeMap *srcattr=source->getAttributes(); + if(srcattr!=0) + for(XMLSize_t i=0;igetLength();++i) + { + DOMAttr *attr = (DOMAttr *) srcattr->item(i); + if (attr -> getSpecified() || cloningDoc) { // not a default attribute or we are in the process of cloning the elements from inside a DOMDocumentType + DOMAttr *nattr = (DOMAttr *) importNode(attr, true, cloningDoc); + if (attr -> getLocalName() == 0) + newelement->setAttributeNode(nattr); + else + newelement->setAttributeNodeNS(nattr); + + // if the imported attribute is of ID type, register the new node in fNodeIDMap + if (attr->isId()) { + castToNodeImpl(nattr)->isIdAttr(true); + if (!fNodeIDMap) + fNodeIDMap = new (this) DOMNodeIDMap(500, this); + fNodeIDMap->add((DOMAttr*)nattr); + } + } + } + newnode=newelement; + + } + break; + case DOMNode::ATTRIBUTE_NODE : + { + DOMAttrImpl* newattr=NULL; + if (source->getLocalName() == 0) + newattr = (DOMAttrImpl*)createAttribute(source->getNodeName()); + else { + newattr = (DOMAttrImpl*)createAttributeNS(source->getNamespaceURI(), source->getNodeName()); + } + DOMTypeInfoImpl* clonedTypeInfo=NULL; + // if the source has type informations, copy them + DOMPSVITypeInfo* sourcePSVI=(DOMPSVITypeInfo*)source->getFeature(XMLUni::fgXercescInterfacePSVITypeInfo, 0); + if(sourcePSVI && sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Schema_Specified)) + clonedTypeInfo=new (this) DOMTypeInfoImpl(this, sourcePSVI); + else + { + const DOMTypeInfo * typeInfo=((DOMAttr*)source)->getSchemaTypeInfo(); + // copy it only if it has valid data + if(typeInfo && typeInfo->getTypeName()!=NULL) + clonedTypeInfo=new (this) DOMTypeInfoImpl(typeInfo->getTypeNamespace(), typeInfo->getTypeName()); + } + if(clonedTypeInfo) + newattr->setSchemaTypeInfo(clonedTypeInfo); + newnode=newattr; + } + deep = true; + // Kids carry value + + break; + case DOMNode::TEXT_NODE : + newnode = createTextNode(source->getNodeValue()); + break; + case DOMNode::CDATA_SECTION_NODE : + newnode = createCDATASection(source->getNodeValue()); + break; + case DOMNode::ENTITY_REFERENCE_NODE : + { + DOMEntityReferenceImpl* newentityRef = (DOMEntityReferenceImpl*)createEntityReference(source->getNodeName()); + newnode=newentityRef; + // Only the EntityReference itself is copied, even if a deep import is requested, since the source and + // destination documents might have defined the entity differently. + deep = false; + } + break; + case DOMNode::ENTITY_NODE : + { + DOMEntity *srcentity=(DOMEntity *)source; + DOMEntityImpl *newentity = (DOMEntityImpl *)createEntity(source->getNodeName()); + newentity->setPublicId(srcentity->getPublicId()); + newentity->setSystemId(srcentity->getSystemId()); + newentity->setNotationName(srcentity->getNotationName()); + newentity->setBaseURI(srcentity->getBaseURI()); + // Kids carry additional value + newnode=newentity; + castToNodeImpl(newentity)->setReadOnly(false, true);// allow deep import temporarily + } + break; + case DOMNode::PROCESSING_INSTRUCTION_NODE : + newnode = createProcessingInstruction(source->getNodeName(), source->getNodeValue()); + break; + case DOMNode::COMMENT_NODE : + newnode = createComment(source->getNodeValue()); + break; + case DOMNode::DOCUMENT_TYPE_NODE : + { + // unless this is used as part of cloning a Document + // forbid it for the sake of being compliant to the DOM spec + if (!cloningDoc) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + + DOMDocumentType *srcdoctype = (DOMDocumentType *)source; + DOMDocumentTypeImpl *newdoctype = (DOMDocumentTypeImpl *) + createDocumentType(srcdoctype->getNodeName(), + srcdoctype->getPublicId(), + srcdoctype->getSystemId()); + // Values are on NamedNodeMaps + DOMNamedNodeMap *smap = srcdoctype->getEntities(); + DOMNamedNodeMap *tmap = newdoctype->getEntities(); + if(smap != 0) { + for(XMLSize_t i = 0; i < smap->getLength(); i++) { + tmap->setNamedItem(importNode(smap->item(i), true, cloningDoc)); + } + } + smap = srcdoctype->getNotations(); + tmap = newdoctype->getNotations(); + if (smap != 0) { + for(XMLSize_t i = 0; i < smap->getLength(); i++) { + tmap->setNamedItem(importNode(smap->item(i), true, cloningDoc)); + } + } + const XMLCh* intSubset=srcdoctype->getInternalSubset(); + if(intSubset != 0) { + newdoctype->setInternalSubset(intSubset); + } + + // detect if the DTD being copied is our own implementation, and use the provided methods + try + { + DOMDocumentTypeImpl* docTypeImpl=(DOMDocumentTypeImpl*)(srcdoctype->getFeature(XMLUni::fgXercescInterfaceDOMDocumentTypeImpl, XMLUni::fgZeroLenString)); + if(docTypeImpl) + { + smap = docTypeImpl->getElements(); + tmap = newdoctype->getElements(); + if (smap != 0) { + for(XMLSize_t i = 0; i < smap->getLength(); i++) { + tmap->setNamedItem(importNode(smap->item(i), true, cloningDoc)); + } + } + } + } catch(DOMException&) { + } + + newnode = newdoctype; + } + break; + case DOMNode::DOCUMENT_FRAGMENT_NODE : + newnode = createDocumentFragment(); + // No name, kids carry value + break; + case DOMNode::NOTATION_NODE : + { + DOMNotation *srcnotation=(DOMNotation *)source; + DOMNotationImpl *newnotation = (DOMNotationImpl *)createNotation(source->getNodeName()); + newnotation->setPublicId(srcnotation->getPublicId()); + newnotation->setSystemId(srcnotation->getSystemId()); + newnotation->setBaseURI(srcnotation->getBaseURI()); + newnode=newnotation; + // No name, no value + break; + } + + case DOMNode::DOCUMENT_NODE : // Document can't be child of Document + default: // Unknown node type + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + } + + // If deep, replicate and attach the kids. + if (deep) + for (DOMNode *srckid = source->getFirstChild(); + srckid != 0; + srckid = srckid->getNextSibling()) + { + newnode->appendChild(importNode(srckid, true, cloningDoc)); + } + + if (newnode->getNodeType() == DOMNode::ENTITY_NODE) { + castToNodeImpl(newnode)->setReadOnly(true, true); + errorChecking = oldErrorCheckingFlag; + } + + if (cloningDoc) + { + // we know for sure that the source node is a DOMNodeImpl, as cloningDoc is set to true when + // a DOMDocumentImpl is cloned + castToNodeImpl(source)->callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, source, newnode); + } + else + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_IMPORTED, source, newnode); + + return newnode; +} + +// user data utility +void* DOMDocumentImpl::setUserData(DOMNodeImpl* n, const XMLCh* key, void* data, DOMUserDataHandler* handler) +{ + void* oldData = 0; + unsigned int keyId=fUserDataTableKeys.addOrFind(key); + + if (!fUserDataTable) { + // create the table on heap so that it can be cleaned in destructor + fUserDataTable = new (fMemoryManager) RefHash2KeysTableOf + ( + 109 + , true + , fMemoryManager + ); + } + else { + DOMUserDataRecord* oldDataRecord = fUserDataTable->get((void*)n, keyId); + + if (oldDataRecord) { + oldData = oldDataRecord->getKey(); + fUserDataTable->removeKey((void*)n, keyId); + } + } + + if (data) { + + // clone the key first, and create the DOMUserDataRecord + // create on the heap and adopted by the hashtable which will delete it upon removal. + fUserDataTable->put((void*)n, keyId, new (fMemoryManager) DOMUserDataRecord(data, handler)); + } + else { + RefHash2KeysTableOfEnumerator enumKeys(fUserDataTable, false, fMemoryManager); + enumKeys.setPrimaryKey(n); + if (!enumKeys.hasMoreElements()) + n->hasUserData(false); + } + + return oldData; +} + +void* DOMDocumentImpl::getUserData(const DOMNodeImpl* n, const XMLCh* key) const +{ + if (fUserDataTable) { + unsigned int keyId=fUserDataTableKeys.getId(key); + if(keyId!=0) { + DOMUserDataRecord* dataRecord = fUserDataTable->get((void*)n, keyId); + if (dataRecord) + return dataRecord->getKey(); + } + } + + return 0; +} + +void DOMDocumentImpl::callUserDataHandlers(const DOMNodeImpl* n, DOMUserDataHandler::DOMOperationType operation, const DOMNode* src, DOMNode* dst) const +{ + if (fUserDataTable) { + RefHash2KeysTableOfEnumerator userDataEnum(fUserDataTable, false, fMemoryManager); + userDataEnum.setPrimaryKey(n); + // Create a snapshot of the handlers to be called, as the "handle" callback could be invalidating the enumerator by calling + // setUserData on the dst node + ValueVectorOf< int > snapshot(3, fMemoryManager); + while (userDataEnum.hasMoreElements()) { + // get the key + void* key; + int key2; + userDataEnum.nextElementKey(key,key2); + snapshot.addElement(key2); + } + ValueVectorEnumerator< int > snapshotEnum(&snapshot); + while(snapshotEnum.hasMoreElements()) + { + int key2=snapshotEnum.nextElement(); + + // get the DOMUserDataRecord + DOMUserDataRecord* userDataRecord = fUserDataTable->get((void*)n,key2); + + // get the handler + DOMUserDataHandler* handler = userDataRecord->getValue(); + + if (handler) { + // get the data + void* data = userDataRecord->getKey(); + const XMLCh* userKey = fUserDataTableKeys.getValueForId(key2); + handler->handle(operation, userKey, data, src, dst); + } + } + // if the operation is NODE_DELETED, we in fact should remove the data from the table + if (operation == DOMUserDataHandler::NODE_DELETED) + fUserDataTable->removeKey((void*)n); + } +} + + +void DOMDocumentImpl::transferUserData(DOMNodeImpl* n1, DOMNodeImpl* n2) +{ + if (fUserDataTable) { + fUserDataTable->transferElement((void*)n1, (void*)n2); + n1->hasUserData(false); + n2->hasUserData(true); + } +} + + +DOMNode* DOMDocumentImpl::renameNode(DOMNode* n, const XMLCh* namespaceURI, const XMLCh* name) +{ + if (n->getOwnerDocument() != this) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, getMemoryManager()); + + switch (n->getNodeType()) { + case ELEMENT_NODE: + return ((DOMElementImpl*)n)->rename(namespaceURI, name); + case ATTRIBUTE_NODE: + return ((DOMAttrImpl*)n)->rename(namespaceURI, name); + default: + break; + } + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + + return 0; +} + +void DOMDocumentImpl::release() +{ + DOMDocument* doc = (DOMDocument*) this; + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + + // notify userdatahandler first, if we have some + if (fUserDataTable) + releaseDocNotifyUserData(this); + + // release the docType in case it was created from heap + if (fDocType) { + castToNodeImpl(fDocType)->isToBeReleased(true); + fDocType->release(); + } + + // delete the document memory pool + delete doc; +} + +void DOMDocumentImpl::releaseDocNotifyUserData(DOMNode* object) +{ + DOMNode *child = object->getFirstChild(); + + while( child != 0) + { + + DOMNamedNodeMap *attrlist=child->getAttributes(); + + if(attrlist!=0) + for(XMLSize_t i=0;igetLength();++i) + releaseDocNotifyUserData(attrlist->item(i)); + + releaseDocNotifyUserData(child); + child = child->getNextSibling(); + } + + castToNodeImpl(object)->callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); +} + +void DOMDocumentImpl::release(DOMNode* object, DOMMemoryManager::NodeObjectType type) +{ + if (!fRecycleNodePtr) + fRecycleNodePtr = new (fMemoryManager) RefArrayOf (15, fMemoryManager); + + if (!fRecycleNodePtr->operator[](type)) + fRecycleNodePtr->operator[](type) = new (fMemoryManager) RefStackOf (15, false, fMemoryManager); + + fRecycleNodePtr->operator[](type)->push(object); +} + +void DOMDocumentImpl::releaseBuffer(DOMBuffer* buffer) +{ + if (!fRecycleBufferPtr) + fRecycleBufferPtr = new (fMemoryManager) RefStackOf (15, false, fMemoryManager); + + fRecycleBufferPtr->push(buffer); +} + +DOMBuffer* DOMDocumentImpl::popBuffer(XMLSize_t nMinSize) +{ + if (!fRecycleBufferPtr || fRecycleBufferPtr->empty()) + return 0; + + for(XMLSize_t index=fRecycleBufferPtr->size()-1;index>0;index--) + if(fRecycleBufferPtr->elementAt(index)->getCapacity()>=nMinSize) + return fRecycleBufferPtr->popAt(index); + // if we didn't find a buffer big enough, get the last one + return fRecycleBufferPtr->pop(); +} + + +void * DOMDocumentImpl::allocate(XMLSize_t amount, DOMMemoryManager::NodeObjectType type) +{ + if (!fRecycleNodePtr) + return allocate(amount); + + DOMNodePtr* ptr = fRecycleNodePtr->operator[](type); + if (!ptr || ptr->empty()) + return allocate(amount); + + return (void*) ptr->pop(); + +} + +bool DOMDocumentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const +{ + // check for '+DOMMemoryManager' + if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfaceDOMMemoryManager)) + return true; + if(feature && *feature) + { + if((*feature==chPlus && XMLString::equals(feature+1, XMLUni::fgXercescInterfaceDOMDocumentImpl)) || + XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentImpl)) + return true; + } + return fNode.isSupported (feature, version); +} + +void* DOMDocumentImpl::getFeature(const XMLCh* feature, const XMLCh* version) const +{ + if(XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMMemoryManager)) + return (DOMMemoryManager*)this; + if(XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentImpl)) + return (DOMDocumentImpl*)this; + return fNode.getFeature(feature,version); +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMDocumentImpl.hpp b/include/xercesc/dom/impl/DOMDocumentImpl.hpp new file mode 100644 index 0000000..77abee0 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDocumentImpl.hpp @@ -0,0 +1,507 @@ +/* + * 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: DOMDocumentImpl.hpp 1662888 2015-02-28 02:26:43Z scantor $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DOMNodeImpl.hpp" +#include "DOMStringPool.hpp" +#include "DOMParentNode.hpp" +#include "DOMDeepNodeListPool.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMAttrImpl; +class DOMCDATASectionImpl; +class DOMCommentImpl; +class DOMConfiguration; +class DOMDeepNodeListImpl; +class DOMDocumentFragmentImpl; +class DOMDocumentTypeImpl; +class DOMElementImpl; +class DOMEntityImpl; +class DOMEntityReferenceImpl; +class DOMNotationImpl; +class DOMProcessingInstructionImpl; +class DOMTextImpl; +class DOMNodeIteratorImpl; +class DOMNormalizer; +class DOMTreeWalkerImpl; +class DOMNodeFilter; +class DOMNodeFilterImpl; +class DOMImplementation; +class DOMNodeIDMap; +class DOMRangeImpl; +class DOMBuffer; +class MemoryManager; +class XPathNSResolver; +class XPathExpression; + +typedef RefVectorOf Ranges; +typedef RefVectorOf NodeIterators; +typedef KeyRefPair DOMUserDataRecord; +typedef RefStackOf DOMNodePtr; + +class CDOM_EXPORT DOMDocumentImpl: public XMemory, public DOMMemoryManager, public DOMDocument { +public: + // ----------------------------------------------------------------------- + // data + // ----------------------------------------------------------------------- + DOMNodeImpl fNode; // Implements common node functionality. + DOMParentNode fParent; // Implements common parent node functionality + DOMNodeIDMap* fNodeIDMap; // for use by GetElementsById(). + +public: + DOMDocumentImpl(DOMImplementation* domImpl, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + DOMDocumentImpl(const XMLCh* namespaceURI, //DOM Level 2 + const XMLCh* qualifiedName, + DOMDocumentType* doctype, + DOMImplementation* domImpl, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual ~DOMDocumentImpl(); + + void setDocumentType(DOMDocumentType *doctype); + +public: + // Add all functions that are pure virtual in DOMNODE + DOMNODE_FUNCTIONS; + +public: + // Add all functions that are pure virtual in DOMDocument + virtual DOMAttr* createAttribute(const XMLCh *name); + virtual DOMCDATASection* createCDATASection(const XMLCh *data); + virtual DOMComment* createComment(const XMLCh *data); + virtual DOMDocumentFragment* createDocumentFragment(); + virtual DOMDocumentType* createDocumentType(const XMLCh *name); + virtual DOMDocumentType* createDocumentType(const XMLCh *qName, + const XMLCh *publicId, + const XMLCh *systemId); + virtual DOMElement* createElement(const XMLCh * tagName); + virtual DOMElement* createElementNoCheck(const XMLCh *tagName); + virtual DOMEntity* createEntity(const XMLCh * name); + virtual DOMEntityReference* createEntityReference(const XMLCh * name); + virtual DOMNotation* createNotation(const XMLCh * name); + virtual DOMProcessingInstruction* createProcessingInstruction(const XMLCh * target, const XMLCh * data); + virtual DOMText* createTextNode(const XMLCh * data); + virtual DOMDocumentType* getDoctype() const; + virtual DOMElement* getDocumentElement() const; + virtual DOMNodeList* getElementsByTagName(const XMLCh * tagname) const; + virtual DOMImplementation* getImplementation() const; + bool isXMLName(const XMLCh * s); + virtual DOMNodeIterator* createNodeIterator(DOMNode *root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* filter, + bool entityReferenceExpansion); + virtual DOMTreeWalker* createTreeWalker(DOMNode *root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* filter, + bool entityReferenceExpansion); + + + virtual DOMRange* createRange(); + virtual Ranges* getRanges() const; //non-standard api + virtual NodeIterators* getNodeIterators() const; //non-standard api + virtual void removeRange(DOMRangeImpl* range); //non-standard api + virtual void removeNodeIterator(DOMNodeIteratorImpl* nodeIterator); //non-standard api + + virtual DOMXPathExpression* createExpression(const XMLCh *expression, + const DOMXPathNSResolver *resolver); + virtual DOMXPathNSResolver* createNSResolver(const DOMNode *nodeResolver); + virtual DOMXPathResult* evaluate(const XMLCh *expression, + const DOMNode *contextNode, + const DOMXPathNSResolver *resolver, + DOMXPathResult::ResultType type, + DOMXPathResult* result); + + + // Extension to be called by the Parser + DOMEntityReference* createEntityReferenceByParser(const XMLCh * name); + + // Add all functions that are pure virtual in DOMMemoryManager + virtual XMLSize_t getMemoryAllocationBlockSize() const; + virtual void setMemoryAllocationBlockSize(XMLSize_t size); + virtual void* allocate(XMLSize_t amount); + virtual void* allocate(XMLSize_t amount, DOMMemoryManager::NodeObjectType type); + virtual void release(DOMNode* object, DOMMemoryManager::NodeObjectType type); + virtual XMLCh* cloneString(const XMLCh *src); + + // + // Functions to keep track of document mutations, so that node list chached + // information can be invalidated. One global changes counter per document. + // + virtual void changed(); + virtual int changes() const; + + /** + * Sets whether the DOM implementation performs error checking + * upon operations. Turning off error checking only affects + * the following DOM checks: + *

    + *
  • Checking strings to make sure that all characters are + * legal XML characters + *
  • Hierarchy checking such as allowed children, checks for + * cycles, etc. + *
+ *

+ * Turning off error checking does not turn off the + * following checks: + *

    + *
  • Read only checks + *
  • Checks related to DOM events + *
+ */ + inline void setErrorChecking(bool check) { + errorChecking = check; + } + + /** + * Returns true if the DOM implementation performs error checking. + */ + inline bool getErrorChecking() const { + return errorChecking; + } + + //Introduced in DOM Level 2 + virtual DOMNode* importNode(const DOMNode *source, bool deep); + virtual DOMElement* createElementNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName); + virtual DOMElement* createElementNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + const XMLFileLoc lineNo, + const XMLFileLoc columnNo); + virtual DOMAttr* createAttributeNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName); + virtual DOMNodeList* getElementsByTagNameNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual DOMElement* getElementById(const XMLCh *elementId) const; + + //Introduced in DOM Level 3 + virtual const XMLCh* getInputEncoding() const; + virtual const XMLCh* getXmlEncoding() const; + virtual bool getXmlStandalone() const; + virtual void setXmlStandalone(bool standalone); + virtual const XMLCh* getXmlVersion() const; + virtual void setXmlVersion(const XMLCh* version); + virtual const XMLCh* getDocumentURI() const; + virtual void setDocumentURI(const XMLCh* documentURI); + virtual bool getStrictErrorChecking() const; + virtual void setStrictErrorChecking(bool strictErrorChecking); + virtual DOMNode* adoptNode(DOMNode* source); + virtual void normalizeDocument(); + virtual DOMConfiguration* getDOMConfig() const; + + void setInputEncoding(const XMLCh* actualEncoding); + void setXmlEncoding(const XMLCh* encoding); + // helper functions to prevent storing userdata pointers on every node. + void* setUserData(DOMNodeImpl* n, + const XMLCh* key, + void* data, + DOMUserDataHandler* handler); + void* getUserData(const DOMNodeImpl* n, + const XMLCh* key) const; + void callUserDataHandlers(const DOMNodeImpl* n, + DOMUserDataHandler::DOMOperationType operation, + const DOMNode* src, + DOMNode* dst) const; + void transferUserData(DOMNodeImpl* n1, DOMNodeImpl* n2); + + DOMNode* renameNode(DOMNode* n, + const XMLCh* namespaceURI, + const XMLCh* name); + + //Return the index > 0 of ':' in the given qualified name qName="prefix:localName". + //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd". + static int indexofQualifiedName(const XMLCh * qName); + static bool isKidOK(DOMNode *parent, DOMNode *child); + + inline DOMNodeIDMap* getNodeIDMap() {return fNodeIDMap;}; + + + // + // Memory Management Functions. All memory is allocated by and owned by + // a document, and is not recovered until the + // document itself is deleted. + // + const XMLCh* getPooledString(const XMLCh*); + const XMLCh* getPooledNString(const XMLCh*, XMLSize_t); + void deleteHeap(); + void releaseDocNotifyUserData(DOMNode* object); + void releaseBuffer(DOMBuffer* buffer); + DOMBuffer* popBuffer(XMLSize_t nMinSize); + MemoryManager* getMemoryManager() const; + + // Factory methods for getting/creating node lists. + // Because nothing is ever deleted, the implementation caches and recycles + // previously used instances of DOMDeepNodeList + // + DOMNodeList* getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName); + DOMNodeList* getDeepNodeList(const DOMNode *rootNode, //DOM Level 2 + const XMLCh *namespaceURI, + const XMLCh *localName); + +protected: + //Internal helper functions + virtual DOMNode* importNode(const DOMNode *source, bool deep, bool cloningNode); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMDocumentImpl(const DOMDocumentImpl &); + DOMDocumentImpl & operator = (const DOMDocumentImpl &); + +protected: + // ----------------------------------------------------------------------- + // data + // ----------------------------------------------------------------------- + // New data introduced in DOM Level 3 + const XMLCh* fInputEncoding; + const XMLCh* fXmlEncoding; + bool fXmlStandalone; + const XMLCh* fXmlVersion; + const XMLCh* fDocumentURI; + DOMConfiguration* fDOMConfiguration; + + XMLStringPool fUserDataTableKeys; + RefHash2KeysTableOf* fUserDataTable; + + + // Per-Document heap Variables. + // The heap consists of one or more biggish blocks which are + // sub-allocated for individual allocations of nodes, strings, etc. + // The big blocks form a linked list, allowing them to be located for deletion. + // + // There is no provision for deleting suballocated blocks, other than + // deleting the entire heap when the document is deleted. + // + // There is no header on individual sub-allocated blocks. + // The header on big blocks consists only of a single back pointer to + // the previously allocated big block (our linked list of big blocks) + // + // + // revisit - this heap should be encapsulated into its own + // class, rather than hanging naked on Document. + // + void* fCurrentBlock; + char* fFreePtr; + XMLSize_t fFreeBytesRemaining, + fHeapAllocSize; + + // To recycle the DOMNode pointer + RefArrayOf* fRecycleNodePtr; + + // To recycle DOMBuffer pointer + RefStackOf* fRecycleBufferPtr; + + // Pool of DOMNodeList for getElementsByTagName + DOMDeepNodeListPool* fNodeListPool; + + // Other data + DOMDocumentType* fDocType; + DOMElement* fDocElement; + + DOMStringPoolEntry** fNameTable; + XMLSize_t fNameTableSize; + + DOMNormalizer* fNormalizer; + Ranges* fRanges; + NodeIterators* fNodeIterators; + MemoryManager* fMemoryManager; // configurable memory manager + DOMImplementation* fDOMImplementation; + + int fChanges; + bool errorChecking; // Bypass error checking. + +}; + +inline MemoryManager* DOMDocumentImpl::getMemoryManager() const +{ + return fMemoryManager; +} + +inline const XMLCh* DOMDocumentImpl::getPooledString(const XMLCh *in) +{ + if (in == 0) + return 0; + + DOMStringPoolEntry **pspe; + DOMStringPoolEntry *spe; + + XMLSize_t inHash = XMLString::hash(in, fNameTableSize); + pspe = &fNameTable[inHash]; + while (*pspe != 0) + { + if (XMLString::equals((*pspe)->fString, in)) + return (*pspe)->fString; + pspe = &((*pspe)->fNext); + } + + // This string hasn't been seen before. Add it to the pool. + // + + // Compute size to allocate. Note that there's 1 char of string + // declared in the struct, so we don't need to add one again to + // account for the trailing null. + // + XMLSize_t n = XMLString::stringLen(in); + XMLSize_t sizeToAllocate = sizeof(DOMStringPoolEntry) + n*sizeof(XMLCh); + *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate); + spe->fNext = 0; + XMLString::copyString((XMLCh*)spe->fString, in); + + return spe->fString; +} + +inline const XMLCh* DOMDocumentImpl::getPooledNString(const XMLCh *in, XMLSize_t n) +{ + if (in == 0) + return 0; + + DOMStringPoolEntry **pspe; + DOMStringPoolEntry *spe; + + XMLSize_t inHash = XMLString::hashN(in, n, fNameTableSize); + pspe = &fNameTable[inHash]; + while (*pspe != 0) + { + if (XMLString::stringLen((*pspe)->fString) == n && XMLString::equalsN((*pspe)->fString, in, n)) + return (*pspe)->fString; + pspe = &((*pspe)->fNext); + } + + // This string hasn't been seen before. Add it to the pool. + // + + // Compute size to allocate. Note that there's 1 char of string + // declared in the struct, so we don't need to add one again to + // account for the trailing null. + // + XMLSize_t sizeToAllocate = sizeof(DOMStringPoolEntry) + n*sizeof(XMLCh); + *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate); + spe->fNext = 0; + XMLString::copyNString((XMLCh*)spe->fString, in, n); + + return spe->fString; +} + +inline int DOMDocumentImpl::indexofQualifiedName(const XMLCh* name) +{ + int i = 0; + int colon = -1; + int colon_count = 0; + for (; *name != 0; ++i, ++name) + { + if (*name == chColon) + { + ++colon_count; + colon = i; + } + } + + if (i == 0 || colon == 0 || colon == (i - 1) || colon_count > 1) + return -1; + + return colon != -1 ? colon : 0; +} + +XERCES_CPP_NAMESPACE_END + +// --------------------------------------------------------------------------- +// +// Operator new. Global overloaded version, lets any object be allocated on +// the heap owned by a document. +// +// --------------------------------------------------------------------------- +inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *doc, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type) +{ + void *p = doc->allocate(amt, type); + return p; +} + +inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type) +{ + XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager* mgr=(XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager*)doc->getFeature(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgXercescInterfaceDOMMemoryManager,0); + void* p=0; + if(mgr) + p = mgr->allocate(amt, type); + return p; +} + +inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *doc) +{ + void* p = doc->allocate(amt); + return p; +} + +inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc) +{ + XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager* mgr=(XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager*)doc->getFeature(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgXercescInterfaceDOMMemoryManager,0); + void* p=0; + if(mgr) + p = mgr->allocate(amt); + return p; +} + +// --------------------------------------------------------------------------- +// For DOM: +// Bypass compiler warning: +// no matching operator delete found; memory will not be freed if initialization throws an exception +// --------------------------------------------------------------------------- +#if !defined(XERCES_NO_MATCHING_DELETE_OPERATOR) +inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * /*doc*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType /*type*/) +{ + return; +} +inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * /*doc*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType /*type*/) +{ + return; +} + +inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * /*doc*/) +{ + return; +} +inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * /*doc*/) +{ + return; +} +#endif + +#endif diff --git a/include/xercesc/dom/impl/DOMDocumentTypeImpl.cpp b/include/xercesc/dom/impl/DOMDocumentTypeImpl.cpp new file mode 100644 index 0000000..9d5469e --- /dev/null +++ b/include/xercesc/dom/impl/DOMDocumentTypeImpl.cpp @@ -0,0 +1,555 @@ +/* + * 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: DOMDocumentTypeImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#include "DOMDocumentTypeImpl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DOMNamedNodeMapImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMCasts.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +static DOMDocument* sDocument = 0; +static XMLMutex* sDocumentMutex = 0; + +void XMLInitializer::initializeDOMDocumentTypeImpl() +{ + sDocumentMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager); + + static const XMLCh gCoreStr[] = { chLatin_C, chLatin_o, chLatin_r, chLatin_e, chNull }; + DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(gCoreStr); + sDocument = impl->createDocument(); // document type object (DTD). +} + +void XMLInitializer::terminateDOMDocumentTypeImpl() +{ + sDocument->release(); + sDocument = 0; + + delete sDocumentMutex; + sDocumentMutex = 0; +} + +DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc, + const XMLCh *dtName, + bool heap) + : fNode(ownerDoc), + fParent(ownerDoc), + fName(0), + fEntities(0), + fNotations(0), + fElements(0), + fPublicId(0), + fSystemId(0), + fInternalSubset(0), + fIntSubsetReading(false), + fIsCreatedFromHeap(heap) +{ + if (ownerDoc) + { + fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(dtName); + fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this); + fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this); + fElements = new (ownerDoc) DOMNamedNodeMapImpl(this); + } + else + { + XMLMutexLock lock(sDocumentMutex); + DOMDocument* doc = sDocument; + fName = ((DOMDocumentImpl *)doc)->getPooledString(dtName); + fEntities = new (doc) DOMNamedNodeMapImpl(this); + fNotations= new (doc) DOMNamedNodeMapImpl(this); + fElements = new (doc) DOMNamedNodeMapImpl(this); + } +} + + +//Introduced in DOM Level 2 +DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc, + const XMLCh *qualifiedName, + const XMLCh *pubId, + const XMLCh *sysId, + bool heap) + : fNode(ownerDoc), + fParent(ownerDoc), + fName(0), + fEntities(0), + fNotations(0), + fElements(0), + fPublicId(0), + fSystemId(0), + fInternalSubset(0), + fIntSubsetReading(false), + fIsCreatedFromHeap(heap) +{ + int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); + if (index < 0) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + else if (index > 0) + { + // we have to make sure the qualifiedName has correct prefix and localName + // although we don't really to store them separately + XMLCh* newName; + XMLCh temp[256]; + if (index >= 255) + newName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate + ( + (XMLString::stringLen(qualifiedName)+1) * sizeof(XMLCh) + );//new XMLCh[XMLString::stringLen(qualifiedName)+1]; + else + newName = temp; + + XMLString::copyNString(newName, qualifiedName, index); + newName[index] = chNull; + + // Before we carry on, we should check if the prefix or localName are valid XMLName + if (ownerDoc) { + if (!((DOMDocumentImpl*)ownerDoc)->isXMLName(newName) || !((DOMDocumentImpl*)ownerDoc)->isXMLName(qualifiedName+index+1)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + } + else { + // document is not there yet, so assume XML 1.0 + if (!XMLChar1_0::isValidName(newName) || !XMLChar1_0::isValidName(qualifiedName+index+1)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + } + + if (index >= 255) + XMLPlatformUtils::fgMemoryManager->deallocate(newName);//delete[] newName; + } + + if (ownerDoc) + { + DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc; + fPublicId = docImpl->cloneString(pubId); + fSystemId = docImpl->cloneString(sysId); + fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(qualifiedName); + fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this); + fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this); + fElements = new (ownerDoc) DOMNamedNodeMapImpl(this); + } + else + { + XMLMutexLock lock(sDocumentMutex); + DOMDocument* doc = sDocument; + fPublicId = ((DOMDocumentImpl*) doc)->cloneString(pubId); + fSystemId = ((DOMDocumentImpl*) doc)->cloneString(sysId); + fName = ((DOMDocumentImpl*) doc)->getPooledString(qualifiedName); + fEntities = new (doc) DOMNamedNodeMapImpl(this); + fNotations= new (doc) DOMNamedNodeMapImpl(this); + fElements = new (doc) DOMNamedNodeMapImpl(this); + } +} + + +DOMDocumentTypeImpl::DOMDocumentTypeImpl(const DOMDocumentTypeImpl &other, bool heap, bool deep) + : fNode(other.fNode), + fParent(other.fParent), + fChild(other.fChild), + fName(0), + fEntities(0), + fNotations(0), + fElements(0), + fPublicId(0), + fSystemId(0), + fInternalSubset(0), + fIntSubsetReading(other.fIntSubsetReading), + fIsCreatedFromHeap(heap) +{ + fName = other.fName; + + //DOM Level 2 + fPublicId = other.fPublicId; + fSystemId = other.fSystemId; + fInternalSubset = other.fInternalSubset; + + if ((DOMDocumentImpl *)this->fNode.getOwnerDocument() && deep) + fParent.cloneChildren(&other); + + fEntities = other.fEntities->cloneMap(this); + fNotations= other.fNotations->cloneMap(this); + fElements = other.fElements->cloneMap(this); +} + + +DOMDocumentTypeImpl::~DOMDocumentTypeImpl() +{ +} + + +DOMNode *DOMDocumentTypeImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = 0; + DOMDocument* doc = castToNodeImpl(this)->getOwnerDocument(); + if (doc != 0) + newNode = new (doc, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep); + else + { + XMLMutexLock lock(sDocumentMutex); + newNode = new (sDocument, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep); + } + + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + +/** + * NON-DOM + * set the ownerDocument of this node and its children + */ +void DOMDocumentTypeImpl::setOwnerDocument(DOMDocument *doc) { + + if (castToNodeImpl(this)->getOwnerDocument()) { + fNode.setOwnerDocument(doc); + fParent.setOwnerDocument(doc); + } + else { + if (doc) { + DOMDocumentImpl *docImpl = (DOMDocumentImpl *)doc; + + fPublicId = docImpl->cloneString(fPublicId); + fSystemId = docImpl->cloneString(fSystemId); + fInternalSubset = docImpl->cloneString(fInternalSubset); + fName = docImpl->getPooledString(fName); + + fNode.setOwnerDocument(doc); + fParent.setOwnerDocument(doc); + + DOMNamedNodeMapImpl* entitiesTemp = fEntities->cloneMap(this); + DOMNamedNodeMapImpl* notationsTemp = fNotations->cloneMap(this); + DOMNamedNodeMapImpl* elementsTemp = fElements->cloneMap(this); + + fEntities = entitiesTemp; + fNotations = notationsTemp; + fElements = elementsTemp; + } + } +} + +const XMLCh * DOMDocumentTypeImpl::getNodeName() const +{ + return fName; +} + + +DOMNode::NodeType DOMDocumentTypeImpl::getNodeType() const { + return DOMNode::DOCUMENT_TYPE_NODE; +} + + +DOMNamedNodeMap *DOMDocumentTypeImpl::getEntities() const +{ + return fEntities; +} + + + +const XMLCh * DOMDocumentTypeImpl::getName() const +{ + return fName; +} + + +DOMNamedNodeMap *DOMDocumentTypeImpl::getNotations() const +{ + return fNotations; +} + + +DOMNamedNodeMap *DOMDocumentTypeImpl::getElements() const +{ + return fElements; +} + + +void DOMDocumentTypeImpl::setNodeValue(const XMLCh *val) +{ + fNode.setNodeValue(val); +} + + +void DOMDocumentTypeImpl::setReadOnly(bool readOnl, bool deep) +{ + fNode.setReadOnly(readOnl,deep); + if (fEntities) + fEntities->setReadOnly(readOnl,true); + if (fNotations) + fNotations->setReadOnly(readOnl,true); +} + + +//Introduced in DOM Level 2 + +const XMLCh * DOMDocumentTypeImpl::getPublicId() const +{ + return fPublicId; +} + + +const XMLCh * DOMDocumentTypeImpl::getSystemId() const +{ + return fSystemId; +} + + +const XMLCh * DOMDocumentTypeImpl::getInternalSubset() const +{ + return fInternalSubset; +} + +bool DOMDocumentTypeImpl::isIntSubsetReading() const +{ + return fIntSubsetReading; +} + + +//set functions + +void DOMDocumentTypeImpl::setPublicId(const XMLCh *value) +{ + // revist. Why shouldn't 0 be assigned like any other value? + if (value == 0) + return; + + DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument(); + if (doc != 0) + fPublicId = doc->cloneString(value); + else { + XMLMutexLock lock(sDocumentMutex); + fPublicId = ((DOMDocumentImpl *)sDocument)->cloneString(value); + } +} + +void DOMDocumentTypeImpl::setSystemId(const XMLCh *value) +{ + DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument(); + if (doc != 0) + fSystemId = doc->cloneString(value); + else { + XMLMutexLock lock(sDocumentMutex); + fSystemId = ((DOMDocumentImpl *)sDocument)->cloneString(value); + } +} + +void DOMDocumentTypeImpl::setInternalSubset(const XMLCh *value) +{ + DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument(); + if (doc != 0) + fInternalSubset = doc->cloneString(value); + else { + XMLMutexLock lock(sDocumentMutex); + fInternalSubset = ((DOMDocumentImpl *)sDocument)->cloneString(value); + } +} + +void DOMDocumentTypeImpl::release() +{ + if (fNode.isOwned()) { + if (fNode.isToBeReleased()) { + // we are calling from documnet.release() which will notify the user data handler + if (fIsCreatedFromHeap) { + DOMDocumentType* docType = this; + delete docType; + } + } + else + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } + else { + if (fIsCreatedFromHeap) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + DOMDocumentType* docType = this; + delete docType; + } + else { + DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + doc->release(this, DOMMemoryManager::DOCUMENT_TYPE_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } + } + } +} + + +// +// Delegation for functions inherited from Node +// + + DOMNode* DOMDocumentTypeImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } + DOMNamedNodeMap* DOMDocumentTypeImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMDocumentTypeImpl::getChildNodes() const {return fParent.getChildNodes (); } + DOMNode* DOMDocumentTypeImpl::getFirstChild() const {return fParent.getFirstChild (); } + DOMNode* DOMDocumentTypeImpl::getLastChild() const {return fParent.getLastChild (); } + const XMLCh* DOMDocumentTypeImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMDocumentTypeImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMDocumentTypeImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMDocumentTypeImpl::getNodeValue() const {return fNode.getNodeValue (); } + DOMDocument* DOMDocumentTypeImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } + const XMLCh* DOMDocumentTypeImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMDocumentTypeImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMDocumentTypeImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMDocumentTypeImpl::hasChildNodes() const {return fParent.hasChildNodes (); } + DOMNode* DOMDocumentTypeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fParent.insertBefore (newChild, refChild); } + void DOMDocumentTypeImpl::normalize() {fParent.normalize (); } + DOMNode* DOMDocumentTypeImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } + DOMNode* DOMDocumentTypeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fParent.replaceChild (newChild, oldChild); } + void DOMDocumentTypeImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMDocumentTypeImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMDocumentTypeImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + void* DOMDocumentTypeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMDocumentTypeImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + const XMLCh* DOMDocumentTypeImpl::getBaseURI() const {return fNode.getBaseURI(); } + short DOMDocumentTypeImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMDocumentTypeImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMDocumentTypeImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMDocumentTypeImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMDocumentTypeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMDocumentTypeImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + + +bool DOMDocumentTypeImpl::isEqualNode(const DOMNode* arg) const +{ + if (isSameNode(arg)) { + return true; + } + + if (!fNode.isEqualNode(arg)) { + return false; + } + + DOMDocumentType* argDT = (DOMDocumentType*) arg; + // check the string values + if (!getPublicId()) { + if (argDT->getPublicId()) { + return false; + } + } + else if (!XMLString::equals(getPublicId(), argDT->getPublicId())) { + return false; + } + + if (!getSystemId()) { + if (argDT->getSystemId()) { + return false; + } + } + else if (!XMLString::equals(getSystemId(), argDT->getSystemId())) { + return false; + } + + if (!getInternalSubset()) { + if (argDT->getInternalSubset()) { + return false; + } + } + else if (!XMLString::equals(getInternalSubset(), argDT->getInternalSubset())) { + return false; + } + + // check the notations + if (getNotations()) { + if (!argDT->getNotations()) + return false; + + DOMNamedNodeMap* map1 = getNotations(); + DOMNamedNodeMap* map2 = argDT->getNotations(); + + XMLSize_t len = map1->getLength(); + if (len != map2->getLength()) { + return false; + } + for (XMLSize_t i = 0; i < len; i++) { + DOMNode* n1 = map1->item(i); + DOMNode* n2 = map2->getNamedItem(n1->getNodeName()); + if (!n2 || !n1->isEqualNode(n2)) { + return false; + } + } + } + else { + if (argDT->getNotations()) + return false; + } + + // check the entities + if (getEntities()) { + if (!argDT->getEntities()) + return false; + + DOMNamedNodeMap* map1 = getEntities(); + DOMNamedNodeMap* map2 = argDT->getEntities(); + + XMLSize_t len = map1->getLength(); + if (len != map2->getLength()) { + return false; + } + for (XMLSize_t i = 0; i < len; i++) { + DOMNode* n1 = map1->item(i); + DOMNode* n2 = map2->getNamedItem(n1->getNodeName()); + if (!n2 || !n1->isEqualNode(n2)) { + return false; + } + } + } + else { + if (argDT->getEntities()) + return false; + } + + return fParent.isEqualNode(arg); +} + +bool DOMDocumentTypeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const +{ + // check for 'DOMDocumentTypeImpl' or '+DOMDocumentTypeImpl' + if(feature && *feature) + { + if((*feature==chPlus && XMLString::equals(feature+1, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) || + XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) + return true; + } + return fNode.isSupported (feature, version); +} + +void* DOMDocumentTypeImpl::getFeature(const XMLCh* feature, const XMLCh* version) const +{ + if(XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) + return (DOMDocumentTypeImpl*)this; + return fNode.getFeature(feature,version); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMDocumentTypeImpl.hpp b/include/xercesc/dom/impl/DOMDocumentTypeImpl.hpp new file mode 100644 index 0000000..3716411 --- /dev/null +++ b/include/xercesc/dom/impl/DOMDocumentTypeImpl.hpp @@ -0,0 +1,107 @@ +/* + * 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: DOMDocumentTypeImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTTYPEIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMDOCUMENTTYPEIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + + +#include +#include +#include "DOMNodeImpl.hpp" +#include "DOMChildNode.hpp" +#include "DOMParentNode.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNamedNodeMapImpl; + +class CDOM_EXPORT DOMDocumentTypeImpl: public DOMDocumentType { +protected: + DOMNodeImpl fNode; + DOMParentNode fParent; + DOMChildNode fChild; + + const XMLCh * fName; + DOMNamedNodeMapImpl* fEntities; + DOMNamedNodeMapImpl* fNotations; + DOMNamedNodeMapImpl* fElements; + const XMLCh * fPublicId; + const XMLCh * fSystemId; + const XMLCh * fInternalSubset; + + bool fIntSubsetReading; + bool fIsCreatedFromHeap; + + virtual void setPublicId(const XMLCh * value); + virtual void setSystemId(const XMLCh * value); + virtual void setInternalSubset(const XMLCh *value); + bool isIntSubsetReading() const; + + friend class AbstractDOMParser; + friend class DOMDocumentImpl; + +public: + DOMDocumentTypeImpl(DOMDocument *, const XMLCh *, bool); + DOMDocumentTypeImpl(DOMDocument *, + const XMLCh *qualifiedName, //DOM Level 2 + const XMLCh *publicId, const XMLCh *systemId, bool); + DOMDocumentTypeImpl(const DOMDocumentTypeImpl &other, bool heap, bool deep=false); + virtual ~DOMDocumentTypeImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + virtual void setOwnerDocument(DOMDocument *doc); + virtual DOMNamedNodeMap * getEntities() const; + virtual const XMLCh * getName() const; + virtual DOMNamedNodeMap * getNotations() const; + virtual DOMNamedNodeMap * getElements() const; + virtual void setReadOnly(bool readOnly, bool deep); + + //Introduced in DOM Level 2 + + virtual const XMLCh * getPublicId() const; + virtual const XMLCh * getSystemId() const; + virtual const XMLCh * getInternalSubset() const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMDocumentTypeImpl & operator = (const DOMDocumentTypeImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMElementImpl.cpp b/include/xercesc/dom/impl/DOMElementImpl.cpp new file mode 100644 index 0000000..8ddc78b --- /dev/null +++ b/include/xercesc/dom/impl/DOMElementImpl.cpp @@ -0,0 +1,880 @@ +/* + * 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: DOMElementImpl.cpp 901107 2010-01-20 08:45:02Z borisk $ + */ + +#include "DOMElementImpl.hpp" + +#include +#include +#include +#include +#include + +#include "DOMAttrMapImpl.hpp" +#include "DOMAttrImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMParentNode.hpp" +#include "DOMCasts.hpp" +#include "DOMElementNSImpl.hpp" +#include "DOMTypeInfoImpl.hpp" + +#include "DOMDocumentTypeImpl.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMAttr; + +DOMElementImpl::DOMElementImpl(DOMDocument *ownerDoc, const XMLCh *eName) + : fNode(ownerDoc), fParent(ownerDoc), fAttributes(0), fDefaultAttributes(0) +{ + DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc; + fName = docImpl->getPooledString(eName); + setupDefaultAttributes(); + if (!fDefaultAttributes) { + fDefaultAttributes = new (docImpl) DOMAttrMapImpl(this); + fAttributes = new (docImpl) DOMAttrMapImpl(this); + } + else { + fAttributes = new (docImpl) DOMAttrMapImpl(this, fDefaultAttributes); + } +} + + +DOMElementImpl::DOMElementImpl(const DOMElementImpl &other, bool deep) + : DOMElement(other), + fNode (other.fParent.fOwnerDocument), + fParent (other.fParent.fOwnerDocument), + fAttributes(0), + fDefaultAttributes(0) +{ + fName = other.fName; + + if (deep) + fParent.cloneChildren(&other); + + if (other.getAttributes()) + { + fAttributes = ((DOMAttrMapImpl *)other.getAttributes())->cloneAttrMap(this); + } + + if (other.getDefaultAttributes()) + { + fDefaultAttributes = ((DOMAttrMapImpl *)other.getDefaultAttributes())->cloneAttrMap(this); + } + + if (!fDefaultAttributes) + setupDefaultAttributes(); + + if (!fDefaultAttributes) + fDefaultAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this); + + if (!fAttributes) { + if (!fDefaultAttributes) { + fAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this); + } + else { + fAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this, fDefaultAttributes); + } + } + +} + + +DOMElementImpl::~DOMElementImpl() +{ +} + + +DOMNode *DOMElementImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ELEMENT_OBJECT) DOMElementImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + + + +const XMLCh * DOMElementImpl::getNodeName() const { + return fName; +} + + +DOMNode::NodeType DOMElementImpl::getNodeType() const { + return DOMNode::ELEMENT_NODE; +} + + +const XMLCh * DOMElementImpl::getAttribute(const XMLCh *nam) const +{ + DOMNode * attr = fAttributes->getNamedItem(nam); + if (attr) + return attr->getNodeValue(); + + return XMLUni::fgZeroLenString; +} + + + +DOMAttr *DOMElementImpl::getAttributeNode(const XMLCh *nam) const +{ + return (DOMAttr *)fAttributes->getNamedItem(nam); +} + + +DOMNamedNodeMap *DOMElementImpl::getAttributes() const +{ + DOMElementImpl *ncThis = (DOMElementImpl *)this; // cast off const + return ncThis->fAttributes; +} + + + +DOMNodeList *DOMElementImpl::getElementsByTagName(const XMLCh *tagname) const +{ + DOMDocumentImpl *docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument; + return docImpl->getDeepNodeList(this,tagname); +} + + +const XMLCh * DOMElementImpl::getTagName() const +{ + return fName; +} + + +void DOMElementImpl::removeAttribute(const XMLCh *nam) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + int i = fAttributes->findNamePoint(nam); + if (i >= 0) + { + DOMNode *att = fAttributes->removeNamedItemAt(i); + ((DOMAttrImpl *)att)->removeAttrFromIDNodeMap(); + att->release(); + } +} + + + +DOMAttr *DOMElementImpl::removeAttributeNode(DOMAttr *oldAttr) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + DOMNode* found = 0; + + // Since there is no removeAttributeNodeNS, check if this oldAttr has NS or not + const XMLCh* localName = oldAttr->getLocalName(); + int i = 0; + if (localName) + i = fAttributes->findNamePoint(oldAttr->getNamespaceURI(), localName); + else + i = fAttributes->findNamePoint(oldAttr->getName()); + + if (i >= 0) { + // If it is in fact the right object, remove it. + found = fAttributes->item(i); + if (found == oldAttr) { + fAttributes->removeNamedItemAt(i); + ((DOMAttrImpl *)oldAttr)->removeAttrFromIDNodeMap(); + } + else + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); + + } + else + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); + + return (DOMAttr *)found; +} + + + +void DOMElementImpl::setAttribute(const XMLCh *nam, const XMLCh *val) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + DOMAttr* newAttr = getAttributeNode(nam); + if (!newAttr) + { + newAttr = fParent.fOwnerDocument->createAttribute(nam); + fAttributes->setNamedItem(newAttr); + } + + newAttr->setNodeValue(val); +} + +void DOMElementImpl::setIdAttribute(const XMLCh* name, bool isId) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + DOMAttr *attr = getAttributeNode(name); + + if (!attr) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); + + if(isId) + ((DOMAttrImpl *)attr)->addAttrToIDNodeMap(); + else + ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap(); +} + +void DOMElementImpl::setIdAttributeNS(const XMLCh* namespaceURI, const XMLCh* localName, bool isId) { + + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + DOMAttr *attr = getAttributeNodeNS(namespaceURI, localName); + + if (!attr) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); + + if(isId) + ((DOMAttrImpl *)attr)->addAttrToIDNodeMap(); + else + ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap(); +} + + +void DOMElementImpl::setIdAttributeNode(const DOMAttr *idAttr, bool isId) { + + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + DOMAttr *attr; + const XMLCh* localName = idAttr->getLocalName(); + if (localName) + attr = getAttributeNodeNS(idAttr->getNamespaceURI(), idAttr->getLocalName()); + else + attr = getAttributeNode(idAttr->getName()); + + if(!attr) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); + + if(isId) + ((DOMAttrImpl *)attr)->addAttrToIDNodeMap(); + else + ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap(); +} + + +DOMAttr * DOMElementImpl::setAttributeNode(DOMAttr *newAttr) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager); + // revisit. Exception doesn't match test. + + // This will throw INUSE if necessary + DOMAttr *oldAttr = (DOMAttr *) fAttributes->setNamedItem(newAttr); + + return oldAttr; +} + + +void DOMElementImpl::setNodeValue(const XMLCh *x) +{ + fNode.setNodeValue(x); +} + + + +void DOMElementImpl::setReadOnly(bool readOnl, bool deep) +{ + fNode.setReadOnly(readOnl,deep); + fAttributes->setReadOnly(readOnl,true); +} + + +//Introduced in DOM Level 2 +const XMLCh * DOMElementImpl::getAttributeNS(const XMLCh *fNamespaceURI, + const XMLCh *fLocalName) const +{ + DOMAttr * attr= + (DOMAttr *)(fAttributes->getNamedItemNS(fNamespaceURI, fLocalName)); + return (attr==0) ? XMLUni::fgZeroLenString : attr->getValue(); +} + + +void DOMElementImpl::setAttributeNS(const XMLCh *fNamespaceURI, + const XMLCh *qualifiedName, const XMLCh *fValue) +{ + if (fNode.isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); + if (index < 0) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + DOMAttr* newAttr = getAttributeNodeNS(fNamespaceURI, qualifiedName+index); + if (!newAttr) + { + newAttr = fParent.fOwnerDocument->createAttributeNS(fNamespaceURI, qualifiedName); + fAttributes->setNamedItemNS(newAttr); + } + + newAttr->setNodeValue(fValue); +} + + +void DOMElementImpl::removeAttributeNS(const XMLCh *fNamespaceURI, + const XMLCh *fLocalName) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + int i = fAttributes->findNamePoint(fNamespaceURI, fLocalName); + if (i >= 0) + { + DOMNode *att = fAttributes->removeNamedItemAt(i); + att->release(); + } +} + + +DOMAttr *DOMElementImpl::getAttributeNodeNS(const XMLCh *fNamespaceURI, + const XMLCh *fLocalName) const +{ + return (DOMAttr *)fAttributes->getNamedItemNS(fNamespaceURI, fLocalName); +} + + +DOMAttr *DOMElementImpl::setAttributeNodeNS(DOMAttr *newAttr) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + if (newAttr -> getOwnerDocument() != fParent.fOwnerDocument) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager); + + // This will throw INUSE if necessary + DOMAttr *oldAttr = (DOMAttr *) fAttributes->setNamedItemNS(newAttr); + + return oldAttr; +} + + +DOMNodeList *DOMElementImpl::getElementsByTagNameNS(const XMLCh *namespaceURI, + const XMLCh *localName) const +{ + DOMDocumentImpl *docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument; + return docImpl->getDeepNodeList(this, namespaceURI, localName); +} + +bool DOMElementImpl::hasAttributes() const +{ + return (fAttributes != 0 && fAttributes->getLength() != 0); +} + + +bool DOMElementImpl::hasAttribute(const XMLCh *name) const +{ + return (getAttributeNode(name) != 0); +} + + +bool DOMElementImpl::hasAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const +{ + return (getAttributeNodeNS(namespaceURI, localName) != 0); +} + + +// util functions for default attributes +// returns the default attribute map for this node from the owner document +DOMAttrMapImpl *DOMElementImpl::getDefaultAttributes() const +{ + return fDefaultAttributes; +} + +// initially set up the default attribute information based on doctype information +void DOMElementImpl::setupDefaultAttributes() +{ + DOMDocument *tmpdoc = fParent.fOwnerDocument; + if ((fNode.fOwnerNode == 0) || (tmpdoc == 0) || (tmpdoc->getDoctype() == 0)) + return; + + DOMNode *eldef = ((DOMDocumentTypeImpl*)tmpdoc->getDoctype())->getElements()->getNamedItem(getNodeName()); + DOMAttrMapImpl* defAttrs = (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes()); + + if (defAttrs) + fDefaultAttributes = new (tmpdoc) DOMAttrMapImpl(this, defAttrs); +} + +DOMAttr * DOMElementImpl::setDefaultAttributeNode(DOMAttr *newAttr) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager); + // revisit. Exception doesn't match test. + + // This will throw INUSE if necessary + DOMAttr *oldAttr = (DOMAttr *) fDefaultAttributes->setNamedItem(newAttr); + fAttributes->hasDefaults(true); + + return oldAttr; +} + + +DOMAttr *DOMElementImpl::setDefaultAttributeNodeNS(DOMAttr *newAttr) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + if (newAttr -> getOwnerDocument() != fParent.fOwnerDocument) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager); + + // This will throw INUSE if necessary + DOMAttr *oldAttr = (DOMAttr *) fDefaultAttributes->setNamedItemNS(newAttr); + fAttributes->hasDefaults(true); + + return oldAttr; +} + +void DOMElementImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + // release children + fParent.release(); + // release attributes + fAttributes->hasDefaults(false); + XMLSize_t count; + while((count = fAttributes->getLength()) != 0) + { + DOMNode* attr = fAttributes->removeNamedItemAt(count-1); + attr->release(); + } + + doc->release(this, DOMMemoryManager::ELEMENT_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +const XMLCh* DOMElementImpl::getBaseURI() const +{ + const XMLCh* baseURI = fNode.fOwnerNode->getBaseURI(); + if (fAttributes) { + const XMLCh baseString[] = + { + chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull + }; + DOMNode* attrNode = fAttributes->getNamedItemNS(DOMNodeImpl::getXmlURIString(), baseString); + if (attrNode==NULL) { + const XMLCh xmlBaseString[] = + { + chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull + }; + attrNode = fAttributes->getNamedItem(xmlBaseString); + } + if (attrNode) { + const XMLCh* uri = attrNode->getNodeValue(); + if (uri && *uri) {// attribute value is always empty string + // if there is a base URI for the parent node, use it to resolve relative URI + if(baseURI) + { + try { + DOMDocumentImpl* doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + XMLUri temp(baseURI, doc->getMemoryManager()); + XMLUri temp2(&temp, uri, doc->getMemoryManager()); + uri = doc->cloneString(temp2.getUriText()); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...){ + // REVISIT: what should happen in this case? + return 0; + } + } + return uri; + } + } + } + return baseURI; +} + + + +// +// Functions inherited from Node +// + DOMNode* DOMElementImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } + DOMNodeList* DOMElementImpl::getChildNodes() const {return fParent.getChildNodes (); } + DOMNode* DOMElementImpl::getFirstChild() const {return fParent.getFirstChild (); } + DOMNode* DOMElementImpl::getLastChild() const {return fParent.getLastChild (); } + const XMLCh* DOMElementImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMElementImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMElementImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMElementImpl::getNodeValue() const {return fNode.getNodeValue (); } + DOMDocument* DOMElementImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } + const XMLCh* DOMElementImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMElementImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMElementImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMElementImpl::hasChildNodes() const {return fParent.hasChildNodes (); } + DOMNode* DOMElementImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fParent.insertBefore (newChild, refChild); } + void DOMElementImpl::normalize() {fParent.normalize (); } + DOMNode* DOMElementImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } + DOMNode* DOMElementImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fParent.replaceChild (newChild, oldChild); } + bool DOMElementImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMElementImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMElementImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + void* DOMElementImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMElementImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + short DOMElementImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMElementImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMElementImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMElementImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMElementImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMElementImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMElementImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + + + +bool DOMElementImpl::isEqualNode(const DOMNode* arg) const +{ + if (isSameNode(arg)) { + return true; + } + + if (!fNode.isEqualNode(arg)) { + return false; + } + + bool hasAttrs = hasAttributes(); + + if (hasAttrs != arg->hasAttributes()) { + return false; + } + + if (hasAttrs) { + DOMNamedNodeMap* map1 = getAttributes(); + DOMNamedNodeMap* map2 = arg->getAttributes(); + + XMLSize_t len = map1->getLength(); + if (len != map2->getLength()) { + return false; + } + for (XMLSize_t i = 0; i < len; i++) { + DOMNode* n1 = map1->item(i); + if (!n1->getLocalName()) { // DOM Level 1 Node + DOMNode* n2 = map2->getNamedItem(n1->getNodeName()); + if (!n2 || !n1->isEqualNode(n2)) { + return false; + } + } + else { + DOMNode* n2 = map2->getNamedItemNS(n1->getNamespaceURI(), + n1->getLocalName()); + if (!n2 || !n1->isEqualNode(n2)) { + return false; + } + } + } + } + + return fParent.isEqualNode(arg); +} + +DOMNode* DOMElementImpl::rename(const XMLCh* namespaceURI, const XMLCh* name) +{ + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + + if (!namespaceURI || !*namespaceURI) { + fName = doc->getPooledString(name); + fAttributes->reconcileDefaultAttributes(getDefaultAttributes()); + + // and fire user data NODE_RENAMED event + castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this); + + return this; + } + else { + + // create a new ElementNS + DOMElementNSImpl* newElem = (DOMElementNSImpl*)doc->createElementNS(namespaceURI, name); + + // transfer the userData + doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newElem)); + + // remove old node from parent if any + DOMNode* parent = getParentNode(); + DOMNode* nextSib = getNextSibling(); + if (parent) { + parent->removeChild(this); + } + + // move children to new node + DOMNode* child = getFirstChild(); + while (child) { + removeChild(child); + newElem->appendChild(child); + child = getFirstChild(); + } + + // insert new node where old one was + if (parent) { + parent->insertBefore(newElem, nextSib); + } + + // move specified attributes to new node + newElem->fAttributes->moveSpecifiedAttributes(fAttributes); + + // and fire user data NODE_RENAMED event + castToNodeImpl(newElem)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newElem); + + return newElem; + } +} + +const DOMTypeInfo *DOMElementImpl::getSchemaTypeInfo() const +{ + return &DOMTypeInfoImpl::g_DtdValidatedElement; +} + +// DOMElementTraversal +DOMElement * DOMElementImpl::getFirstElementChild() const +{ + DOMNode* n = getFirstChild(); + while (n != NULL) { + switch (n->getNodeType()) { + case DOMNode::ELEMENT_NODE: + return (DOMElement*) n; + case DOMNode::ENTITY_REFERENCE_NODE: + { + DOMElement* e = getFirstElementChild(n); + if (e != NULL) + return e; + } + break; + default: + break; + } + n = n->getNextSibling(); + } + return NULL; +} + +DOMElement * DOMElementImpl::getLastElementChild() const +{ + DOMNode* n = getLastChild(); + while (n != NULL) { + switch (n->getNodeType()) { + case DOMNode::ELEMENT_NODE: + return (DOMElement*) n; + case DOMNode::ENTITY_REFERENCE_NODE: + { + DOMElement* e = getLastElementChild(n); + if (e != NULL) + return e; + } + break; + default: + break; + } + n = n->getPreviousSibling(); + } + return NULL; +} + +DOMElement * DOMElementImpl::getNextElementSibling() const +{ + DOMNode* n = getNextLogicalSibling(this); + while (n != NULL) { + switch (n->getNodeType()) { + case DOMNode::ELEMENT_NODE: + return (DOMElement*) n; + case DOMNode::ENTITY_REFERENCE_NODE: + { + DOMElement* e = getFirstElementChild(n); + if (e != NULL) + return e; + } + break; + default: + break; + } + n = getNextLogicalSibling(n); + } + return NULL; +} + +DOMElement * DOMElementImpl::getPreviousElementSibling() const +{ + DOMNode* n = getPreviousLogicalSibling(this); + while (n != NULL) { + switch (n->getNodeType()) { + case DOMNode::ELEMENT_NODE: + return (DOMElement*) n; + case DOMNode::ENTITY_REFERENCE_NODE: + { + DOMElement* e = getLastElementChild(n); + if (e != NULL) + return e; + } + break; + default: + break; + } + n = getPreviousLogicalSibling(n); + } + return NULL; +} + +XMLSize_t DOMElementImpl::getChildElementCount() const +{ + XMLSize_t count = 0; + DOMElement* child = getFirstElementChild(); + while (child != NULL) { + ++count; + child = child->getNextElementSibling(); + } + return count; +} + +// Returns the first element node found from a +// non-recursive in order traversal of the given node. +DOMElement* DOMElementImpl::getFirstElementChild(const DOMNode* n) const +{ + const DOMNode* top = n; + while (n != NULL) { + if (n->getNodeType() == DOMNode::ELEMENT_NODE) { + return (DOMElement*) n; + } + DOMNode* next = n->getFirstChild(); + while (next == NULL) { + if (top == n) { + break; + } + next = n->getNextSibling(); + if (next == NULL) { + n = n->getParentNode(); + if (n == NULL || top == n) { + return NULL; + } + } + } + n = next; + } + return NULL; +} + +// Returns the first element node found from a +// non-recursive reverse order traversal of the given node. +DOMElement* DOMElementImpl::getLastElementChild(const DOMNode* n) const +{ + const DOMNode* top = n; + while (n != NULL) { + if (n->getNodeType() == DOMNode::ELEMENT_NODE) { + return (DOMElement*) n; + } + DOMNode* next = n->getLastChild(); + while (next == NULL) { + if (top == n) { + break; + } + next = n->getPreviousSibling(); + if (next == NULL) { + n = n->getParentNode(); + if (n == NULL || top == n) { + return NULL; + } + } + } + n = next; + } + return NULL; +} + +// Returns the next logical sibling with respect to the given node. +DOMNode* DOMElementImpl::getNextLogicalSibling(const DOMNode* n) const +{ + DOMNode* next = n->getNextSibling(); + // If "n" has no following sibling and its parent is an entity reference node we + // need to continue the search through the following siblings of the entity + // reference as these are logically siblings of the given node. + if (next == NULL) { + DOMNode* parent = n->getParentNode(); + while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) { + next = parent->getNextSibling(); + if (next != NULL) { + break; + } + parent = parent->getParentNode(); + } + } + return next; +} + +// Returns the previous logical sibling with respect to the given node. +DOMNode* DOMElementImpl::getPreviousLogicalSibling(const DOMNode* n) const +{ + DOMNode* prev = n->getPreviousSibling(); + // If "n" has no previous sibling and its parent is an entity reference node we + // need to continue the search through the previous siblings of the entity + // reference as these are logically siblings of the given node. + if (prev == NULL) { + DOMNode* parent = n->getParentNode(); + while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) { + prev = parent->getPreviousSibling(); + if (prev != NULL) { + break; + } + parent = parent->getParentNode(); + } + } + return prev; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMElementImpl.hpp b/include/xercesc/dom/impl/DOMElementImpl.hpp new file mode 100644 index 0000000..8075a7c --- /dev/null +++ b/include/xercesc/dom/impl/DOMElementImpl.hpp @@ -0,0 +1,143 @@ +/* + * 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: DOMElementImpl.hpp 792236 2009-07-08 17:22:35Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMELEMENTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMELEMENTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include +#include +#include + +#include "DOMChildNode.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMParentNode.hpp" + +#include "DOMAttrMapImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMTypeInfo; +class DOMNodeList; +class DOMAttrMapImpl; +class DOMDocument; + + + + +class CDOM_EXPORT DOMElementImpl: public DOMElement { +public: + DOMNodeImpl fNode; + DOMParentNode fParent; + DOMChildNode fChild; + DOMAttrMapImpl *fAttributes; + DOMAttrMapImpl *fDefaultAttributes; + const XMLCh *fName; + +public: + DOMElementImpl(DOMDocument *ownerDoc, const XMLCh *name); + + DOMElementImpl(const DOMElementImpl &other, bool deep=false); + virtual ~DOMElementImpl(); + +public: + // Declare functions from DOMNode. They all must be implemented by this class + DOMNODE_FUNCTIONS; + +public: + // Functions introduced on Element... + virtual const XMLCh* getAttribute(const XMLCh *name) const; + virtual DOMAttr* getAttributeNode(const XMLCh *name) const; + virtual DOMNodeList* getElementsByTagName(const XMLCh *tagname) const; + virtual const XMLCh* getTagName() const; + virtual void removeAttribute(const XMLCh *name); + virtual DOMAttr* removeAttributeNode(DOMAttr * oldAttr); + virtual void setAttribute(const XMLCh *name, const XMLCh *value); + virtual DOMAttr* setAttributeNode(DOMAttr *newAttr); + virtual void setReadOnly(bool readOnly, bool deep); + + //Introduced in DOM Level 2 + virtual const XMLCh* getAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual void setAttributeNS(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + const XMLCh *value); + virtual void removeAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName); + virtual DOMAttr* getAttributeNodeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual DOMAttr* setAttributeNodeNS(DOMAttr *newAttr); + virtual DOMNodeList* getElementsByTagNameNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual bool hasAttribute(const XMLCh *name) const; + virtual bool hasAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + + //Introduced in DOM level 3 + virtual void setIdAttribute(const XMLCh* name, bool isId); + virtual void setIdAttributeNS(const XMLCh* namespaceURI, const XMLCh* localName, bool isId); + virtual void setIdAttributeNode(const DOMAttr *idAttr, bool isId); + virtual const DOMTypeInfo * getSchemaTypeInfo() const; + + // for handling of default attribute + virtual DOMAttr* setDefaultAttributeNode(DOMAttr *newAttr); + virtual DOMAttr* setDefaultAttributeNodeNS(DOMAttr *newAttr); + virtual DOMAttrMapImpl* getDefaultAttributes() const; + + // helper function for DOM Level 3 renameNode + virtual DOMNode* rename(const XMLCh* namespaceURI, const XMLCh* name); + + // DOMElementTraversal + virtual DOMElement * getFirstElementChild() const; + virtual DOMElement * getLastElementChild() const; + virtual DOMElement * getPreviousElementSibling() const; + virtual DOMElement * getNextElementSibling() const; + virtual XMLSize_t getChildElementCount() const; + +protected: + // default attribute helper functions + virtual void setupDefaultAttributes(); + + // helper function for DOMElementTraversal methods + DOMElement* getFirstElementChild(const DOMNode* n) const; + DOMElement* getLastElementChild(const DOMNode* n) const; + DOMNode* getNextLogicalSibling(const DOMNode* n) const; + DOMNode* getPreviousLogicalSibling(const DOMNode* n) const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMElementImpl & operator = (const DOMElementImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMElementNSImpl.cpp b/include/xercesc/dom/impl/DOMElementNSImpl.cpp new file mode 100644 index 0000000..31ebb29 --- /dev/null +++ b/include/xercesc/dom/impl/DOMElementNSImpl.cpp @@ -0,0 +1,264 @@ +/* + * 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: DOMElementNSImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#include +#include "DOMElementNSImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMTypeInfoImpl.hpp" +#include "DOMCasts.hpp" +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMElementNSImpl::DOMElementNSImpl(DOMDocument *ownerDoc, const XMLCh *nam) : + DOMElementImpl(ownerDoc, nam) +{ + this->fNamespaceURI=0; //DOM Level 2 + this->fLocalName=0; //DOM Level 2 + this->fPrefix=0; + this->fSchemaType = 0; +} + +//Introduced in DOM Level 2 +DOMElementNSImpl::DOMElementNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *qualifiedName) : + DOMElementImpl(ownerDoc, qualifiedName) +{ + setName(namespaceURI, qualifiedName); + this->fSchemaType = 0; +} + +DOMElementNSImpl::DOMElementNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *prefix, + const XMLCh *localName, + const XMLCh *qualifiedName) + : DOMElementImpl(ownerDoc, qualifiedName) +{ + this->fSchemaType = 0; + + DOMDocumentImpl* docImpl = (DOMDocumentImpl*)fParent.fOwnerDocument; + + if (prefix == 0 || *prefix == 0) + { + fPrefix = 0; + fLocalName = fName; + } + else + { + fPrefix = docImpl->getPooledString(prefix); + fLocalName = docImpl->getPooledString(localName); + } + + // DOM Level 3: namespace URI is never empty string. + // + const XMLCh * URI = DOMNodeImpl::mapPrefix ( + fPrefix, + (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI, + DOMNode::ELEMENT_NODE); + + fNamespaceURI = (URI == 0) ? 0 : docImpl->getPooledString(URI); +} + +DOMElementNSImpl::DOMElementNSImpl(const DOMElementNSImpl &other, bool deep) : + DOMElementImpl(other, deep) +{ + this->fNamespaceURI = other.fNamespaceURI; //DOM Level 2 + this->fLocalName = other.fLocalName; //DOM Level 2 + this->fPrefix = other.fPrefix; + this->fSchemaType = other.fSchemaType; +} + +DOMNode * DOMElementNSImpl::cloneNode(bool deep) const { + DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ELEMENT_NS_OBJECT) DOMElementNSImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + +const XMLCh * DOMElementNSImpl::getNamespaceURI() const +{ + return fNamespaceURI; +} + +const XMLCh * DOMElementNSImpl::getPrefix() const +{ + return fPrefix; +} + + +const XMLCh * DOMElementNSImpl::getLocalName() const +{ + return fLocalName; +} + +void DOMElementNSImpl::setPrefix(const XMLCh *prefix) +{ + if (fNode.isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + if (fNamespaceURI == 0 || fNamespaceURI[0] == chNull) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + if (prefix == 0 || *prefix == 0) { + fPrefix = 0; + fName = fLocalName; + return; + } + + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + + if(!doc->isXMLName(prefix)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, GetDOMNodeMemoryManager); + + const XMLCh * xml = DOMNodeImpl::getXmlString(); + const XMLCh * xmlURI = DOMNodeImpl::getXmlURIString(); + + if (XMLString::equals(prefix, xml) && + !XMLString::equals(fNamespaceURI, xmlURI)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + + if (XMLString::indexOf(prefix, chColon) != -1) { + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + } + + this-> fPrefix = doc->getPooledString(prefix); + + XMLSize_t prefixLen = XMLString::stringLen(prefix); + XMLSize_t newQualifiedNameLen = prefixLen+1+XMLString::stringLen(fLocalName); + + XMLCh *newName; + XMLCh temp[256]; + if (newQualifiedNameLen >= 255) + newName = (XMLCh*) doc->getMemoryManager()->allocate + ( + newQualifiedNameLen * sizeof(XMLCh) + );//new XMLCh[newQualifiedNameLen]; + else + newName = temp; + + // newName = prefix + chColon + fLocalName; + XMLString::copyString(newName, prefix); + newName[prefixLen] = chColon; + XMLString::copyString(&newName[prefixLen+1], fLocalName); + + fName = doc->getPooledString(newName); + + if (newQualifiedNameLen >= 255) + doc->getMemoryManager()->deallocate(newName);//delete[] newName; + +} + +void DOMElementNSImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fParent.release(); + doc->release(this, DOMMemoryManager::ELEMENT_NS_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +DOMNode* DOMElementNSImpl::rename(const XMLCh* namespaceURI, const XMLCh* name) +{ + setName(namespaceURI, name); + fAttributes->reconcileDefaultAttributes(getDefaultAttributes()); + // and fire user data NODE_RENAMED event + castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this); + + return this; +} + +void DOMElementNSImpl::setName(const XMLCh *namespaceURI, + const XMLCh *qualifiedName) +{ + DOMDocumentImpl* ownerDoc = (DOMDocumentImpl *) fParent.fOwnerDocument; + this->fName = ownerDoc->getPooledString(qualifiedName); + + int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); + if (index < 0) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + + if (index == 0) + { + //qualifiedName contains no ':' + // + fPrefix = 0; + fLocalName = fName; + } + else + { //0 < index < this->name.length()-1 + // + fPrefix = ownerDoc->getPooledNString(qualifiedName, index); + fLocalName = ownerDoc->getPooledString(fName+index+1); + + // Before we carry on, we should check if the prefix or localName are valid XMLName + if (!ownerDoc->isXMLName(fPrefix) || !ownerDoc->isXMLName(fLocalName)) + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); + } + + // DOM Level 3: namespace URI is never empty string. + // + const XMLCh * URI = DOMNodeImpl::mapPrefix ( + fPrefix, + (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI, + DOMNode::ELEMENT_NODE); + + fNamespaceURI = (URI == 0) ? 0 : ownerDoc->getPooledString(URI); +} + +const DOMTypeInfo *DOMElementNSImpl::getSchemaTypeInfo() const +{ + if(!fSchemaType) + return &DOMTypeInfoImpl::g_DtdValidatedElement; + return fSchemaType; +} + +void DOMElementNSImpl::setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo) +{ + fSchemaType = typeInfo; +} + +bool DOMElementNSImpl::isSupported(const XMLCh *feature, const XMLCh *version) const +{ + // check for '+DOMPSVITypeInfo' + if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfacePSVITypeInfo)) + return true; + return fNode.isSupported (feature, version); +} + +void* DOMElementNSImpl::getFeature(const XMLCh* feature, const XMLCh* version) const +{ + if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo)) + return (DOMPSVITypeInfo*)fSchemaType; + return DOMElementImpl::getFeature(feature, version); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMElementNSImpl.hpp b/include/xercesc/dom/impl/DOMElementNSImpl.hpp new file mode 100644 index 0000000..140ecc2 --- /dev/null +++ b/include/xercesc/dom/impl/DOMElementNSImpl.hpp @@ -0,0 +1,95 @@ +/* + * 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: DOMElementNSImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMELEMENTNSIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMELEMENTNSIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include "DOMElementImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMTypeInfoImpl; + +class CDOM_EXPORT DOMElementNSImpl: public DOMElementImpl { +protected: + //Introduced in DOM Level 2 + const XMLCh * fNamespaceURI; //namespace URI of this node + const XMLCh * fLocalName; //local part of qualified name + const XMLCh * fPrefix; + const DOMTypeInfoImpl *fSchemaType; + +public: + DOMElementNSImpl(DOMDocument *ownerDoc, const XMLCh *name); + DOMElementNSImpl(DOMDocument *ownerDoc, //DOM Level 2 + const XMLCh *namespaceURI, + const XMLCh *qualifiedName); + DOMElementNSImpl(const DOMElementNSImpl &other, bool deep=false); + + // Fast construction without any checks for name validity. Used in + // parsing. + // + DOMElementNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *prefix, // Null or empty - no prefix. + const XMLCh *localName, + const XMLCh *qualifiedName); + + virtual DOMNode * cloneNode(bool deep) const; + virtual bool isSupported(const XMLCh *feature, const XMLCh *version) const; + virtual void* getFeature(const XMLCh* feature, const XMLCh* version) const; + + //Introduced in DOM Level 2 + virtual const XMLCh *getNamespaceURI() const; + virtual const XMLCh *getPrefix() const; + virtual const XMLCh *getLocalName() const; + virtual void setPrefix(const XMLCh *prefix); + virtual void release(); + + //Introduced in DOM Level 3 + virtual const DOMTypeInfo * getSchemaTypeInfo() const; + + // helper function for DOM Level 3 renameNode + virtual DOMNode* rename(const XMLCh* namespaceURI, const XMLCh* name); + void setName(const XMLCh* namespaceURI, const XMLCh* name); + + //helper function for DOM Level 3 TypeInfo + virtual void setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMElementNSImpl & operator = (const DOMElementNSImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMEntityImpl.cpp b/include/xercesc/dom/impl/DOMEntityImpl.cpp new file mode 100644 index 0000000..5224bb8 --- /dev/null +++ b/include/xercesc/dom/impl/DOMEntityImpl.cpp @@ -0,0 +1,295 @@ +/* + * 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: DOMEntityImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ + +#include +#include +#include +#include "DOMEntityImpl.hpp" +#include "DOMDocumentImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +DOMEntityImpl::DOMEntityImpl(DOMDocument *ownerDoc, const XMLCh *eName) + : fNode(ownerDoc), + fParent(ownerDoc), + fPublicId(0), + fSystemId(0), + fNotationName(0), + fRefEntity(0), + fInputEncoding(0), + fXmlEncoding(0), + fXmlVersion(0), + fBaseURI(0), + fEntityRefNodeCloned(false) +{ + fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(eName); + fNode.setReadOnly(true, true); +} + + +DOMEntityImpl::DOMEntityImpl(const DOMEntityImpl &other, bool deep) + : DOMEntity(other), + fNode(other.fNode), + fParent(other.fParent), + fName(other.fName), + fPublicId(other.fPublicId), + fSystemId(other.fSystemId), + fNotationName(other.fNotationName), + fRefEntity(other.fRefEntity), + fInputEncoding(other.fInputEncoding), + fXmlEncoding(other.fXmlEncoding), + fXmlVersion(other.fXmlVersion), + fBaseURI(other.fBaseURI), + fEntityRefNodeCloned(false) +{ + if (deep) + fParent.cloneChildren(&other); + fNode.setReadOnly(true, true); +} + + +DOMEntityImpl::~DOMEntityImpl() { +} + + +DOMNode *DOMEntityImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ENTITY_OBJECT) DOMEntityImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMEntityImpl::getNodeName() const { + return fName; +} + + +DOMNode::NodeType DOMEntityImpl::getNodeType() const { + return DOMNode::ENTITY_NODE; +} + + +const XMLCh * DOMEntityImpl::getNotationName() const +{ + return fNotationName; +} + + +const XMLCh * DOMEntityImpl::getPublicId() const { + return fPublicId; +} + + +const XMLCh * DOMEntityImpl::getSystemId() const +{ + return fSystemId; +} + + +const XMLCh* DOMEntityImpl::getBaseURI() const +{ + return fBaseURI; +} + + +void DOMEntityImpl::setNodeValue(const XMLCh *arg) +{ + fNode.setNodeValue(arg); +} + + +void DOMEntityImpl::setNotationName(const XMLCh *arg) +{ + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + fNotationName = doc->cloneString(arg); +} + + +void DOMEntityImpl::setPublicId(const XMLCh *arg) +{ + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + fPublicId = doc->cloneString(arg); +} + + +void DOMEntityImpl::setSystemId(const XMLCh *arg) +{ + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + fSystemId = doc->cloneString(arg); +} + + +void DOMEntityImpl::setBaseURI(const XMLCh* baseURI) { + if (baseURI && *baseURI) { + XMLCh* temp = (XMLCh*) ((DOMDocumentImpl *)fParent.fOwnerDocument)->allocate((XMLString::stringLen(baseURI) + 9)*sizeof(XMLCh)); + XMLString::fixURI(baseURI, temp); + fBaseURI = temp; + } + else + fBaseURI = 0; +} + + +void DOMEntityImpl::setEntityRef(DOMEntityReference* other) +{ + fRefEntity = other; +} + + +DOMEntityReference* DOMEntityImpl::getEntityRef() const +{ + return fRefEntity; +} + +void DOMEntityImpl::cloneEntityRefTree() const +{ + if (fEntityRefNodeCloned) + return; + + // cast off const. This method is const because it is + // called from a bunch of logically const methods, like + // getFirstChild(). + DOMEntityImpl *ncThis = (DOMEntityImpl *)this; + + //lazily clone the entityRef tree to this entity + if (fParent.fFirstChild != 0) + return; + + if (!fRefEntity) + return; + + ncThis->fEntityRefNodeCloned = true; + ncThis->fNode.setReadOnly(false, true); + ncThis->fParent.cloneChildren(fRefEntity); + ncThis->fNode.setReadOnly(true, true); +} + +DOMNode * DOMEntityImpl::getFirstChild() const +{ + cloneEntityRefTree(); + return fParent.fFirstChild; +} + +DOMNode * DOMEntityImpl::getLastChild() const +{ + cloneEntityRefTree(); + return fParent.getLastChild(); +} + +DOMNodeList* DOMEntityImpl::getChildNodes() const +{ + cloneEntityRefTree(); + return this->fParent.getChildNodes(); + +} + +bool DOMEntityImpl::hasChildNodes() const +{ + cloneEntityRefTree(); + return fParent.fFirstChild!=0; +} + + +void DOMEntityImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fParent.release(); + doc->release(this, DOMMemoryManager::ENTITY_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +// +// Functions inherited from Node +// + + DOMNode* DOMEntityImpl::appendChild(DOMNode *newChild) {cloneEntityRefTree(); return fParent.appendChild (newChild); } + DOMNamedNodeMap* DOMEntityImpl::getAttributes() const {return fNode.getAttributes (); } + const XMLCh* DOMEntityImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMEntityImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMEntityImpl::getNextSibling() const {return fNode.getNextSibling (); } + const XMLCh* DOMEntityImpl::getNodeValue() const {return fNode.getNodeValue (); } + DOMDocument* DOMEntityImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } + const XMLCh* DOMEntityImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMEntityImpl::getParentNode() const {return fNode.getParentNode (); } + DOMNode* DOMEntityImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } + DOMNode* DOMEntityImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {cloneEntityRefTree(); return fParent.insertBefore (newChild, refChild); } + void DOMEntityImpl::normalize() {cloneEntityRefTree(); fParent.normalize (); } + DOMNode* DOMEntityImpl::removeChild(DOMNode *oldChild) {cloneEntityRefTree(); return fParent.removeChild (oldChild); } + DOMNode* DOMEntityImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {cloneEntityRefTree(); return fParent.replaceChild (newChild, oldChild); } + bool DOMEntityImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMEntityImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMEntityImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMEntityImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMEntityImpl::isEqualNode(const DOMNode* arg) const {cloneEntityRefTree(); return fParent.isEqualNode(arg); } + void* DOMEntityImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMEntityImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + short DOMEntityImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMEntityImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMEntityImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMEntityImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMEntityImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMEntityImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMEntityImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + + +//Introduced in DOM Level 3 +const XMLCh* DOMEntityImpl::getInputEncoding() const { + return fInputEncoding; +} + +void DOMEntityImpl::setInputEncoding(const XMLCh* actualEncoding){ + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + fInputEncoding = doc->cloneString(actualEncoding); +} + +const XMLCh* DOMEntityImpl::getXmlEncoding() const { + return fXmlEncoding; +} + +void DOMEntityImpl::setXmlEncoding(const XMLCh* encoding){ + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + fXmlEncoding = doc->cloneString(encoding); +} + +const XMLCh* DOMEntityImpl::getXmlVersion() const { + return fXmlVersion; +} + +void DOMEntityImpl::setXmlVersion(const XMLCh* version){ + DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; + fXmlVersion = doc->cloneString(version); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMEntityImpl.hpp b/include/xercesc/dom/impl/DOMEntityImpl.hpp new file mode 100644 index 0000000..6750b3f --- /dev/null +++ b/include/xercesc/dom/impl/DOMEntityImpl.hpp @@ -0,0 +1,107 @@ +/* + * 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: DOMEntityImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMENTITYIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMENTITYIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include "DOMNodeImpl.hpp" +#include "DOMParentNode.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMEntityReference; + +class CDOM_EXPORT DOMEntityImpl: public DOMEntity { +protected: + DOMNodeImpl fNode; + DOMParentNode fParent; + + const XMLCh * fName; + const XMLCh * fPublicId; + const XMLCh * fSystemId; + const XMLCh * fNotationName; + DOMEntityReference* fRefEntity; + + // New data introduced in DOM Level 3 + const XMLCh* fInputEncoding; + const XMLCh* fXmlEncoding; + const XMLCh* fXmlVersion; + const XMLCh* fBaseURI; + bool fEntityRefNodeCloned; + + // helper function + void cloneEntityRefTree() const; + + friend class XercesDOMParser; + +public: + DOMEntityImpl(DOMDocument *doc, const XMLCh *eName); + DOMEntityImpl(const DOMEntityImpl &other, bool deep=false); + virtual ~DOMEntityImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + virtual const XMLCh * getPublicId() const; + virtual const XMLCh * getSystemId() const; + virtual const XMLCh * getNotationName() const; + virtual void setNotationName(const XMLCh *arg); + virtual void setPublicId(const XMLCh *arg); + virtual void setSystemId(const XMLCh *arg); + + //DOM Level 2 additions. Non standard functions + virtual void setEntityRef(DOMEntityReference *); + virtual DOMEntityReference* getEntityRef() const; + + //Introduced in DOM Level 3 + virtual const XMLCh* getInputEncoding() const; + virtual const XMLCh* getXmlEncoding() const; + virtual const XMLCh* getXmlVersion() const; + virtual void setBaseURI(const XMLCh *arg); + + void setInputEncoding(const XMLCh* actualEncoding); + void setXmlEncoding(const XMLCh* encoding); + void setXmlVersion(const XMLCh* version); +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMEntityImpl & operator = (const DOMEntityImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/impl/DOMEntityReferenceImpl.cpp b/include/xercesc/dom/impl/DOMEntityReferenceImpl.cpp new file mode 100644 index 0000000..9f52ef2 --- /dev/null +++ b/include/xercesc/dom/impl/DOMEntityReferenceImpl.cpp @@ -0,0 +1,223 @@ +/* + * 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: DOMEntityReferenceImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ + +#include "DOMDocumentImpl.hpp" +#include "DOMDocumentTypeImpl.hpp" +#include "DOMEntityImpl.hpp" +#include "DOMEntityReferenceImpl.hpp" + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMEntityReferenceImpl::DOMEntityReferenceImpl(DOMDocument *ownerDoc, + const XMLCh *entityName) + : fNode(ownerDoc), fParent(ownerDoc), fBaseURI(0) +{ + fName = ((DOMDocumentImpl*)fParent.fOwnerDocument)->getPooledString(entityName); + // EntityReference behaves as a read-only node, since its contents + // reflect the Entity it refers to -- but see setNodeName(). + //retrieve the corresponding entity content + + if (ownerDoc) { + if (ownerDoc->getDoctype()) { + if (ownerDoc->getDoctype()->getEntities()) { + DOMEntityImpl* entity = (DOMEntityImpl*)ownerDoc->getDoctype()->getEntities()->getNamedItem(entityName); + if (entity) { + fBaseURI = entity->getBaseURI(); + DOMEntityReference* refEntity = entity->getEntityRef(); + if (refEntity) { + fParent.cloneChildren(refEntity); + } + } + } + } + } + + fNode.setReadOnly(true, true); +} + + +DOMEntityReferenceImpl::DOMEntityReferenceImpl(DOMDocument *ownerDoc, + const XMLCh *entityName, + bool cloneChild) + : fNode(ownerDoc), fParent(ownerDoc), fBaseURI(0) +{ + fName = ((DOMDocumentImpl*)fParent.fOwnerDocument)->getPooledString(entityName); + // EntityReference behaves as a read-only node, since its contents + // reflect the Entity it refers to -- but see setNodeName(). + //retrieve the corresponding entity content + + if (ownerDoc) { + if (ownerDoc->getDoctype()) { + if (ownerDoc->getDoctype()->getEntities()) { + DOMEntityImpl* entity = (DOMEntityImpl*)ownerDoc->getDoctype()->getEntities()->getNamedItem(entityName); + if (entity) { + fBaseURI = entity->getBaseURI(); + if (cloneChild) { + DOMEntityReference* refEntity = entity->getEntityRef(); + if (refEntity) { + fParent.cloneChildren(refEntity); + } + } + } + } + } + } + + fNode.setReadOnly(true, true); +} + +DOMEntityReferenceImpl::DOMEntityReferenceImpl(const DOMEntityReferenceImpl &other, + bool deep) + : DOMEntityReference(other), + fNode(other.fNode), + fParent(other.fParent), + fChild(other.fChild), + fName(other.fName), + fBaseURI(other.fBaseURI) +{ + if (deep) + fParent.cloneChildren(&other); + fNode.setReadOnly(true, true); +} + + + +DOMEntityReferenceImpl::~DOMEntityReferenceImpl() +{ +} + +DOMNode *DOMEntityReferenceImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMEntityReferenceImpl::getNodeName() const +{ + return fName; +} + + +DOMNode::NodeType DOMEntityReferenceImpl::getNodeType() const { + return DOMNode::ENTITY_REFERENCE_NODE; +} + + + +/** +* EntityReferences never have a nodeValue. +* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) +*/ +void DOMEntityReferenceImpl::setNodeValue(const XMLCh *x) +{ + fNode.setNodeValue(x); +} + + +/** +* EntityRef is already, and must be, a read-only node. Attempts to change +* that will throw a NO_MODIFICATION_ALLOWED_ERR DOMException. +*

+* If you want to alter its contents, edit the Entity definition. +* +* @param readOnly boolean +*/ +void DOMEntityReferenceImpl::setReadOnly(bool readOnl,bool deep) +{ + if(((DOMDocumentImpl *)fParent.fOwnerDocument)->getErrorChecking() && readOnl==false) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + fNode.setReadOnly(readOnl,deep); +} + + +void DOMEntityReferenceImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument; + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fParent.release(); + doc->release(this, DOMMemoryManager::ENTITY_REFERENCE_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +const XMLCh* DOMEntityReferenceImpl::getBaseURI() const +{ + return fBaseURI; +} + + + +// +// Delegate functions from Node to the appropriate implementation. +// + + + DOMNode* DOMEntityReferenceImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } + DOMNamedNodeMap* DOMEntityReferenceImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMEntityReferenceImpl::getChildNodes() const {return fParent.getChildNodes (); } + DOMNode* DOMEntityReferenceImpl::getFirstChild() const {return fParent.getFirstChild (); } + DOMNode* DOMEntityReferenceImpl::getLastChild() const {return fParent.getLastChild (); } + const XMLCh* DOMEntityReferenceImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMEntityReferenceImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMEntityReferenceImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMEntityReferenceImpl::getNodeValue() const {return fNode.getNodeValue (); } + DOMDocument* DOMEntityReferenceImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } + const XMLCh* DOMEntityReferenceImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMEntityReferenceImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMEntityReferenceImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMEntityReferenceImpl::hasChildNodes() const {return fParent.hasChildNodes (); } + DOMNode* DOMEntityReferenceImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fParent.insertBefore (newChild, refChild); } + void DOMEntityReferenceImpl::normalize() {fParent.normalize (); } + DOMNode* DOMEntityReferenceImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } + DOMNode* DOMEntityReferenceImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fParent.replaceChild (newChild, oldChild); } + bool DOMEntityReferenceImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMEntityReferenceImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMEntityReferenceImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMEntityReferenceImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMEntityReferenceImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg); } + void* DOMEntityReferenceImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMEntityReferenceImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + short DOMEntityReferenceImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMEntityReferenceImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMEntityReferenceImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMEntityReferenceImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMEntityReferenceImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMEntityReferenceImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMEntityReferenceImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMEntityReferenceImpl.hpp b/include/xercesc/dom/impl/DOMEntityReferenceImpl.hpp new file mode 100644 index 0000000..26a7188 --- /dev/null +++ b/include/xercesc/dom/impl/DOMEntityReferenceImpl.hpp @@ -0,0 +1,79 @@ +/* + * 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: DOMEntityReferenceImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMENTITYREFERENCEIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMENTITYREFERENCEIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include + +#include "DOMParentNode.hpp" +#include "DOMChildNode.hpp" +#include "DOMNodeImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMEntityReferenceImpl: public DOMEntityReference +{ +protected: + DOMNodeImpl fNode; + DOMParentNode fParent; + DOMChildNode fChild; + + const XMLCh *fName; + const XMLCh *fBaseURI; + + friend class XercesDOMParser; + +public: + DOMEntityReferenceImpl(DOMDocument *ownerDoc, const XMLCh *entityName); + DOMEntityReferenceImpl(DOMDocument *ownerDoc, const XMLCh *entityName, bool cloneChild); + DOMEntityReferenceImpl(const DOMEntityReferenceImpl &other, bool deep=false); + virtual ~DOMEntityReferenceImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + virtual void setReadOnly(bool readOnly,bool deep); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMEntityReferenceImpl & operator = (const DOMEntityReferenceImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/impl/DOMErrorImpl.cpp b/include/xercesc/dom/impl/DOMErrorImpl.cpp new file mode 100644 index 0000000..f4c8ac0 --- /dev/null +++ b/include/xercesc/dom/impl/DOMErrorImpl.cpp @@ -0,0 +1,90 @@ +/* + * 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: DOMErrorImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMErrorImpl.hpp" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// DOMErrorImpl: Constructors and Destructor +// --------------------------------------------------------------------------- +DOMErrorImpl::DOMErrorImpl(const ErrorSeverity severity) : +fAdoptLocation(false) +, fSeverity(severity) +, fMessage(0) +, fLocation(0) +, fType(0) +, fRelatedData(0) +{ +} + +DOMErrorImpl::DOMErrorImpl(const ErrorSeverity severity, + const XMLCh* const message, + DOMLocator* const location) : +fAdoptLocation(false) +, fSeverity(severity) +, fMessage(message) +, fLocation(location) +, fType(0) +, fRelatedData(0) +{ +} + +DOMErrorImpl::DOMErrorImpl(const ErrorSeverity severity, + const XMLCh* type, + const XMLCh* message, + void* relatedData) : +fAdoptLocation(false) +, fSeverity(severity) +, fMessage(message) +, fLocation(0) +, fType(type) +, fRelatedData(relatedData) +{ + +} + +DOMErrorImpl::~DOMErrorImpl() +{ + if (fAdoptLocation) + delete fLocation; +} + +// --------------------------------------------------------------------------- +// DOMErrorImpl: Setter methods +// --------------------------------------------------------------------------- +void DOMErrorImpl::setLocation(DOMLocator* const location) +{ + if (fAdoptLocation) + delete fLocation; + + fLocation = location; +} + +void DOMErrorImpl::setRelatedException(void*) const +{ + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMErrorImpl.hpp b/include/xercesc/dom/impl/DOMErrorImpl.hpp new file mode 100644 index 0000000..f4e8488 --- /dev/null +++ b/include/xercesc/dom/impl/DOMErrorImpl.hpp @@ -0,0 +1,188 @@ +/* + * 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: DOMErrorImpl.hpp 676853 2008-07-15 09:58:05Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMERRORIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMERRORIMPL_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * Introduced in DOM Level 3 + * Implementation of a DOMError interface. + * + * @see DOMError#DOMError + */ + +class CDOM_EXPORT DOMErrorImpl : public DOMError +{ +public: + /** @name Constructors and Destructor */ + //@{ + + /** Constructors */ + DOMErrorImpl(const ErrorSeverity severity); + + DOMErrorImpl + ( + const ErrorSeverity severity + , const XMLCh* const message + , DOMLocator* const location + ); + + DOMErrorImpl + ( + const ErrorSeverity severity + , const XMLCh* type + , const XMLCh* message + , void* relatedData + ); + + /** Desctructor */ + virtual ~DOMErrorImpl(); + + //@} + + // DOMError interface + virtual ErrorSeverity getSeverity() const; + virtual const XMLCh* getMessage() const; + virtual DOMLocator* getLocation() const; + virtual void* getRelatedException() const; + virtual const XMLCh* getType() const; + virtual void* getRelatedData() const; + + // Setters + void setSeverity(const ErrorSeverity severity); + void setMessage(const XMLCh* const message); + void setLocation(DOMLocator* const location); + void setAdoptLocation(const bool value); + void setRelatedException(void* exc) const; + void setType(const XMLCh* type); + void setRelatedData(void* relatedData); + +private: + /* Unimplemented constructors and operators */ + + /* Copy constructor */ + DOMErrorImpl(const DOMErrorImpl&); + + /* Assignment operator */ + DOMErrorImpl& operator=(const DOMErrorImpl&); + +protected: + // ----------------------------------------------------------------------- + // Private data members + // + // fAdoptLocation + // Indicates whether we own the DOMLocator object or not. + // + // fSeverity + // The type of the error. + // + // fMessage + // The error message. + // + // fLocation + // The location info of the error. + // + // fType + // The type of the error. + // + // fRelatedData + // The data related to this error. + // + // ----------------------------------------------------------------------- + bool fAdoptLocation; + ErrorSeverity fSeverity; + const XMLCh* fMessage; + DOMLocator* fLocation; + const XMLCh* fType; + void* fRelatedData; +}; + +// --------------------------------------------------------------------------- +// DOMErrorImpl: Getter methods +// --------------------------------------------------------------------------- +inline DOMError::ErrorSeverity DOMErrorImpl::getSeverity() const +{ + return fSeverity; +} + +inline const XMLCh* DOMErrorImpl::getMessage() const +{ + return fMessage; +} + +inline DOMLocator* DOMErrorImpl::getLocation() const +{ + return fLocation; +} + +inline void* DOMErrorImpl::getRelatedException() const +{ + return 0; +} + +inline const XMLCh* DOMErrorImpl::getType() const +{ + return fType; +} + +inline void* DOMErrorImpl::getRelatedData() const +{ + return fRelatedData; +} + +// --------------------------------------------------------------------------- +// DOMErrorImpl: Setter methods +// --------------------------------------------------------------------------- +inline void DOMErrorImpl::setSeverity(const ErrorSeverity severity) +{ + fSeverity = severity; +} + +inline void DOMErrorImpl::setMessage(const XMLCh* const message) +{ + fMessage = message; +} + +inline void DOMErrorImpl::setAdoptLocation(const bool value) +{ + fAdoptLocation = value; +} + +inline void DOMErrorImpl::setType(const XMLCh* type) +{ + fType = type; +} + +inline void DOMErrorImpl::setRelatedData(void* relatedData) +{ + fRelatedData = relatedData; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMImplementationImpl.cpp b/include/xercesc/dom/impl/DOMImplementationImpl.cpp new file mode 100644 index 0000000..9924006 --- /dev/null +++ b/include/xercesc/dom/impl/DOMImplementationImpl.cpp @@ -0,0 +1,291 @@ +/* + * 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: DOMImplementationImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMImplementationImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMDocumentTypeImpl.hpp" +#include "DOMLSSerializerImpl.hpp" +#include "DOMLSInputImpl.hpp" +#include "DOMLSOutputImpl.hpp" +#include "DOMImplementationListImpl.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// ------------------------------------------------------------ +// Static constants +// ------------------------------------------------------------ +static const XMLCh g1_0[] = // Points to "1.0" + {chDigit_1, chPeriod, chDigit_0, chNull}; +static const XMLCh g2_0[] = // Points to "2.0" + {chDigit_2, chPeriod, chDigit_0, chNull}; +static const XMLCh g3_0[] = // Points to "3.0" + {chDigit_3, chPeriod, chDigit_0, chNull}; +static const XMLCh gTrav[] = // Points to "Traversal" + {chLatin_T, chLatin_r, chLatin_a, chLatin_v, chLatin_e, chLatin_r, + chLatin_s, chLatin_a, chLatin_l, chNull}; +static const XMLCh gCore[] = // Points to "Core" + {chLatin_C, chLatin_o, chLatin_r, chLatin_e, chNull}; +static const XMLCh gRange[] = // Points to "Range" + {chLatin_R, chLatin_a, chLatin_n, chLatin_g, chLatin_e, chNull}; +static const XMLCh gLS[] = // Points to "LS" + {chLatin_L, chLatin_S, chNull}; +static const XMLCh gXPath[] = // Points to "XPath" + {chLatin_X, chLatin_P, chLatin_a, chLatin_t, chLatin_h, chNull}; + + +static XMLMsgLoader *sMsgLoader = 0; +static DOMImplementationImpl *gDomimp = 0; + +void XMLInitializer::initializeDOMImplementationImpl() +{ + sMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLDOMMsgDomain); + + if (!sMsgLoader) + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); + + gDomimp = new DOMImplementationImpl; +} + +void XMLInitializer::terminateDOMImplementationImpl() +{ + delete gDomimp; + gDomimp = 0; + + delete sMsgLoader; + sMsgLoader = 0; +} + +// +// +XMLMsgLoader* DOMImplementationImpl::getMsgLoader4DOM() +{ + return sMsgLoader; +} + +DOMImplementationImpl *DOMImplementationImpl::getDOMImplementationImpl() +{ + return gDomimp; +} + +// ------------------------------------------------------------ +// DOMImplementation Virtual interface +// ------------------------------------------------------------ +bool DOMImplementationImpl::hasFeature(const XMLCh * feature, const XMLCh * version) const +{ + if (!feature) + return false; + + // ignore the + modifier + if(*feature==chPlus) + feature++; + + bool anyVersion = (version == 0 || !*version); + bool version1_0 = XMLString::equals(version, g1_0); + bool version2_0 = XMLString::equals(version, g2_0); + bool version3_0 = XMLString::equals(version, g3_0); + + // Currently, we support only XML Level 1 version 1.0 + if (XMLString::compareIStringASCII(feature, XMLUni::fgXMLString) == 0 + && (anyVersion || version1_0 || version2_0)) + return true; + + if (XMLString::compareIStringASCII(feature, gCore) == 0 + && (anyVersion || version1_0 || version2_0 || version3_0)) + return true; + + if (XMLString::compareIStringASCII(feature, gTrav) == 0 + && (anyVersion || version2_0)) + return true; + + if (XMLString::compareIStringASCII(feature, gRange) == 0 + && (anyVersion || version2_0)) + return true; + + if (XMLString::compareIStringASCII(feature, gLS) == 0 + && (anyVersion || version3_0)) + return true; + + if (XMLString::compareIStringASCII(feature, gXPath) == 0 + && (anyVersion || version3_0)) + return true; + + return false; +} + + +//Introduced in DOM Level 2 +DOMDocumentType *DOMImplementationImpl::createDocumentType(const XMLCh *qualifiedName, + const XMLCh * publicId, const XMLCh *systemId) +{ + // assume XML 1.0 since we do not know its version yet. + if(!XMLChar1_0::isValidName(qualifiedName)) + throw DOMException(DOMException::INVALID_CHARACTER_ERR, 0); + + //to do: do we need to create with user's memorymanager??? + DOMDocumentTypeImpl* docType = new DOMDocumentTypeImpl(0, qualifiedName, publicId, systemId, true); + return docType; +} + +DOMDocument *DOMImplementationImpl::createDocument(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, DOMDocumentType *doctype, + MemoryManager* const manager) +{ + return new (manager) DOMDocumentImpl(namespaceURI, qualifiedName, doctype, this, manager); +} + + +//Introduced in DOM Level 3 +void* DOMImplementationImpl::getFeature(const XMLCh*, const XMLCh*) const { + return 0; +} + +// Non-standard extension +DOMDocument *DOMImplementationImpl::createDocument(MemoryManager* const manager) +{ + return new (manager) DOMDocumentImpl(this, manager); +} + +// +// DOMImplementation::getImplementation. DOMImplementation is supposed to +// be a pure interface class. This one static +// function is the hook that lets things get started. +DOMImplementation *DOMImplementation::getImplementation() +{ + return (DOMImplementation*) DOMImplementationImpl::getDOMImplementationImpl(); +} + +bool DOMImplementation::loadDOMExceptionMsg +( + const short msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars +) +{ + // Figure out which exception range this code is and load the corresponding + // message. + // + if (msgToLoad <= 50) + { + // DOMException + return sMsgLoader->loadMsg(XMLDOMMsg::DOMEXCEPTION_ERRX+msgToLoad, toFill, maxChars); + } + else if (msgToLoad <= 80) + { + // DOMXPathException + return sMsgLoader->loadMsg(XMLDOMMsg::DOMXPATHEXCEPTION_ERRX+msgToLoad-DOMXPathException::INVALID_EXPRESSION_ERR+1, toFill, maxChars); + } + else if (msgToLoad <= 110) + { + // DOMXLSException + return sMsgLoader->loadMsg(XMLDOMMsg::DOMLSEXCEPTION_ERRX+msgToLoad-DOMLSException::PARSE_ERR+1, toFill, maxChars); + } + else + { + // DOMRangeException + return sMsgLoader->loadMsg(XMLDOMMsg::DOMRANGEEXCEPTION_ERRX+msgToLoad-DOMRangeException::BAD_BOUNDARYPOINTS_ERR+1, toFill, maxChars); + } +} + +// ------------------------------------------------------------ +// DOMImplementationLS Virtual interface +// ------------------------------------------------------------ +//Introduced in DOM Level 3 +DOMLSParser* DOMImplementationImpl::createLSParser( const DOMImplementationLSMode mode, + const XMLCh* const /*schemaType*/, + MemoryManager* const manager, + XMLGrammarPool* const gramPool) +{ + if (mode == DOMImplementationLS::MODE_ASYNCHRONOUS) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, manager); + + // TODO: schemaType + return new (manager) DOMLSParserImpl(0, manager, gramPool); +} + + +DOMLSSerializer* DOMImplementationImpl::createLSSerializer(MemoryManager* const manager) +{ + return new (manager) DOMLSSerializerImpl(manager); +} + +DOMLSInput* DOMImplementationImpl::createLSInput(MemoryManager* const manager) +{ + return new (manager) DOMLSInputImpl(manager); +} + +DOMLSOutput* DOMImplementationImpl::createLSOutput(MemoryManager* const manager) +{ + return new (manager) DOMLSOutputImpl(manager); +} + +// ------------------------------------------------------------ +// DOMImplementationSource Virtual interface +// ------------------------------------------------------------ +DOMImplementation* DOMImplementationImpl::getDOMImplementation(const XMLCh* features) const +{ + DOMImplementation* impl = DOMImplementation::getImplementation(); + + XMLStringTokenizer tokenizer(features, XMLPlatformUtils::fgMemoryManager); + const XMLCh* feature = 0; + + while (feature || tokenizer.hasMoreTokens()) { + + if (!feature) + feature = tokenizer.nextToken(); + + const XMLCh* version = 0; + const XMLCh* token = tokenizer.nextToken(); + + if (token && XMLString::isDigit(token[0])) + version = token; + + if (!impl->hasFeature(feature, version)) + return 0; + + if (!version) + feature = token; + } + return impl; +} + +DOMImplementationList* DOMImplementationImpl::getDOMImplementationList(const XMLCh* features) const +{ + DOMImplementationListImpl* list = new DOMImplementationListImpl; + DOMImplementation* myImpl=getDOMImplementation(features); + if(myImpl) + list->add(myImpl); + return list; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMImplementationImpl.hpp b/include/xercesc/dom/impl/DOMImplementationImpl.hpp new file mode 100644 index 0000000..e68a323 --- /dev/null +++ b/include/xercesc/dom/impl/DOMImplementationImpl.hpp @@ -0,0 +1,102 @@ +/* + * 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: DOMImplementationImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLMsgLoader; + +class DOMImplementationImpl: public XMemory, + public DOMImplementation, + public DOMImplementationSource +{ +private: + DOMImplementationImpl(const DOMImplementationImpl &); + DOMImplementationImpl & operator = (const DOMImplementationImpl &); + friend class XMLInitializer; + +protected: + DOMImplementationImpl() {}; + +public: + virtual ~DOMImplementationImpl() {}; + static DOMImplementationImpl* getDOMImplementationImpl(); + static XMLMsgLoader* getMsgLoader4DOM(); + + // ------------------------------------------------------------ + // DOMImplementation Virtual interface + // ------------------------------------------------------------ + virtual bool hasFeature(const XMLCh * feature, const XMLCh * version) const; + + // Introduced in DOM Level 2 + virtual DOMDocumentType* createDocumentType(const XMLCh *qualifiedName, + const XMLCh * publicId, + const XMLCh *systemId); + virtual DOMDocument* createDocument(const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + DOMDocumentType *doctype, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + // DOM Level 3 + virtual void* getFeature(const XMLCh* feature, const XMLCh* version) const; + + // Non-standard extension + virtual DOMDocument* createDocument(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + // ------------------------------------------------------------ + // DOMImplementationLS Virtual interface + // ------------------------------------------------------------ + // Introduced in DOM Level 3 + virtual DOMLSParser* createLSParser(const DOMImplementationLSMode mode, + const XMLCh* const schemaType, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager, + XMLGrammarPool* const gramPool = 0); + virtual DOMLSSerializer* createLSSerializer(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual DOMLSInput* createLSInput(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual DOMLSOutput* createLSOutput(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + // ------------------------------------------------------------ + // DOMImplementationSource Virtual interface + // ------------------------------------------------------------ + virtual DOMImplementation* getDOMImplementation(const XMLCh* features) const; + virtual DOMImplementationList* getDOMImplementationList(const XMLCh* features) const; + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMImplementationListImpl.cpp b/include/xercesc/dom/impl/DOMImplementationListImpl.cpp new file mode 100644 index 0000000..dd3bfbc --- /dev/null +++ b/include/xercesc/dom/impl/DOMImplementationListImpl.cpp @@ -0,0 +1,59 @@ +/* + * 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: DOMImplementationListImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMImplementationListImpl.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMImplementationListImpl::DOMImplementationListImpl() +{ + fList=new RefVectorOf(3, false); +} + + +DOMImplementationListImpl:: ~DOMImplementationListImpl() +{ + delete fList; +} + + +void DOMImplementationListImpl::add(DOMImplementation* impl) { + fList->addElement(impl); +} + +XMLSize_t DOMImplementationListImpl::getLength() const{ + return fList->size(); +} + + +DOMImplementation *DOMImplementationListImpl::item(XMLSize_t index) const +{ + if(indexsize()) + return fList->elementAt(index); + return 0; +} + +void DOMImplementationListImpl::release() { + delete this; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMImplementationListImpl.hpp b/include/xercesc/dom/impl/DOMImplementationListImpl.hpp new file mode 100644 index 0000000..d501e65 --- /dev/null +++ b/include/xercesc/dom/impl/DOMImplementationListImpl.hpp @@ -0,0 +1,56 @@ +/* + * 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: DOMImplementationListImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONLISTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMIMPLEMENTATIONLISTIMPL_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMImplementation; + +class CDOM_EXPORT DOMImplementationListImpl: public DOMImplementationList +{ +protected: + RefVectorOf *fList; + +private: + // Unused, and unimplemented constructors, operators, etc. + DOMImplementationListImpl(const DOMImplementationListImpl & other); + DOMImplementationListImpl & operator = (const DOMImplementationListImpl & other); + +public: + DOMImplementationListImpl(); + void add(DOMImplementation* impl); + + virtual ~DOMImplementationListImpl(); + virtual DOMImplementation * item(XMLSize_t index) const; + virtual XMLSize_t getLength() const; + virtual void release(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMImplementationRegistry.cpp b/include/xercesc/dom/impl/DOMImplementationRegistry.cpp new file mode 100644 index 0000000..5d7dc11 --- /dev/null +++ b/include/xercesc/dom/impl/DOMImplementationRegistry.cpp @@ -0,0 +1,117 @@ +/* + * 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: DOMImplementationRegistry.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include "DOMImplementationImpl.hpp" +#include "DOMImplementationListImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +// Points to the singleton instance of a registry of DOMImplementationSource. +// +static RefVectorOf* gDOMImplSrcVector = 0; + +// Global mutex that is used to synchronize access to the vector. +// +static XMLMutex* gDOMImplSrcVectorMutex = 0; + +void XMLInitializer::initializeDOMImplementationRegistry() +{ + gDOMImplSrcVectorMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager); + gDOMImplSrcVector = new RefVectorOf(3, false); +} + +void XMLInitializer::terminateDOMImplementationRegistry() +{ + delete gDOMImplSrcVector; + gDOMImplSrcVector = 0; + + delete gDOMImplSrcVectorMutex; + gDOMImplSrcVectorMutex = 0; +} + +// ----------------------------------------------------------------------- +// DOMImplementationRegistry Functions +// ----------------------------------------------------------------------- +DOMImplementation *DOMImplementationRegistry::getDOMImplementation(const XMLCh* features) { + + XMLMutexLock lock(gDOMImplSrcVectorMutex); + + XMLSize_t len = gDOMImplSrcVector->size(); + + // Put our defined source there + if (len == 0) { + gDOMImplSrcVector->addElement((DOMImplementationSource*)DOMImplementationImpl::getDOMImplementationImpl()); + + len = gDOMImplSrcVector->size(); + } + + for (XMLSize_t i = len; i > 0; i--) { + DOMImplementationSource* source = gDOMImplSrcVector->elementAt(i-1); + DOMImplementation* impl = source->getDOMImplementation(features); + if (impl) + return impl; + } + + return 0; +} + +DOMImplementationList* DOMImplementationRegistry::getDOMImplementationList(const XMLCh* features) { + + DOMImplementationListImpl* list = new DOMImplementationListImpl; + + XMLMutexLock lock(gDOMImplSrcVectorMutex); + + XMLSize_t len = gDOMImplSrcVector->size(); + + // Put our defined source there + if (len == 0) + gDOMImplSrcVector->addElement((DOMImplementationSource*)DOMImplementationImpl::getDOMImplementationImpl()); + + len = gDOMImplSrcVector->size(); + + for (XMLSize_t i = len; i > 0; i--) { + DOMImplementationSource* source = gDOMImplSrcVector->elementAt(i-1); + DOMImplementationList* oneList = source->getDOMImplementationList(features); + XMLSize_t oneListLen=oneList->getLength(); + for(XMLSize_t j=0; jadd(oneList->item(j)); + oneList->release(); + } + + return list; +} + +void DOMImplementationRegistry::addSource (DOMImplementationSource* source) +{ + XMLMutexLock lock(gDOMImplSrcVectorMutex); + gDOMImplSrcVector->addElement(source); +} + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/dom/impl/DOMLSInputImpl.cpp b/include/xercesc/dom/impl/DOMLSInputImpl.cpp new file mode 100644 index 0000000..c70dc96 --- /dev/null +++ b/include/xercesc/dom/impl/DOMLSInputImpl.cpp @@ -0,0 +1,95 @@ +/* + * 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: DOMLSInputImpl.cpp 752848 2009-03-12 12:44:40Z amassari $ + */ + +#include "DOMLSInputImpl.hpp" + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMLSInputImpl::DOMLSInputImpl(MemoryManager* const manager /*= XMLPlatformUtils::fgMemoryManager*/) +:fStringData(0) +,fByteStream(0) +,fEncoding(0) +,fPublicId(0) +,fSystemId(0) +,fBaseURI(0) +,fIssueFatalErrorIfNotFound(true) +,fMemoryManager(manager) +{ +} + +DOMLSInputImpl::~DOMLSInputImpl() +{ + fMemoryManager->deallocate(fEncoding); + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); + fMemoryManager->deallocate(fBaseURI); +} + +void DOMLSInputImpl::setStringData(const XMLCh* data) +{ + fStringData=data; + setEncoding(XMLUni::fgXMLChEncodingString); +} + +void DOMLSInputImpl::setByteStream(InputSource* stream) +{ + fByteStream=stream; +} + +void DOMLSInputImpl::setEncoding(const XMLCh* const encodingStr) +{ + fMemoryManager->deallocate(fEncoding); + fEncoding = XMLString::replicate(encodingStr, fMemoryManager); +} + +void DOMLSInputImpl::setPublicId(const XMLCh* const publicId) +{ + fMemoryManager->deallocate(fPublicId); + fPublicId = XMLString::replicate(publicId, fMemoryManager); +} + +void DOMLSInputImpl::setSystemId(const XMLCh* const systemId) +{ + fMemoryManager->deallocate(fSystemId); + fSystemId = XMLString::replicate(systemId, fMemoryManager); +} + +void DOMLSInputImpl::setBaseURI(const XMLCh* const baseURI) +{ + fMemoryManager->deallocate(fBaseURI); + fBaseURI = XMLString::replicate(baseURI, fMemoryManager); +} + +void DOMLSInputImpl::setIssueFatalErrorIfNotFound(bool flag) +{ + fIssueFatalErrorIfNotFound=flag; +} + +void DOMLSInputImpl::release() +{ + delete this; +} + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/dom/impl/DOMLSInputImpl.hpp b/include/xercesc/dom/impl/DOMLSInputImpl.hpp new file mode 100644 index 0000000..cad5d62 --- /dev/null +++ b/include/xercesc/dom/impl/DOMLSInputImpl.hpp @@ -0,0 +1,134 @@ +/* + * 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: DOMLSInputImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSINPUTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSINPUTIMPL_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class CDOM_EXPORT DOMLSInputImpl : public XMemory, public DOMLSInput +{ + +public: + + DOMLSInputImpl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~DOMLSInputImpl(); + + virtual const XMLCh* getStringData() const; + virtual InputSource* getByteStream() const; + virtual const XMLCh* getEncoding() const; + virtual const XMLCh* getPublicId() const; + virtual const XMLCh* getSystemId() const; + virtual const XMLCh* getBaseURI() const; + + virtual void setStringData(const XMLCh* data); + virtual void setByteStream(InputSource* stream); + virtual void setEncoding(const XMLCh* const encodingStr); + virtual void setPublicId(const XMLCh* const publicId); + virtual void setSystemId(const XMLCh* const systemId); + virtual void setBaseURI(const XMLCh* const baseURI); + + virtual void setIssueFatalErrorIfNotFound(bool flag); + virtual bool getIssueFatalErrorIfNotFound() const; + virtual void release(); + + +private: + /** unimplemented copy ctor and assignment operator */ + DOMLSInputImpl(const DOMLSInputImpl&); + DOMLSInputImpl & operator = (const DOMLSInputImpl&); + +protected: + // ----------------------------------------------------------------------- + // Private data members + // + // fStringData + // We don't own it + // + // fByteStream + // We don't own it + // + // fEncoding + // We own it + // + // fPublicId + // We own it + // + // fSystemId + // We own it + // + // fBaseURI + // We own it + // + // ----------------------------------------------------------------------- + + const XMLCh *fStringData; + InputSource *fByteStream; + XMLCh *fEncoding; + XMLCh *fPublicId; + XMLCh *fSystemId; + XMLCh *fBaseURI; + bool fIssueFatalErrorIfNotFound; + MemoryManager* fMemoryManager; +}; + +inline const XMLCh* DOMLSInputImpl::getStringData() const +{ + return fStringData; +} + +inline InputSource* DOMLSInputImpl::getByteStream() const +{ + return fByteStream; +} + +inline const XMLCh* DOMLSInputImpl::getEncoding() const +{ + return fEncoding; +} + +inline const XMLCh* DOMLSInputImpl::getPublicId() const +{ + return fPublicId; +} + +inline const XMLCh* DOMLSInputImpl::getSystemId() const +{ + return fSystemId; +} + +inline const XMLCh* DOMLSInputImpl::getBaseURI() const +{ + return fBaseURI; +} + +inline bool DOMLSInputImpl::getIssueFatalErrorIfNotFound() const +{ + return fIssueFatalErrorIfNotFound; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMLSOutputImpl.cpp b/include/xercesc/dom/impl/DOMLSOutputImpl.cpp new file mode 100644 index 0000000..07ba2c8 --- /dev/null +++ b/include/xercesc/dom/impl/DOMLSOutputImpl.cpp @@ -0,0 +1,66 @@ +/* + * 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: DOMLSOutputImpl.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include "DOMLSOutputImpl.hpp" + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMLSOutputImpl::DOMLSOutputImpl(MemoryManager* const manager /*= XMLPlatformUtils::fgMemoryManager*/) +:fByteStream(0) +,fEncoding(0) +,fSystemId(0) +,fMemoryManager(manager) +{ +} + +DOMLSOutputImpl::~DOMLSOutputImpl() +{ + fMemoryManager->deallocate(fEncoding); + fMemoryManager->deallocate(fSystemId); +} + +void DOMLSOutputImpl::setByteStream(XMLFormatTarget* stream) +{ + fByteStream=stream; +} + +void DOMLSOutputImpl::setEncoding(const XMLCh* const encodingStr) +{ + fMemoryManager->deallocate(fEncoding); + fEncoding = XMLString::replicate(encodingStr, fMemoryManager); +} + +void DOMLSOutputImpl::setSystemId(const XMLCh* const systemId) +{ + fMemoryManager->deallocate(fSystemId); + fSystemId = XMLString::replicate(systemId, fMemoryManager); +} + +void DOMLSOutputImpl::release() +{ + delete this; +} + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/dom/impl/DOMLSOutputImpl.hpp b/include/xercesc/dom/impl/DOMLSOutputImpl.hpp new file mode 100644 index 0000000..2d3565e --- /dev/null +++ b/include/xercesc/dom/impl/DOMLSOutputImpl.hpp @@ -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: DOMLSOutputImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSOUTPUTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSOUTPUTIMPL_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class CDOM_EXPORT DOMLSOutputImpl : public XMemory, public DOMLSOutput +{ + +public: + + DOMLSOutputImpl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~DOMLSOutputImpl(); + + virtual XMLFormatTarget* getByteStream() const; + virtual const XMLCh* getEncoding() const; + virtual const XMLCh* getSystemId() const; + + virtual void setByteStream(XMLFormatTarget* stream); + virtual void setEncoding(const XMLCh* const encodingStr); + virtual void setSystemId(const XMLCh* const systemId); + + virtual void release(); + +private: + + /** unimplemented copy ctor and assignment operator */ + DOMLSOutputImpl(const DOMLSOutputImpl&); + DOMLSOutputImpl & operator = (const DOMLSOutputImpl&); + +protected: + // ----------------------------------------------------------------------- + // Private data members + // + // fByteStream + // We don't own it + // + // fEncoding + // We own it + // + // fSystemId + // We own it + // + // ----------------------------------------------------------------------- + + XMLFormatTarget *fByteStream; + XMLCh *fEncoding; + XMLCh *fSystemId; + MemoryManager* fMemoryManager; +}; + +inline XMLFormatTarget* DOMLSOutputImpl::getByteStream() const +{ + return fByteStream; +} + +inline const XMLCh* DOMLSOutputImpl::getEncoding() const +{ + return fEncoding; +} + +inline const XMLCh* DOMLSOutputImpl::getSystemId() const +{ + return fSystemId; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMLSSerializerImpl.cpp b/include/xercesc/dom/impl/DOMLSSerializerImpl.cpp new file mode 100644 index 0000000..1d83aaa --- /dev/null +++ b/include/xercesc/dom/impl/DOMLSSerializerImpl.cpp @@ -0,0 +1,1721 @@ +/* + * 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: DOMLSSerializerImpl.cpp 1662868 2015-02-28 00:52:04Z scantor $ + */ + +#include "DOMLSSerializerImpl.hpp" +#include "DOMLSOutputImpl.hpp" +#include "DOMErrorImpl.hpp" +#include "DOMLocatorImpl.hpp" +#include "DOMImplementationImpl.hpp" +#include "DOMStringListImpl.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// Local const data +// +// --------------------------------------------------------------------------- + +static const int INVALID_FEATURE_ID = -1; +static const int CANONICAL_FORM_ID = 0x0; +static const int DISCARD_DEFAULT_CONTENT_ID = 0x1; +static const int ENTITIES_ID = 0x2; +static const int FORMAT_PRETTY_PRINT_ID = 0x3; +static const int NORMALIZE_CHARACTERS_ID = 0x4; +static const int SPLIT_CDATA_SECTIONS_ID = 0x5; +static const int VALIDATION_ID = 0x6; +static const int WHITESPACE_IN_ELEMENT_CONTENT_ID = 0x7; +static const int BYTE_ORDER_MARK_ID = 0x8; +static const int XML_DECLARATION = 0x9; +static const int FORMAT_PRETTY_PRINT_1ST_LEVEL_ID = 0xA; + +// feature true false +// ================================================================================ +//canonical-form [optional] Not Supported [required] (default) +//discard-default-content [required] (default) [required] +//entity [required] (default) [optional] +//format-pretty-print [optional] Partially Supported [required] (default) +//normalize-characters [optional] Not Supported [required] (default) +//split-cdata-sections [required] (default) [required] +//validation [optional] Not Supported [required] (default) +//whitespace-in-element-content [requierd] (default) [optional] Not Supported +// + +// +// Each feature has 2 entries in this array, +// the first for "true", +// the second for "false". +// +static const bool featuresSupported[] = { + false, true, // canonical-form + true, true, // discard-default-content + true, true, // entity + true, true, // format-pretty-print + false, true, // normalize-characters + true, true, // split-cdata-sections + false, true, // validation + true, false, // whitespace-in-element-content + true, true, // http://apache.org/xml/features/dom/byte-order-mark + true, true, // xml-declaration + true, true // http://apache.org/xml/features/pretty-print/space-first-level-elements +}; + +// default end-of-line sequence +static const XMLCh gEOLSeq[] = +{ + chLF, chNull +}; + +//UTF-8 +static const XMLCh gUTF8[] = +{ + chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull +}; + +// +static const XMLCh gEndPI[] = +{ + chQuestion, chCloseAngle, chNull +}; + +// +static const XMLCh gXMLDecl_endtag[] = +{ + chQuestion, chCloseAngle, chNull +}; + +// +static const XMLCh gEndCDATA[] = +{ +// chCloseSquare, chCloseAngle, chCloseAngle, chNull // test only: ]>> + chCloseSquare, chCloseSquare, chCloseAngle, chNull +}; + +// +static const XMLCh gEndComment[] = +{ + chDash, chDash, chCloseAngle, chNull +}; + +//setUnRepFlags(XMLFormatter::UnRep_Fail); \ +try \ +{ \ + action; \ +} \ +catch(TranscodingException const &e) \ +{ \ + reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, e.getMessage()); \ + throw e; \ +} + +DOMLSSerializerImpl::~DOMLSSerializerImpl() +{ + fMemoryManager->deallocate(fNewLine);//delete [] fNewLine; + delete fNamespaceStack; + delete fSupportedParameters; + // we don't own/adopt error handler and filter +} + +DOMLSSerializerImpl::DOMLSSerializerImpl(MemoryManager* const manager) +:fFeatures(0) +,fNewLine(0) +,fErrorHandler(0) +,fFilter(0) +,fDocumentVersion(XMLUni::fgVersion1_0) +,fSupportedParameters(0) +,fEncodingUsed(0) +,fNewLineUsed(0) +,fFormatter(0) +,fErrorCount(0) +,fCurrentLine(0) +,fLineFeedInTextNodePrinted(false) +,fLastWhiteSpaceInTextNode(0) +,fNamespaceStack(0) +,fMemoryManager(manager) +{ + fNamespaceStack=new (fMemoryManager) RefVectorOf< RefHashTableOf >(1, true, fMemoryManager); + + // + // set features to default setting + // + setFeature(CANONICAL_FORM_ID, false); + setFeature(DISCARD_DEFAULT_CONTENT_ID, true ); + setFeature(ENTITIES_ID, true ); + setFeature(FORMAT_PRETTY_PRINT_ID, false); + setFeature(NORMALIZE_CHARACTERS_ID, false); + setFeature(SPLIT_CDATA_SECTIONS_ID, true ); + setFeature(VALIDATION_ID, false); + setFeature(WHITESPACE_IN_ELEMENT_CONTENT_ID, true ); + setFeature(BYTE_ORDER_MARK_ID, false); + setFeature(XML_DECLARATION, true ); + setFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID, true ); + + fSupportedParameters=new (fMemoryManager) DOMStringListImpl(12, fMemoryManager); + fSupportedParameters->add(XMLUni::fgDOMErrorHandler); + fSupportedParameters->add(XMLUni::fgDOMWRTCanonicalForm); + fSupportedParameters->add(XMLUni::fgDOMWRTDiscardDefaultContent); + fSupportedParameters->add(XMLUni::fgDOMWRTEntities); + fSupportedParameters->add(XMLUni::fgDOMWRTFormatPrettyPrint); + fSupportedParameters->add(XMLUni::fgDOMWRTNormalizeCharacters); + fSupportedParameters->add(XMLUni::fgDOMWRTSplitCdataSections); + fSupportedParameters->add(XMLUni::fgDOMWRTValidation); + fSupportedParameters->add(XMLUni::fgDOMWRTWhitespaceInElementContent); + fSupportedParameters->add(XMLUni::fgDOMWRTBOM); + fSupportedParameters->add(XMLUni::fgDOMXMLDeclaration); + fSupportedParameters->add(XMLUni::fgDOMWRTXercesPrettyPrint); +} + +bool DOMLSSerializerImpl::canSetParameter(const XMLCh* featName + , const void* /*value*/) const +{ + if(XMLString::compareIStringASCII(featName, XMLUni::fgDOMErrorHandler)==0) + return true; + return false; +} + +bool DOMLSSerializerImpl::canSetParameter(const XMLCh* featName + , bool state) const +{ + int featureId = INVALID_FEATURE_ID; + return checkFeature(featName, false, featureId) ? canSetFeature(featureId, state) : false; +} + +void DOMLSSerializerImpl::setParameter(const XMLCh* featName + , const void* value) +{ + if(XMLString::compareIStringASCII(featName, XMLUni::fgDOMErrorHandler)==0) + fErrorHandler = (DOMErrorHandler*)value; + else + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager); +} + +void DOMLSSerializerImpl::setParameter(const XMLCh* featName + , bool state) +{ + int featureId = INVALID_FEATURE_ID; + checkFeature(featName, true, featureId); + + if (!canSetFeature(featureId, state)) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager); + + setFeature(featureId, state); + + // + // setting "canonical-form" to true will set the parameters "format-pretty-print", + // "discard-default-content", and "xml-declaration", to false + // + if ((featureId == CANONICAL_FORM_ID) && state) + { + setFeature(FORMAT_PRETTY_PRINT_ID, false); + setFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID, false); + setFeature(DISCARD_DEFAULT_CONTENT_ID, false); + setFeature(XML_DECLARATION, false); + } + // Setting one of those parameters to true will set "canonical-form" to false. + if ((featureId == FORMAT_PRETTY_PRINT_ID || featureId == DISCARD_DEFAULT_CONTENT_ID || featureId == XML_DECLARATION) && state) + setFeature(CANONICAL_FORM_ID, false); +} + +const void* DOMLSSerializerImpl::getParameter(const XMLCh* featName) const +{ + if(XMLString::compareIStringASCII(featName, XMLUni::fgDOMErrorHandler)==0) + { + return (void*)fErrorHandler; + } + else + { + int featureId = INVALID_FEATURE_ID; + checkFeature(featName, true, featureId); + return (void*)getFeature(featureId); + } +} + +const DOMStringList* DOMLSSerializerImpl::getParameterNames() const +{ + return fSupportedParameters; +} + +void DOMLSSerializerImpl::setNewLine(const XMLCh* const newLine) +{ + fMemoryManager->deallocate(fNewLine);//delete [] fNewLine; + fNewLine = XMLString::replicate(newLine, fMemoryManager); +} + +const XMLCh* DOMLSSerializerImpl::getNewLine() const +{ + return fNewLine; +} + +void DOMLSSerializerImpl::setFilter(DOMLSSerializerFilter *filter) +{ + fFilter = filter; +} + +DOMLSSerializerFilter* DOMLSSerializerImpl::getFilter() const +{ + return fFilter; +} + +// +// +// +bool DOMLSSerializerImpl::write(const DOMNode* nodeToWrite, + DOMLSOutput* const destination) +{ + XMLFormatTarget* pTarget=destination->getByteStream(); + Janitor janTarget(0); + if(!pTarget) + { + const XMLCh* szSystemId=destination->getSystemId(); + if(!szSystemId) + { + //TODO: report error "missing target" + return false; + } + pTarget=new LocalFileFormatTarget(szSystemId, fMemoryManager); + janTarget.reset(pTarget); + } + /** + * When writing to a LSOutput, the encoding is found by looking at the encoding information + * that is reachable through the LSOutput and the item to be written (or its owner document) in this order: + * + * 1. LSOutput.encoding, + * 2. Document.inputEncoding, + * 3. Document.xmlEncoding. + * + * If no encoding is reachable through the above properties, a default encoding of "UTF-8" will be used. + * If the specified encoding is not supported an "unsupported-encoding" fatal error is raised. + */ + fEncodingUsed = gUTF8; + + const DOMDocument *docu = (nodeToWrite->getNodeType() == DOMNode::DOCUMENT_NODE)? + (const DOMDocument*)nodeToWrite : nodeToWrite->getOwnerDocument(); + + const XMLCh* lsEncoding=destination->getEncoding(); + if (lsEncoding && *lsEncoding) + { + fEncodingUsed = lsEncoding; + } + else if (docu) + { + const XMLCh* tmpEncoding = docu->getInputEncoding(); + + if ( tmpEncoding && *tmpEncoding) + { + fEncodingUsed = tmpEncoding; + } + else + { + tmpEncoding = docu->getXmlEncoding(); + + if ( tmpEncoding && *tmpEncoding) + { + fEncodingUsed = tmpEncoding; + } + } + } + + + /** + * The end-of-line sequence of characters to be used in the XML being + * written out. The only permitted values are these: + * . null + * + * Use a default end-of-line sequence. DOM implementations should choose + * the default to match the usual convention for text files in the + * environment being used. Implementations must choose a default + * sequence that matches one of those allowed by 2.11 "End-of-Line + * Handling". + * + * CR The carriage-return character (#xD) + * CR-LF The carriage-return and line-feed characters (#xD #xA) + * LF The line-feed character (#xA) + * + * The default value for this attribute is null + */ + fNewLineUsed = (fNewLine && *fNewLine)? fNewLine : gEOLSeq; + + /** + * get Document Version + */ + fDocumentVersion = (docu && docu->getXmlVersion() && *(docu->getXmlVersion()))?docu->getXmlVersion():XMLUni::fgVersion1_0; + + fErrorCount = 0; + + fLineFeedInTextNodePrinted = false; + fLastWhiteSpaceInTextNode = 0; + + try + { + fFormatter = new (fMemoryManager) XMLFormatter( fEncodingUsed + ,fDocumentVersion + ,pTarget + ,XMLFormatter::NoEscapes + ,XMLFormatter::UnRep_CharRef + ,fMemoryManager); + } + catch (const TranscodingException& e) + { + reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, e.getMessage()); + return false; + } + + try + { + Janitor janName(fFormatter); + processNode(nodeToWrite); + pTarget->flush(); + } + + // + // The serialize engine (processNode) throws an exception to abort + // serialization if + // + // . A fatal error occurs which renders the output ill-formed, or + // . Instructed by the application's error handler + // + catch (const TranscodingException&) + { + pTarget->flush(); + return false; + } + + catch (const XMLDOMMsg::Codes) + { + pTarget->flush(); + return false; + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) + { + pTarget->flush(); + throw; + } + + // + // true if node was successfully serialized and + // false in case a failure occured and the + // failure wasn't canceled by the error handler. + // + return ((fErrorCount == 0)? true : false); +} + +bool DOMLSSerializerImpl::writeToURI(const DOMNode* nodeToWrite, const XMLCh* uri) +{ + DOMLSOutputImpl output(fMemoryManager); + output.setSystemId(uri); + return write(nodeToWrite, &output); +} + +// +// We don't throw DOMSTRING_SIZE_ERR since we are no longer +// using DOMString. +// +XMLCh* DOMLSSerializerImpl::writeToString(const DOMNode* nodeToWrite, MemoryManager* manager /*= NULL*/) +{ + if(manager==NULL) + manager = fMemoryManager; + MemBufFormatTarget destination(1023, manager); + bool retVal; + + bool bBOMFlag=getFeature(BYTE_ORDER_MARK_ID); + setFeature(BYTE_ORDER_MARK_ID, false); + try + { + DOMLSOutputImpl output(manager); + output.setByteStream(&destination); + output.setEncoding(XMLUni::fgUTF16EncodingString); + retVal = write(nodeToWrite, &output); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) + { + // + // there is a possibility that memory allocation + // exception thrown in XMLBuffer class + // + setFeature(BYTE_ORDER_MARK_ID, bBOMFlag); + return 0; + } + + setFeature(BYTE_ORDER_MARK_ID, bBOMFlag); + return (retVal ? XMLString::replicate((XMLCh*) destination.getRawBuffer(), manager) : 0); +} + +// +// Characters not representable in output encoding, +// +// 1. CHARACTER DATA (outside of markup) --- no error +// ordinary character -> numeric character reference +// '<' and '&' -> < and & +// +// 2. Within MARKUP, but outside of attributes +// reported as an error --- ERROR +// markup: +// start tag done +// end tag done +// empty element tag done +// entity references done +// character references // REVISIT +// comments done +// CDATA section delimiters done, done +// document type declarartions done +// processing instructions (PI) done +// +// 3. With in ATTRIBUTE +// -> numeric character reference +// no quotes -> in quotes +// with quotes, no apostrophe -> in apostrophe +// with quotes and apostrophe -> in quotes and " +// +// 4. CDATA sections +// "split_cdata_section" true --- char ref +// false --- ERROR +// +// --------------------------------------------------------------------------- +// Stream out a DOM node, and, recursively, all of its children. This +// function is the heart of writing a DOM tree out as XML source. Give it +// a document node and it will do the whole thing. +// --------------------------------------------------------------------------- + +void DOMLSSerializerImpl::processNode(const DOMNode* const nodeToWrite, int level) +{ + + // Get the name and value out for convenience + const XMLCh* nodeName = nodeToWrite->getNodeName(); + const XMLCh* nodeValue = nodeToWrite->getNodeValue(); + XMLSize_t lent = XMLString::stringLen(nodeValue); + + switch (nodeToWrite->getNodeType()) + { + case DOMNode::TEXT_NODE: + { + if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) + break; + + if (getFeature(FORMAT_PRETTY_PRINT_ID)) + { + fLineFeedInTextNodePrinted = false; + fLastWhiteSpaceInTextNode = 0; + + if(XMLChar1_0::isAllSpaces(nodeValue, XMLString::stringLen(nodeValue))) + { + // skips whitespace-only text nodes unless whitespace-in-element is set. + if (!getFeature(WHITESPACE_IN_ELEMENT_CONTENT_ID)) + { + break; + } + else + { + // + // we need to trace if newline(s) have been printed out + // to avoid generate extra newline for pretty printing, + // as well as the number of whitespaces after the last + // newline character to do indentation properly. + // + int pos = XMLString::lastIndexOf(nodeValue, chLF); + if (-1 != pos) + { + fLineFeedInTextNodePrinted = true; + fLastWhiteSpaceInTextNode = (unsigned int)(lent - pos); + } + else + { + // for those platforms using chCR alone as + // a newline character + pos = XMLString::lastIndexOf(nodeValue, chCR); + if (-1 != pos) + { + fLineFeedInTextNodePrinted = true; + fLastWhiteSpaceInTextNode = (unsigned int)(lent - pos); + } + } + } + } + } + + setURCharRef(); // character data + fFormatter->formatBuf(nodeValue, lent, XMLFormatter::CharEscapes); + break; + } + + case DOMNode::PROCESSING_INSTRUCTION_NODE: + { + if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) + break; + + if(level == 1 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID)) + printNewLine(); + + printNewLine(); + printIndent(level); + + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << gStartPI << nodeName; + if (lent > 0) + { + *fFormatter << chSpace << nodeValue; + } + *fFormatter << gEndPI; + ) + break; + } + + case DOMNode::DOCUMENT_NODE: // Not to be shown to Filter + { + + // output BOM if needed + processBOM(); + + setURCharRef(); + const DOMDocument *docu = (const DOMDocument*)nodeToWrite; + + //[23] XMLDecl ::= '' + //[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') + //[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName + //[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) + // + + if (getFeature(XML_DECLARATION)) { + // use the version and encoding resolved + *fFormatter << gXMLDecl_VersionInfo << fDocumentVersion << gXMLDecl_separator; + *fFormatter << gXMLDecl_EncodingDecl << fEncodingUsed << gXMLDecl_separator; + + const XMLCh* st = (docu->getXmlStandalone())? XMLUni::fgYesString : XMLUni::fgNoString; + *fFormatter << gXMLDecl_SDDecl << st << gXMLDecl_separator; + + *fFormatter << gXMLDecl_endtag; + } + + DOMNodeSPtr child = nodeToWrite->getFirstChild(); + while( child != 0) + { + processNode(child, level); + child = child->getNextSibling(); + } + printNewLine(); + break; + } + + case DOMNode::DOCUMENT_FRAGMENT_NODE: + { + + setURCharRef(); + + DOMNode *child = nodeToWrite->getFirstChild(); + while( child != 0) + { + processNode(child, level); + child = child->getNextSibling(); + } + printNewLine(); + break; + } + + case DOMNode::ELEMENT_NODE: + { + DOMNodeFilter::FilterAction filterAction = checkFilter(nodeToWrite); + + if ( filterAction == DOMNodeFilter::FILTER_REJECT) + break; + + if (!fLineFeedInTextNodePrinted) + { + if(level == 1 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID)) + printNewLine(); + + printNewLine(); + } + else + { + fLineFeedInTextNodePrinted = false; + } + + printIndent(level); + + //track the line number the current node begins on + int nodeLine = fCurrentLine; + + // add an entry in the namespace stack + RefHashTableOf* namespaceMap=NULL; + + if ( filterAction == DOMNodeFilter::FILTER_ACCEPT) + { + // this element attributes child elements + // accept yes yes yes + // skip no no yes + // + TRY_CATCH_THROW + ( + // The name has to be representable without any escapes + *fFormatter << XMLFormatter::NoEscapes + << chOpenAngle << nodeName; + ) + + // Output any attributes on this element + setURCharRef(); + DOMNamedNodeMap *attributes = nodeToWrite->getAttributes(); + XMLSize_t attrCount = attributes->getLength(); + + // check if the namespace for the current node is already defined + const XMLCh* prefix = nodeToWrite->getPrefix(); + const XMLCh* uri = nodeToWrite->getNamespaceURI(); + if((uri && uri[0]) || ((prefix==0 || prefix[0]==0) && isDefaultNamespacePrefixDeclared())) + { + if(prefix==0 || prefix[0]==0) + prefix=XMLUni::fgZeroLenString; + if(!isNamespaceBindingActive(prefix, uri)) + { + if(namespaceMap==NULL) + { + namespaceMap=new (fMemoryManager) RefHashTableOf(12, false, fMemoryManager); + fNamespaceStack->addElement(namespaceMap); + } + namespaceMap->put((void*)prefix,(XMLCh*)uri); + *fFormatter << XMLFormatter::NoEscapes + << chSpace << XMLUni::fgXMLNSString; + if(!XMLString::equals(prefix,XMLUni::fgZeroLenString)) + *fFormatter << chColon << prefix; + *fFormatter << chEqual << chDoubleQuote + << XMLFormatter::AttrEscapes + << uri + << XMLFormatter::NoEscapes + << chDoubleQuote; + } + } + + bool discard = getFeature(DISCARD_DEFAULT_CONTENT_ID); + for (XMLSize_t i = 0; i < attrCount; i++) + { + DOMAttrSPtr attribute = (DOMAttr*)attributes->item(i); + + // Not to be shown to Filter + + // + //"discard-default-content" + // true + // [required] (default) + // Use whatever information available to the implementation + // (i.e. XML schema, DTD, the specified flag on Attr nodes, + // and so on) to decide what attributes and content should be + // discarded or not. + // Note that the specified flag on Attr nodes in itself is + // not always reliable, it is only reliable when it is set + // to false since the only case where it can be set to false + // is if the attribute was created by the implementation. + // The default content won't be removed if an implementation + // does not have any information available. + // false + // [required] + // Keep all attributes and all content. + // + if (discard && !((DOMAttr*)attribute )->getSpecified()) + continue; + // + // Again the name has to be completely representable. But the + // attribute can have refs and requires the attribute style + // escaping. + // + + // if this attribute is a namespace declaration, add it to the namespace map for the current level + const XMLCh* ns = attribute->getNamespaceURI(); + if (ns != 0 ) + { + if(XMLString::equals(ns, XMLUni::fgXMLNSURIName)) + { + if(namespaceMap==NULL) + { + namespaceMap=new (fMemoryManager) RefHashTableOf(12, false, fMemoryManager); + fNamespaceStack->addElement(namespaceMap); + } + const XMLCh* nsPrefix = attribute->getLocalName(); + if(XMLString::equals(attribute->getNodeName(),XMLUni::fgXMLNSString)) + nsPrefix = XMLUni::fgZeroLenString; + if(namespaceMap->containsKey((void*)nsPrefix)) + continue; + namespaceMap->put((void*)attribute->getLocalName(),(XMLCh*)attribute->getNodeValue()); + } + else if(!XMLString::equals(ns, XMLUni::fgXMLURIName)) + { + // check if the namespace for the current node is already defined + const XMLCh* prefix = attribute->getPrefix(); + if(prefix && prefix[0]) + { + const XMLCh* uri = attribute->getNamespaceURI(); + if(!isNamespaceBindingActive(prefix, uri)) + { + if(namespaceMap==NULL) + { + namespaceMap=new (fMemoryManager) RefHashTableOf(12, false, fMemoryManager); + fNamespaceStack->addElement(namespaceMap); + } + namespaceMap->put((void*)prefix,(XMLCh*)uri); + *fFormatter << XMLFormatter::NoEscapes + << chSpace << XMLUni::fgXMLNSString << chColon << prefix + << chEqual << chDoubleQuote + << XMLFormatter::AttrEscapes + << uri + << XMLFormatter::NoEscapes + << chDoubleQuote; + } + } + } + } + if (XMLString::equals(ns, XMLUni::fgXMLNSURIName) || checkFilter(attribute) == DOMNodeFilter::FILTER_ACCEPT) + { + *fFormatter << XMLFormatter::NoEscapes + << chSpace << attribute->getNodeName() + << chEqual << chDoubleQuote + << XMLFormatter::AttrEscapes; + if (getFeature(ENTITIES_ID)) + { + DOMNodeSPtr child = attribute->getFirstChild(); + while( child != 0) + { + if(child->getNodeType()==DOMNode::TEXT_NODE) + *fFormatter << child->getNodeValue(); + else if(child->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE) + *fFormatter << XMLFormatter::NoEscapes + << chAmpersand << child->getNodeName() << chSemiColon + << XMLFormatter::AttrEscapes; + child = child->getNextSibling(); + } + } + else + *fFormatter << attribute->getNodeValue(); + *fFormatter << XMLFormatter::NoEscapes + << chDoubleQuote; + } + } // end of for + } // end of FILTER_ACCEPT + + level++; + + // FILTER_SKIP may start from here + + // + // Test for the presence of children, which includes both + // text content and nested elements. + // + DOMNodeSPtr child = nodeToWrite->getFirstChild(); + if (child != 0) + { + // There are children. Close start-tag, and output children. + // No escapes are legal here + if (filterAction == DOMNodeFilter::FILTER_ACCEPT) + *fFormatter << XMLFormatter::NoEscapes << chCloseAngle; + + while( child != 0) + { + processNode(child, level); + child = child->getNextSibling(); + } + + level--; + + if (filterAction == DOMNodeFilter::FILTER_ACCEPT) + { + //if we are not on the same line as when we started + //this node then print a new line and indent + if(nodeLine != fCurrentLine) + { + if (!fLineFeedInTextNodePrinted) + { + printNewLine(); + } + else + { + fLineFeedInTextNodePrinted = false; + } + + if(nodeLine != fCurrentLine && level == 0 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID)) + printNewLine(); + + printIndent(level); + } + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << gEndElement + << nodeName << chCloseAngle; + ) + + } + } + else + { + level--; + + // + // There were no children. Output the short form close of + // the element start tag, making it an empty-element tag. + // + if (filterAction == DOMNodeFilter::FILTER_ACCEPT) + { + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << chForwardSlash << chCloseAngle; + ) + } + } + + // remove the namespace map at this level + if(namespaceMap!=NULL) + fNamespaceStack->removeLastElement(); + + break; + } + case DOMNode::ATTRIBUTE_NODE: + { + if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) + break; + + const XMLCh* localName = nodeToWrite->getLocalName(); + + // check if this is a DOM Level 1 Node + if(localName == 0) + *fFormatter << XMLFormatter::NoEscapes + << nodeToWrite->getNodeName(); + else + *fFormatter << XMLFormatter::NoEscapes + << chOpenCurly << nodeToWrite->getNamespaceURI() + << chCloseCurly << localName; + *fFormatter << chEqual << chDoubleQuote + << XMLFormatter::AttrEscapes; + if (getFeature(ENTITIES_ID)) + { + DOMNodeSPtr child = nodeToWrite->getFirstChild(); + while( child != 0) + { + if(child->getNodeType()==DOMNode::TEXT_NODE) + *fFormatter << child->getNodeValue(); + else if(child->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE) + *fFormatter << XMLFormatter::NoEscapes + << chAmpersand << child->getNodeName() << chSemiColon + << XMLFormatter::AttrEscapes; + child = child->getNextSibling(); + } + } + else + *fFormatter << nodeValue; + *fFormatter << XMLFormatter::NoEscapes + << chDoubleQuote; + + break; + } + case DOMNode::ENTITY_REFERENCE_NODE: + { + //"entities" + //true + //[required] (default) + //Keep EntityReference and Entity nodes in the document. + + //false + //[optional] + //Remove all EntityReference and Entity nodes from the document, + // putting the entity expansions directly in their place. + // Text nodes are into "normal" form. + //Only EntityReference nodes to non-defined entities are kept in the document. + + if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) + break; + + if (getFeature(ENTITIES_ID)) + { + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << chAmpersand + << nodeName << chSemiColon; + ) + } + else + { + // check if the referenced entity is defined or not + if (nodeToWrite->getOwnerDocument()->getDoctype()->getEntities()->getNamedItem(nodeName)) + { + DOMNodeSPtr child; + for (child = nodeToWrite->getFirstChild(); + child != 0; + child = child->getNextSibling()) + { + processNode(child, level); + } + } + else + { + TRY_CATCH_THROW + ( + *fFormatter< unrep-char + // =============================================================== + // true split split + // false fails fails + // + case DOMNode::CDATA_SECTION_NODE: + { + if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) + break; + + if (getFeature(SPLIT_CDATA_SECTIONS_ID)) + { + // it is fairly complicated and we process this + // in a separate function. + procCdataSection(nodeValue, nodeToWrite); + } + else + { + // search for "]]>", the node value is not supposed to have this + if (XMLString::patternMatch((XMLCh*) nodeValue, gEndCDATA) != -1) + { + reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::Writer_NestedCDATA); + } + + TRY_CATCH_THROW + ( + // transcoder throws exception for unrep chars + *fFormatter << XMLFormatter::NoEscapes << gStartCDATA << nodeValue << gEndCDATA; + ) + } + + break; + } + + case DOMNode::COMMENT_NODE: + { + if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) + break; + + // Figure out if we want pretty-printing for this comment. + // If this comment node does not have any element siblings + // (i.e., it is a text node) then we don't want to add any + // whitespaces since that might be significant to the + // application. Otherwise we want pretty-printing. + // + + bool pretty = (level == 0); // Document-level comments. + + if (!pretty) + { + // See if we have any element siblings. + // + const DOMNode* s = nodeToWrite->getNextSibling (); + + while (s != 0 && s->getNodeType () != DOMNode::ELEMENT_NODE) + s = s->getNextSibling (); + + if (s != 0) + pretty = true; + else + { + s = nodeToWrite->getPreviousSibling (); + + while (s != 0 && s->getNodeType () != DOMNode::ELEMENT_NODE) + s = s->getPreviousSibling (); + + if (s != 0) + pretty = true; + } + } + + if (pretty) + { + if(level == 1 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID)) + printNewLine(); + + printNewLine(); + printIndent(level); + } + + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << gStartComment + << nodeValue << gEndComment; + ) + break; + } + + case DOMNode::DOCUMENT_TYPE_NODE: // Not to be shown to Filter + { + const DOMDocumentType *doctype = (const DOMDocumentType *)nodeToWrite; + + fFormatter->setEscapeFlags(XMLFormatter::NoEscapes); + + printNewLine(); + printIndent(level); + + TRY_CATCH_THROW + ( + *fFormatter << gStartDoctype << nodeName; + + const XMLCh *id = doctype->getPublicId(); + if (id && *id) + { + *fFormatter << chSpace << gPublic << id << chDoubleQuote; + + id = doctype->getSystemId(); + if (id && *id) + { + *fFormatter << chSpace << chDoubleQuote << id << chDoubleQuote; + } + else + { + // + // 4.2.2 External Entities + // [Definition: If the entity is not internal, + // it is an external entity, declared as follows:] + // External Entity Declaration + // [75] ExternalID ::= 'SYSTEM' S SystemLiteral + // | 'PUBLIC' S PubidLiteral S SystemLiteral + // + reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::Writer_NotRecognizedType); + // systemLiteral not found + } + } + else + { + id = doctype->getSystemId(); + if (id && *id) + { + *fFormatter << chSpace << gSystem << id << chDoubleQuote; + } + } + + id = doctype->getInternalSubset(); + if (id && *id) + { + *fFormatter << chSpace << chOpenSquare << id << chCloseSquare; + } + + *fFormatter << chCloseAngle; + ) // end of TRY_CATCH_THROW + + break; + } + + case DOMNode::ENTITY_NODE: // Not to be shown to Filter + { + // + // REVISIT: how does the feature "entities" impact + // entity node? + // + printNewLine(); + printIndent(level); + + fFormatter->setEscapeFlags(XMLFormatter::NoEscapes); + *fFormatter << gStartEntity << nodeName; + + const XMLCh * id = ((const DOMEntity*)nodeToWrite)->getPublicId(); + if (id) + *fFormatter << gPublic << id << chDoubleQuote; + + id = ((const DOMEntity*)nodeToWrite)->getSystemId(); + if (id) + *fFormatter << gSystem << id << chDoubleQuote; + + id = ((const DOMEntity*)nodeToWrite)->getNotationName(); + if (id) + *fFormatter << gNotation << id << chDoubleQuote; + + *fFormatter << chCloseAngle; + + break; + } + + default: + /*** + This is an implementation specific behaviour, we abort if a user derived class has not dealt with + this node type. + ***/ + { + if(!customNodeSerialize(nodeToWrite, level)) { + reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::Writer_NotRecognizedType); + // UnreognizedNodeType; + } + } + + break; + } + +} + +bool DOMLSSerializerImpl::customNodeSerialize(const DOMNode* const, int) { + return false; +} + +// +// +DOMNodeFilter::FilterAction DOMLSSerializerImpl::checkFilter(const DOMNode* const node) const +{ + if (!fFilter || + ((fFilter->getWhatToShow() & (1 << (node->getNodeType() - 1))) == 0)) + return DOMNodeFilter::FILTER_ACCEPT; + + // + // if and only if there is a filter, and it is interested + // in the node type, then we pass the node to the filter + // for examination + // + return (DOMNodeFilter::FilterAction) fFilter->acceptNode(node); +} + + +bool DOMLSSerializerImpl::checkFeature(const XMLCh* const featName + , bool toThrow + , int& featureId) const +{ + // check for null and/or empty feature name + if (!featName || !*featName) + { + if (toThrow) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager); + + return false; + } + + featureId = INVALID_FEATURE_ID; + + if (XMLString::equals(featName, XMLUni::fgDOMWRTCanonicalForm)) + featureId = CANONICAL_FORM_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTDiscardDefaultContent)) + featureId = DISCARD_DEFAULT_CONTENT_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTEntities)) + featureId = ENTITIES_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTFormatPrettyPrint)) + featureId = FORMAT_PRETTY_PRINT_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTNormalizeCharacters)) + featureId = NORMALIZE_CHARACTERS_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTSplitCdataSections)) + featureId = SPLIT_CDATA_SECTIONS_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTValidation)) + featureId = VALIDATION_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTWhitespaceInElementContent)) + featureId = WHITESPACE_IN_ELEMENT_CONTENT_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTBOM)) + featureId = BYTE_ORDER_MARK_ID; + else if (XMLString::equals(featName, XMLUni::fgDOMXMLDeclaration)) + featureId = XML_DECLARATION; + else if (XMLString::equals(featName, XMLUni::fgDOMWRTXercesPrettyPrint)) + featureId = FORMAT_PRETTY_PRINT_1ST_LEVEL_ID; + + + //feature name not resolvable + if (featureId == INVALID_FEATURE_ID) + { + if (toThrow) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager); + + return false; + } + + return true; +} + +bool DOMLSSerializerImpl::reportError(const DOMNode* const errorNode + , DOMError::ErrorSeverity errorType + , const XMLCh* const errorMsg) +{ + bool toContinueProcess = true; // default value for no error handler + + if (fErrorHandler) + { + DOMLocatorImpl locator(0, 0, (DOMNode*) errorNode, 0); + DOMErrorImpl domError(errorType , errorMsg, &locator); + try + { + toContinueProcess = fErrorHandler->handleError(domError); + } + catch(...) + { + } + } + + if (errorType != DOMError::DOM_SEVERITY_WARNING) + fErrorCount++; + + return toContinueProcess; +} + +bool DOMLSSerializerImpl::reportError(const DOMNode* const errorNode + , DOMError::ErrorSeverity errorType + , XMLDOMMsg::Codes toEmit) +{ + const XMLSize_t msgSize = 1023; + XMLCh errText[msgSize + 1]; + + DOMImplementationImpl::getMsgLoader4DOM()->loadMsg(toEmit, errText, msgSize); + + bool toContinueProcess = true; // default value for no error handler + + if (fErrorHandler) + { + DOMLocatorImpl locator(0, 0, (DOMNode*) errorNode, 0); + DOMErrorImpl domError(errorType , errText, &locator); + try + { + toContinueProcess = fErrorHandler->handleError(domError); + } + catch(...) + { + } + } + + if (errorType != DOMError::DOM_SEVERITY_WARNING) + fErrorCount++; + + if (errorType == DOMError::DOM_SEVERITY_FATAL_ERROR || !toContinueProcess) + throw toEmit; + + return toContinueProcess; +} + +// +// +// +void DOMLSSerializerImpl::procCdataSection(const XMLCh* const nodeValue + , const DOMNode* const nodeToWrite) +{ + static const XMLSize_t offset = XMLString::stringLen(gEndCDATA); + + /*** + * Append a ']]>' at the end + */ + XMLSize_t len = XMLString::stringLen(nodeValue); + XMLCh* repNodeValue = (XMLCh*) fMemoryManager->allocate + ( + (len + offset + 1) * sizeof(XMLCh) + );//new XMLCh [len + offset + 1]; + XMLString::copyString(repNodeValue, nodeValue); + XMLString::catString(repNodeValue, gEndCDATA); + ArrayJanitor jName(repNodeValue, fMemoryManager); + + XMLCh* curPtr = (XMLCh*) repNodeValue; + XMLCh* nextPtr = 0; + int endTagPos = -1; + + bool endTagFound = true; + + while (endTagFound) + { + endTagPos = XMLString::patternMatch(curPtr, gEndCDATA); + if (endTagPos != -1) + { + nextPtr = curPtr + endTagPos + offset; // skip the ']]>' + *(curPtr + endTagPos) = chNull; //nullify the first ']' + if (XMLSize_t(endTagPos) != len) + reportError(nodeToWrite, DOMError::DOM_SEVERITY_WARNING, XMLDOMMsg::Writer_NestedCDATA); + len = len - endTagPos - offset; + } + else + { + endTagFound = false; + } + + /*** + to check ]]>]]> + ***/ + if (endTagPos == 0) + { + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << gStartCDATA << gEndCDATA; + ) + } + else + { + procUnrepCharInCdataSection(curPtr, nodeToWrite); + } + + if (endTagFound) + { + *(nextPtr - offset) = chCloseSquare; //restore the first ']' + curPtr = nextPtr; + } + } +} + +// +// +// +void DOMLSSerializerImpl::procUnrepCharInCdataSection(const XMLCh* const nodeValue + , const DOMNode* const nodeToWrite) +{ + // + // We have to check each character and see if it could be represented. + // As long as it can, we just keep up with where we started and how + // many chars we've checked. When we hit an unrepresentable one, we + // stop, transcode everything we've collected, then start handling + // the unrepresentables via char refs. We repeat this until we get all + // the chars done. + // + const XMLCh* srcPtr = nodeValue; + const XMLCh* endPtr = nodeValue + XMLString::stringLen(nodeValue); + + // Set up the common part of the buffer that we build char refs into + XMLCh tmpBuf[32]; + tmpBuf[0] = chAmpersand; + tmpBuf[1] = chPound; + tmpBuf[2] = chLatin_x; + + while (srcPtr < endPtr) + { + const XMLCh* tmpPtr = srcPtr; + while (tmpPtr < endPtr) + { + if (fFormatter->getTranscoder()->canTranscodeTo(*tmpPtr)) + tmpPtr++; + else + break; + } + + if (tmpPtr > srcPtr) + { + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << gStartCDATA; + ) + + // We got at least some chars that can be done normally + fFormatter->formatBuf + ( + srcPtr + , tmpPtr - srcPtr + , XMLFormatter::NoEscapes + , XMLFormatter::UnRep_Fail + ); + + TRY_CATCH_THROW + ( + *fFormatter << XMLFormatter::NoEscapes << gEndCDATA; + ) + + // Update the source pointer to our new spot + srcPtr = tmpPtr; + } + else + { + // + // We hit something unrepresentable. So continue forward doing + // char refs until we hit something representable again or the + // end of input. + // + + // one warning for consective unrep chars + reportError(nodeToWrite, DOMError::DOM_SEVERITY_WARNING, XMLDOMMsg::Writer_NotRepresentChar); + + while (srcPtr < endPtr) + { + // Build a char ref for the current char + XMLString::binToText(*srcPtr, &tmpBuf[3], 8, 16, fMemoryManager); + const XMLSize_t bufLen = XMLString::stringLen(tmpBuf); + tmpBuf[bufLen] = chSemiColon; + tmpBuf[bufLen+1] = chNull; + + // And now call recursively back to our caller to format this + fFormatter->formatBuf + ( + tmpBuf + , bufLen + 1 + , XMLFormatter::NoEscapes + , XMLFormatter::UnRep_Fail + ); + + // Move up the source pointer and break out if needed + srcPtr++; + if (fFormatter->getTranscoder()->canTranscodeTo(*srcPtr)) + break; + } + } + } +} + +void DOMLSSerializerImpl::processNode(const DOMNode* const nodeToWrite) +{ + processNode(nodeToWrite, 0); +} + +bool DOMLSSerializerImpl::canSetFeature(const int featureId + , bool val) const +{ + return featuresSupported[2*featureId + (val? 0: 1)]; +} + +void DOMLSSerializerImpl::printNewLine() +{ + if (getFeature(FORMAT_PRETTY_PRINT_ID)) + { + fCurrentLine++; + *fFormatter << fNewLineUsed; + } +} + +void DOMLSSerializerImpl::printIndent(unsigned int level) +{ + if (getFeature(FORMAT_PRETTY_PRINT_ID)) + { + if (fLastWhiteSpaceInTextNode) + { + unsigned int indentLevel = fLastWhiteSpaceInTextNode/2; // two chSpaces equals one indent level + fLastWhiteSpaceInTextNode = 0; + // if fLastWhiteSpaceInTextNode/2 is greater than level, then + // it means too many spaces have been written to the + // output stream and we can no longer indent properly + if(indentLevel < level) + level -= indentLevel; + else + level = 0; + } + + for(unsigned int i = 0; i < level; i++) + *fFormatter << chSpace << chSpace; + } +} + +void DOMLSSerializerImpl::release() +{ + DOMLSSerializerImpl* writer = (DOMLSSerializerImpl*) this; + delete writer; +} + +void DOMLSSerializerImpl::processBOM() +{ + // if the feature is not set, don't output bom + if (!getFeature(BYTE_ORDER_MARK_ID)) + return; + + if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF8EncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF8EncodingString2) == 0) ) + { + fFormatter->writeBOM(BOM_utf8, 3); + } + else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16LEncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16LEncodingString2) == 0) ) + { + fFormatter->writeBOM(BOM_utf16le, 2); + } + else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16BEncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16BEncodingString2) == 0) ) + { + fFormatter->writeBOM(BOM_utf16be, 2); + } + else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString2) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString3) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString4) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString5) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString6) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString7) == 0) ) + { + if (XMLPlatformUtils::fgXMLChBigEndian) + fFormatter->writeBOM(BOM_utf16be, 2); + else + fFormatter->writeBOM(BOM_utf16le, 2); + } + else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4LEncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4LEncodingString2) == 0) ) + { + fFormatter->writeBOM(BOM_ucs4le, 4); + } + else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4BEncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4BEncodingString2) == 0) ) + { + fFormatter->writeBOM(BOM_ucs4be, 4); + } + else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString2) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString3) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString4) == 0) || + (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString5) == 0) ) + { + if (XMLPlatformUtils::fgXMLChBigEndian) + fFormatter->writeBOM(BOM_ucs4be, 4); + else + fFormatter->writeBOM(BOM_ucs4le, 4); + } +} + +bool DOMLSSerializerImpl::isDefaultNamespacePrefixDeclared() const +{ + for(XMLSize_t i=fNamespaceStack->size();i>0;i--) + { + RefHashTableOf* curNamespaceMap=fNamespaceStack->elementAt(i-1); + const XMLCh* thisUri=curNamespaceMap->get((void*)XMLUni::fgZeroLenString); + if(thisUri) + return true; + } + return false; +} + +bool DOMLSSerializerImpl::isNamespaceBindingActive(const XMLCh* prefix, const XMLCh* uri) const +{ + for(XMLSize_t i=fNamespaceStack->size();i>0;i--) + { + RefHashTableOf* curNamespaceMap=fNamespaceStack->elementAt(i-1); + const XMLCh* thisUri=curNamespaceMap->get((void*)prefix); + // if the prefix has been declared, check if it binds to the correct namespace, otherwise, reports it isn't bound + if(thisUri) + return XMLString::equals(thisUri,uri); + } + return false; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMLSSerializerImpl.hpp b/include/xercesc/dom/impl/DOMLSSerializerImpl.hpp new file mode 100644 index 0000000..3281f75 --- /dev/null +++ b/include/xercesc/dom/impl/DOMLSSerializerImpl.hpp @@ -0,0 +1,232 @@ +/* + * 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: DOMLSSerializerImpl.hpp 695856 2008-09-16 12:52:32Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLSSERIALIZERMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLSSERIALIZERMPL_HPP + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMStringListImpl; + +class CDOM_EXPORT DOMLSSerializerImpl : public XMemory, + public DOMLSSerializer, + public DOMConfiguration +{ + +public: + + /** @name Constructor and Destructor */ + //@{ + + /** + * Constructor. + */ + DOMLSSerializerImpl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Destructor. + */ + ~DOMLSSerializerImpl(); + //@} + + /** @name Implementation of DOMLSSerializer interface */ + //@{ + + virtual DOMConfiguration* getDomConfig(); + + virtual void setNewLine(const XMLCh* const newLine); + virtual const XMLCh* getNewLine() const; + + virtual void setFilter(DOMLSSerializerFilter *filter); + virtual DOMLSSerializerFilter* getFilter() const; + + virtual bool write(const DOMNode* nodeToWrite, + DOMLSOutput* const destination); + virtual bool writeToURI(const DOMNode* nodeToWrite, + const XMLCh* uri); + /** + * The caller is responsible for the release of the returned string + */ + virtual XMLCh* writeToString(const DOMNode* nodeToWrite, MemoryManager* manager = NULL); + virtual void release(); + + //@} + + /** @name Implementation of DOMConfiguration interface */ + //@{ + virtual void setParameter(const XMLCh* name, const void* value); + virtual void setParameter(const XMLCh* name, bool value); + virtual const void* getParameter(const XMLCh* name) const; + virtual bool canSetParameter(const XMLCh* name, const void* value) const; + virtual bool canSetParameter(const XMLCh* name, bool value) const; + virtual const DOMStringList* getParameterNames() const; + //@} + +private: + + /** unimplemented copy ctor and assignment operator */ + DOMLSSerializerImpl(const DOMLSSerializerImpl&); + DOMLSSerializerImpl & operator = (const DOMLSSerializerImpl&); + +protected: + /** helper **/ + void processNode(const DOMNode* const); + + void procCdataSection(const XMLCh* const nodeValue + , const DOMNode* const nodeToWrite); + + void procUnrepCharInCdataSection(const XMLCh* const nodeValue + , const DOMNode* const nodeToWrite); + +protected: + /** + * Overidden by derived classes to extend the abilities of the standard writer + * always returns false in the default implementation + * @return true if the method deals with nodeToWrite + */ + virtual bool customNodeSerialize(const DOMNode* const nodeToWrite, int level); + + DOMNodeFilter::FilterAction checkFilter(const DOMNode* const) const; + + bool checkFeature(const XMLCh* const featName + , bool state + , int& featureId) const; + + bool reportError(const DOMNode* const errorNode + , DOMError::ErrorSeverity errorType + , const XMLCh* const errorMsg); + bool reportError(const DOMNode* const errorNode + , DOMError::ErrorSeverity errorType + , XMLDOMMsg::Codes toEmit); + + bool canSetFeature(const int featureId + , bool val) const; + void setFeature(const int featureId + , bool val); + bool getFeature(const int featureId) const; + + void printNewLine(); + void setURCharRef(); + bool isDefaultNamespacePrefixDeclared() const; + bool isNamespaceBindingActive(const XMLCh* prefix, const XMLCh* uri) const; + + + void printIndent(unsigned int level); + //does the actual work for processNode while keeping track of the level + void processNode(const DOMNode* const nodeToWrite, int level); + + void processBOM(); + + // ----------------------------------------------------------------------- + // Private data members + // + // fFeatures + // + // fNewLine + // own it + // + // fErrorHandler + // don't own it + // + // fFilter + // don't own it + // + // fDocumentVersion + // The XML Version of the document to be serialized. + // + // fSupportedParameters + // A list of the parameters that can be set, including the ones + // specific of Xerces + // + // fEncodingUsed (session var) + // the actual encoding used in write(), + // it does not own any data(memory). + // + // fNewLineUsed (session var) + // the actual "end of line" sequence used in write(), + // it does not own any data(memory). + // + // fFormatter (session var) + // the formatter used in write() + // + // fErrorCount + // the count of error encountered in the serialization, + // which neither the error handler, nor the serializer itself, + // treat as fatal. And the serializer will return true/false + // based on this value. + // + // fCurrentLine + // the current line. Used to track the line number the current + // node begins on + // + // ----------------------------------------------------------------------- + + int fFeatures; + XMLCh *fNewLine; + DOMErrorHandler *fErrorHandler; + DOMLSSerializerFilter *fFilter; + const XMLCh *fDocumentVersion; + DOMStringListImpl *fSupportedParameters; + + //session vars + const XMLCh *fEncodingUsed; + const XMLCh *fNewLineUsed; + XMLFormatter *fFormatter; + int fErrorCount; + int fCurrentLine; + bool fLineFeedInTextNodePrinted; + unsigned int fLastWhiteSpaceInTextNode; + + RefVectorOf< RefHashTableOf >* fNamespaceStack; + MemoryManager* fMemoryManager; +}; + +inline DOMConfiguration* DOMLSSerializerImpl::getDomConfig() +{ + return this; +} + +inline void DOMLSSerializerImpl::setFeature(const int featureId + , bool val) +{ + (val)? fFeatures |= (1<setUnRepFlags(XMLFormatter::UnRep_CharRef); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMLocatorImpl.cpp b/include/xercesc/dom/impl/DOMLocatorImpl.cpp new file mode 100644 index 0000000..7d078b5 --- /dev/null +++ b/include/xercesc/dom/impl/DOMLocatorImpl.cpp @@ -0,0 +1,60 @@ +/* + * 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: DOMLocatorImpl.cpp 676853 2008-07-15 09:58:05Z borisk $ + */ + +#include "DOMLocatorImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// DOMLocatorImpl: Constructors and Destructor +// --------------------------------------------------------------------------- +DOMLocatorImpl::DOMLocatorImpl() : +fLineNum(0) +, fColumnNum(0) +, fByteOffset(~(XMLFilePos(0))) +, fUtf16Offset(~(XMLFilePos(0))) +, fRelatedNode(0) +, fURI(0) +{ +} + + +DOMLocatorImpl::DOMLocatorImpl(const XMLFileLoc lineNum, + const XMLFileLoc columnNum, + DOMNode* const errorNode, + const XMLCh* const uri, + const XMLFilePos byteOffset, + const XMLFilePos utf16Offset) : +fLineNum(lineNum) +, fColumnNum(columnNum) +, fByteOffset(byteOffset) +, fUtf16Offset(utf16Offset) +, fRelatedNode(errorNode) +, fURI(uri) +{ +} + +DOMLocatorImpl::~DOMLocatorImpl() +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMLocatorImpl.hpp b/include/xercesc/dom/impl/DOMLocatorImpl.hpp new file mode 100644 index 0000000..2075794 --- /dev/null +++ b/include/xercesc/dom/impl/DOMLocatorImpl.hpp @@ -0,0 +1,187 @@ +/* + * 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: DOMLocatorImpl.hpp 676853 2008-07-15 09:58:05Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMLOCATORIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMLOCATORIMPL_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Introduced in DOM Level 3 + * + * Implementation of a DOMLocator interface. + * + * @see DOMLocator#DOMLocator + */ + +class CDOM_EXPORT DOMLocatorImpl : public DOMLocator +{ +public: + /** @name Constructors and Destructor */ + //@{ + + /** Constructor */ + DOMLocatorImpl(); + + DOMLocatorImpl + ( + const XMLFileLoc lineNum + , const XMLFileLoc columnNum + , DOMNode* const errorNode + , const XMLCh* const uri + , const XMLFilePos offset = ~(XMLFilePos(0)) + , const XMLFilePos utf16Offset = ~(XMLFilePos(0)) + ); + + /** Desctructor */ + virtual ~DOMLocatorImpl(); + + //@} + + // DOMLocator interface + virtual XMLFileLoc getLineNumber() const; + virtual XMLFileLoc getColumnNumber() const; + virtual XMLFilePos getByteOffset() const; + virtual XMLFilePos getUtf16Offset() const; + virtual DOMNode* getRelatedNode() const; + virtual const XMLCh* getURI() const; + + // Setter functions + void setLineNumber(const XMLFileLoc lineNumber); + void setColumnNumber(const XMLFileLoc columnNumber); + void setByteOffset(const XMLFilePos offset); + void setUtf16Offset(const XMLFilePos offset); + void setRelatedNode(DOMNode* const errorNode); + void setURI(const XMLCh* const uri); + + +private : + /* Unimplemented constructors and operators */ + + /* Copy constructor */ + DOMLocatorImpl(const DOMLocatorImpl&); + + /* Assignment operator */ + DOMLocatorImpl& operator=(const DOMLocatorImpl&); + +protected: + // ----------------------------------------------------------------------- + // Private data members + // + // fLineNum + // fColumnNum + // Track line/column number of where the error occured + // + // fByteOffset + // Track byte offset in the input source where the error + // occured + // + // fUtf16Offset + // Track character offset in the input source where the error + // occured + // + // fRelatedNode + // Current node where the error occured + // + // fURI + // The uri where the error occured + // ----------------------------------------------------------------------- + XMLFileLoc fLineNum; + XMLFileLoc fColumnNum; + XMLFilePos fByteOffset; + XMLFilePos fUtf16Offset; + DOMNode* fRelatedNode; + const XMLCh* fURI; +}; + + +// --------------------------------------------------------------------------- +// DOMLocatorImpl: Getter methods +// --------------------------------------------------------------------------- +inline XMLFileLoc DOMLocatorImpl::getLineNumber() const +{ + return fLineNum; +} + +inline XMLFileLoc DOMLocatorImpl::getColumnNumber() const +{ + return fColumnNum; +} + +inline XMLFilePos DOMLocatorImpl::getByteOffset() const +{ + return fByteOffset; +} + +inline XMLFilePos DOMLocatorImpl::getUtf16Offset() const +{ + return fUtf16Offset; +} + +inline DOMNode* DOMLocatorImpl::getRelatedNode() const +{ + return fRelatedNode; +} + +inline const XMLCh* DOMLocatorImpl::getURI() const +{ + return fURI; +} + + +// --------------------------------------------------------------------------- +// DOMLocatorImpl: Setter methods +// --------------------------------------------------------------------------- +inline void DOMLocatorImpl::setLineNumber(const XMLFileLoc lineNumber) +{ + fLineNum = lineNumber; +} + +inline void DOMLocatorImpl::setColumnNumber(const XMLFileLoc columnNumber) +{ + fColumnNum = columnNumber; +} + +inline void DOMLocatorImpl::setByteOffset(const XMLFilePos offset) +{ + fByteOffset = offset; +} + +inline void DOMLocatorImpl::setUtf16Offset(const XMLFilePos offset) +{ + fUtf16Offset = offset; +} + +inline void DOMLocatorImpl::setRelatedNode(DOMNode* const errorNode) +{ + fRelatedNode = errorNode; +} + +inline void DOMLocatorImpl::setURI(const XMLCh* const uri) +{ + fURI = uri; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp b/include/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp new file mode 100644 index 0000000..5f471ca --- /dev/null +++ b/include/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp @@ -0,0 +1,340 @@ +/* + * 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: DOMNamedNodeMapImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ + + +#include +#include +#include +#include + +#include "DOMNodeVector.hpp" +#include "DOMNamedNodeMapImpl.hpp" +#include "DOMCasts.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMNodeImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod) +{ + fOwnerNode=ownerNod; + memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*)); +} + +DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl() +{ +} + +bool DOMNamedNodeMapImpl::readOnly() +{ + return castToNodeImpl(fOwnerNode)->isReadOnly(); +} + +DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod) +{ + DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument()); + DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod); + + for(XMLSize_t index=0;indexsize(); + newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size); + for (XMLSize_t i = 0; i < size; ++i) { + DOMNode *s = fBuckets[index]->elementAt(i); + DOMNode *n = s->cloneNode(true); + castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified()); + castToNodeImpl(n)->fOwnerNode = ownerNod; + castToNodeImpl(n)->isOwned(true); + newmap->fBuckets[index]->addElement(n); + } + } + + return newmap; +} + + +XMLSize_t DOMNamedNodeMapImpl::getLength() const +{ + XMLSize_t count=0; + for(XMLSize_t index=0;indexsize()); + return count; +} + +DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const +{ + XMLSize_t count=0; + for(XMLSize_t i=0;isize(); + if(index>=count && index<(count+thisBucket)) + return fBuckets[i]->elementAt(index-count); + count+=thisBucket; + } + return NULL; +} + + +DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const +{ + XMLSize_t hash=XMLString::hash(name,MAP_SIZE); + if(fBuckets[hash]==0) + return 0; + + XMLSize_t i = 0; + XMLSize_t size = fBuckets[hash]->size(); + for (i = 0; i < size; ++i) { + DOMNode *n=fBuckets[hash]->elementAt(i); + if(XMLString::equals(name,n->getNodeName())) + return n; + } + + return 0; +} + + +// +// removeNamedItem() - Remove the named item, and return it. +// The caller can release the +// returned item if it's not used +// we can't do it here because the caller would +// never see the returned node. +// +DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name) +{ + if (this->readOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + XMLSize_t hash=XMLString::hash(name,MAP_SIZE); + if(fBuckets[hash]==0) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + DOMDocument *doc = fOwnerNode->getOwnerDocument(); + + XMLSize_t i = 0; + XMLSize_t size = fBuckets[hash]->size(); + for (i = 0; i < size; ++i) { + DOMNode *n=fBuckets[hash]->elementAt(i); + if(XMLString::equals(name,n->getNodeName())) { + fBuckets[hash]->removeElementAt(i); + castToNodeImpl(n)->fOwnerNode = doc; + castToNodeImpl(n)->isOwned(false); + return n; + } + } + + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); + return 0; +} + + + +// +// setNamedItem() Put the item into the NamedNodeList by name. +// If an item with the same name already was +// in the list, replace it. Return the old +// item, if there was one. +// Caller is responsible for arranging for +// deletion of the old item if its ref count is +// zero. +// +DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg) +{ + DOMDocument *doc = fOwnerNode->getOwnerDocument(); + DOMNodeImpl *argImpl = castToNodeImpl(arg); + if(argImpl->getOwnerDocument() != doc) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager); + if (this->readOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode)) + throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); + + argImpl->fOwnerNode = fOwnerNode; + argImpl->isOwned(true); + + const XMLCh* name=arg->getNodeName(); + XMLSize_t hash=XMLString::hash(name,MAP_SIZE); + if(fBuckets[hash]==0) + fBuckets[hash] = new (doc) DOMNodeVector(doc, 3); + + XMLSize_t i = 0; + XMLSize_t size = fBuckets[hash]->size(); + for (i = 0; i < size; ++i) { + DOMNode *n=fBuckets[hash]->elementAt(i); + if(XMLString::equals(name,n->getNodeName())) { + fBuckets[hash]->setElementAt(arg,i); + castToNodeImpl(n)->fOwnerNode = doc; + castToNodeImpl(n)->isOwned(false); + return n; + } + } + fBuckets[hash]->addElement(arg); + return 0; +} + + +void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep) +{ + // this->fReadOnly=readOnl; + if(deep) { + for (XMLSize_t index = 0; index < MAP_SIZE; index++) { + if(fBuckets[index]==0) + continue; + XMLSize_t sz = fBuckets[index]->size(); + for (XMLSize_t i=0; ielementAt(i))->setReadOnly(readOnl, deep); + } + } +} + + +//Introduced in DOM Level 2 + +DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const +{ + // the map is indexed using the full name of nodes; to search given a namespace and a local name + // we have to do a linear search + for (XMLSize_t index = 0; index < MAP_SIZE; index++) { + if(fBuckets[index]==0) + continue; + + XMLSize_t i = 0; + XMLSize_t size = fBuckets[index]->size(); + for (i = 0; i < size; ++i) { + DOMNode *n=fBuckets[index]->elementAt(i); + const XMLCh * nNamespaceURI = n->getNamespaceURI(); + const XMLCh * nLocalName = n->getLocalName(); + if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match + continue; + else { + if (XMLString::equals(localName, nLocalName) + || + (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) + return n; + } + } + } + return 0; +} + + +// +// setNamedItemNS() Put the item into the NamedNodeList by name. +// If an item with the same name already was +// in the list, replace it. Return the old +// item, if there was one. +// Caller is responsible for arranging for +// deletion of the old item if its ref count is +// zero. +// +DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg) +{ + DOMDocument *doc = fOwnerNode->getOwnerDocument(); + DOMNodeImpl *argImpl = castToNodeImpl(arg); + if (argImpl->getOwnerDocument() != doc) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager); + if (this->readOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + if (argImpl->isOwned()) + throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); + + argImpl->fOwnerNode = fOwnerNode; + argImpl->isOwned(true); + + const XMLCh* namespaceURI=arg->getNamespaceURI(); + const XMLCh* localName=arg->getLocalName(); + // the map is indexed using the full name of nodes; to search given a namespace and a local name + // we have to do a linear search + for (XMLSize_t index = 0; index < MAP_SIZE; index++) { + if(fBuckets[index]==0) + continue; + + XMLSize_t i = 0; + XMLSize_t size = fBuckets[index]->size(); + for (i = 0; i < size; ++i) { + DOMNode *n=fBuckets[index]->elementAt(i); + const XMLCh * nNamespaceURI = n->getNamespaceURI(); + const XMLCh * nLocalName = n->getLocalName(); + if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match + continue; + else { + if (XMLString::equals(localName, nLocalName) + || + (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) { + fBuckets[index]->setElementAt(arg,i); + castToNodeImpl(n)->fOwnerNode = doc; + castToNodeImpl(n)->isOwned(false); + return n; + } + } + } + } + // if not found, add it using the full name as key + return setNamedItem(arg); +} + + +// removeNamedItemNS() - Remove the named item, and return it. +// The caller can release the +// returned item if it's not used +// we can't do it here because the caller would +// never see the returned node. +DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName) +{ + if (this->readOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); + + // the map is indexed using the full name of nodes; to search given a namespace and a local name + // we have to do a linear search + for (XMLSize_t index = 0; index < MAP_SIZE; index++) { + if(fBuckets[index]==0) + continue; + + DOMDocument *doc = fOwnerNode->getOwnerDocument(); + XMLSize_t i = 0; + XMLSize_t size = fBuckets[index]->size(); + for (i = 0; i < size; ++i) { + DOMNode *n=fBuckets[index]->elementAt(i); + const XMLCh * nNamespaceURI = n->getNamespaceURI(); + const XMLCh * nLocalName = n->getLocalName(); + if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match + continue; + else { + if (XMLString::equals(localName, nLocalName) + || + (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) { + fBuckets[index]->removeElementAt(i); + castToNodeImpl(n)->fOwnerNode = doc; + castToNodeImpl(n)->isOwned(false); + return n; + } + } + } + } + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMNamedNodeMapImpl.hpp b/include/xercesc/dom/impl/DOMNamedNodeMapImpl.hpp new file mode 100644 index 0000000..a8bf8e7 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNamedNodeMapImpl.hpp @@ -0,0 +1,80 @@ +/* + * 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: DOMNamedNodeMapImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNAMEDNODEMAPIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNAMEDNODEMAPIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNodeVector; +class DOMNode; + +#define MAP_SIZE 193 + +class CDOM_EXPORT DOMNamedNodeMapImpl: public DOMNamedNodeMap { +protected: + DOMNodeVector* fBuckets[MAP_SIZE]; + DOMNode* fOwnerNode; // the node this map belongs to + //bool fReadOnly; // revisit - flag on owner node instead? + + bool readOnly(); // revisit. Look at owner node read-only. + +public: + DOMNamedNodeMapImpl(DOMNode *ownerNode); + + virtual ~DOMNamedNodeMapImpl(); + virtual DOMNamedNodeMapImpl *cloneMap(DOMNode *ownerNode); + virtual void setReadOnly(bool readOnly, bool deep); + + virtual XMLSize_t getLength() const; + virtual DOMNode* item(XMLSize_t index) const; + virtual DOMNode* getNamedItem(const XMLCh *name) const; + virtual DOMNode* setNamedItem(DOMNode *arg); + virtual DOMNode* removeNamedItem(const XMLCh *name); + + //Introduced in DOM Level 2 + virtual DOMNode* getNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual DOMNode* setNamedItemNS(DOMNode *arg); + virtual DOMNode* removeNamedItemNS(const XMLCh *namespaceURI, + const XMLCh *localName); +private: + // unimplemented + DOMNamedNodeMapImpl(const DOMNamedNodeMapImpl &); + DOMNamedNodeMapImpl & operator = (const DOMNamedNodeMapImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNodeIDMap.cpp b/include/xercesc/dom/impl/DOMNodeIDMap.cpp new file mode 100644 index 0000000..dab9722 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeIDMap.cpp @@ -0,0 +1,230 @@ +/* + * 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: DOMNodeIDMap.cpp 678144 2008-07-19 12:08:55Z borisk $ + */ + +#include "DOMAttrImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMNodeIDMap.hpp" + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +static const XMLSize_t gPrimes[] = {997, 9973, 99991, 999983, 0 }; // To do - add a few more. + +static const float gMaxFill = 0.8f; // The maximum fraction of the total + // table entries to consume before exanding. + +DOMNodeIDMap::DOMNodeIDMap(XMLSize_t initialSize, DOMDocument *doc) +: fNumEntries(0) +, fDoc(doc) +{ + for (fSizeIndex = 0; gPrimes[fSizeIndex] < initialSize; fSizeIndex++) + { + if (gPrimes[fSizeIndex] == 0) + { + // We need a bigger size than the largest available one. + // Big trouble. + fSizeIndex--; + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NodeIDMap_GrowErr, ((DOMDocumentImpl *)fDoc)->getMemoryManager()); + } + } + + fSize = gPrimes[fSizeIndex]; + fMaxEntries = (XMLSize_t)(float(fSize) * gMaxFill); + + //fTable = new (fDoc) DOMAttr*[fSize]; + fTable = (DOMAttr**) ((DOMDocumentImpl *)fDoc)->allocate(sizeof(DOMAttr*) * fSize); + XMLSize_t i; + for (i=0; i= fMaxEntries) + growTable(); + + fNumEntries++; + + // + // Hash the value string from the ID attribute being added to the table + // 0 < Initial hash value < table size. + // An initial hash of zero would cause the rehash to fail. + // + const XMLCh *id=attr->getValue(); + XMLSize_t initalHash = XMLString::hash(id, fSize-1); + initalHash++; + XMLSize_t currentHash = initalHash; + + // + // Loop looking for an empty slot for this ID. + // Don't even bother checking to see if the ID is already there - + // the table is only filled by the parser from valid documents, which + // can not have duplicates. Behavior of invalid docs is not defined. + // + while (fTable[currentHash]!=0 && fTable[currentHash]!=(DOMAttr *)-1) + { + currentHash += initalHash; // rehash + if (currentHash >= fSize) + currentHash = currentHash % fSize; + } + + // + // We've found our slot. Stick the pointer to the attr into it. + // + fTable[currentHash] = attr; + +} + + +void DOMNodeIDMap::remove(DOMAttr *attr) +{ + // + // Hash the value string from the ID attribute being added to the table + // 0 < Initial hash value < table size. + // An initial hash of zero would cause the rehash to fail. + // + const XMLCh *id=attr->getValue(); + XMLSize_t initalHash = XMLString::hash(id, fSize-1); + initalHash++; + XMLSize_t currentHash = initalHash; + + // + // Loop looking for a slot pointing to an attr with this id. + // + DOMAttr *tableSlot; + while ((tableSlot= fTable[currentHash])!=0) + { + if (tableSlot == attr) + { + // Found the attribute. Set the slot to -1 to indicate + // that it was once used, meaning that lookups, while never + // matching here, can not stop either, but must rehash again + // and continue searching. + fTable[currentHash] = (DOMAttr *)-1; + return; + } + + currentHash += initalHash; // rehash. + if (currentHash >= fSize) + currentHash = currentHash % fSize; + } + // There is no matching entry in the table +} + + +DOMAttr *DOMNodeIDMap::find(const XMLCh *id) +{ + // + // Get the hashcode for the supplied string. + // + XMLSize_t initalHash = XMLString::hash(id, fSize-1); + initalHash++; + XMLSize_t currentHash = initalHash; + + // + // Loop looking for a slot pointing to an attr with this id. + // + DOMAttr *tableSlot; + while ((tableSlot= fTable[currentHash])!=0) + { + if ((tableSlot != (DOMAttr *)-1) && XMLString::equals(tableSlot->getValue(), id)) + return tableSlot; + + currentHash += initalHash; // rehash + if (currentHash >= fSize) + currentHash = currentHash % fSize; + } + // There is no matching entry in the table + return 0; +} + + +// +// Grow the table to the next larger size. +// It has gotten too full for efficient operation. +// (We never fill it all the way) +// +void DOMNodeIDMap::growTable() +{ + DOMAttr **oldTable = fTable; + XMLSize_t oldSize = fSize; + + // + // Figure the new table size. + // +#if defined(XERCES_DEBUG) + fprintf(stderr, "growing...\n"); +#endif + fSizeIndex++; + fSize = gPrimes[fSizeIndex]; + if (fSize == 0) + { + // We need to grow bigger than the largest available size. + // Big trouble. + fSizeIndex--; + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NodeIDMap_GrowErr, ((DOMDocumentImpl *)fDoc)->getMemoryManager()); + } + + // + // Allocate the new table. + // + //fTable = new (fDoc) DOMAttr *[fSize]; + fTable = (DOMAttr**) ((DOMDocumentImpl *)fDoc)->allocate(sizeof(DOMAttr*) * fSize); + XMLSize_t i; + for (i=0; i for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +XERCES_CPP_NAMESPACE_BEGIN + + +// +// Class DOMNodeIDMap is a hash table that is used in the implementation of +// of DOM_Document::getElementsByID(). +// +// Why Yet Another HashTable implementation? Becuase it can be significantly +// smaller when tuned for this exact usage, and the generic RefHashTableOf +// from the xerces utils project is not a paricularly good fit. +// +class DOMAttr; +class DOMDocument; + + +class DOMNodeIDMap { +public: + + DOMNodeIDMap(XMLSize_t initialSize, DOMDocument *doc); // Create a new hash table, sized to hold "initialSize" + // Entries. It will automatically grow if need be. + + ~DOMNodeIDMap(); + +private: + DOMNodeIDMap(const DOMNodeIDMap &other); // No copy, assignement, comparison. + DOMNodeIDMap &operator = (const DOMNodeIDMap &other); + bool operator == (const DOMNodeIDMap &other); + +public: + void add(DOMAttr *attr); // Add the specified attribute to the table. + void remove(DOMAttr *other); // Remove the specified attribute. + // Does nothing if the node is not in the table. + DOMAttr *find(const XMLCh *ID); // Find the attribute node in the table with this ID + +private: + void growTable(); + +private: + DOMAttr **fTable; + XMLSize_t fSizeIndex; // Index of the current table size in the + // array of possible table sizes. + XMLSize_t fSize; // The current size of the table array + // (number of slots, not bytes.) + XMLSize_t fNumEntries; // The number of entries used. + XMLSize_t fMaxEntries; // The max number of entries to use before + // growing the table. + DOMDocument *fDoc; // The owning document. +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNodeImpl.cpp b/include/xercesc/dom/impl/DOMNodeImpl.cpp new file mode 100644 index 0000000..94b0799 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeImpl.cpp @@ -0,0 +1,1028 @@ +/* + * 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: DOMNodeImpl.cpp 1662873 2015-02-28 01:07:36Z scantor $ + */ + +// This class doesn't support having any children, and implements the behavior +// of an empty NodeList as far getChildNodes is concerned. +// The ParentNode subclass overrides this behavior. + + +#include "DOMCasts.hpp" + +#include "DOMDocumentTypeImpl.hpp" +#include "DOMElementImpl.hpp" +#include "DOMAttrImpl.hpp" + +#include +#include + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +//Though DOMNodeImpl does not derivate from DOMNode, it shares +//the same GetDOMNodeMemoryManager + +const unsigned short DOMNodeImpl::READONLY = 0x1<<0; +const unsigned short DOMNodeImpl::SYNCDATA = 0x1<<1; +const unsigned short DOMNodeImpl::SYNCCHILDREN = 0x1<<2; +const unsigned short DOMNodeImpl::OWNED = 0x1<<3; +const unsigned short DOMNodeImpl::FIRSTCHILD = 0x1<<4; +const unsigned short DOMNodeImpl::SPECIFIED = 0x1<<5; +const unsigned short DOMNodeImpl::IGNORABLEWS = 0x1<<6; +const unsigned short DOMNodeImpl::SETVALUE = 0x1<<7; +const unsigned short DOMNodeImpl::ID_ATTR = 0x1<<8; +const unsigned short DOMNodeImpl::USERDATA = 0x1<<9; +const unsigned short DOMNodeImpl::LEAFNODETYPE = 0x1<<10; +const unsigned short DOMNodeImpl::CHILDNODE = 0x1<<11; +const unsigned short DOMNodeImpl::TOBERELEASED = 0x1<<12; + +// +// +static DOMNodeListImpl *gEmptyNodeList = 0; // Singleton empty node list. + +void XMLInitializer::initializeDOMNodeListImpl() +{ + gEmptyNodeList = new DOMNodeListImpl(0); +} + +void XMLInitializer::terminateDOMNodeListImpl() +{ + delete gEmptyNodeList; + gEmptyNodeList = 0; +} + +// ----------------------------------------------------------------------- +// DOMNodeImpl Functions +// ----------------------------------------------------------------------- +DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode) +: fOwnerNode(ownerNode) +{ + this->flags = 0; + // as long as we do not have any owner, fOwnerNode is our ownerDocument +} + +// This only makes a shallow copy, cloneChildren must also be called for a +// deep clone +DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other) +{ + this->flags = other.flags; + this->isReadOnly(false); + + // Need to break the association w/ original parent + this->fOwnerNode = other.getOwnerDocument(); + this->isOwned(false); +} + + + +DOMNodeImpl::~DOMNodeImpl() { +} + + +DOMNode * DOMNodeImpl::appendChild(DOMNode *) +{ + // Only node types that don't allow children will use this default function. + // Others will go to DOMParentNode::appendChild. + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager); + return 0; + // return insertBefore(newChild, 0); +} + + +DOMNamedNodeMap * DOMNodeImpl::getAttributes() const { + return 0; // overridden in ElementImpl +} + + +DOMNodeList *DOMNodeImpl::getChildNodes() const { + return gEmptyNodeList; +} + + + +DOMNode * DOMNodeImpl::getFirstChild() const { + return 0; // overridden in ParentNode +} + + +DOMNode * DOMNodeImpl::getLastChild() const +{ + return 0; // overridden in ParentNode +} + + +DOMNode * DOMNodeImpl::getNextSibling() const { + return 0; // overridden in ChildNode +} + + +const XMLCh * DOMNodeImpl::getNodeValue() const { + return 0; // Overridden by anything that has a value +} + + +// +// Unlike the external getOwnerDocument, this one returns the owner document +// for document nodes as well as all of the other node types. +// +DOMDocument *DOMNodeImpl::getOwnerDocument() const +{ + if (!this->isLeafNode()) + { + DOMElementImpl *ep = (DOMElementImpl *)castToNode(this); + return ep->fParent.fOwnerDocument; + } + + // Leaf node types - those that cannot have children, like Text. + if (isOwned()) { + + DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument(); + + if (!ownerDoc) { + + assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE); + return (DOMDocument *)fOwnerNode; + } + else { + return ownerDoc; + } + } else { + assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE); + return (DOMDocument *)fOwnerNode; + } +} + + +void DOMNodeImpl::setOwnerDocument(DOMDocument *doc) { + // if we have an owner we rely on it to have it right + // otherwise fOwnerNode is our ownerDocument + if (!isOwned()) { + // revisit. Problem with storage for doctype nodes that were created + // on the system heap in advance of having a document. + fOwnerNode = doc; + } +} + +DOMNode * DOMNodeImpl::getParentNode() const +{ + return 0; // overridden in ChildNode +} + + +DOMNode* DOMNodeImpl::getPreviousSibling() const +{ + return 0; // overridden in ChildNode +} + +bool DOMNodeImpl::hasChildNodes() const +{ + return false; +} + + + +DOMNode *DOMNodeImpl::insertBefore(DOMNode *, DOMNode *) { + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNodeMemoryManager); + return 0; +} + + +DOMNode *DOMNodeImpl::removeChild(DOMNode *) +{ + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); + return 0; +} + + +DOMNode *DOMNodeImpl::replaceChild(DOMNode *, DOMNode *) +{ + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager); + return 0; +} + + + +void DOMNodeImpl::setNodeValue(const XMLCh *) +{ + // Default behavior is to do nothing, overridden in some subclasses +} + + + +void DOMNodeImpl::setReadOnly(bool readOnl, bool deep) +{ + this->isReadOnly(readOnl); + + if (deep) { + for (DOMNode *mykid = castToNode(this)->getFirstChild(); + mykid != 0; + mykid = mykid->getNextSibling()) { + + short kidNodeType = mykid->getNodeType(); + + switch (kidNodeType) { + case DOMNode::ENTITY_REFERENCE_NODE: + break; + case DOMNode::ELEMENT_NODE: + ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true); + break; + case DOMNode::DOCUMENT_TYPE_NODE: + ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true); + break; + default: + castToNodeImpl(mykid)->setReadOnly(readOnl, true); + break; + } + } + } +} + + +//Introduced in DOM Level 2 + +void DOMNodeImpl::normalize() +{ + // does nothing by default, overridden by subclasses +} + + +bool DOMNodeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const +{ + return DOMImplementation::getImplementation()->hasFeature(feature, version); +} + +const XMLCh *DOMNodeImpl::getNamespaceURI() const +{ + return 0; +} + +const XMLCh *DOMNodeImpl::getPrefix() const +{ + return 0; +} + +const XMLCh *DOMNodeImpl::getLocalName() const +{ + return 0; +} + + +void DOMNodeImpl::setPrefix(const XMLCh *) +{ + throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); +} + + +bool DOMNodeImpl::hasAttributes() const { + return 0; // overridden in ElementImpl +} + + + + + +const XMLCh *DOMNodeImpl::getXmlString() {return XMLUni::fgXMLString;} +const XMLCh *DOMNodeImpl::getXmlURIString() {return XMLUni::fgXMLURIName;} +const XMLCh *DOMNodeImpl::getXmlnsString() {return XMLUni::fgXMLNSString;} +const XMLCh *DOMNodeImpl::getXmlnsURIString() {return XMLUni::fgXMLNSURIName;} + +//Return a URI mapped from the given prefix and namespaceURI as below +// prefix namespaceURI output +//--------------------------------------------------- +// "xml" xmlURI xmlURI +// "xml" otherwise NAMESPACE_ERR +// "xmlns" xmlnsURI xmlnsURI (nType = ATTRIBUTE_NODE only) +// "xmlns" otherwise NAMESPACE_ERR (nType = ATTRIBUTE_NODE only) +// != null null or "" NAMESPACE_ERR +// else any namesapceURI +const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix, + const XMLCh *namespaceURI, short nType) +{ + if (prefix == 0) + return namespaceURI; + + if (XMLString::equals(prefix, XMLUni::fgXMLString)) { + if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) + return XMLUni::fgXMLURIName; + throw DOMException(DOMException::NAMESPACE_ERR, 0); + } else if (nType == DOMNode::ATTRIBUTE_NODE && XMLString::equals(prefix, XMLUni::fgXMLNSString)) { + if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName)) + return XMLUni::fgXMLNSURIName; + throw DOMException(DOMException::NAMESPACE_ERR, 0); + } else if (namespaceURI == 0 || *namespaceURI == 0) + throw DOMException(DOMException::NAMESPACE_ERR, 0); + return namespaceURI; +} + +//Introduced in DOM Level 3 +void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) +{ + if (!data && !hasUserData()) + return 0; + + hasUserData(true); + return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler); +} + +void* DOMNodeImpl::getUserData(const XMLCh* key) const +{ + if (hasUserData()) + return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key); + return 0; +} + +void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation, + const DOMNode* src, + DOMNode* dst) const +{ + DOMDocumentImpl* doc=(DOMDocumentImpl*)getOwnerDocument(); + if (doc) + doc->callUserDataHandlers(this, operation, src, dst); +} + +bool DOMNodeImpl::isSameNode(const DOMNode* other) const +{ + return (castToNode(this) == other); +} + +bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const +{ + if (!arg) + return false; + + if (isSameNode(arg)) { + return true; + } + + DOMNode* thisNode = castToNode(this); + + if (arg->getNodeType() != thisNode->getNodeType()) { + return false; + } + + // the compareString will check null string as well + if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) { + return false; + } + + if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) { + return false; + } + + if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) { + return false; + } + + if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) { + return false; + } + + if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) { + return false; + } + + return true; +} + +const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* namespaceURI) const { + // REVISIT: When Namespaces 1.1 comes out this may not be true + // Prefix can't be bound to null namespace + if (namespaceURI == 0) { + return 0; + } + + DOMNode *thisNode = castToNode(this); + + short type = thisNode->getNodeType(); + + switch (type) { + case DOMNode::ELEMENT_NODE: { + return lookupPrefix(namespaceURI, (DOMElement*)thisNode); + } + case DOMNode::DOCUMENT_NODE:{ + return ((DOMDocument*)thisNode)->getDocumentElement()->lookupPrefix(namespaceURI); + } + + case DOMNode::ENTITY_NODE : + case DOMNode::NOTATION_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + case DOMNode::DOCUMENT_TYPE_NODE: + // type is unknown + return 0; + case DOMNode::ATTRIBUTE_NODE:{ + if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) { + return fOwnerNode->lookupPrefix(namespaceURI); + } + return 0; + } + default:{ + DOMNode *ancestor = getElementAncestor(thisNode); + if (ancestor != 0) { + return ancestor->lookupPrefix(namespaceURI); + } + return 0; + } + } +} + + +DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const { + DOMNode* parent = currentNode->getParentNode(); + while(parent != 0) { + short type = parent->getNodeType(); + if (type == DOMNode::ELEMENT_NODE) { + return parent; + } + parent=parent->getParentNode(); + } + return 0; +} + + +const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* const namespaceURI, DOMElement *originalElement) const { + DOMNode *thisNode = castToNode(this); + + const XMLCh* ns = thisNode->getNamespaceURI(); + // REVISIT: if no prefix is available is it null or empty string, or + // could be both? + const XMLCh* prefix = thisNode->getPrefix(); + + if (ns != 0 && XMLString::equals(ns,namespaceURI) && prefix != 0) { + const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(prefix); + if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) { + return prefix; + } + } + if (thisNode->hasAttributes()) { + DOMNamedNodeMap *nodeMap = thisNode->getAttributes(); + + if(nodeMap != 0) { + XMLSize_t length = nodeMap->getLength(); + + for (XMLSize_t i = 0;i < length;i++) { + DOMNode *attr = nodeMap->item(i); + const XMLCh* attrPrefix = attr->getPrefix(); + const XMLCh* value = attr->getNodeValue(); + + ns = attr->getNamespaceURI(); + + if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) { + // DOM Level 2 nodes + if ((attrPrefix != 0 && XMLString::equals(attrPrefix, XMLUni::fgXMLNSString)) && + XMLString::equals(value, namespaceURI)) { + const XMLCh* localname= attr->getLocalName(); + const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(localname); + if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) { + return localname; + } + } + } + } + } + } + DOMNode *ancestor = getElementAncestor(thisNode); + if (ancestor != 0) { + return castToNodeImpl(ancestor)->lookupPrefix(namespaceURI, originalElement); + } + return 0; +} + +const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const { + DOMNode *thisNode = castToNode(this); + + short type = thisNode->getNodeType(); + switch (type) { + case DOMNode::ELEMENT_NODE : { + const XMLCh* ns = thisNode->getNamespaceURI(); + const XMLCh* prefix = thisNode->getPrefix(); + if (ns != 0) { + // REVISIT: is it possible that prefix is empty string? + if (specifiedPrefix == 0 && prefix == specifiedPrefix) { + // looking for default namespace + return ns; + } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) { + // non default namespace + return ns; + } + } + if (thisNode->hasAttributes()) { + DOMNamedNodeMap *nodeMap = thisNode->getAttributes(); + if(nodeMap != 0) { + XMLSize_t length = nodeMap->getLength(); + for (XMLSize_t i = 0;i < length;i++) { + DOMNode *attr = nodeMap->item(i); + const XMLCh *attrPrefix = attr->getPrefix(); + const XMLCh *value = attr->getNodeValue(); + ns = attr->getNamespaceURI(); + + if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) { + // at this point we are dealing with DOM Level 2 nodes only + if (specifiedPrefix == 0 && + XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) { + // default namespace + return value; + } else if (attrPrefix != 0 && + XMLString::equals(attrPrefix, XMLUni::fgXMLNSString) && + XMLString::equals(attr->getLocalName(), specifiedPrefix)) { + // non default namespace + return value; + } + } + } + } + } + DOMNode *ancestor = getElementAncestor(thisNode); + if (ancestor != 0) { + return ancestor->lookupNamespaceURI(specifiedPrefix); + } + return 0; + } + case DOMNode::DOCUMENT_NODE : { + return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix); + } + case DOMNode::ENTITY_NODE : + case DOMNode::NOTATION_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + case DOMNode::DOCUMENT_TYPE_NODE: + // type is unknown + return 0; + case DOMNode::ATTRIBUTE_NODE:{ + if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) { + return fOwnerNode->lookupNamespaceURI(specifiedPrefix); + } + return 0; + } + default:{ + DOMNode *ancestor = getElementAncestor(castToNode(this)); + if (ancestor != 0) { + return ancestor->lookupNamespaceURI(specifiedPrefix); + } + return 0; + } + } +} + + +const XMLCh* DOMNodeImpl::getBaseURI() const{ + DOMNode *thisNode = castToNode(this); + DOMNode* parent = thisNode->getParentNode(); + if (parent) + return parent->getBaseURI(); + else + return 0; +} + +const DOMNode* DOMNodeImpl::getTreeParentNode(const DOMNode* node) const { + const DOMNode* parent=node->getParentNode(); + if(parent) + return parent; + short nodeType=node->getNodeType(); + switch(nodeType) + { + case DOMNode::ATTRIBUTE_NODE: return ((const DOMAttr*)node)->getOwnerElement(); + case DOMNode::NOTATION_NODE: + case DOMNode::ENTITY_NODE: return node->getOwnerDocument()->getDoctype(); + } + return 0; +} + +short DOMNodeImpl::compareDocumentPosition(const DOMNode* other) const { + DOMNode* thisNode = castToNode(this); + + // If the two nodes being compared are the same node, then no flags are set on the return. + if (thisNode == other) + return 0; + + //if this is a custom node, we don't really know what to do, just return + //user should provide its own compareDocumentPosition logic, and shouldn't reach here + if(thisNode->getNodeType() > 12) { + return 0; + } + + //if it is a custom node we must ask it for the order + if(other->getNodeType() > 12) { + return reverseTreeOrderBitPattern(other->compareDocumentPosition(thisNode)); + } + + // Otherwise, the order of two nodes is determined by looking for common containers -- + // containers which contain both. A node directly contains any child nodes. + // A node also directly contains any other nodes attached to it such as attributes + // contained in an element or entities and notations contained in a document type. + // Nodes contained in contained nodes are also contained, but less-directly as + // the number of intervening containers increases. + + // If one of the nodes being compared contains the other node, then the container precedes + // the contained node, and reversely the contained node follows the container. For example, + // when comparing an element against its own attribute or child, the element node precedes + // its attribute node and its child node, which both follow it. + + const DOMNode* tmpNode; + const DOMNode* myRoot = castToNode(this); + int myDepth=0; + while((tmpNode=getTreeParentNode(myRoot))!=0) + { + myRoot=tmpNode; + if(myRoot==other) + return DOMNode::DOCUMENT_POSITION_CONTAINS | DOMNode::DOCUMENT_POSITION_PRECEDING; + myDepth++; + } + + const DOMNode* hisRoot = other; + int hisDepth=0; + while((tmpNode=getTreeParentNode(hisRoot))!=0) + { + hisRoot=tmpNode; + if(hisRoot==thisNode) + return DOMNode::DOCUMENT_POSITION_CONTAINED_BY | DOMNode::DOCUMENT_POSITION_FOLLOWING; + hisDepth++; + } + + // If there is no common container node, then the order is based upon order between the + // root container of each node that is in no container. In this case, the result is + // disconnected and implementation-specific. This result is stable as long as these + // outer-most containing nodes remain in memory and are not inserted into some other + // containing node. This would be the case when the nodes belong to different documents + // or fragments, and cloning the document or inserting a fragment might change the order. + + if(myRoot!=hisRoot) + return DOMNode::DOCUMENT_POSITION_DISCONNECTED | DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | + (myRoot hisDepth) { + for (int i= 0 ; i < myDepth - hisDepth; i++) + myRoot = getTreeParentNode(myRoot); + } + else { + for (int i = 0; i < hisDepth - myDepth; i++) + hisRoot = getTreeParentNode(hisRoot); + } + + // We now have nodes at the same depth in the tree. Find a common ancestor. + const DOMNode *myNodeP=myRoot; + const DOMNode *hisNodeP=hisRoot; + while(myRoot!=hisRoot) + { + myNodeP = myRoot; + hisNodeP = hisRoot; + myRoot = getTreeParentNode(myRoot); + hisRoot = getTreeParentNode(hisRoot); + } + + short myNodeType=myNodeP->getNodeType(); + short hisNodeType=hisNodeP->getNodeType(); + bool bMyNodeIsChild=(myNodeType!=DOMNode::ATTRIBUTE_NODE && myNodeType!=DOMNode::ENTITY_NODE && myNodeType!=DOMNode::NOTATION_NODE); + bool bHisNodeIsChild=(hisNodeType!=DOMNode::ATTRIBUTE_NODE && hisNodeType!=DOMNode::ENTITY_NODE && hisNodeType!=DOMNode::NOTATION_NODE); + + // If these two determining nodes are both child nodes, then the natural DOM order of these + // determining nodes within the containing node is returned as the order of the corresponding nodes. + // This would be the case, for example, when comparing two child elements of the same element. + if(bMyNodeIsChild && bHisNodeIsChild) + { + while(myNodeP != 0) + { + myNodeP = myNodeP->getNextSibling(); + if(myNodeP == hisNodeP) + return DOMNode::DOCUMENT_POSITION_FOLLOWING; + } + return DOMNode::DOCUMENT_POSITION_PRECEDING; + } + + // If one of the two determining nodes is a child node and the other is not, then the corresponding + // node of the child node follows the corresponding node of the non-child node. This would be the case, + // for example, when comparing an attribute of an element with a child element of the same element. + else if(!bMyNodeIsChild && bHisNodeIsChild) + return DOMNode::DOCUMENT_POSITION_FOLLOWING; + else if(bMyNodeIsChild && !bHisNodeIsChild) + return DOMNode::DOCUMENT_POSITION_PRECEDING; + + else + { + // If neither of the two determining node is a child node and one determining node has a greater value + // of nodeType than the other, then the corresponding node precedes the other. This would be the case, + // for example, when comparing an entity of a document type against a notation of the same document type. + if(myNodeType!=hisNodeType) + return (myNodeTypeallocate((nBufferLength+1) * sizeof(XMLCh)); + getTextContent(pzBuffer, nBufferLength); + pzBuffer[nBufferLength] = 0; + + return pzBuffer; + +} + +const XMLCh* DOMNodeImpl::getTextContent(XMLCh* pzBuffer, XMLSize_t& rnBufferLength) const +{ + XMLSize_t nRemainingBuffer = rnBufferLength; + rnBufferLength = 0; + + if (pzBuffer) + *pzBuffer = 0; + + DOMNode *thisNode = castToNode(this); + + switch (thisNode->getNodeType()) + { + case DOMNode::ELEMENT_NODE: + case DOMNode::ENTITY_NODE: + case DOMNode::ENTITY_REFERENCE_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + { + DOMNode* current = thisNode->getFirstChild(); + + while (current != NULL) + { + if (current->getNodeType() != DOMNode::COMMENT_NODE && + current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE) + { + + if (pzBuffer) + { + XMLSize_t nContentLength = nRemainingBuffer; + castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength); + rnBufferLength += nContentLength; + nRemainingBuffer -= nContentLength; + } + else + { + XMLSize_t nContentLength = 0; + castToNodeImpl(current)->getTextContent(NULL, nContentLength); + rnBufferLength += nContentLength; + } + } + + current = current->getNextSibling(); + + } + } + + break; + + case DOMNode::ATTRIBUTE_NODE: + case DOMNode::TEXT_NODE: + case DOMNode::CDATA_SECTION_NODE: + case DOMNode::COMMENT_NODE: + case DOMNode::PROCESSING_INSTRUCTION_NODE: + { + const XMLCh* pzValue = thisNode->getNodeValue(); + XMLSize_t nStrLen = XMLString::stringLen(pzValue); + + if (pzBuffer) + { + XMLSize_t nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer; + XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength); + rnBufferLength += nContentLength; + nRemainingBuffer -= nContentLength; + } + else + { + rnBufferLength += nStrLen; + } + + } + + break; + + /*** + DOCUMENT_NODE + DOCUMENT_TYPE_NODE + NOTATION_NODE + ***/ + default: + + break; + } + + return pzBuffer; + +} + +void DOMNodeImpl::setTextContent(const XMLCh* textContent){ + DOMNode *thisNode = castToNode(this); + switch (thisNode->getNodeType()) + { + case DOMNode::ELEMENT_NODE: + case DOMNode::ENTITY_NODE: + case DOMNode::ENTITY_REFERENCE_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + { + if (isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + // Remove all childs + DOMNode* current = thisNode->getFirstChild(); + while (current != NULL) + { + thisNode->removeChild(current); + current = thisNode->getFirstChild(); + } + if (textContent != NULL) + { + // Add textnode containing data + current = ((DOMDocumentImpl*)thisNode->getOwnerDocument())->createTextNode(textContent); + thisNode->appendChild(current); + } + } + break; + + case DOMNode::ATTRIBUTE_NODE: + case DOMNode::TEXT_NODE: + case DOMNode::CDATA_SECTION_NODE: + case DOMNode::COMMENT_NODE: + case DOMNode::PROCESSING_INSTRUCTION_NODE: + if (isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + + thisNode->setNodeValue(textContent); + break; + + case DOMNode::DOCUMENT_NODE: + case DOMNode::DOCUMENT_TYPE_NODE: + case DOMNode::NOTATION_NODE: + break; + + default: + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager); + } +} + + +bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{ + DOMNode *thisNode = castToNode(this); + short type = thisNode->getNodeType(); + switch (type) { + case DOMNode::ELEMENT_NODE: { + const XMLCh *prefix = thisNode->getPrefix(); + + // REVISIT: is it possible that prefix is empty string? + if (prefix == 0 || !*prefix) { + return XMLString::equals(namespaceURI, thisNode->getNamespaceURI()); + } + + if (thisNode->hasAttributes()) { + DOMElement *elem = (DOMElement *)thisNode; + DOMNode *attr = elem->getAttributeNodeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString); + if (attr != 0) { + const XMLCh *value = attr->getNodeValue(); + return XMLString::equals(namespaceURI, value); + } + } + DOMNode *ancestor = getElementAncestor(thisNode); + if (ancestor != 0) { + return ancestor->isDefaultNamespace(namespaceURI); + } + + return false; + } + case DOMNode::DOCUMENT_NODE:{ + return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI); + } + + case DOMNode::ENTITY_NODE : + case DOMNode::NOTATION_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + case DOMNode::DOCUMENT_TYPE_NODE: + // type is unknown + return false; + case DOMNode::ATTRIBUTE_NODE:{ + if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) { + return fOwnerNode->isDefaultNamespace(namespaceURI); + + } + return false; + } + default:{ + DOMNode *ancestor = getElementAncestor(thisNode); + if (ancestor != 0) { + return ancestor->isDefaultNamespace(namespaceURI); + } + return false; + } + + } +} + +void* DOMNodeImpl::getFeature(const XMLCh*, const XMLCh*) const { + return 0; +} + + +// non-standard extension +void DOMNodeImpl::release() +{ + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/dom/impl/DOMNodeImpl.hpp b/include/xercesc/dom/impl/DOMNodeImpl.hpp new file mode 100644 index 0000000..9c6c278 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeImpl.hpp @@ -0,0 +1,382 @@ +/* + * 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: DOMNodeImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODEIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODEIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +/** + * A DOMNodeImpl doesn't have any children, and can therefore only be directly + * inherited by classes of nodes that never have any, such as Text nodes. For + * other types, such as Element, classes must inherit from ParentNode. + *

+ * All nodes in a single document must originate + * in that document. (Note that this is much tighter than "must be + * same implementation") Nodes are all aware of their ownerDocument, + * and attempts to mismatch will throw WRONG_DOCUMENT_ERR. + *

+ * However, to save memory not all nodes always have a direct reference + * to their ownerDocument. When a node is owned by another node it relies + * on its owner to store its ownerDocument. Parent nodes always store it + * though, so there is never more than one level of indirection. + * And when a node doesn't have an owner, ownerNode refers to its + * ownerDocument. + **/ + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNamedNodeMap; +class DOMNodeList; +class DOMNode; +class DOMDocument; +class DOMElement; + +class CDOM_EXPORT DOMNodeImpl { +public: + + // data + DOMNode *fOwnerNode; // typically the parent but not always! + + unsigned short flags; + + static const unsigned short READONLY; + static const unsigned short SYNCDATA; + static const unsigned short SYNCCHILDREN; + static const unsigned short OWNED; + static const unsigned short FIRSTCHILD; + static const unsigned short SPECIFIED; + static const unsigned short IGNORABLEWS; + static const unsigned short SETVALUE; + static const unsigned short ID_ATTR; + static const unsigned short USERDATA; + static const unsigned short LEAFNODETYPE; + static const unsigned short CHILDNODE; + static const unsigned short TOBERELEASED; + + +public: + DOMNodeImpl(DOMNode *ownerDocument); + DOMNodeImpl(const DOMNodeImpl &other); + ~DOMNodeImpl(); + + DOMNode * appendChild(DOMNode *newChild); + DOMNamedNodeMap * getAttributes() const; + DOMNodeList * getChildNodes() const; + DOMNode * getFirstChild() const; + DOMNode * getLastChild() const; + const XMLCh * getLocalName() const; + const XMLCh * getNamespaceURI() const; + DOMNode * getNextSibling() const; + const XMLCh * getNodeValue() const; + DOMDocument * getOwnerDocument() const; + DOMNode * getParentNode() const; + const XMLCh * getPrefix() const; + DOMNode * getPreviousSibling() const; + bool hasChildNodes() const; + DOMNode * insertBefore(DOMNode *newChild, DOMNode *refChild); + void normalize(); + DOMNode * removeChild(DOMNode *oldChild); + DOMNode * replaceChild(DOMNode *newChild, DOMNode *oldChild); + void setNodeValue(const XMLCh *value); + void setPrefix(const XMLCh *fPrefix); + void setReadOnly(bool readOnly, bool deep); + bool isSupported(const XMLCh *feature, const XMLCh *version) const; + bool hasAttributes() const; + + // Introduced in DOM Level 3 + void* setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler); + void* getUserData(const XMLCh* key) const; + bool isSameNode(const DOMNode* other) const; + bool isEqualNode(const DOMNode* arg) const; + const XMLCh* getBaseURI() const ; + short compareDocumentPosition(const DOMNode* other) const; + const XMLCh* getTextContent() const ; + const XMLCh* getTextContent(XMLCh* pzBuffer, XMLSize_t& rnBufferLength) const; + void setTextContent(const XMLCh* textContent) ; + const XMLCh* lookupPrefix(const XMLCh* namespaceURI) const ; + bool isDefaultNamespace(const XMLCh* namespaceURI) const ; + const XMLCh* lookupNamespaceURI(const XMLCh* prefix) const ; + void* getFeature(const XMLCh* feature, const XMLCh* version) const; + + + // Helper functions for DOM Level 3 + void release(); + void callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation, + const DOMNode* src, + DOMNode* dst) const; + //reverses the bit pattern given by compareDocumentPosition + short reverseTreeOrderBitPattern(short pattern) const; + const DOMNode* getTreeParentNode(const DOMNode* node) const; + + + //Utility, not part of DOM Level 2 API + static bool isKidOK(DOMNode *parent, DOMNode *child); + static const XMLCh *mapPrefix(const XMLCh *prefix, + const XMLCh *namespaceURI, short nType); + + static const XMLCh *getXmlnsString(); + static const XMLCh *getXmlnsURIString(); + static const XMLCh *getXmlString(); + static const XMLCh *getXmlURIString(); + +public: // should really be protected - ALH + + DOMNode* getElementAncestor (const DOMNode* currentNode) const; + const XMLCh* lookupPrefix(const XMLCh* const namespaceURI, DOMElement *el) const ; + void setOwnerDocument(DOMDocument *doc); + + /* + * Flags setters and getters + */ + + inline bool isReadOnly() const { + return (flags & READONLY) != 0; + } + + inline void isReadOnly(bool value) { + flags = (value ? flags | READONLY : flags & ~READONLY); + } + + inline bool needsSyncData() const { + return (flags & SYNCDATA) != 0; + } + + inline void needsSyncData(bool value) { + flags = (value ? flags | SYNCDATA : flags & ~SYNCDATA); + } + + inline bool needsSyncChildren() const { + return (flags & SYNCCHILDREN) != 0; + } + + inline void needsSyncChildren(bool value) { + flags = (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN); + } + + // For Attributes, true if the attr node is attached to an element. + // For all other node types, true if the node has a parent node. + inline bool isOwned() const { + return (flags & OWNED) != 0; + } + + inline void isOwned(bool value) { + flags = (value ? flags | OWNED : flags & ~OWNED); + } + + inline bool isFirstChild() const { + return (flags & FIRSTCHILD) != 0; + } + + inline void isFirstChild(bool value) { + flags = (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD); + } + + inline bool isSpecified() const { + return (flags & SPECIFIED) != 0; + } + + inline void isSpecified(bool value) { + flags = (value ? flags | SPECIFIED : flags & ~SPECIFIED); + } + + inline bool ignorableWhitespace() const { + return (flags & IGNORABLEWS) != 0; + } + + inline void ignorableWhitespace(bool value) { + flags = (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS); + } + + inline bool setValue() const { + return (flags & SETVALUE) != 0; + } + + inline void setValue(bool value) { + flags = (value ? flags | SETVALUE : flags & ~SETVALUE); + } + + inline bool isIdAttr() const { + return (flags & ID_ATTR) != 0; + } + + inline void isIdAttr(bool value) { + flags = (value ? flags | ID_ATTR : flags & ~ID_ATTR); + } + + inline bool hasUserData() const { + return (flags & USERDATA) != 0; + } + + inline void hasUserData(bool value) { + flags = (value ? flags | USERDATA : flags & ~USERDATA); + } + + // + // LeafNode is set true for node types that can not be ParentNodes (can't have children) + // This knowledge is used to allow casting from any unknown node type to the + // IDParentImpl or IDChildImpl parts of the node. + // + inline bool isLeafNode() const { + return (flags & LEAFNODETYPE) != 0; + } + + inline void setIsLeafNode(bool value) { + flags = (value ? flags | LEAFNODETYPE : flags & ~LEAFNODETYPE); + } + + + // + // ChildNode is set true for node types that can be children of other nodes, and + // therefore include a DOMChildNode data member. Note that all of the leaf + // node types (above flag) are also ChildNodes, but not all ChildNodes are + // leaf nodes. + inline bool isChildNode() const { + return (flags & CHILDNODE) != 0; + } + + inline void setIsChildNode(bool value) { + flags = (value ? flags | CHILDNODE : flags & ~CHILDNODE); + } + + // True if this node has to be released regardless if it has a owner or not + // This is true if called from fParent->release() + inline bool isToBeReleased() const { + return (flags & TOBERELEASED) != 0; + } + + inline void isToBeReleased(bool value) { + flags = (value ? flags | TOBERELEASED : flags & ~TOBERELEASED); + } + +}; + + +// This macro lists all of the pure virtual functions declared in DOMNode that must +// be implemented by all node types. Since there is no inheritance of implementation, +// using this macro in the class declaration of the node types make it easier to +// accurately get all of the functions declared. +// +#define DOMNODE_FUNCTIONS \ + virtual DOMNode* appendChild(DOMNode *newChild) ;\ + virtual DOMNode* cloneNode(bool deep) const ;\ + virtual DOMNamedNodeMap* getAttributes() const ;\ + virtual DOMNodeList* getChildNodes() const ;\ + virtual DOMNode* getFirstChild() const ;\ + virtual DOMNode* getLastChild() const ;\ + virtual const XMLCh* getLocalName() const ;\ + virtual const XMLCh* getNamespaceURI() const ;\ + virtual DOMNode* getNextSibling() const ;\ + virtual const XMLCh* getNodeName() const ;\ + virtual NodeType getNodeType() const ;\ + virtual const XMLCh* getNodeValue() const ;\ + virtual DOMDocument* getOwnerDocument() const ;\ + virtual const XMLCh* getPrefix() const ;\ + virtual DOMNode* getParentNode() const ;\ + virtual DOMNode* getPreviousSibling() const ;\ + virtual bool hasChildNodes() const ;\ + virtual DOMNode* insertBefore(DOMNode *newChild, DOMNode *refChild) ;\ + virtual void normalize() ;\ + virtual DOMNode* removeChild(DOMNode *oldChild) ;\ + virtual DOMNode* replaceChild(DOMNode *newChild, DOMNode *oldChild) ;\ + virtual void setNodeValue(const XMLCh *nodeValue) ;\ + virtual bool isSupported(const XMLCh *feature, const XMLCh *version) const ;\ + virtual bool hasAttributes() const ;\ + virtual void setPrefix(const XMLCh * prefix) ;\ + virtual void* setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) ;\ + virtual void* getUserData(const XMLCh* key) const ;\ + virtual bool isSameNode(const DOMNode* other) const;\ + virtual bool isEqualNode(const DOMNode* arg) const;\ + virtual const XMLCh* getBaseURI() const ;\ + virtual short compareDocumentPosition(const DOMNode* other) const ;\ + virtual const XMLCh* getTextContent() const ;\ + const XMLCh* getTextContent(XMLCh* pzBuffer, unsigned int& rnBufferLength) const;\ + virtual void setTextContent(const XMLCh* textContent) ;\ + virtual const XMLCh* lookupPrefix(const XMLCh* namespaceURI) const ;\ + virtual bool isDefaultNamespace(const XMLCh* namespaceURI) const;\ + virtual const XMLCh* lookupNamespaceURI(const XMLCh* prefix) const ;\ + virtual void* getFeature(const XMLCh* feature, const XMLCh* version) const ;\ + virtual void release() + + +/* + * Here are dummy stubs for most of the functions introduced by DOMNode. + * Each subclass of DOMNode will have something like this that delegates each + * function to the appropriate implementation. + * Functions that must be supplied by every node class are omitted. + * + DOMNode* xxx::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); }; + DOMNamedNodeMap* xxx::getAttributes() const {return fNode.getAttributes (); }; + DOMNodeList* xxx::getChildNodes() const {return fParent.getChildNodes (); }; + DOMNode* xxx::getFirstChild() const {return fParent.getFirstChild (); }; + DOMNode* xxx::getLastChild() const {return fParent.getLastChild (); }; + const XMLCh* xxx::getLocalName() const {return fNode.getLocalName (); }; + const XMLCh* xxx::getNamespaceURI() const {return fNode.getNamespaceURI (); }; + DOMNode* xxx::getNextSibling() const {return fChild.getNextSibling (); }; + const XMLCh* xxx::getNodeValue() const {return fNode.getNodeValue (); }; + DOMDocument* xxx::getOwnerDocument() const {return fNode.getOwnerDocument (); }; + const XMLCh* xxx::getPrefix() const {return fNode.getPrefix (); }; + DOMNode* xxx::getParentNode() const {return fChild.getParentNode (this); }; + DOMNode* xxx::getPreviousSibling() const {return fChild.getPreviousSibling (this); }; + bool xxx::hasChildNodes() const {return fParent.hasChildNodes (); }; + DOMNode* xxx::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fParent.insertBefore (newChild, refChild); }; + void xxx::normalize() {fParent.normalize(); }; + DOMNode* xxx::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); }; + DOMNode* xxx::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fParent.replaceChild (newChild, oldChild); }; + bool xxx::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); }; + void xxx::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); }; + bool xxx::hasAttributes() const {return fNode.hasAttributes(); }; + bool xxx::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); }; + bool xxx::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); }; + void* xxx::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); }; + void* xxx::getUserData(const XMLCh* key) const {return fNode.getUserData(key); }; + const XMLCh* xxx::getBaseURI() const {return fNode.getBaseURI(); }; + short xxx::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }; + const XMLCh* xxx::getTextContent() const {return fNode.getTextContent(); }; + void xxx::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }; + const XMLCh* xxx::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); }; + bool xxx::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }; + const XMLCh* xxx::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); }; + void* xxx::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }; + + +*/ + + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNodeIteratorImpl.cpp b/include/xercesc/dom/impl/DOMNodeIteratorImpl.cpp new file mode 100644 index 0000000..49bdcb5 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeIteratorImpl.cpp @@ -0,0 +1,365 @@ +/* + * 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: DOMNodeIteratorImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +////////////////////////////////////////////////////////////////////// +// DOMNodeIteratorImpl.cpp: implementation of the DOMNodeIteratorImpl class. +// +////////////////////////////////////////////////////////////////////// + +#include "DOMNodeIteratorImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +DOMNodeIteratorImpl::DOMNodeIteratorImpl (DOMDocument* doc, + DOMNode* root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* nodeFilter, + bool expandEntityRef) +: fRoot(root), + fDocument(doc), + fWhatToShow(whatToShow), + fNodeFilter(nodeFilter), + fExpandEntityReferences(expandEntityRef), + fDetached(false), + fCurrentNode(0), + fForward(true) +{ + +} + + +DOMNodeIteratorImpl::DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy) + : DOMNodeIterator(toCopy), + fRoot(toCopy.fRoot), + fDocument(toCopy.fDocument), + fWhatToShow(toCopy.fWhatToShow), + fNodeFilter(toCopy.fNodeFilter), + fExpandEntityReferences(toCopy.fExpandEntityReferences), + fDetached(toCopy.fDetached), + fCurrentNode(toCopy.fCurrentNode), + fForward(toCopy.fForward) +{ +} + + +DOMNodeIteratorImpl& DOMNodeIteratorImpl::operator= (const DOMNodeIteratorImpl& other) { + fRoot = other.fRoot; + fCurrentNode = other.fRoot; + fWhatToShow = other.fWhatToShow; + fNodeFilter = other.fNodeFilter; + fForward = other.fForward; + fDetached = other.fDetached; + fExpandEntityReferences = other.fExpandEntityReferences; + fDocument = other.fDocument; + return *this; +} + +DOMNodeIteratorImpl::~DOMNodeIteratorImpl () +{ + fDetached = false; +} + + +void DOMNodeIteratorImpl::detach () +{ + fDetached = true; + ((DOMDocumentImpl *)fDocument)->removeNodeIterator(this); +} + + +DOMNode* DOMNodeIteratorImpl::getRoot() { + return fRoot; +} + + +// Implementation Note: Note that the iterator looks at whatToShow +// and filter values at each call, and therefore one _could_ add +// setters for these values and alter them while iterating! + +/** Return the whatToShow value */ + +DOMNodeFilter::ShowType DOMNodeIteratorImpl::getWhatToShow () { + return fWhatToShow; +} + + +/** Return the filter */ + +DOMNodeFilter* DOMNodeIteratorImpl::getFilter () { + return fNodeFilter; +} + +/** Get the expandEntity reference flag. */ +bool DOMNodeIteratorImpl::getExpandEntityReferences() +{ + return fExpandEntityReferences; +} + +/** Return the next DOMNode* in the Iterator. The node is the next node in + * depth-first order which also passes the filter, and whatToShow. + * A 0 return means either that + */ + +DOMNode* DOMNodeIteratorImpl::nextNode () { + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); + + // if root is 0 there is no next node-> + if (!fRoot) + return 0; + + DOMNode* aNextNode = fCurrentNode; + bool accepted = false; // the next node has not been accepted. + + while (!accepted) { + + // if last direction is not forward, repeat node-> + if (!fForward && (aNextNode != 0)) { + //System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName()); + aNextNode = fCurrentNode; + } else { + // else get the next node via depth-first + aNextNode = nextNode(aNextNode, true); + } + + fForward = true; //REVIST: should direction be set forward before 0 check? + + // nothing in the list. return 0. + if (!aNextNode) return 0; + + // does node pass the filters and whatToShow? + accepted = acceptNode(aNextNode); + if (accepted) { + // if so, then the node is the current node-> + fCurrentNode = aNextNode; + return fCurrentNode; + } + } + + // no nodes, or no accepted nodes. + return 0; +} + + +/** Return the previous Node in the Iterator. The node is the next node in + * _backwards_ depth-first order which also passes the filter, and whatToShow. + */ + +DOMNode* DOMNodeIteratorImpl::previousNode () { + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); + + // if the root is 0, or the current node is 0, return 0. + if (!fRoot || !fCurrentNode) return 0; + + DOMNode* aPreviousNode = fCurrentNode; + bool accepted = false; + + while (!accepted) { + + if (fForward && (aPreviousNode != 0)) { + //repeat last node-> + aPreviousNode = fCurrentNode; + } else { + // get previous node in backwards depth first order. + aPreviousNode = previousNode(aPreviousNode); + } + + // we are going backwards + fForward = false; + + // if the new previous node is 0, we're at head or past the root, + // so return 0. + if (!aPreviousNode) return 0; + + // check if node passes filters and whatToShow. + accepted = acceptNode(aPreviousNode); + if (accepted) { + // if accepted, update the current node, and return it. + fCurrentNode = aPreviousNode; + return fCurrentNode; + } + } + // there are no nodes? + return 0; +} + + +/** The node is accepted if it passes the whatToShow and the filter. */ +bool DOMNodeIteratorImpl::acceptNode (DOMNode* node) { + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); + + if (fNodeFilter == 0) { + return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0); + } else { + return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0) + && fNodeFilter->acceptNode(node) == DOMNodeFilter::FILTER_ACCEPT; + } +} + + +/** Return node, if matches or any parent if matches. */ +DOMNode* DOMNodeIteratorImpl::matchNodeOrParent (DOMNode* node) { + + for (DOMNode* n = fCurrentNode; n != fRoot; n = n->getParentNode()) { + if (node == n) return n; + } + + return 0; +} + + +/** The method nextNode(DOMNode, bool) returns the next node + * from the actual DOM tree. + * + * The bool visitChildren determines whether to visit the children. + * The result is the nextNode. + */ + +DOMNode* DOMNodeIteratorImpl::nextNode (DOMNode* node, bool visitChildren) { + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); + + if (!node) return fRoot; + + DOMNode* result = 0; + // only check children if we visit children. + if (visitChildren) { + //if hasChildren, return 1st child. + if ((fExpandEntityReferences || node->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) && + node->hasChildNodes()) { + result = node->getFirstChild(); + return result; + } + } + + // if hasSibling, return sibling + if (node != fRoot) { + result = node->getNextSibling(); + if (result != 0) return result; + + + // return parent's 1st sibling. + DOMNode* parent = node->getParentNode(); + while ((parent != 0) && parent != fRoot) { + result = parent->getNextSibling(); + if (result != 0) { + return result; + } else { + parent = parent->getParentNode(); + } + + } // while (parent != 0 && parent != fRoot) { + } + // end of list, return 0 + return 0; +} + + +/** The method previousNode(DOMNode) returns the previous node + * from the actual DOM tree. + */ + +DOMNode* DOMNodeIteratorImpl::previousNode (DOMNode* node) { + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); + + DOMNode* result = 0; + + // if we're at the root, return 0. + if (node == fRoot) + return 0; + + // get sibling + result = node->getPreviousSibling(); + if (!result) { + //if 1st sibling, return parent + result = node->getParentNode(); + return result; + } + + // if sibling has children, keep getting last child of child. + if (result->hasChildNodes()) { + while ((fExpandEntityReferences || result->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) && + result->hasChildNodes()) { + result = result->getLastChild(); + } + } + + return result; +} + + +/** Fix-up the iterator on a remove. Called by DOM or otherwise, + * before an actual DOM remove. + */ + +void DOMNodeIteratorImpl::removeNode (DOMNode* node) { + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); + + // Implementation note: Fix-up means setting the current node properly + // after a remove. + + if (!node) return; + + DOMNode* deleted = matchNodeOrParent(node); + + if (!deleted) return; + + if (fForward) { + fCurrentNode = previousNode(deleted); + } else + // if (!fForward) + { + DOMNode* next = nextNode(deleted, false); + if (next != 0) { + // normal case: there _are_ nodes following this in the iterator. + fCurrentNode = next; + } else { + // the last node in the iterator is to be removed, + // so we set the current node to be the previous one. + fCurrentNode = previousNode(deleted); + fForward = true; + } + + } + +} + + +void DOMNodeIteratorImpl::release() +{ + detach(); + + // for performance reason, do not recycle pointer + // chance that this is allocated again and again is not usual +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMNodeIteratorImpl.hpp b/include/xercesc/dom/impl/DOMNodeIteratorImpl.hpp new file mode 100644 index 0000000..50fc784 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeIteratorImpl.hpp @@ -0,0 +1,122 @@ +/* + * 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: DOMNodeIteratorImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODEITERATORIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODEITERATORIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +////////////////////////////////////////////////////////////////////// +// DOMNodeIteratorImpl.hpp: interface for the DOMNodeIteratorImpl class. +// +////////////////////////////////////////////////////////////////////// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { + protected: + // + // Data + // + // The root. + DOMNode* fRoot; + + // The Document used to create this iterator + DOMDocument* fDocument; + + // The whatToShow mask. + DOMNodeFilter::ShowType fWhatToShow; + + // The NodeFilter reference. + DOMNodeFilter* fNodeFilter; + + + // The expandEntity reference flag. + bool fExpandEntityReferences; + bool fDetached; + + + // + // Iterator state - current node and direction. + // + // Note: The current node and direction are sufficient to implement + // the desired behaviour of the current pointer being _between_ + // two nodes. The fCurrentNode is actually the last node returned, + // and the + // direction is whether the pointer is in front or behind this node. + // (usually akin to whether the node was returned via nextNode()) + // (eg fForward = true) or previousNode() (eg fForward = false). + // The last Node returned. + DOMNode* fCurrentNode; + + // The direction of the iterator on the fCurrentNode. + // + // nextNode() == fForward = true;
+ // previousNode() == fForward = false;
+ //
+ bool fForward; + + public: + virtual ~DOMNodeIteratorImpl (); + DOMNodeIteratorImpl ( + DOMDocument* fDocument, + DOMNode* root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* nodeFilter, + bool expandEntityRef); + + DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy); + DOMNodeIteratorImpl& operator= (const DOMNodeIteratorImpl& other); + + virtual DOMNode* getRoot (); + virtual DOMNodeFilter::ShowType getWhatToShow (); + virtual DOMNodeFilter* getFilter (); + // Get the expandEntity reference flag. + virtual bool getExpandEntityReferences(); + + virtual DOMNode* nextNode (); + virtual DOMNode* previousNode (); + virtual void detach (); + + virtual void release(); + void removeNode (DOMNode* node); + + protected: + DOMNode* matchNodeOrParent (DOMNode* node); + DOMNode* nextNode (DOMNode* node, bool visitChildren); + DOMNode* previousNode (DOMNode* node); + bool acceptNode (DOMNode* node); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNodeListImpl.cpp b/include/xercesc/dom/impl/DOMNodeListImpl.cpp new file mode 100644 index 0000000..228dd13 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeListImpl.cpp @@ -0,0 +1,72 @@ +/* + * 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: DOMNodeListImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + + +#include +#include "DOMNodeListImpl.hpp" +#include "DOMCasts.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +// revisit +// this implementation is too stupid - needs a cache of some kind. +// + +DOMNodeListImpl::DOMNodeListImpl(DOMParentNode *node) +: fNode(node) +{ +} + + +DOMNodeListImpl:: ~DOMNodeListImpl() +{ +} + + + +XMLSize_t DOMNodeListImpl::getLength() const{ + XMLSize_t count = 0; + if (fNode) { + DOMNode *node = fNode->fFirstChild; + while(node != 0){ + ++count; + node = castToChildImpl(node)->nextSibling; + } + } + + return count; +} + + + +DOMNode *DOMNodeListImpl::item(XMLSize_t index) const{ + if (fNode) { + DOMNode *node = fNode->fFirstChild; + for(XMLSize_t i=0; inextSibling; + return node; + } + return 0; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMNodeListImpl.hpp b/include/xercesc/dom/impl/DOMNodeListImpl.hpp new file mode 100644 index 0000000..8117ee3 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeListImpl.hpp @@ -0,0 +1,73 @@ +/* + * 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: DOMNodeListImpl.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNODELISTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNODELISTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +// NodeList implementation class - +// This is for NodeLists returned by GetChildNodes only, not for +// node lists returned by GetElementsByTagName +// +// Every node type capable of having children has (as an embedded member) +// an instance of this class. To hold down the size overhead on each node, a +// cache of extended data for active node lists is maintained +// separately. +// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMParentNode; +class DOMNode; + +class CDOM_EXPORT DOMNodeListImpl: public DOMNodeList +{ +protected: + DOMParentNode *fNode; + +private: + // Unused, and unimplemented constructors, operators, etc. + DOMNodeListImpl(); + DOMNodeListImpl(const DOMNodeListImpl & other); + DOMNodeListImpl & operator = (const DOMNodeListImpl & other); + +public: + DOMNodeListImpl(DOMParentNode *node); + virtual ~DOMNodeListImpl(); + virtual DOMNode * item(XMLSize_t index) const; + virtual XMLSize_t getLength() const; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNodeVector.cpp b/include/xercesc/dom/impl/DOMNodeVector.cpp new file mode 100644 index 0000000..cba8e64 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNodeVector.cpp @@ -0,0 +1,123 @@ +/* + * 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: DOMNodeVector.cpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +// +// file: DOMNodeVector.cpp +// Implementation of class DOMNodeVector. +// (Use of STL vector, or equivalent, would have been nice, +// but is not available. 'DOMNode *' is the only type +// kept in Vectors in this DOM implementation, so this is +// a hardwired implementation for that type. +// + +#include "DOMNodeVector.hpp" +#include "DOMDocumentImpl.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +DOMNodeVector::DOMNodeVector(DOMDocument *doc) +{ + init(doc, 10); +} + +DOMNodeVector::DOMNodeVector(DOMDocument *doc, XMLSize_t size) { + init(doc, size); +} + + +void DOMNodeVector::init(DOMDocument *doc, XMLSize_t size) { + assert(size > 0); + data = (DOMNode**) ((DOMDocumentImpl *)doc)->allocate(sizeof(DOMNode*) * size); + assert(data != 0); + for (XMLSize_t i=0; igetOwnerDocument(); + + //DOMNode **newData = new (doc) DOMNode *[newAllocatedSize]; + DOMNode **newData = (DOMNode**) ((DOMDocumentImpl *)doc)->allocate(sizeof(DOMNode*) * newAllocatedSize); + + assert(newData != 0); + for (XMLSize_t i=0; iindex; --i) { + data[i] = data[i-1]; + } + data[index] = elem; + ++nextFreeSlot; + +} + + +void DOMNodeVector::removeElementAt(XMLSize_t index) { + assert(index < nextFreeSlot); + for (XMLSize_t i=index; i for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMNode; +class DOMDocument; + + +class DOMNodeVector { +private: + DOMNode **data; + XMLSize_t allocatedSize; + XMLSize_t nextFreeSlot; + void init(DOMDocument *doc, XMLSize_t size); + void checkSpace(); + + // unimplemented + DOMNodeVector ( const DOMNodeVector& toCopy); + DOMNodeVector& operator= (const DOMNodeVector& other); + +public: + DOMNodeVector(DOMDocument *doc); + DOMNodeVector(DOMDocument *doc, XMLSize_t size); + ~DOMNodeVector(); + + XMLSize_t size(); + DOMNode* elementAt(XMLSize_t index); + DOMNode* lastElement(); + void addElement(DOMNode *); + void insertElementAt(DOMNode *, XMLSize_t index); + void setElementAt(DOMNode *val, XMLSize_t index); + void removeElementAt(XMLSize_t index); + void reset(); +}; + +inline DOMNode *DOMNodeVector::elementAt(XMLSize_t index) { + if (index >= nextFreeSlot) + return 0; + return data[index]; +} + +inline DOMNode *DOMNodeVector::lastElement() { + if (nextFreeSlot == 0) + return 0; + return data[nextFreeSlot-1]; +} + +inline XMLSize_t DOMNodeVector::size() { + return nextFreeSlot; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNormalizer.cpp b/include/xercesc/dom/impl/DOMNormalizer.cpp new file mode 100644 index 0000000..649c5a1 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNormalizer.cpp @@ -0,0 +1,500 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "DOMConfigurationImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMElementImpl.hpp" +#include "DOMErrorImpl.hpp" +#include "DOMEntityReferenceImpl.hpp" +#include "DOMNormalizer.hpp" +#include "DOMTextImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +static XMLMsgLoader* gMsgLoader = 0; + +void XMLInitializer::initializeDOMNormalizer() +{ + gMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain); + + if (!gMsgLoader) + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); +} + +void XMLInitializer::terminateDOMNormalizer() +{ + delete gMsgLoader; + gMsgLoader = 0; +} + +// +// +DOMNormalizer::DOMNormalizer(MemoryManager* const manager) + : fDocument(0) + , fConfiguration(0) + , fErrorHandler(0) + , fNSScope(0) + , fNewNamespaceCount(1) + , fMemoryManager(manager) +{ + fNSScope = new (fMemoryManager) InScopeNamespaces(fMemoryManager); +} + +DOMNormalizer::~DOMNormalizer() { + delete fNSScope; +} + +void DOMNormalizer::normalizeDocument(DOMDocumentImpl *doc) { + + fDocument = doc; + fConfiguration = (DOMConfigurationImpl*)doc->getDOMConfig(); + DOMConfigurationImpl *dci = (DOMConfigurationImpl*)fDocument->getDOMConfig(); + if(dci) + fErrorHandler = dci->getErrorHandler(); + else + fErrorHandler = 0; + + DOMNode *child = 0; + DOMNode *next = 0; + ((DOMNormalizer *)this)->fNewNamespaceCount = 1; + + for(child = doc->getFirstChild();child != 0; child = next) { + next = child->getNextSibling(); + child = normalizeNode(child); + if(child != 0) { + next = child; + } + } +} + +DOMNode * DOMNormalizer::normalizeNode(DOMNode *node) const { + switch(node->getNodeType()) { + case DOMNode::ELEMENT_NODE: { + fNSScope->addScope(fMemoryManager); + DOMNamedNodeMap *attrMap = node->getAttributes(); + + if(fConfiguration->featureValues & DOMConfigurationImpl::FEATURE_NAMESPACES) { + namespaceFixUp((DOMElementImpl*)node); + } + else { + //this is done in namespace fixup so no need to do it if namespace is on + if(attrMap) { + for(XMLSize_t i = 0; i < attrMap->getLength(); i++) { + attrMap->item(i)->normalize(); + } + } + } + + DOMNode *child = node->getFirstChild(); + DOMNode *next = 0; + for (; child != 0; child = next) { + next = child->getNextSibling(); + child = normalizeNode(child); + if(child != 0) { + next = child; + } + } + fNSScope->removeScope(); + break; + } + case DOMNode::COMMENT_NODE: { + if (!(fConfiguration->featureValues & DOMConfigurationImpl::FEATURE_COMMENTS)) { + DOMNode *prevSibling = node->getPreviousSibling(); + DOMNode *parent = node->getParentNode(); + // remove the comment node + parent->removeChild(node); + if (prevSibling != 0 && prevSibling->getNodeType() == DOMNode::TEXT_NODE) { + DOMNode *nextSibling = prevSibling->getNextSibling(); + if (nextSibling != 0 && nextSibling->getNodeType() == DOMNode::TEXT_NODE) { + ((DOMTextImpl*)nextSibling)->insertData(0, prevSibling->getNodeValue()); + parent->removeChild(prevSibling); + return nextSibling; + } + } + } + break; + } + case DOMNode::CDATA_SECTION_NODE: { + if (!(fConfiguration->featureValues & DOMConfigurationImpl::FEATURE_CDATA_SECTIONS)) { + // convert CDATA to TEXT nodes + DOMText *text = fDocument->createTextNode(node->getNodeValue()); + DOMNode *parent = node->getParentNode(); + DOMNode *prevSibling = node->getPreviousSibling(); + node = parent->replaceChild(text, node); + if (prevSibling != 0 && prevSibling->getNodeType() == DOMNode::TEXT_NODE) { + text->insertData(0, prevSibling->getNodeValue()); + parent->removeChild(prevSibling); + } + return text; // Don't advance; + } + break; + } + case DOMNode::TEXT_NODE: { + DOMNode *next = node->getNextSibling(); + + if(next != 0 && next->getNodeType() == DOMNode::TEXT_NODE) { + ((DOMText*)node)->appendData(next->getNodeValue()); + node->getParentNode()->removeChild(next); + return node; + } else { + const XMLCh* nv = node->getNodeValue(); + if (nv == 0 || *nv == 0) { + node->getParentNode()->removeChild(node); + } + } + } + default: + break; + } + + return 0; +} + + +void DOMNormalizer::namespaceFixUp(DOMElementImpl *ele) const { + DOMAttrMapImpl *attrMap = ele->fAttributes; + + XMLSize_t len = attrMap->getLength(); + //get the ns info from the attrs + for(XMLSize_t i = 0; i < len; i++) { + DOMAttr *at = (DOMAttr*)attrMap->item(i); + + //normalize the attr whatever happens + at->normalize(); + + const XMLCh *uri = at->getNamespaceURI(); + const XMLCh *value = at->getNodeValue(); + + if(XMLString::equals(XMLUni::fgXMLNSURIName, uri)) { + if(XMLString::equals(XMLUni::fgXMLNSURIName, value)) { + error(XMLErrs::NSDeclInvalid, ele); + } + else { + const XMLCh *prefix = at->getPrefix(); + + if(XMLString::equals(prefix, XMLUni::fgXMLNSString)) { + fNSScope->addOrChangeBinding(at->getLocalName(), value, fMemoryManager); + } + else { + fNSScope->addOrChangeBinding(XMLUni::fgZeroLenString, value, fMemoryManager); + } + } + } + } + + const XMLCh* prefix = ele->getPrefix(); + prefix ? prefix : prefix = XMLUni::fgZeroLenString; + const XMLCh* uri = ele->getNamespaceURI(); + uri ? uri : uri = XMLUni::fgZeroLenString; + + if(!XMLString::equals(uri, XMLUni::fgZeroLenString)) { + if(!fNSScope->isValidBinding(prefix, uri)) { + addOrChangeNamespaceDecl(prefix, uri, ele); + fNSScope->addOrChangeBinding(prefix, uri, fMemoryManager); + } + } + else { + if(ele->getLocalName() == 0) { + error(XMLErrs::DOMLevel1Node, ele); + } + else if(!fNSScope->isValidBinding(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString)) { + addOrChangeNamespaceDecl(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, ele); + fNSScope->addOrChangeBinding(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, fMemoryManager); + } + } + + //fix up non ns attrs + len = attrMap->getLength(); + + // hp aCC complains this i is a redefinition of the i on line 283 + for(XMLSize_t j = 0; j < len; j++) { + DOMAttr *at = (DOMAttr*)attrMap->item(j); + const XMLCh *uri = at->getNamespaceURI(); + const XMLCh* prefix = at->getPrefix(); + + if(!XMLString::equals(XMLUni::fgXMLNSURIName, uri)) { + if(uri != 0) { + if(prefix == 0 || !fNSScope->isValidBinding(prefix, uri)) { + + const XMLCh* newPrefix = fNSScope->getPrefix(uri); + + if(newPrefix != 0) { + at->setPrefix(newPrefix); + } + else { + if(prefix != 0 && !fNSScope->getUri(prefix)) { + fNSScope->addOrChangeBinding(prefix, uri, fMemoryManager); + addOrChangeNamespaceDecl(prefix, uri, ele); + } + else { + newPrefix = addCustomNamespaceDecl(uri, ele); + fNSScope->addOrChangeBinding(newPrefix, uri, fMemoryManager); + at->setPrefix(newPrefix); + } + } + } + } + else if(at->getLocalName() == 0) { + error(XMLErrs::DOMLevel1Node, at); + } + } + } +} + + + +const XMLCh * DOMNormalizer::integerToXMLCh(unsigned int i) const { + XMLCh *buf = (XMLCh*) fMemoryManager->allocate(15 * sizeof(XMLCh));//new XMLCh[15]; + XMLCh *pos = buf + sizeof(buf) - sizeof(XMLCh); + *pos = chNull; + + do { + switch(i % 10) { + case 0 : *--pos = chDigit_0;break; + case 1 : *--pos = chDigit_1;break; + case 2 : *--pos = chDigit_2;break; + case 3 : *--pos = chDigit_3;break; + case 4 : *--pos = chDigit_4;break; + case 5 : *--pos = chDigit_5;break; + case 6 : *--pos = chDigit_6;break; + case 7 : *--pos = chDigit_7;break; + case 8 : *--pos = chDigit_8;break; + case 9 : *--pos = chDigit_9;break; + default:; + } + i /= 10; + } while (i); + + const XMLCh *copy = fDocument->getPooledString(pos); + fMemoryManager->deallocate(buf);//delete[] buf; + return copy; +} + + + + + +void DOMNormalizer::addOrChangeNamespaceDecl(const XMLCh* prefix, const XMLCh* uri, DOMElementImpl* element) const { + + if (XMLString::equals(prefix, XMLUni::fgZeroLenString)) { + element->setAttributeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString, uri); + } else { + XMLBuffer buf(1023, fMemoryManager); + buf.set(XMLUni::fgXMLNSString); + buf.append(chColon); + buf.append(prefix); + element->setAttributeNS(XMLUni::fgXMLNSURIName, buf.getRawBuffer(), uri); + } +} + +const XMLCh* DOMNormalizer::addCustomNamespaceDecl(const XMLCh* uri, DOMElementImpl *element) const { + XMLBuffer preBuf(1023, fMemoryManager); + preBuf.append(chLatin_N); + preBuf.append(chLatin_S); + preBuf.append(integerToXMLCh(fNewNamespaceCount)); + ((DOMNormalizer *)this)->fNewNamespaceCount++; + + while(fNSScope->getUri(preBuf.getRawBuffer())) { + preBuf.reset(); + preBuf.append(chLatin_N); + preBuf.append(chLatin_S); + preBuf.append(integerToXMLCh(fNewNamespaceCount)); + ((DOMNormalizer *)this)->fNewNamespaceCount++; + } + + XMLBuffer buf(1023, fMemoryManager); + buf.set(XMLUni::fgXMLNSString); + buf.append(chColon); + buf.append(preBuf.getRawBuffer()); + element->setAttributeNS(XMLUni::fgXMLNSURIName, buf.getRawBuffer(), uri); + + return element->getAttributeNodeNS(XMLUni::fgXMLNSURIName, preBuf.getRawBuffer())->getLocalName(); +} + +XMLSize_t DOMNormalizer::InScopeNamespaces::size() { + return fScopes->size(); +} + +DOMNormalizer::InScopeNamespaces::InScopeNamespaces(MemoryManager* const manager) +: lastScopeWithBindings(0) +{ + fScopes = new (manager) RefVectorOf(10, true, manager); +} + +DOMNormalizer::InScopeNamespaces::~InScopeNamespaces() { + delete fScopes; +} + +void DOMNormalizer::InScopeNamespaces::addOrChangeBinding(const XMLCh *prefix, const XMLCh *uri, + MemoryManager* const manager) { + XMLSize_t s = fScopes->size(); + + if(!s) + addScope(manager); + + Scope *curScope = fScopes->elementAt(s - 1); + curScope->addOrChangeBinding(prefix, uri, manager); + + lastScopeWithBindings = curScope; +} + +void DOMNormalizer::InScopeNamespaces::addScope(MemoryManager* const manager) { + Scope *s = new (manager) Scope(lastScopeWithBindings); + fScopes->addElement(s); +} + +void DOMNormalizer::InScopeNamespaces::removeScope() { + lastScopeWithBindings = fScopes->elementAt(fScopes->size() - 1)->fBaseScopeWithBindings; + Scope *s = fScopes->orphanElementAt(fScopes->size() - 1); + delete s; +} + +bool DOMNormalizer::InScopeNamespaces::isValidBinding(const XMLCh* prefix, const XMLCh* uri) const { + const XMLCh* actual = fScopes->elementAt(fScopes->size() - 1)->getUri(prefix); + if(actual == 0 || !XMLString::equals(actual, uri)) + return false; + return true; +} + +const XMLCh* DOMNormalizer::InScopeNamespaces::getPrefix(const XMLCh* uri) const { + return fScopes->elementAt(fScopes->size() - 1)->getPrefix(uri); +} + +const XMLCh* DOMNormalizer::InScopeNamespaces::getUri(const XMLCh* prefix) const { + return fScopes->elementAt(fScopes->size() - 1)->getUri(prefix); +} + + + +DOMNormalizer::InScopeNamespaces::Scope::Scope(Scope *baseScopeWithBindings) : fBaseScopeWithBindings(baseScopeWithBindings), fPrefixHash(0), fUriHash(0) +{ +} + +DOMNormalizer::InScopeNamespaces::Scope::~Scope() { + delete fPrefixHash; + delete fUriHash; +} + +void DOMNormalizer::InScopeNamespaces::Scope::addOrChangeBinding(const XMLCh *prefix, const XMLCh *uri, + MemoryManager* const manager) { + //initialize and copy forward now we need to + if(!fUriHash) { + fPrefixHash = new (manager) RefHashTableOf(10, (bool) false, manager); + fUriHash = new (manager) RefHashTableOf(10, (bool) false, manager); + + if(fBaseScopeWithBindings) { + RefHashTableOfEnumerator preEnumer(fBaseScopeWithBindings->fPrefixHash, false, manager); + while(preEnumer.hasMoreElements()) { + const XMLCh* prefix = (XMLCh*) preEnumer.nextElementKey(); + const XMLCh* uri = fBaseScopeWithBindings->fPrefixHash->get((void*)prefix); + + //have to cast here because otherwise we have delete problems under windows :( + fPrefixHash->put((void *)prefix, (XMLCh*)uri); + } + + RefHashTableOfEnumerator uriEnumer(fBaseScopeWithBindings->fUriHash, false, manager); + while(uriEnumer.hasMoreElements()) { + const XMLCh* uri = (XMLCh*) uriEnumer.nextElementKey(); + const XMLCh* prefix = fBaseScopeWithBindings->fUriHash->get((void*)uri); + + //have to cast here because otherwise we have delete problems under windows :( + fUriHash->put((void *)uri, (XMLCh*)prefix); + } + } + } + + const XMLCh *oldUri = fPrefixHash->get(prefix); + if(oldUri) { + fUriHash->removeKey(oldUri); + } + + fPrefixHash->put((void *)prefix, (XMLCh*)uri); + fUriHash->put((void *)uri, (XMLCh*)prefix); +} + +const XMLCh* DOMNormalizer::InScopeNamespaces::Scope::getUri(const XMLCh *prefix) const { + const XMLCh* uri = 0; + + if(fPrefixHash) { + uri = fPrefixHash->get(prefix); + } + else if(fBaseScopeWithBindings) { + uri = fBaseScopeWithBindings->getUri(prefix); + } + + return uri ? uri : 0; +} + +const XMLCh* DOMNormalizer::InScopeNamespaces::Scope::getPrefix(const XMLCh* uri) const { + const XMLCh* prefix = 0; + + if(fUriHash) { + prefix = fUriHash->get(uri); + } + else if(fBaseScopeWithBindings) { + prefix = fBaseScopeWithBindings->getPrefix(uri); + } + return prefix ? prefix : 0; +} + +void DOMNormalizer::error(const XMLErrs::Codes code, const DOMNode *node) const +{ + if (fErrorHandler) { + + // Load the message into alocal and replace any tokens found in + // the text. + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + if (!gMsgLoader->loadMsg(code, errText, maxChars)) + { + // Should probably load a default message here + } + + DOMErrorImpl domError( + XMLErrs::DOMErrorType (code), 0, errText, (void*)node); + bool toContinueProcess = true; + try + { + toContinueProcess = fErrorHandler->handleError(domError); + } + catch(...) + { + } + if (!toContinueProcess) + throw (XMLErrs::Codes) code; + } +} + + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMNormalizer.hpp b/include/xercesc/dom/impl/DOMNormalizer.hpp new file mode 100644 index 0000000..4823e09 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNormalizer.hpp @@ -0,0 +1,166 @@ +/* + * 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: DOMNormalizer.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNORMALIZER_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNORMALIZER_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMConfigurationImpl; +class DOMErrorHandler; +class DOMDocumentImpl; +class DOMNode; +class DOMElementImpl; +class DOMAttr; +class DOMNamedNodeMap; + +class DOMNormalizer : public XMemory { + + //the following are the data structures maintain the stack of namespace information + class InScopeNamespaces : public XMemory { + class Scope : public XMemory { + public: + Scope(Scope *baseScopeWithBindings); + ~Scope(); + void addOrChangeBinding(const XMLCh *prefix, const XMLCh *uri, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + const XMLCh* getUri(const XMLCh *prefix) const; + const XMLCh* getPrefix(const XMLCh* uri) const; + Scope *fBaseScopeWithBindings; + + private: + RefHashTableOf *fPrefixHash; + RefHashTableOf *fUriHash; + // unimplemented + Scope ( const Scope& toCopy); + Scope& operator= (const Scope& other); + }; + + public: + InScopeNamespaces(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~InScopeNamespaces(); + void addOrChangeBinding(const XMLCh *prefix, const XMLCh *uri, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + void addScope(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + void removeScope(); + bool isValidBinding(const XMLCh* prefix, const XMLCh* uri) const; + const XMLCh* getOrDeclarePrefix(const XMLCh* uri); + const XMLCh* getPrefix(const XMLCh* uri) const; + const XMLCh* getUri(const XMLCh* prefix) const; + XMLSize_t size(); + + private: + RefVectorOf *fScopes; + Scope *lastScopeWithBindings; + // unimplemented + InScopeNamespaces ( const InScopeNamespaces& toCopy); + InScopeNamespaces& operator= (const InScopeNamespaces& other); + }; + +public: + DOMNormalizer(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~DOMNormalizer(); + + /** + * Main entry method to normalize a document + */ + void normalizeDocument(DOMDocumentImpl *doc); + +private: + // unimplemented + DOMNormalizer ( const DOMNormalizer& toCopy); + DOMNormalizer& operator= (const DOMNormalizer& other); + +protected: + /** + * Recursively normalizes a node + */ + DOMNode * normalizeNode(DOMNode *node) const; + + /** + * Helper method that fixes up the namespace declarations according to the + * DOM Level 3 psydocode + */ + void namespaceFixUp(DOMElementImpl *ele) const; + + /** + * Converts an integer to an XMLCh - max 15 digits long. + */ + const XMLCh * integerToXMLCh(unsigned int i) const; + + /** + * Adds a namespace attribute or replaces the value of existing namespace + * attribute with the given prefix and value for URI. + * In case prefix is empty will add/update default namespace declaration. + */ + void addOrChangeNamespaceDecl(const XMLCh* prefix, const XMLCh* uri, DOMElementImpl *element) const; + + /** + * Adds a custom namespace in the form "NSx" where x is an integer that + * has not yet used in the document + */ + const XMLCh* addCustomNamespaceDecl(const XMLCh* uri, DOMElementImpl *element) const; + + + /** + * Report an error + */ + void error(const XMLErrs::Codes code, const DOMNode *node) const; + + // + // fDocument - the document we are operating on + // + // fDOMConfiguration - the configuration from the document + // + // fErrorHandler - the errorhandler to be used when reporting errors during normalization + // + // fNSScope - the data stucture that holds the prefix-uri information + // + // fNewNamespaceCount - the number of custom namespace declarations we have created + // + DOMDocumentImpl *fDocument; + DOMConfigurationImpl *fConfiguration; + DOMErrorHandler *fErrorHandler; + InScopeNamespaces *fNSScope; + unsigned int fNewNamespaceCount; + MemoryManager* fMemoryManager; +}; + + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMNotationImpl.cpp b/include/xercesc/dom/impl/DOMNotationImpl.cpp new file mode 100644 index 0000000..b916582 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNotationImpl.cpp @@ -0,0 +1,179 @@ +/* + * 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: DOMNotationImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMDocumentImpl.hpp" +#include "DOMNotationImpl.hpp" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMNotationImpl::DOMNotationImpl(DOMDocument *ownerDoc, const XMLCh *nName) + : fNode(ownerDoc), fName(0), fPublicId(0), fSystemId(0), fBaseURI(0) +{ + fNode.setIsLeafNode(true); + fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(nName); +} + +DOMNotationImpl::DOMNotationImpl(const DOMNotationImpl &other, bool /*deep*/) + : DOMNotation(other), + fNode(other.fNode), + fName(other.fName), + fPublicId(other.fPublicId), + fSystemId(other.fSystemId), + fBaseURI(other.fBaseURI) +{ + fNode.setIsLeafNode(true); +} + + +DOMNotationImpl::~DOMNotationImpl() +{ +} + + +DOMNode *DOMNotationImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (getOwnerDocument(), DOMMemoryManager::NOTATION_OBJECT) DOMNotationImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMNotationImpl::getNodeName() const { + return fName; +} + + +DOMNode::NodeType DOMNotationImpl::getNodeType() const { + return DOMNode::NOTATION_NODE; +} + + + +const XMLCh * DOMNotationImpl::getPublicId() const +{ + return fPublicId; +} + + +const XMLCh * DOMNotationImpl::getSystemId() const +{ + return fSystemId; +} + + +void DOMNotationImpl::setNodeValue(const XMLCh *arg) +{ + fNode.setNodeValue(arg); +} + + +void DOMNotationImpl::setPublicId(const XMLCh *arg) +{ + if(fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR,0, GetDOMNodeMemoryManager); + + fPublicId = ((DOMDocumentImpl *)getOwnerDocument())->cloneString(arg); +} + + +void DOMNotationImpl::setSystemId(const XMLCh *arg) +{ + if(fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR,0, GetDOMNodeMemoryManager); + + fSystemId = ((DOMDocumentImpl *)getOwnerDocument())->cloneString(arg); +} + +void DOMNotationImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + doc->release(this, DOMMemoryManager::NOTATION_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +void DOMNotationImpl::setBaseURI(const XMLCh* baseURI) { + if (baseURI && *baseURI) { + XMLCh* temp = (XMLCh*) ((DOMDocumentImpl *)getOwnerDocument())->allocate((XMLString::stringLen(baseURI) + 9)*sizeof(XMLCh)); + XMLString::fixURI(baseURI, temp); + fBaseURI = temp; + } + else + fBaseURI = 0; +} + +const XMLCh* DOMNotationImpl::getBaseURI() const +{ + return fBaseURI; +} + + + DOMNode* DOMNotationImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); } + DOMNamedNodeMap* DOMNotationImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMNotationImpl::getChildNodes() const {return fNode.getChildNodes (); } + DOMNode* DOMNotationImpl::getFirstChild() const {return fNode.getFirstChild (); } + DOMNode* DOMNotationImpl::getLastChild() const {return fNode.getLastChild (); } + const XMLCh* DOMNotationImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMNotationImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMNotationImpl::getNextSibling() const {return fNode.getNextSibling (); } + const XMLCh* DOMNotationImpl::getNodeValue() const {return fNode.getNodeValue (); } + DOMDocument* DOMNotationImpl::getOwnerDocument() const {return fNode.getOwnerDocument (); } + const XMLCh* DOMNotationImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMNotationImpl::getParentNode() const {return fNode.getParentNode (); } + DOMNode* DOMNotationImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } + bool DOMNotationImpl::hasChildNodes() const {return fNode.hasChildNodes (); } + DOMNode* DOMNotationImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fNode.insertBefore (newChild, refChild); } + void DOMNotationImpl::normalize() {fNode.normalize (); } + DOMNode* DOMNotationImpl::removeChild(DOMNode *oldChild) {return fNode.removeChild (oldChild); } + DOMNode* DOMNotationImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fNode.replaceChild (newChild, oldChild); } + bool DOMNotationImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMNotationImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMNotationImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMNotationImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMNotationImpl::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); } + void* DOMNotationImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMNotationImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + short DOMNotationImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMNotationImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMNotationImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMNotationImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMNotationImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMNotationImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMNotationImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMNotationImpl.hpp b/include/xercesc/dom/impl/DOMNotationImpl.hpp new file mode 100644 index 0000000..888c184 --- /dev/null +++ b/include/xercesc/dom/impl/DOMNotationImpl.hpp @@ -0,0 +1,93 @@ +/* + * 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: DOMNotationImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMNOTATIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMNOTATIONIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +#include "DOMNodeImpl.hpp" + +class DOMDocument; + + +class CDOM_EXPORT DOMNotationImpl: public DOMNotation { +public: + DOMNodeImpl fNode; + + const XMLCh * fName; + const XMLCh * fPublicId; + const XMLCh * fSystemId; + const XMLCh * fBaseURI; + +public: + DOMNotationImpl(DOMDocument *ownerDoc, const XMLCh *); + DOMNotationImpl(const DOMNotationImpl &other, bool deep=false); + + virtual ~DOMNotationImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + // + // The Public Identifier for this Notation. If no public identifier + // was specified, this will be null. + virtual const XMLCh * getPublicId() const; + + // The System Identifier for this Notation. If no system identifier + // was specified, this will be null. + virtual const XMLCh * getSystemId() const; + + // NON-DOM: The Public Identifier for this Notation. If no public + // identifier was specified, this will be null. + virtual void setPublicId(const XMLCh *arg); + + + // NON-DOM: The System Identifier for this Notation. If no system + // identifier was specified, this will be null. + virtual void setSystemId(const XMLCh *arg); + + // NON-DOM: set base uri + virtual void setBaseURI(const XMLCh *arg); + +private: + // unimplemented + DOMNotationImpl& operator= (const DOMNotationImpl& other); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMParentNode.cpp b/include/xercesc/dom/impl/DOMParentNode.cpp new file mode 100644 index 0000000..c1eae24 --- /dev/null +++ b/include/xercesc/dom/impl/DOMParentNode.cpp @@ -0,0 +1,464 @@ +/* + * 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: DOMParentNode.cpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#include +#include +#include + +#include "DOMDocumentImpl.hpp" +#include "DOMRangeImpl.hpp" +#include "DOMNodeIteratorImpl.hpp" +#include "DOMParentNode.hpp" +#include "DOMCasts.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +DOMParentNode::DOMParentNode(DOMDocument *ownerDoc) + : fOwnerDocument(ownerDoc), fFirstChild(0), fChildNodeList(this) +{ +} + +// This only makes a shallow copy, cloneChildren must also be called for a +// deep clone +DOMParentNode::DOMParentNode(const DOMParentNode &other) : + fChildNodeList(this) +{ + this->fOwnerDocument = other.fOwnerDocument; + + // Need to break the association w/ original kids + this->fFirstChild = 0; +} + +void DOMParentNode::changed() +{ + ((DOMDocumentImpl*)fOwnerDocument)->changed(); +} + + +int DOMParentNode::changes() const +{ + return ((DOMDocumentImpl*)fOwnerDocument)->changes(); +} + + +DOMNode * DOMParentNode::appendChild(DOMNode *newChild) +{ + return insertBefore(newChild, 0); +} + + +void DOMParentNode::cloneChildren(const DOMNode *other) { + // for (DOMNode *mykid = other.getFirstChild(); + for (DOMNode *mykid = other->getFirstChild(); + mykid != 0; + mykid = mykid->getNextSibling()) + { + appendChild(mykid->cloneNode(true)); + } +} + +DOMDocument * DOMParentNode::getOwnerDocument() const { + return fOwnerDocument; +} + +// unlike getOwnerDocument this is not overriden by DocumentImpl to return 0 +DOMDocument * DOMParentNode::getDocument() const { + return fOwnerDocument; +} + +void DOMParentNode::setOwnerDocument(DOMDocument* doc) { + fOwnerDocument = doc; +} + +DOMNodeList *DOMParentNode::getChildNodes() const { + const DOMNodeList *ret = &fChildNodeList; + return (DOMNodeList *)ret; // cast off const. +} + + +DOMNode * DOMParentNode::getFirstChild() const { + return fFirstChild; +} + + +DOMNode * DOMParentNode::getLastChild() const +{ + return lastChild(); +} + +DOMNode * DOMParentNode::lastChild() const +{ + // last child is stored as the previous sibling of first child + if (fFirstChild == 0) { + return 0; + } + + DOMChildNode *firstChild = castToChildImpl(fFirstChild); + DOMNode *ret = firstChild->previousSibling; + return ret; +} + + +// +// revisit. Is this function used anywhere? I don't see it. +// +void DOMParentNode::lastChild(DOMNode *node) { + // store lastChild as previous sibling of first child + if (fFirstChild != 0) { + DOMChildNode *firstChild = castToChildImpl(fFirstChild); + firstChild->previousSibling = node; + } +} + + +bool DOMParentNode::hasChildNodes() const +{ + return fFirstChild!=0; +} + + + +DOMNode *DOMParentNode::insertBefore(DOMNode *newChild, DOMNode *refChild) { + //not really in the specs, but better than nothing + if(newChild==NULL) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); + + DOMNodeImpl *thisNodeImpl = castToNodeImpl(this); + if (thisNodeImpl->isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager); + + if (newChild->getOwnerDocument() != fOwnerDocument) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMParentNodeMemoryManager); + + // Prevent cycles in the tree + //only need to do this if the node has children + if(newChild->hasChildNodes()) { + bool treeSafe=true; + for(DOMNode *a=castToNode(this)->getParentNode(); + treeSafe && a!=0; + a=a->getParentNode()) + treeSafe=(newChild!=a); + if(!treeSafe) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); + } + + // refChild must in fact be a child of this node (or 0) + if (refChild!=0 && refChild->getParentNode() != castToNode(this)) + throw DOMException(DOMException::NOT_FOUND_ERR,0, GetDOMParentNodeMemoryManager); + + // if the new node has to be placed before itself, we don't have to do anything + // (even worse, we would crash if we continue, as we assume they are two distinct nodes) + if (refChild!=0 && newChild->isSameNode(refChild)) + return newChild; + + if (newChild->getNodeType() == DOMNode::DOCUMENT_FRAGMENT_NODE) + { + // SLOW BUT SAFE: We could insert the whole subtree without + // juggling so many next/previous pointers. (Wipe out the + // parent's child-list, patch the parent pointers, set the + // ends of the list.) But we know some subclasses have special- + // case behavior they add to insertBefore(), so we don't risk it. + // This approch also takes fewer bytecodes. + + // NOTE: If one of the children is not a legal child of this + // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children + // have been transferred. (Alternative behaviors would be to + // reparent up to the first failure point or reparent all those + // which are acceptable to the target node, neither of which is + // as robust. PR-DOM-0818 isn't entirely clear on which it + // recommends????? + + // No need to check kids for right-document; if they weren't, + // they wouldn't be kids of that DocFrag. + for(DOMNode *kid=newChild->getFirstChild(); // Prescan + kid!=0; + kid=kid->getNextSibling()) + { + if (!DOMDocumentImpl::isKidOK(castToNode(this), kid)) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); + } + while(newChild->hasChildNodes()) // Move + castToNode(this)->insertBefore(newChild->getFirstChild(),refChild); + } + + else if (!DOMDocumentImpl::isKidOK(castToNode(this), newChild)) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); + + else + { + DOMNode *oldparent=newChild->getParentNode(); + if(oldparent!=0) + oldparent->removeChild(newChild); + + // Attach up + castToNodeImpl(newChild)->fOwnerNode = castToNode(this); + castToNodeImpl(newChild)->isOwned(true); + + // Attach before and after + // Note: fFirstChild.previousSibling == lastChild!! + if (fFirstChild == 0) { + // this our first and only child + fFirstChild = newChild; + castToNodeImpl(newChild)->isFirstChild(true); + // castToChildImpl(newChild)->previousSibling = newChild; + DOMChildNode *newChild_ci = castToChildImpl(newChild); + newChild_ci->previousSibling = newChild; + } else { + if (refChild == 0) { + // this is an append + DOMNode *lastChild = castToChildImpl(fFirstChild)->previousSibling; + castToChildImpl(lastChild)->nextSibling = newChild; + castToChildImpl(newChild)->previousSibling = lastChild; + castToChildImpl(fFirstChild)->previousSibling = newChild; + } else { + // this is an insert + if (refChild == fFirstChild) { + // at the head of the list + castToNodeImpl(fFirstChild)->isFirstChild(false); + castToChildImpl(newChild)->nextSibling = fFirstChild; + castToChildImpl(newChild)->previousSibling = castToChildImpl(fFirstChild)->previousSibling; + castToChildImpl(fFirstChild)->previousSibling = newChild; + fFirstChild = newChild; + castToNodeImpl(newChild)->isFirstChild(true); + } else { + // somewhere in the middle + DOMNode *prev = castToChildImpl(refChild)->previousSibling; + castToChildImpl(newChild)->nextSibling = refChild; + castToChildImpl(prev)->nextSibling = newChild; + castToChildImpl(refChild)->previousSibling = newChild; + castToChildImpl(newChild)->previousSibling = prev; + } + } + } + } + + changed(); + + if (fOwnerDocument != 0) { + Ranges* ranges = ((DOMDocumentImpl*)fOwnerDocument)->getRanges(); + if ( ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateRangeForInsertedNode(newChild); + } + } + } + } + + return newChild; +} + + + +DOMNode *DOMParentNode::removeChild(DOMNode *oldChild) +{ + if (castToNodeImpl(this)->isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager); + + if (oldChild == 0 || oldChild->getParentNode() != castToNode(this)) + throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMParentNodeMemoryManager); + + if (fOwnerDocument != 0) { + //notify iterators + NodeIterators* nodeIterators = ((DOMDocumentImpl*)fOwnerDocument)->getNodeIterators(); + if (nodeIterators != 0) { + XMLSize_t sz = nodeIterators->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i) != 0) + nodeIterators->elementAt(i)->removeNode(oldChild); + } + } + } + + //fix other ranges for change before deleting the node + Ranges* ranges = ((DOMDocumentImpl*)fOwnerDocument)->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i) != 0) + ranges->elementAt(i)->updateRangeForDeletedNode(oldChild); + } + } + } + } + + + // Patch linked list around oldChild + // Note: lastChild == fFirstChild->previousSibling + if (oldChild == fFirstChild) { + // removing first child + castToNodeImpl(oldChild)->isFirstChild(false); + fFirstChild = castToChildImpl(oldChild)->nextSibling; + if (fFirstChild != 0) { + castToNodeImpl(fFirstChild)->isFirstChild(true); + castToChildImpl(fFirstChild)->previousSibling = castToChildImpl(oldChild)->previousSibling; + } + } else { + DOMNode *prev = castToChildImpl(oldChild)->previousSibling; + DOMNode *next = castToChildImpl(oldChild)->nextSibling; + castToChildImpl(prev)->nextSibling = next; + if (next == 0) { + // removing last child + castToChildImpl(fFirstChild)->previousSibling = prev; + } else { + // removing some other child in the middle + castToChildImpl(next)->previousSibling = prev; + } + } + + // Remove oldChild's references to tree + castToNodeImpl(oldChild)->fOwnerNode = fOwnerDocument; + castToNodeImpl(oldChild)->isOwned(false); + castToChildImpl(oldChild)->nextSibling = 0; + castToChildImpl(oldChild)->previousSibling = 0; + + changed(); + + return oldChild; +} + + +DOMNode *DOMParentNode::replaceChild(DOMNode *newChild, DOMNode *oldChild) +{ + insertBefore(newChild, oldChild); + // changed() already done. + return removeChild(oldChild); +} + + +DOMNode * DOMParentNode::appendChildFast(DOMNode *newChild) +{ + // This function makes the following assumptions: + // + // - newChild != 0 + // - newChild is not read-only + // - newChild is not a document fragment + // - owner documents of this node and newChild are the same + // - appending newChild to this node cannot result in a cycle + // - DOMDocumentImpl::isKidOK (this, newChild) return true (that is, + // appending newChild to this node results in a valid structure) + // - newChild->getParentNode() is 0 + // - there are no ranges set for this document + // + + // Attach up + castToNodeImpl(newChild)->fOwnerNode = castToNode(this); + castToNodeImpl(newChild)->isOwned(true); + + // Attach before and after + // Note: fFirstChild.previousSibling == lastChild!! + if (fFirstChild != 0) + { + DOMNode *lastChild = castToChildImpl(fFirstChild)->previousSibling; + castToChildImpl(lastChild)->nextSibling = newChild; + castToChildImpl(newChild)->previousSibling = lastChild; + castToChildImpl(fFirstChild)->previousSibling = newChild; + } + else + { + // this our first and only child + fFirstChild = newChild; + castToNodeImpl(newChild)->isFirstChild(true); + // castToChildImpl(newChild)->previousSibling = newChild; + DOMChildNode *newChild_ci = castToChildImpl(newChild); + newChild_ci->previousSibling = newChild; + } + + return newChild; +} + + +//Introduced in DOM Level 2 + +void DOMParentNode::normalize() +{ + DOMNode *kid, *next; + for (kid = fFirstChild; kid != 0; kid = next) + { + next = castToChildImpl(kid)->nextSibling; + + // If kid and next are both Text nodes (but _not_ CDATASection, + // which is a subclass of Text), they can be merged. + if (next != 0 && + kid->getNodeType() == DOMNode::TEXT_NODE && + next->getNodeType() == DOMNode::TEXT_NODE ) + { + ((DOMTextImpl *) kid)->appendData(((DOMTextImpl *) next)->getData()); + // revisit: + // should I release the removed node? + // not released in case user still referencing it externally + removeChild(next); + next = kid; // Don't advance; there might be another. + } + + // Otherwise it might be an Element, which is handled recursively + else + if (kid->getNodeType() == DOMNode::ELEMENT_NODE) + kid->normalize(); + } + + // changed() will have occurred when the removeChild() was done, + // so does not have to be reissued. +} + +//Introduced in DOM Level 3 + +bool DOMParentNode::isEqualNode(const DOMNode* arg) const +{ + if (arg && castToNodeImpl(this)->isSameNode(arg)) + return true; + + if (arg && castToNodeImpl(this)->isEqualNode(arg)) + { + DOMNode *kid, *argKid; + for (kid = fFirstChild, argKid = arg->getFirstChild(); + kid != 0 && argKid != 0; + kid = kid->getNextSibling(), argKid = argKid->getNextSibling()) + { + if (!kid->isEqualNode(argKid)) + return false; + } + return (kid || argKid) ? false : true; + } + return false; +} + + +//Non-standard extension +void DOMParentNode::release() +{ + DOMNode *kid, *next; + for (kid = fFirstChild; kid != 0; kid = next) + { + next = castToChildImpl(kid)->nextSibling; + + // set is Owned false before releasing its child + castToNodeImpl(kid)->isToBeReleased(true); + kid->release(); + } +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMParentNode.hpp b/include/xercesc/dom/impl/DOMParentNode.hpp new file mode 100644 index 0000000..cd571a5 --- /dev/null +++ b/include/xercesc/dom/impl/DOMParentNode.hpp @@ -0,0 +1,114 @@ +/* + * 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: DOMParentNode.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMPARENTNODE_HPP) +#define XERCESC_INCLUDE_GUARD_DOMPARENTNODE_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +/** + * ParentNode provides the capability of having child + * nodes. Not every node in the DOM can have children, so only nodes that can + * should include this class and pay the price for it. + *

+ * While we have a direct reference to the first child, the last child is + * stored as the previous sibling of the first child. First child nodes are + * marked as being so, and getNextSibling hides this fact. + * + **/ + +#include +#include "DOMNodeListImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class DOMChildNode; +class DOMDocument; +class DOMNode; +class DOMNodeList; + +class CDOM_EXPORT DOMParentNode { +public: + DOMDocument *fOwnerDocument; // Document this node belongs to + DOMNode *fFirstChild; + DOMNodeListImpl fChildNodeList; // for GetChildNodes() + +public: + DOMParentNode(DOMDocument *ownerDocument); + DOMParentNode(const DOMParentNode &other); + + DOMDocument * getOwnerDocument() const; + void setOwnerDocument(DOMDocument* doc); + + // Track changes to the node tree structure under this node. An optimization + // for NodeLists. + int changes() const; + void changed(); + + DOMNode* appendChild(DOMNode *newChild); + DOMNodeList* getChildNodes() const; + DOMNode* getFirstChild() const; + DOMNode* getLastChild() const; + bool hasChildNodes() const; + DOMNode* insertBefore(DOMNode *newChild, DOMNode *refChild); + DOMNode* item(unsigned int index) const; + DOMNode* removeChild(DOMNode *oldChild); + DOMNode* replaceChild(DOMNode *newChild, DOMNode *oldChild); + + // Append certain types of nodes fast. Used to speed up XML to DOM + // parsing. See the function implementation for detail. + virtual DOMNode* appendChildFast(DOMNode *newChild); + + //Introduced in DOM Level 2 + void normalize(); + + //Introduced in DOM Level 3 + bool isEqualNode(const DOMNode* arg) const; + + // NON-DOM + // unlike getOwnerDocument this never returns null, even for Document nodes + DOMDocument * getDocument() const; + void release(); + + +public: + void cloneChildren(const DOMNode *other); + DOMNode * lastChild() const; + void lastChild(DOMNode *); + +private: + // unimplemented + DOMParentNode& operator= (const DOMParentNode& other); +}; + +#define GetDOMParentNodeMemoryManager GET_DIRECT_MM(fOwnerDocument) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp b/include/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp new file mode 100644 index 0000000..7f37f08 --- /dev/null +++ b/include/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp @@ -0,0 +1,215 @@ +/* + * 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: DOMProcessingInstructionImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ + +#include "DOMProcessingInstructionImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMStringPool.hpp" +#include "DOMRangeImpl.hpp" + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMProcessingInstructionImpl::DOMProcessingInstructionImpl(DOMDocument *ownerDoc, + const XMLCh *targt, + const XMLCh *dat) + : fNode(ownerDoc), fCharacterData(ownerDoc, dat), fBaseURI(0) +{ + fNode.setIsLeafNode(true); + this->fTarget = ((DOMDocumentImpl *)ownerDoc)->cloneString(targt); +} + + +DOMProcessingInstructionImpl::DOMProcessingInstructionImpl( + const DOMProcessingInstructionImpl &other, + bool /*deep*/) + : DOMProcessingInstruction(other), + fNode(other.fNode), + fChild(other.fChild), + fCharacterData(other.fCharacterData), + fTarget(other.fTarget), + fBaseURI(other.fBaseURI) +{ + fNode.setIsLeafNode(true); +} + + +DOMProcessingInstructionImpl::~DOMProcessingInstructionImpl() +{ +} + + +DOMNode *DOMProcessingInstructionImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (getOwnerDocument(), DOMMemoryManager::PROCESSING_INSTRUCTION_OBJECT) DOMProcessingInstructionImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMProcessingInstructionImpl::getNodeName() const +{ + return fTarget; +} + + +DOMNode::NodeType DOMProcessingInstructionImpl::getNodeType() const { + return DOMNode::PROCESSING_INSTRUCTION_NODE; +} + + +/** A PI's "target" states what processor channel the PI's data +should be directed to. It is defined differently in HTML and XML. + + In XML, a PI's "target" is the first (whitespace-delimited) token + following the "release(this, DOMMemoryManager::PROCESSING_INSTRUCTION_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +void DOMProcessingInstructionImpl::setBaseURI(const XMLCh* baseURI) { + this->fBaseURI = ((DOMDocumentImpl *)getOwnerDocument())->cloneString(baseURI); +} + +const XMLCh* DOMProcessingInstructionImpl::getBaseURI() const +{ + return fBaseURI? fBaseURI : fNode.fOwnerNode->getBaseURI(); +} + +// Non standard extension for the range to work +DOMProcessingInstruction *DOMProcessingInstructionImpl::splitText(XMLSize_t offset) +{ + if (fNode.isReadOnly()) + { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + XMLSize_t len = fCharacterData.fDataBuf->getLen(); + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager); + + DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument(); + DOMProcessingInstruction *newText = + doc->createProcessingInstruction( + fTarget, this->substringData(offset, len - offset)); + + DOMNode *parent = getParentNode(); + if (parent != 0) + parent->insertBefore(newText, getNextSibling()); + + fCharacterData.fDataBuf->chop(offset); + + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateSplitInfo( this, newText, offset); + } + } + } + } + + return newText; +} + +// +// Delegation stubs for inherited functions +// + DOMNode* DOMProcessingInstructionImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); } + DOMNamedNodeMap* DOMProcessingInstructionImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMProcessingInstructionImpl::getChildNodes() const {return fNode.getChildNodes (); } + DOMNode* DOMProcessingInstructionImpl::getFirstChild() const {return fNode.getFirstChild (); } + DOMNode* DOMProcessingInstructionImpl::getLastChild() const {return fNode.getLastChild (); } + const XMLCh* DOMProcessingInstructionImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMProcessingInstructionImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMProcessingInstructionImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMProcessingInstructionImpl::getNodeValue() const {return fCharacterData.getNodeValue (); } + DOMDocument* DOMProcessingInstructionImpl::getOwnerDocument() const {return fNode.getOwnerDocument (); } + const XMLCh* DOMProcessingInstructionImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMProcessingInstructionImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMProcessingInstructionImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMProcessingInstructionImpl::hasChildNodes() const {return fNode.hasChildNodes (); } + DOMNode* DOMProcessingInstructionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fNode.insertBefore (newChild, refChild); } + void DOMProcessingInstructionImpl::normalize() {fNode.normalize (); } + DOMNode* DOMProcessingInstructionImpl::removeChild(DOMNode *oldChild) {return fNode.removeChild (oldChild); } + DOMNode* DOMProcessingInstructionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fNode.replaceChild (newChild, oldChild); } + bool DOMProcessingInstructionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMProcessingInstructionImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMProcessingInstructionImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMProcessingInstructionImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMProcessingInstructionImpl::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); } + void* DOMProcessingInstructionImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMProcessingInstructionImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + short DOMProcessingInstructionImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMProcessingInstructionImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMProcessingInstructionImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMProcessingInstructionImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMProcessingInstructionImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMProcessingInstructionImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMProcessingInstructionImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + +// +// Delegation of CharacerData functions. +// + + + const XMLCh* DOMProcessingInstructionImpl::getData() const {return fCharacterData.getData();} + void DOMProcessingInstructionImpl::deleteData(XMLSize_t offset, XMLSize_t count) + {fCharacterData.deleteData(this, offset, count);} + const XMLCh* DOMProcessingInstructionImpl::substringData(XMLSize_t offset, XMLSize_t count) const + {return fCharacterData.substringData(this, offset, count);} + void DOMProcessingInstructionImpl::setData(const XMLCh *data) {fCharacterData.setData(this, data);} + void DOMProcessingInstructionImpl::setNodeValue(const XMLCh *nodeValue) {fCharacterData.setNodeValue (this, nodeValue); } + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMProcessingInstructionImpl.hpp b/include/xercesc/dom/impl/DOMProcessingInstructionImpl.hpp new file mode 100644 index 0000000..4d90d15 --- /dev/null +++ b/include/xercesc/dom/impl/DOMProcessingInstructionImpl.hpp @@ -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: DOMProcessingInstructionImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMPROCESSINGINSTRUCTIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMPROCESSINGINSTRUCTIONIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include +#include +#include "DOMCharacterDataImpl.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMChildNode.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class DocumentImpl; + + +class CDOM_EXPORT DOMProcessingInstructionImpl: public DOMProcessingInstruction { +protected: + DOMNodeImpl fNode; + DOMChildNode fChild; + // use fCharacterData to store its data so that those character utitlites can be used + DOMCharacterDataImpl fCharacterData; + + XMLCh *fTarget; + const XMLCh *fBaseURI; + +public: + DOMProcessingInstructionImpl(DOMDocument *ownerDoc, + const XMLCh * target, + const XMLCh *data); + DOMProcessingInstructionImpl(const DOMProcessingInstructionImpl &other, + bool deep=false); + virtual ~DOMProcessingInstructionImpl(); + +public: + // Declare all of the functions from DOMNode. + DOMNODE_FUNCTIONS; + +public: + virtual const XMLCh *getData() const; + virtual const XMLCh *getTarget() const; + virtual void setData(const XMLCh *arg); + + // NON-DOM: set base uri + virtual void setBaseURI(const XMLCh* baseURI); + + // Non standard extension for the range to work + void deleteData(XMLSize_t offset, XMLSize_t count); + const XMLCh* substringData(XMLSize_t offset, XMLSize_t count) const; + DOMProcessingInstruction* splitText(XMLSize_t offset); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMProcessingInstructionImpl & operator = (const DOMProcessingInstructionImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/dom/impl/DOMRangeImpl.cpp b/include/xercesc/dom/impl/DOMRangeImpl.cpp new file mode 100644 index 0000000..2fece60 --- /dev/null +++ b/include/xercesc/dom/impl/DOMRangeImpl.cpp @@ -0,0 +1,2115 @@ +/* + * 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: DOMRangeImpl.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#include "DOMRangeImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include "DOMDocumentFragmentImpl.hpp" +#include "DOMCommentImpl.hpp" +#include "DOMProcessingInstructionImpl.hpp" +#include "DOMCasts.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +//--------------------- +// C'tor and D'tor +//--------------------- + +DOMRangeImpl::DOMRangeImpl(DOMDocument* doc, MemoryManager* const manager) + + : fStartContainer(doc), + fStartOffset(0), + fEndContainer(doc), + fEndOffset(0), + fCollapsed(true), + fDocument(doc), + fDetached(false), + fRemoveChild(0), + fMemoryManager(manager) +{ +} + +DOMRangeImpl::DOMRangeImpl(const DOMRangeImpl& other) +: DOMRange(other), + fStartContainer(other.fStartContainer), + fStartOffset(other.fStartOffset), + fEndContainer(other.fEndContainer), + fEndOffset(other.fEndOffset), + fCollapsed(other.fCollapsed), + fDocument(other.fDocument), + fDetached(other.fDetached), + fRemoveChild(other.fRemoveChild), + fMemoryManager(other.fMemoryManager) +{ +} + +DOMRangeImpl::~DOMRangeImpl() +{ +} + + +//------------------------------- +// Public getter functions +//------------------------------- + + +DOMNode* DOMRangeImpl::getStartContainer() const +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + return fStartContainer; +} + +XMLSize_t DOMRangeImpl::getStartOffset() const +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + return fStartOffset; +} + +DOMNode* DOMRangeImpl::getEndContainer() const +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + return fEndContainer; +} + +XMLSize_t DOMRangeImpl::getEndOffset() const +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + return fEndOffset; +} + + + +bool DOMRangeImpl::getCollapsed() const +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + return ((fStartContainer == fEndContainer) + && (fStartOffset == fEndOffset)); +} + +//------------------------------- +// Public setter functions +//------------------------------- + +void DOMRangeImpl::setStartContainer(const DOMNode* node) +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + fStartContainer = (DOMNode*) node; +} + +void DOMRangeImpl::setStartOffset(XMLSize_t offset) +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + fStartOffset = offset; +} + +void DOMRangeImpl::setEndContainer(const DOMNode* node) +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + fEndContainer = (DOMNode*) node; + +} + +void DOMRangeImpl::setEndOffset(XMLSize_t offset) +{ + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + fEndOffset = offset; +} + +void DOMRangeImpl::setStart(const DOMNode* refNode, XMLSize_t offset) +{ + validateNode(refNode); + checkIndex(refNode, offset); + + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) { + collapse(true); //collapse the range positions to start + fCollapsed = true; + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + } + + fStartContainer = (DOMNode*) refNode; + fStartOffset = offset; + + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fEndContainer)) + collapse(true); + + //compare the start and end boundary point + //collapse if start point is after the end point + if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) + collapse(true); //collapse the range positions to start + else + fCollapsed = false; +} + +void DOMRangeImpl::setEnd(const DOMNode* refNode, XMLSize_t offset) +{ + validateNode(refNode); + checkIndex(refNode, offset); + + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) { + collapse(false); //collapse the range positions to end + fCollapsed = true; + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + } + + fEndContainer = (DOMNode*) refNode; + fEndOffset = offset; + + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fStartContainer)) + collapse(false); + + //compare the start and end boundary point + //collapse if start point is after the end point + if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) + collapse(false); //collapse the range positions to end + else + fCollapsed = false; +} + +void DOMRangeImpl::setStartBefore(const DOMNode* refNode) +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + if ( !hasLegalRootContainer(refNode) || !isLegalContainedNode(refNode)) { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) { + collapse(true); //collapse the range positions to start + fCollapsed = true; + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + } + + fStartContainer = refNode->getParentNode(); + XMLSize_t i = 0; + for (DOMNode* n = (DOMNode*) refNode; n!=0; n = n->getPreviousSibling()) { + i++; + } + if (i == 0) + fStartOffset = 0; + else + fStartOffset = i-1; + + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fEndContainer)) + collapse(true); + + //compare the start and end boundary point + //collapse if start point is after the end point + if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) + collapse(true); //collapse the range positions to start + else + fCollapsed = false; +} + +void DOMRangeImpl::setStartAfter(const DOMNode* refNode) +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + if ( !hasLegalRootContainer(refNode) || !isLegalContainedNode(refNode)) { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) { + collapse(true); //collapse the range positions to start + fCollapsed = true; + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + } + + fStartContainer = refNode->getParentNode(); + XMLSize_t i = 0; + for (DOMNode* n = (DOMNode*) refNode; n!=0; n = n->getPreviousSibling()) { + i++; + } + + fStartOffset = i; + + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fEndContainer)) + collapse(true); + + //compare the start and end boundary point + //collapse if start point is after the end point + if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) + collapse(true); //collapse the range positions to start + else + fCollapsed = false; +} + +void DOMRangeImpl::setEndBefore(const DOMNode* refNode) +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + if ( !hasLegalRootContainer(refNode) || !isLegalContainedNode(refNode)) { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) { + collapse(false); //collapse the range positions to end + fCollapsed = true; + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + } + + fEndContainer = refNode->getParentNode(); + XMLSize_t i = 0; + for (DOMNode* n = (DOMNode*) refNode; n!=0; n = n->getPreviousSibling(), i++) ; + + if (i< 1) + fEndOffset = 0; + else + fEndOffset = i-1; + + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fStartContainer)) + collapse(false); + + //compare the start and end boundary point + //collapse if start point is after the end point + if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) + collapse(false); //collapse the range positions to end + else + fCollapsed = false; +} + +void DOMRangeImpl::setEndAfter(const DOMNode* refNode) +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + if ( !hasLegalRootContainer(refNode) || !isLegalContainedNode(refNode)) { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) { + collapse(false); //collapse the range positions to end + fCollapsed = true; + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + } + + fEndContainer = refNode->getParentNode(); + XMLSize_t i = 0; + for (DOMNode* n = (DOMNode*) refNode; n!=0; n = n->getPreviousSibling(), i++) ; + + if (i ==0) + fEndOffset = 0; + else + fEndOffset = i; + + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fStartContainer)) + collapse(false); + + //compare the start and end boundary point + //collapse if start point is after the end point + if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) + collapse(false); //collapse the range positions to end + else + fCollapsed = false; +} +//------------------------------- +// Public Misc. functions +//------------------------------- +void DOMRangeImpl::detach() +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + ((DOMDocumentImpl *)fDocument)->removeRange(this); + + fDetached = true; + + //0ify nodes + fStartContainer = 0; + fStartOffset = 0; + fEndContainer = 0; + fEndOffset = 0; + fCollapsed = true; + + fRemoveChild = 0; +} + +void DOMRangeImpl::collapse(bool toStart) +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + if (toStart) { + fEndContainer = fStartContainer; + fEndOffset = fStartOffset; + } else { + fStartContainer = fEndContainer; + fStartOffset = fEndOffset; + } + fCollapsed = true; +} + +void DOMRangeImpl::selectNode(const DOMNode* refNode) +{ + validateNode(refNode); + if ( !isLegalContainedNode(refNode)) { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + //First check for the text type node + short type = refNode->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + //The node itself is the container. + fStartContainer = (DOMNode*) refNode; + fEndContainer = (DOMNode*) refNode; + + //Select all the contents of the node + fStartOffset = 0; + if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) + fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)refNode)->getData()); + else + fEndOffset = ((DOMText *)refNode)->getLength(); + return; + } + + DOMNode* parent = refNode->getParentNode(); + if (parent != 0 ) // REVIST: what to do if it IS 0? + { + fStartContainer = parent; + fEndContainer = parent; + + XMLSize_t i = 0; + for (DOMNode* n = parent->getFirstChild(); n!=0 && n!=refNode; n = n->getNextSibling()) { + i++; + } + + fStartOffset = i; + fEndOffset = fStartOffset+1; + } +} + +void DOMRangeImpl::selectNodeContents(const DOMNode* node) +{ + validateNode(node); + + fStartContainer = (DOMNode*) node; + fEndContainer = (DOMNode*) node; + + fStartOffset = 0; + short type = node->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE)) { + + fEndOffset = ((DOMText *)node)->getLength(); + return; + } + if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) { + fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)node)->getData()); + return; + } + + DOMNode* first = node->getFirstChild(); + if (first == 0) { + fEndOffset = 0; + return; + } + XMLSize_t i = 0; + for (DOMNode* n = first; n!=0; n = n->getNextSibling()) { + i++; + } + fEndOffset = i; +} + +void DOMRangeImpl::surroundContents(DOMNode* newParent) +{ + if (newParent==0) return; + + //check for elimination criteria + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + if (newParent->getOwnerDocument() !=fDocument) { + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + + int type = newParent->getNodeType(); + if ( !isLegalContainedNode(newParent) + || type == DOMNode::DOCUMENT_TYPE_NODE) + { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + + DOMNode* realStart = fStartContainer; + DOMNode* realEnd = fEndContainer; + + type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + realStart = fStartContainer->getParentNode(); + } + type = fEndContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + realEnd = fEndContainer->getParentNode(); + } + + if (realStart != realEnd) { + throw DOMRangeException( + DOMRangeException::BAD_BOUNDARYPOINTS_ERR, 0, fMemoryManager); + } + + DOMDocumentFragment* frag = (DOMDocumentFragment*) extractContents(); + insertNode(newParent); + newParent->appendChild(frag); + selectNode(newParent); +} + + +short DOMRangeImpl::compareBoundaryPoints(DOMRange::CompareHow how, const DOMRange* srcRange) const +{ + if (fDocument != ((DOMRangeImpl*)srcRange)->fDocument) { + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + DOMNode* pointA; + DOMNode* pointB; + XMLSize_t offsetA, offsetB; + + switch (how) + { + case (DOMRange::START_TO_START) : + pointB = srcRange->getStartContainer(); + pointA = fStartContainer; + offsetB = srcRange->getStartOffset(); + offsetA = fStartOffset; + break; + case (DOMRange::START_TO_END) : + pointB = srcRange->getStartContainer(); + pointA = fEndContainer; + offsetB = srcRange->getStartOffset(); + offsetA = fEndOffset; + break; + case (DOMRange::END_TO_START) : + pointB = srcRange->getEndContainer(); + pointA = fStartContainer; + offsetB = srcRange->getEndOffset(); + offsetA = fStartOffset; + break; + case (DOMRange::END_TO_END) : + pointB = srcRange->getEndContainer(); + pointA = fEndContainer; + offsetB = srcRange->getEndOffset(); + offsetA = fEndOffset; + break; + default: + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + // case 1: same container + if (pointA == pointB) { + if (offsetA < offsetB) return -1; //A before B + if (offsetA == offsetB) return 0; //A equal to B + return 1; // A after B + } + // case 2: Child C of container A is ancestor of B + for (DOMNode* node = pointA->getFirstChild(); node != 0; node=node->getNextSibling()) { + if (isAncestorOf(node, pointB)) { + XMLSize_t index = indexOf(node, pointA); + if (offsetA <= index) return -1; + return 1; + } + } + // case 3: Child C of container B is ancestor of A + for (DOMNode* nd = pointB->getFirstChild(); nd != 0; nd=nd->getNextSibling()) { + if (isAncestorOf(nd, pointA)) { + XMLSize_t index = indexOf(nd, pointB); + if (index < offsetB ) return -1; + return 1; //B strictly before A + } + } + + // case 4: preorder traversal of context tree. + // Instead of literally walking the context tree in pre-order, + // we use relative node depth walking which is usually faster + + int depthDiff = 0; + DOMNode* n = 0; + for ( n = pointB; n != 0; n = n->getParentNode() ) + depthDiff++; + for ( n = pointA; n != 0; n = n->getParentNode() ) + depthDiff--; + while (depthDiff > 0) { + pointB = pointB->getParentNode(); + depthDiff--; + } + while (depthDiff < 0) { + pointA = pointA->getParentNode(); + depthDiff++; + } + for (DOMNode* pB = pointB->getParentNode(), + *pA = pointA->getParentNode(); + pB != pA; + pB = pB->getParentNode(), pA = pA->getParentNode() ) + { + pointB = pB; + pointA = pA; + } + for ( n = pointB->getNextSibling(); + n != 0; + n = n->getNextSibling() ) + { + if (n == pointA) { + return 1; + } + } + return -1; +} + + +void DOMRangeImpl:: deleteContents() +{ + traverseContents(DELETE_CONTENTS); +} + +DOMDocumentFragment* DOMRangeImpl::extractContents() +{ + checkReadOnly(fStartContainer, fEndContainer, fStartOffset, fEndOffset); + return traverseContents(EXTRACT_CONTENTS); +} + +DOMDocumentFragment* DOMRangeImpl::cloneContents() const +{ + // cast off const. + return ((DOMRangeImpl *)this)->traverseContents(CLONE_CONTENTS); +} + + +void DOMRangeImpl::insertNode(DOMNode* newNode) +{ + if (newNode == 0) return; //don't have to do anything + + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + int type = newNode->getNodeType(); + if (type == DOMNode::ATTRIBUTE_NODE + || type == DOMNode::ENTITY_NODE + || type == DOMNode::NOTATION_NODE + || type == DOMNode::DOCUMENT_NODE) + { + throw DOMRangeException( + DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } + + // Prevent cycles in the tree. + //isKidOK() is not checked here as its taken care by insertBefore() function + if (isAncestorOf( newNode, fStartContainer)) { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0, fMemoryManager); + } + + for (DOMNode* aNode = fStartContainer; aNode!=0; aNode = aNode->getParentNode()) { + if (castToNodeImpl(newNode)->isReadOnly()) { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, fMemoryManager); + } + } + + if (fDocument != newNode->getOwnerDocument()) { + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); + } + + + DOMNode* parent; + DOMNode* next; + + type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + + //set 'parent' and 'next' here + parent = fStartContainer->getParentNode(); + + //split the text nodes + if (fStartOffset > 0) { + if (type == DOMNode::COMMENT_NODE) + ((DOMCommentImpl*)fStartContainer)->splitText(fStartOffset); + else if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) + ((DOMProcessingInstructionImpl*)fStartContainer)->splitText(fStartOffset); + else + ((DOMText*)fStartContainer)->splitText(fStartOffset); + } + + //update the new start information later. After inserting the first newNode + if (fStartOffset == 0) + next = fStartContainer; + else + next = fStartContainer->getNextSibling(); + + } // end of text handling + else { + parent = fStartContainer; + + next = fStartContainer->getFirstChild(); + for(XMLSize_t i = 0; (i < fStartOffset) && (next != 0); i++) { + next=next->getNextSibling(); + } + } + + if (parent != 0) { + if (next != 0) + parent->insertBefore(newNode, next); + else + parent->appendChild(newNode); + } +} + +DOMRange* DOMRangeImpl::cloneRange() const +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + DOMRange* range = fDocument->createRange(); + range->setStart(fStartContainer, fStartOffset); + range->setEnd(fEndContainer, fEndOffset); + + return range; +} + +const XMLCh* DOMRangeImpl::toString() const +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + if ((fStartContainer == fEndContainer) && (fEndOffset == fStartOffset)) + return XMLUni::fgZeroLenString; + + DOMNode* node = fStartContainer; + DOMNode* stopNode = fEndContainer; + + XMLBuffer retStringBuf(1023, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + short type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + if (fStartContainer == fEndContainer) { + XMLCh* tempString; + XMLCh temp[4000]; + if ((fEndOffset-fStartOffset) >= 3999) + tempString = (XMLCh*) fMemoryManager->allocate + ( + (fEndOffset - fStartOffset + 1) * sizeof(XMLCh) + );//new XMLCh[fEndOffset-fStartOffset+1]; + else + tempString = temp; + + XMLString::subString(tempString, fStartContainer->getNodeValue(), fStartOffset, fEndOffset, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + const XMLCh* retString = ((DOMDocumentImpl *)fDocument)->getPooledString(tempString); + + if ((fEndOffset-fStartOffset) >= 3999) + fMemoryManager->deallocate(tempString);//delete[] tempString; + + return retString; + } else { + XMLSize_t length = XMLString::stringLen(fStartContainer->getNodeValue()); + if (length != fStartOffset) { + + XMLCh* tempString; + XMLCh temp[4000]; + if ((length - fStartOffset) >= 3999) + tempString = (XMLCh*) fMemoryManager->allocate + ( + (length - fStartOffset + 1) * sizeof(XMLCh) + );//new XMLCh[length - fStartOffset+1]; + else + tempString = temp; + + XMLString::subString(tempString, fStartContainer->getNodeValue(), fStartOffset, length, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + retStringBuf.append(tempString); + + if ((length - fStartOffset) >= 3999) + fMemoryManager->deallocate(tempString);//delete[] tempString; + } + + node = nextNode(node, true); + } + }else { //fStartContainer is not a TextNode + node=node->getFirstChild(); + if (fStartOffset>0) { //find a first node within a range, specified by fStartOffset + XMLSize_t counter = 0; + while (countergetNextSibling(); + counter++; + } + } + if (node == 0) { + node = nextNode(fStartContainer,false); + } + } + + type = fEndContainer->getNodeType(); + if((type != DOMNode::TEXT_NODE + && type != DOMNode::CDATA_SECTION_NODE + && type != DOMNode::COMMENT_NODE + && type != DOMNode::PROCESSING_INSTRUCTION_NODE)) { + int i=(int)fEndOffset; + stopNode = fEndContainer->getFirstChild(); + while( i>0 && stopNode!=0 ){ + --i; + stopNode = stopNode->getNextSibling(); + } + if ( stopNode == 0 ) + stopNode = nextNode( fEndContainer, false ); + } + + while (node != stopNode) { //look into all kids of the Range + if (node == 0) break; + type = node->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + retStringBuf.append(node->getNodeValue()); + } + node = nextNode(node, true); + } + + type = fEndContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + + if (fEndOffset != 0) { + + XMLCh* tempString; + XMLCh temp[4000]; + if (fEndOffset >= 3999) + tempString = (XMLCh*) fMemoryManager->allocate + ( + (fEndOffset+1) * sizeof(XMLCh) + );//new XMLCh[fEndOffset+1]; + else + tempString = temp; + + XMLString::subString(tempString, fEndContainer->getNodeValue(), 0, fEndOffset, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + retStringBuf.append(tempString); + + if (fEndOffset >= 3999) + fMemoryManager->deallocate(tempString);//delete[] tempString; + } + } + return ((DOMDocumentImpl *)fDocument)->getPooledString(retStringBuf.getRawBuffer()); +} + +DOMDocument* DOMRangeImpl::getDocument() +{ + return fDocument; +} + +const DOMNode* DOMRangeImpl::getCommonAncestorContainer() const +{ + return commonAncestorOf(fStartContainer, fEndContainer); + +} + +void DOMRangeImpl::release() +{ + detach(); + // for performance reason, do not recycle pointer + // chance that this is allocated again and again is not usual +} + +//--------------------- +//private functions +//--------------------- + +bool DOMRangeImpl::isValidAncestorType(const DOMNode* node) const +{ + for (DOMNode* aNode = (DOMNode*) node; aNode!=0; aNode = aNode->getParentNode()) { + short type = aNode->getNodeType(); + if ( type == DOMNode::ENTITY_NODE + || type == DOMNode::NOTATION_NODE + || type == DOMNode::DOCUMENT_TYPE_NODE) + return false; + } + return true; +} + +bool DOMRangeImpl::isAncestorOf(const DOMNode* a, const DOMNode* b) { + for (DOMNode* node = (DOMNode*) b; node != 0; node=node->getParentNode()) { + if (node == a) return true; + } + return false; +} + +bool DOMRangeImpl::hasLegalRootContainer(const DOMNode* node) const { + if ( node==0 ) + return false; + + DOMNode* rootContainer = (DOMNode*)node; + for (; rootContainer->getParentNode()!=0; rootContainer = rootContainer->getParentNode()) + ; + + switch( rootContainer->getNodeType() ) { + case DOMNode::ATTRIBUTE_NODE: + case DOMNode::DOCUMENT_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + return true; + default: + return false; + } +} + +bool DOMRangeImpl::isLegalContainedNode(const DOMNode* node ) const { + if ( node==0 ) + return false; + switch( node->getNodeType() ) + { + case DOMNode::DOCUMENT_NODE: + case DOMNode::DOCUMENT_FRAGMENT_NODE: + case DOMNode::ATTRIBUTE_NODE: + case DOMNode::ENTITY_NODE: + case DOMNode::NOTATION_NODE: + return false; + default: + return true; + } +} + +XMLSize_t DOMRangeImpl::indexOf(const DOMNode* child, const DOMNode* parent) const +{ + XMLSize_t i = 0; + if (child->getParentNode() != parent) return (XMLSize_t)-1; + for(DOMNode* node = child->getPreviousSibling(); node!= 0; node=node->getPreviousSibling()) { + i++; + } + return i; +} + +void DOMRangeImpl::validateNode(const DOMNode* node) const +{ + if( fDetached) { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + } + + if ( !isValidAncestorType(node)) { + throw DOMRangeException(DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); + } +} + + +const DOMNode* DOMRangeImpl::commonAncestorOf(const DOMNode* pointA, const DOMNode* pointB) const +{ + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + + //if the containers are same then it itself is its common ancestor. + if (pointA == pointB) + return pointA; + + typedef RefVectorOf VectorNodes; + VectorNodes startV(1, false, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + DOMNode* node; + + for (node=(DOMNode*)pointA; node != 0; node=node->getParentNode()) + { + startV.addElement(node); + } + VectorNodes endV(1, false, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + for (node=(DOMNode*)pointB; node != 0; node=node->getParentNode()) + { + endV.addElement(node); + } + + XMLSize_t s = startV.size(); + XMLSize_t e = endV.size(); + + DOMNode* commonAncestor = 0; + + while (s>0 && e>0) { + if (startV.elementAt(s-1) == endV.elementAt(e-1)) { + commonAncestor = startV.elementAt(s-1); + } + else break; + --s; + --e; + } + + return commonAncestor; +} + +void DOMRangeImpl::checkIndex(const DOMNode* node, XMLSize_t offset) const +{ + short type = node->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { + if (offset > XMLString::stringLen(node->getNodeValue())) + throw DOMException( DOMException::INDEX_SIZE_ERR, 0, fMemoryManager ); + else return; + } + + DOMNode* child = node->getFirstChild(); + XMLSize_t i = 0; + for (; child != 0; i++) { + child = child->getNextSibling(); + } + if (i < offset) { + throw DOMException( DOMException::INDEX_SIZE_ERR, 0, fMemoryManager ); + } + +} + +DOMNode* DOMRangeImpl::nextNode(const DOMNode* node, bool visitChildren) const +{ + + if (node == 0) return 0; + + DOMNode* result; + if (visitChildren) { + result = node->getFirstChild(); + if (result != 0) { + return result; + } + } + + // if hasSibling, return sibling + result = node->getNextSibling(); + if (result != 0) { + return result; + } + + + // return parent's 1st sibling. + DOMNode* parent = node->getParentNode(); + + + while ( (parent != 0) && (parent != fDocument) ) + { + result = parent->getNextSibling(); + if (result != 0) { + return result; + } else { + parent = parent->getParentNode(); + } + + } + // end of list, return 0 + return 0; +} + + +/** This is the master routine invoked to visit the nodes +* selected by this range. For each such node, different +* actions are taken depending on the value of the TraversalType argument. +*/ +DOMDocumentFragment* DOMRangeImpl::traverseContents(TraversalType how) +{ + if (fDetached) + throw DOMException(DOMException::INVALID_STATE_ERR, 0, fMemoryManager); + + if (fStartContainer == 0 || fEndContainer == 0) { + return 0; // REVIST: Throw exception? + } + + /* Traversal is accomplished by first determining the + relationship between the endpoints of the range. + For each of four significant relationships, we will + delegate the traversal call to a method that + can make appropriate assumptions. + */ + + // case 1: same container + if ( fStartContainer == fEndContainer ) + return traverseSameContainer( how ); + + // case 2: Child C of start container is ancestor of end container + // This can be quickly tested by walking the parent chain of + // end container + int endContainerDepth = 0; + for ( DOMNode* c = fEndContainer, *p = c->getParentNode(); + p != 0; + c = p, p = p->getParentNode()) + { + if (p == fStartContainer) + return traverseCommonStartContainer( c, how ); + ++endContainerDepth; + } + + // case 3: Child C of end container is ancestor of start container + // This can be quickly tested by walking the parent chain of A + int startContainerDepth = 0; + for ( DOMNode* c2 = fStartContainer, *p2 = c2->getParentNode(); + p2 != 0; + c2 = p2, p2 = p2->getParentNode()) + { + if (p2 == fEndContainer) + return traverseCommonEndContainer( c2, how ); + ++startContainerDepth; + } + + // case 4: There is a common ancestor container. Find the + // ancestor siblings that are children of that container. + int depthDiff = startContainerDepth - endContainerDepth; + + DOMNode* startNode = fStartContainer; + while (depthDiff > 0) { + startNode = startNode->getParentNode(); + depthDiff--; + } + + DOMNode* endNode = fEndContainer; + while (depthDiff < 0) { + endNode = endNode->getParentNode(); + depthDiff++; + } + + // ascend the ancestor hierarchy until we have a common parent. + for( DOMNode* sp = startNode->getParentNode(), *ep = endNode->getParentNode(); + sp!=ep; + sp = sp->getParentNode(), ep = ep->getParentNode() ) + { + startNode = sp; + endNode = ep; + } + return traverseCommonAncestors( startNode, endNode, how ); + } + +/** + * Visits the nodes selected by this range when we know + * a-priori that the start and end containers are the same. + * + */ +DOMDocumentFragment* DOMRangeImpl::traverseSameContainer( int how ) +{ + DOMDocumentFragment* frag = 0; + if ( how!=DELETE_CONTENTS) + frag = fDocument->createDocumentFragment(); + + // If selection is empty, just return the fragment + if ( fStartOffset==fEndOffset ) + return frag; + + DOMNode* cloneCurrent = 0; + + // Text node needs special case handling + short type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + cloneCurrent = fStartContainer->cloneNode(false); + if (fEndOffset == fStartOffset) { + cloneCurrent->setNodeValue(XMLUni::fgZeroLenString); + } + else { + XMLCh* tempString; + XMLCh temp[4000]; + if (fEndOffset >= 3999) + tempString = (XMLCh*) fMemoryManager->allocate + ( + (fEndOffset+1) * sizeof(XMLCh) + );//new XMLCh[fEndOffset+1]; + else + tempString = temp; + + XMLString::subString(tempString, cloneCurrent->getNodeValue(), fStartOffset, fEndOffset, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + cloneCurrent->setNodeValue(((DOMDocumentImpl *)fDocument)->getPooledString(tempString)); + + if (fEndOffset >= 3999) + fMemoryManager->deallocate(tempString);//delete[] tempString; + } + + // set the original text node to its new value + if ( how != CLONE_CONTENTS ) { + if(type == DOMNode::PROCESSING_INSTRUCTION_NODE) { + ((DOMProcessingInstructionImpl*)fStartContainer)->deleteData(fStartOffset, fEndOffset-fStartOffset); + } + else + ((DOMCharacterData*)fStartContainer)->deleteData(fStartOffset, fEndOffset-fStartOffset); + } + if ( how != DELETE_CONTENTS) + frag->appendChild(cloneCurrent); + } + else { + // Copy nodes between the start/end offsets. + DOMNode* n = getSelectedNode( fStartContainer, (int)fStartOffset ); + int cnt = (int)fEndOffset - (int)fStartOffset; + while( cnt > 0 && n) + { + DOMNode* sibling = n->getNextSibling(); + DOMNode* xferNode = traverseFullySelected( n, how ); + if ( frag!=0 ) + frag->appendChild( xferNode ); + --cnt; + n = sibling; + } + } + + // Nothing is partially selected, so collapse to start point + if ( how != CLONE_CONTENTS ) + collapse(true); + return frag; +} + +/** + * Visits the nodes selected by this range when we know + * a-priori that the start and end containers are not the + * same, but the start container is an ancestor of the end container + * + */ +DOMDocumentFragment* DOMRangeImpl::traverseCommonStartContainer( DOMNode*endAncestor, int how ) +{ + DOMDocumentFragment* frag = 0; + if ( how!=DELETE_CONTENTS) + frag = fDocument->createDocumentFragment(); + DOMNode*n = traverseRightBoundary( endAncestor, how ); + if ( frag!=0 ) + frag->appendChild( n ); + + XMLSize_t endIdx = indexOf( endAncestor, fStartContainer ); + if ( endIdx <= fStartOffset ) + { + // Collapse to just before the endAncestor, which + // is partially selected. + if ( how != CLONE_CONTENTS ) + { + setEndBefore( endAncestor ); + collapse( false ); + } + return frag; + } + + n = endAncestor->getPreviousSibling(); + int cnt = (int)endIdx - (int)fStartOffset; + while( cnt > 0 ) + { + DOMNode* sibling = n->getPreviousSibling(); + DOMNode* xferNode = traverseFullySelected( n, how ); + if ( frag!=0 ) + frag->insertBefore( xferNode, frag->getFirstChild() ); + --cnt; + n = sibling; + } + // Collapse to just before the endAncestor, which + // is partially selected. + if ( how != CLONE_CONTENTS ) + { + setEndBefore( endAncestor ); + collapse( false ); + } + return frag; +} + +/** + * Visits the nodes selected by this range when we know + * a-priori that the start and end containers are not the + * same, but the end container is an ancestor of the start container + * + */ +DOMDocumentFragment* DOMRangeImpl::traverseCommonEndContainer( DOMNode*startAncestor, int how ) +{ + DOMDocumentFragment* frag = 0; + if ( how!=DELETE_CONTENTS) + frag = fDocument->createDocumentFragment(); + DOMNode* n = traverseLeftBoundary( startAncestor, how ); + if ( frag!=0 ) + frag->appendChild( n ); + XMLSize_t startIdx = indexOf( startAncestor, fEndContainer ); + ++startIdx; // Because we already traversed it.... + + int cnt = (int)fEndOffset - (int)startIdx; + n = startAncestor->getNextSibling(); + while( cnt > 0 ) + { + DOMNode* sibling = n->getNextSibling(); + DOMNode* xferNode = traverseFullySelected( n, how ); + if ( frag!=0 ) + frag->appendChild( xferNode ); + --cnt; + n = sibling; + } + + if ( how != CLONE_CONTENTS ) + { + setStartAfter( startAncestor ); + collapse( true ); + } + + return frag; +} + +/** + * Visits the nodes selected by this range when we know + * a-priori that the start and end containers are not + * the same, and we also know that neither the start + * nor end container is an ancestor of the other. + */ +DOMDocumentFragment* DOMRangeImpl::traverseCommonAncestors( DOMNode*startAncestor, DOMNode*endAncestor, int how ) +{ + DOMDocumentFragment* frag = 0; + if ( how!=DELETE_CONTENTS) + frag = fDocument->createDocumentFragment(); + + DOMNode*n = traverseLeftBoundary( startAncestor, how ); + if ( frag!=0 ) + frag->appendChild( n ); + + DOMNode*commonParent = startAncestor->getParentNode(); + XMLSize_t startOffset = indexOf( startAncestor, commonParent ); + XMLSize_t endOffset = indexOf( endAncestor, commonParent ); + ++startOffset; + + int cnt = (int)endOffset - (int)startOffset; + DOMNode* sibling = startAncestor->getNextSibling(); + + while( cnt > 0 ) + { + DOMNode* nextSibling = sibling->getNextSibling(); + n = traverseFullySelected( sibling, how ); + if ( frag!=0 ) + frag->appendChild( n ); + sibling = nextSibling; + --cnt; + } + + n = traverseRightBoundary( endAncestor, how ); + if ( frag!=0 ) + frag->appendChild( n ); + + if ( how != CLONE_CONTENTS ) + { + setStartAfter( startAncestor ); + collapse( true ); + } + return frag; +} + +/** + * Traverses the "right boundary" of this range and + * operates on each "boundary node" according to the + * how parameter. It is a-priori assumed + * by this method that the right boundary does + * not contain the range's start container. + * + * A "right boundary" is best visualized by thinking + * of a sample tree: + * A + * /|\ + * / | \ + * / | \ + * B C D + * /|\ /|\ + * E F G H I J + * + * Imagine first a range that begins between the + * "E" and "F" nodes and ends between the + * "I" and "J" nodes. The start container is + * "B" and the end container is "D". Given this setup, + * the following applies: + * + * Partially Selected Nodes: B, D
+ * Fully Selected Nodes: F, G, C, H, I + * + * The "right boundary" is the highest subtree node + * that contains the ending container. The root of + * this subtree is always partially selected. + * + * In this example, the nodes that are traversed + * as "right boundary" nodes are: H, I, and D. + * + */ +DOMNode* DOMRangeImpl::traverseRightBoundary( DOMNode*root, int how ) +{ + DOMNode*next = getSelectedNode( fEndContainer, (int)fEndOffset-1 ); + bool isFullySelected = ( next!=fEndContainer ); + + if ( next==root ) + return traverseNode( next, isFullySelected, false, how ); + + DOMNode*parent = next->getParentNode(); + DOMNode*clonedParent = traverseNode( parent, false, false, how ); + + while( parent!=0 ) + { + while( next!=0 ) + { + DOMNode* prevSibling = next->getPreviousSibling(); + DOMNode* clonedChild = + traverseNode( next, isFullySelected, false, how ); + if ( how!=DELETE_CONTENTS ) + { + clonedParent->insertBefore( + clonedChild, + clonedParent->getFirstChild() + ); + } + isFullySelected = true; + next = prevSibling; + } + if ( parent==root ) + return clonedParent; + + next = parent->getPreviousSibling(); + parent = parent->getParentNode(); + DOMNode* clonedGrandParent = traverseNode( parent, false, false, how ); + if ( how!=DELETE_CONTENTS ) + clonedGrandParent->appendChild( clonedParent ); + clonedParent = clonedGrandParent; + + } + + // should never occur + return 0; +} + +/** + * Traverses the "left boundary" of this range and + * operates on each "boundary node" according to the + * how parameter. It is a-priori assumed + * by this method that the left boundary does + * not contain the range's end container. + * + * A "left boundary" is best visualized by thinking + * of a sample tree: + * + * A + * /|\ + * / | \ + * / | \ + * B C D + * /|\ /|\ + * E F G H I J + * + * Imagine first a range that begins between the + * "E" and "F" nodes and ends between the + * "I" and "J" nodes. The start container is + * "B" and the end container is "D". Given this setup, + * the following applies: + * + * Partially Selected Nodes: B, D
+ * Fully Selected Nodes: F, G, C, H, I + * + * The "left boundary" is the highest subtree node + * that contains the starting container. The root of + * this subtree is always partially selected. + * + * In this example, the nodes that are traversed + * as "left boundary" nodes are: F, G, and B. + * + */ +DOMNode* DOMRangeImpl::traverseLeftBoundary( DOMNode*root, int how ) +{ + DOMNode*next = getSelectedNode( getStartContainer(), (int)getStartOffset() ); + bool isFullySelected = ( next!=getStartContainer() ); + + if ( next==root ) + return traverseNode( next, isFullySelected, true, how ); + + DOMNode* parent = next->getParentNode(); + DOMNode* clonedParent = traverseNode( parent, false, true, how ); + + while( parent!=0 ) + { + while( next!=0 ) + { + DOMNode* nextSibling = next->getNextSibling(); + DOMNode* clonedChild = + traverseNode( next, isFullySelected, true, how ); + if ( how!=DELETE_CONTENTS ) + clonedParent->appendChild(clonedChild); + isFullySelected = true; + next = nextSibling; + } + if ( parent==root ) + return clonedParent; + + next = parent->getNextSibling(); + parent = parent->getParentNode(); + DOMNode* clonedGrandParent = traverseNode( parent, false, true, how ); + if ( how!=DELETE_CONTENTS ) + clonedGrandParent->appendChild( clonedParent ); + clonedParent = clonedGrandParent; + + } + + // should never occur + return 0; + +} + +/** + * Utility method for traversing a single node. + * Does not properly handle a text node containing both the + * start and end offsets. Such nodes should + * have been previously detected and been routed to traverseTextNode. + * + */ +DOMNode* DOMRangeImpl::traverseNode( DOMNode* n, bool isFullySelected, bool isLeft, int how ) +{ + if ( isFullySelected ) + return traverseFullySelected( n, how ); + + short type = n->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + return traverseTextNode( n, isLeft, how ); + + return traversePartiallySelected( n, how ); +} + +/** + * Utility method for traversing a single node when + * we know a-priori that the node if fully + * selected. + * + */ +DOMNode* DOMRangeImpl::traverseFullySelected( DOMNode* n, int how ) +{ + switch( how ) + { + case CLONE_CONTENTS: + return n->cloneNode( true ); + case EXTRACT_CONTENTS: + return n; + case DELETE_CONTENTS: + // revisit: + // should I release the removed node? + // not released in case user still referencing it externally + n->getParentNode()->removeChild(n); + return 0; + } + return 0; +} + +/** + * Utility method for traversing a single node when + * we know a-priori that the node if partially + * selected and is not a text node. + * + */ +DOMNode* DOMRangeImpl::traversePartiallySelected( DOMNode*n, int how ) +{ + switch( how ) + { + case DELETE_CONTENTS: + return 0; + case CLONE_CONTENTS: + case EXTRACT_CONTENTS: + return n->cloneNode( false ); + } + return 0; +} + +/** + * Utility method for traversing a text node that we know + * a-priori to be on a left or right boundary of the range. + * This method does not properly handle text nodes that contain + * both the start and end points of the range. + * + */ +DOMNode* DOMRangeImpl::traverseTextNode( DOMNode*n, bool isLeft, int how ) +{ + XMLCh* txtValue = XMLString::replicate(n->getNodeValue(), fMemoryManager); + ArrayJanitor janValue(txtValue, fMemoryManager); + + if ( isLeft ) + { + XMLSize_t startLen = XMLString::stringLen(fStartContainer->getNodeValue()); + XMLSize_t offset = getStartOffset(); + + if (offset == 0) { + if ( how != CLONE_CONTENTS ) + n->setNodeValue(XMLUni::fgZeroLenString); + } + else { + XMLCh* oldNodeValue; + XMLCh oldTemp[4000]; + + if (offset >= 3999) { + oldNodeValue = (XMLCh*) fMemoryManager->allocate + ( + (offset+1) * sizeof(XMLCh) + );//new XMLCh[offset+1]; + } + else { + oldNodeValue = oldTemp; + } + XMLString::subString(oldNodeValue, txtValue, 0, offset, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + + if ( how != CLONE_CONTENTS ) + n->setNodeValue( ((DOMDocumentImpl *)fDocument)->getPooledString(oldNodeValue) ); + + if (offset>= 3999) + fMemoryManager->deallocate(oldNodeValue);//delete[] oldNodeValue; + } + + if ( how==DELETE_CONTENTS ) + return 0; + + DOMNode* newNode = n->cloneNode( false ); + + if (startLen == offset) { + newNode->setNodeValue(XMLUni::fgZeroLenString); + } + else { + XMLCh* newNodeValue; + XMLCh newTemp[4000]; + + if (offset >= 3999) { + newNodeValue = (XMLCh*) fMemoryManager->allocate + ( + (offset+1) * sizeof(XMLCh) + );//new XMLCh[offset+1]; + } + else { + newNodeValue = newTemp; + } + XMLString::subString(newNodeValue, txtValue, offset, startLen, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + newNode->setNodeValue( ((DOMDocumentImpl *)fDocument)->getPooledString(newNodeValue) ); + + if (offset>= 3999) + fMemoryManager->deallocate(newNodeValue);//delete[] newNodeValue; + + } + return newNode; + } + else + { + XMLSize_t endLen = XMLString::stringLen(fEndContainer->getNodeValue()); + XMLSize_t offset = getEndOffset(); + + if (endLen == offset) { + if ( how != CLONE_CONTENTS ) + n->setNodeValue(XMLUni::fgZeroLenString); + } + else { + XMLCh* oldNodeValue; + XMLCh oldTemp[4000]; + + if (offset >= 3999) { + oldNodeValue = (XMLCh*) fMemoryManager->allocate + ( + (offset+1) * sizeof(XMLCh) + );//new XMLCh[offset+1]; + } + else { + oldNodeValue = oldTemp; + } + XMLString::subString(oldNodeValue, txtValue, offset, endLen, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + + if ( how != CLONE_CONTENTS ) + n->setNodeValue( ((DOMDocumentImpl *)fDocument)->getPooledString(oldNodeValue) ); + + if (offset>= 3999) + fMemoryManager->deallocate(oldNodeValue);//delete[] oldNodeValue; + } + + if ( how==DELETE_CONTENTS ) + return 0; + + DOMNode* newNode = n->cloneNode( false ); + + if (offset == 0) { + newNode->setNodeValue(XMLUni::fgZeroLenString); + } + else { + XMLCh* newNodeValue; + XMLCh newTemp[4000]; + + if (offset >= 3999) { + newNodeValue = (XMLCh*) fMemoryManager->allocate + ( + (offset+1) * sizeof(XMLCh) + );//new XMLCh[offset+1]; + } + else { + newNodeValue = newTemp; + } + XMLString::subString(newNodeValue, txtValue, 0, offset, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); + newNode->setNodeValue( ((DOMDocumentImpl *)fDocument)->getPooledString(newNodeValue) ); + + if (offset>= 3999) + fMemoryManager->deallocate(newNodeValue);//delete[] newNodeValue; + + } + return newNode; + } +} + +/** + * Utility method to retrieve a child node by index. This method + * assumes the caller is trying to find out which node is + * selected by the given index. Note that if the index is + * greater than the number of children, this implies that the + * first node selected is the parent node itself. + * + */ +DOMNode* DOMRangeImpl::getSelectedNode( DOMNode*container, int offset ) +{ + short type = container->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + return container; + + // This case is an important convenience for + // traverseRightBoundary() + if ( offset<0 ) + return container; + + DOMNode*child = container->getFirstChild(); + while( child!=0 && offset > 0 ) + { + --offset; + child = child->getNextSibling(); + } + if ( child!=0 ) + return child; + return container; +} + +void DOMRangeImpl::checkReadOnly(DOMNode* start, DOMNode* end, + XMLSize_t startOffset, XMLSize_t endOffset) +{ + if ((start == 0) || (end == 0) ) return; + DOMNode*sNode = 0; + + short type = start->getNodeType(); + if ( type == DOMNode::DOCUMENT_TYPE_NODE ) + { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0, fMemoryManager); + } + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (castToNodeImpl(start)->isReadOnly()) { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, fMemoryManager); + } + //if both start and end are text check and return + if (start == end) + return; + + sNode = start; + } else { + //set the start and end nodes to check + sNode = start->getFirstChild(); + for(XMLSize_t i = 0; igetNextSibling(); + } + + DOMNode* eNode; + type = end->getNodeType(); + if ( type == DOMNode::DOCUMENT_TYPE_NODE ) + { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0, fMemoryManager); + } + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + eNode = end; //need to check only till this node + } + else { //need to check all the kids that fall before the end offset value + eNode = end->getFirstChild(); + if (endOffset > 0) { + for (XMLSize_t i = 0; igetNextSibling(); + } + } + //recursivly search if any node is readonly + recurseTreeAndCheck(sNode, eNode); +} + +void DOMRangeImpl::recurseTreeAndCheck(DOMNode* start, DOMNode* end) +{ + for(DOMNode* node=start; node != 0 && node !=end; node=node->getNextSibling()) + { + if ( node->getNodeType()== DOMNode::DOCUMENT_TYPE_NODE ) + { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0, fMemoryManager); + } + + if (castToNodeImpl(node)->isReadOnly()) { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, fMemoryManager); + } + + if (node->hasChildNodes()) { + node = node->getFirstChild(); + recurseTreeAndCheck(node, end); + } + } +} + + +DOMNode* DOMRangeImpl::removeChild(DOMNode* parent, DOMNode* child) +{ + fRemoveChild = child; //only a precaution measure not to update this range data before removal + DOMNode*n = parent->removeChild(child); + fRemoveChild = 0; + return n; +} + + +// +// Mutation functions +// + + +/* This function is called from DOM. +* The text has already been replaced. +* Fix-up any offsets. +*/ +void DOMRangeImpl::receiveReplacedText(DOMNode* node) +{ + if (node == 0) return; + + short type = fStartContainer->getNodeType(); + if (node == fStartContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + fStartOffset = 0; + } + type = fEndContainer->getNodeType(); + if (node == fEndContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + fEndOffset = 0; + } +} + + +/** This function is called from DOM. +* The text has already been deleted. +* Fix-up any offsets. +*/ +void DOMRangeImpl::updateRangeForDeletedText(DOMNode* node, XMLSize_t offset, XMLSize_t count) +{ + if (node == 0) return; + + short type = fStartContainer->getNodeType(); + if (node == fStartContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fStartOffset > offset+count) { + fStartOffset = fStartOffset-count; + } else if (fStartOffset > offset) { + fStartOffset = offset; + } + } + type = fEndContainer->getNodeType(); + if (node == fEndContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fEndOffset > offset+count) { + fEndOffset = fEndOffset-count; + } else if (fEndOffset > offset) { + fEndOffset = offset; + } + } +} + + + +/** This function is called from DOM. +* The text has already beeen inserted. +* Fix-up any offsets. +*/ +void DOMRangeImpl::updateRangeForInsertedText(DOMNode* node, XMLSize_t offset, XMLSize_t count) +{ + if (node == 0) return; + + short type = fStartContainer->getNodeType(); + if (node == fStartContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fStartOffset > offset) { + fStartOffset = offset; + } + } + type = fEndContainer->getNodeType(); + if (node == fEndContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fEndOffset > offset) { + fEndOffset = fEndOffset+count; + } + } +} + + + +/** This function must be called by the DOM _BEFORE_ +* a node is deleted, because at that time it is +* connected in the DOM tree, which we depend on. +*/ +void DOMRangeImpl::updateRangeForDeletedNode(DOMNode* node) +{ + + if (node == 0) return; + if (fRemoveChild == node) return; + + if (node->getParentNode() == fStartContainer) { + XMLSize_t index = indexOf(node, fStartContainer); + if ( fStartOffset > index) { + fStartOffset--; + } + } + + if (node->getParentNode() == fEndContainer) { + XMLSize_t index = indexOf(node, fEndContainer); + if ( fEndOffset > index) { + fEndOffset--; + } + } + + if (node->getParentNode() != fStartContainer + || node->getParentNode() != fEndContainer) { + if (isAncestorOf(node, fStartContainer)) { + DOMNode* tpNode = node->getParentNode(); + setStartContainer( tpNode ); + fStartOffset = indexOf( node, tpNode); + } + if (isAncestorOf(node, fEndContainer)) { + DOMNode* tpNode = node->getParentNode(); + setEndContainer( tpNode ); + fEndOffset = indexOf( node, tpNode); + } + } + +} + +void DOMRangeImpl::updateRangeForInsertedNode(DOMNode* node) { + if (node == 0) return; + + if (node->getParentNode() == fStartContainer) { + XMLSize_t index = indexOf(node, fStartContainer); + if (index < fStartOffset) { + fStartOffset++; + } + } + + if (node->getParentNode() == fEndContainer) { + XMLSize_t index = indexOf(node, fEndContainer); + if (index < fEndOffset) { + fEndOffset++; + } + } +} + + +void DOMRangeImpl::updateSplitInfo(DOMNode* oldNode, DOMNode* startNode, XMLSize_t offset) +{ + if (startNode == 0) return; + + short type = fStartContainer->getNodeType(); + if (oldNode == fStartContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fStartOffset > offset) { + fStartOffset = fStartOffset - offset; + fStartContainer = startNode; + } + } + + type = fEndContainer->getNodeType(); + if (oldNode == fEndContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fEndOffset > offset) { + fEndContainer = startNode; + fEndOffset = fEndOffset - offset; + } + } +} + + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/dom/impl/DOMRangeImpl.hpp b/include/xercesc/dom/impl/DOMRangeImpl.hpp new file mode 100644 index 0000000..fcb68c9 --- /dev/null +++ b/include/xercesc/dom/impl/DOMRangeImpl.hpp @@ -0,0 +1,176 @@ +/* + * 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: DOMRangeImpl.hpp 641193 2008-03-26 08:06:57Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMRANGEIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMRANGEIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + + +class DOMNode; +class DOMDocumentFragment; +class DOMDocument; +class DOMText; +class MemoryManager; + +class CDOM_EXPORT DOMRangeImpl: public DOMRange { +protected: + enum TraversalType { + EXTRACT_CONTENTS = 1, + CLONE_CONTENTS = 2, + DELETE_CONTENTS = 3 + }; + + enum TraversePoint { + BEFORE = -1, + START = 0, + AFTER = 1 + }; + + //private data + + DOMNode* fStartContainer; + XMLSize_t fStartOffset; + DOMNode* fEndContainer; + XMLSize_t fEndOffset; + bool fCollapsed; + DOMDocument* fDocument; + bool fDetached; + + DOMNode* fRemoveChild; + MemoryManager* fMemoryManager; + +public: + //c'tor + DOMRangeImpl(DOMDocument* doc, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + DOMRangeImpl(const DOMRangeImpl& other); + + //d'tor + ~DOMRangeImpl(); + + //getter functions + virtual DOMNode* getStartContainer() const; + virtual XMLSize_t getStartOffset() const; + virtual DOMNode* getEndContainer() const; + virtual XMLSize_t getEndOffset() const; + virtual bool getCollapsed() const; + virtual const DOMNode* getCommonAncestorContainer() const; + + //setter functions + virtual void setStart(const DOMNode *parent, XMLSize_t offset); + virtual void setEnd(const DOMNode *parent, XMLSize_t offset); + + virtual void setStartBefore(const DOMNode *refNode); + virtual void setStartAfter(const DOMNode *refNode); + virtual void setEndBefore(const DOMNode *refNode); + virtual void setEndAfter(const DOMNode *refNode); + + //misc functions + virtual void collapse(bool toStart); + virtual void selectNode(const DOMNode *node); + virtual void selectNodeContents(const DOMNode *node); + + //Functions related to comparing range Boundrary-Points + virtual short compareBoundaryPoints(CompareHow how, const DOMRange* range) const; + virtual void deleteContents(); + virtual DOMDocumentFragment* extractContents(); + virtual DOMDocumentFragment* cloneContents() const; + virtual void insertNode(DOMNode* node); + + //Misc functions + virtual void surroundContents(DOMNode *node); + virtual DOMRange* cloneRange() const; + virtual const XMLCh* toString() const; + virtual void detach(); + virtual void release(); + + //getter functions + DOMDocument* getDocument(); + + // functions to inform all existing valid ranges about a change + void updateSplitInfo(DOMNode* oldNode, DOMNode* startNode, XMLSize_t offset); + void updateRangeForInsertedNode(DOMNode* node); + void receiveReplacedText(DOMNode* node); + void updateRangeForDeletedText(DOMNode* node, XMLSize_t offset, XMLSize_t count); + void updateRangeForInsertedText(DOMNode* node, XMLSize_t offset, XMLSize_t count); + void updateRangeForDeletedNode(DOMNode* node); + +protected: + //setter functions + void setStartContainer(const DOMNode* node); + void setStartOffset(XMLSize_t offset) ; + void setEndContainer(const DOMNode* node); + void setEndOffset(XMLSize_t offset) ; + + //misc functions + void validateNode(const DOMNode* node) const; + bool isValidAncestorType(const DOMNode* node) const; + bool hasLegalRootContainer(const DOMNode* node) const; + bool isLegalContainedNode(const DOMNode* node ) const; + void checkIndex(const DOMNode* node, XMLSize_t offset) const; + static bool isAncestorOf(const DOMNode* a, const DOMNode* b); + + XMLSize_t indexOf(const DOMNode* child, const DOMNode* parent) const; + + const DOMNode* commonAncestorOf(const DOMNode* pointA, const DOMNode* pointB) const; + DOMNode* nextNode(const DOMNode* node, bool visitChildren) const; + DOMDocumentFragment* traverseContents(TraversalType type); + void checkReadOnly(DOMNode* start, DOMNode* end, + XMLSize_t starOffset, XMLSize_t endOffset); + void recurseTreeAndCheck(DOMNode* start, DOMNode* end); + DOMNode* removeChild(DOMNode* parent, DOMNode* child); + + DOMDocumentFragment* traverseSameContainer( int how ); + DOMDocumentFragment* traverseCommonStartContainer( DOMNode *endAncestor, int how ); + DOMDocumentFragment* traverseCommonEndContainer( DOMNode *startAncestor, int how ); + DOMDocumentFragment* traverseCommonAncestors( DOMNode *startAncestor, DOMNode *endAncestor, int how ); + DOMNode* traverseRightBoundary( DOMNode *root, int how ); + DOMNode* traverseLeftBoundary( DOMNode *root, int how ); + DOMNode* traverseNode( DOMNode *n, bool isFullySelected, bool isLeft, int how ); + DOMNode* traverseFullySelected( DOMNode *n, int how ); + DOMNode* traversePartiallySelected( DOMNode *n, int how ); + DOMNode* traverseTextNode( DOMNode *n, bool isLeft, int how ); + DOMNode* getSelectedNode( DOMNode *container, int offset ); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMRangeImpl & operator = (const DOMRangeImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMStringListImpl.cpp b/include/xercesc/dom/impl/DOMStringListImpl.cpp new file mode 100644 index 0000000..0af5d4b --- /dev/null +++ b/include/xercesc/dom/impl/DOMStringListImpl.cpp @@ -0,0 +1,64 @@ +/* + * 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: DOMStringListImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMStringListImpl.hpp" +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMStringListImpl::DOMStringListImpl(int nInitialSize, MemoryManager* manager) +{ + fList=new (manager) RefVectorOf(nInitialSize, false, manager); +} + +DOMStringListImpl::~DOMStringListImpl() +{ + delete fList; +} + + +void DOMStringListImpl::add(const XMLCh* str) { + fList->addElement((XMLCh*)str); +} + +XMLSize_t DOMStringListImpl::getLength() const{ + return fList->size(); +} + + +const XMLCh* DOMStringListImpl::item(XMLSize_t index) const{ + if(indexsize()) + return fList->elementAt(index); + return 0; +} + +bool DOMStringListImpl::contains(const XMLCh* str) const{ + for(XMLSize_t i=0;isize();i++) + if(XMLString::equals(fList->elementAt(i), str)) + return true; + return false; +} + +void DOMStringListImpl::release() { + delete this; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMStringListImpl.hpp b/include/xercesc/dom/impl/DOMStringListImpl.hpp new file mode 100644 index 0000000..3ea2796 --- /dev/null +++ b/include/xercesc/dom/impl/DOMStringListImpl.hpp @@ -0,0 +1,56 @@ +/* + * 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: DOMStringListImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMSTRINGLISTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMSTRINGLISTIMPL_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMStringListImpl: public XMemory, + public DOMStringList +{ +protected: + RefVectorOf *fList; + +private: + // Unused, and unimplemented constructors, operators, etc. + DOMStringListImpl(const DOMStringListImpl & other); + DOMStringListImpl & operator = (const DOMStringListImpl & other); + +public: + DOMStringListImpl(int nInitialSize, MemoryManager* manager); + void add(const XMLCh* impl); + + virtual ~DOMStringListImpl(); + virtual const XMLCh* item(XMLSize_t index) const; + virtual XMLSize_t getLength() const; + virtual bool contains(const XMLCh* str) const; + virtual void release(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMStringPool.cpp b/include/xercesc/dom/impl/DOMStringPool.cpp new file mode 100644 index 0000000..7352f4d --- /dev/null +++ b/include/xercesc/dom/impl/DOMStringPool.cpp @@ -0,0 +1,62 @@ +/* + * 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: DOMStringPool.cpp 678766 2008-07-22 14:00:16Z borisk $ + */ + +#include +#include + +#include "DOMStringPool.hpp" +#include "DOMDocumentImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + +DOMBuffer:: +DOMBuffer(DOMDocumentImpl *doc, XMLSize_t capacity) : + fBuffer(0) + , fIndex(0) + , fCapacity(capacity) + , fDoc(doc) +{ + // Buffer is one larger than capacity, to allow for zero term + fBuffer = (XMLCh*) doc->allocate((fCapacity+1)*sizeof(XMLCh)); + + // Keep it null terminated + fBuffer[0] = XMLCh(0); +} + +// --------------------------------------------------------------------------- +// DOMBuffer: Private helper methods +// --------------------------------------------------------------------------- +void DOMBuffer::expandCapacity(const XMLSize_t extraNeeded) +{ + //not enough room. Calc new capacity and allocate new buffer + const XMLSize_t newCap = (XMLSize_t)((fIndex + extraNeeded) * 1.25); + XMLCh* newBuf = (XMLCh*) fDoc->allocate((newCap+1)*sizeof(XMLCh)); + + // Copy over the old stuff + memcpy(newBuf, fBuffer, fCapacity * sizeof(XMLCh)); + + // revisit: Leave the old buffer in document heap, yes, this is a leak, but live with it! + // store new stuff + fBuffer = newBuf; + fCapacity = newCap; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMStringPool.hpp b/include/xercesc/dom/impl/DOMStringPool.hpp new file mode 100644 index 0000000..92a30ab --- /dev/null +++ b/include/xercesc/dom/impl/DOMStringPool.hpp @@ -0,0 +1,211 @@ +/* + * 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: DOMStringPool.hpp 678766 2008-07-22 14:00:16Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMSTRINGPOOL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMSTRINGPOOL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMDocumentImpl; + +// +// DStringPoolEntry - one of these structs is allocated for each +// XMLCh String in the pool. Each slot in the +// hash table array itself is a pointer to the head +// of a singly-linked list of these structs. +// +// Although this struct is delcared with a string length of one, +// the factory method allocates enough storage to hold the full +// string length. +// +struct DOMStringPoolEntry +{ + DOMStringPoolEntry *fNext; + XMLCh fString[1]; +}; + +// +// DOMBuffer is a lightweight text buffer +// The buffer is not nul terminated until some asks to see the raw buffer +// contents. This also avoids overhead during append operations. +class DOMBuffer +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DOMBuffer(DOMDocumentImpl *doc, XMLSize_t capacity = 31); + + ~DOMBuffer() + { + } + + // ----------------------------------------------------------------------- + // Buffer Management + // ----------------------------------------------------------------------- + void append (const XMLCh* const chars); + void append (const XMLCh* const chars, const XMLSize_t count); + + void set (const XMLCh* const chars); + void set (const XMLCh* const chars, const XMLSize_t count); + + const XMLCh* getRawBuffer() const + { + fBuffer[fIndex] = 0; + return fBuffer; + } + + void reset() + { + fIndex = 0; + fBuffer[0] = 0; + } + + void chop + ( + const XMLSize_t count + ) + { + fBuffer[count] = 0; + fIndex = count; + } + + + // ----------------------------------------------------------------------- + // Getters + // ----------------------------------------------------------------------- + XMLSize_t getLen() const + { + return fIndex; + } + + XMLSize_t getCapacity() const + { + return fCapacity; + } + + // ----------------------------------------------------------------------- + // Private helpers + // ----------------------------------------------------------------------- + void expandCapacity(const XMLSize_t extraNeeded); + + +private : + // ----------------------------------------------------------------------- + // Private data members + // + // fBuffer + // The pointer to the buffer data. Its grown as needed. Its always + // one larger than fCapacity, to leave room for the null terminator. + // + // fIndex + // The current index into the buffer, as characters are appended + // to it. If its zero, then the buffer is empty. + // + // fCapacity + // The current capacity of the buffer. Its actually always one + // larger, to leave room for the null terminator. + // + // fDoc + // For allocating memory + // ----------------------------------------------------------------------- + XMLCh* fBuffer; + XMLSize_t fIndex; + XMLSize_t fCapacity; + DOMDocumentImpl* fDoc; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMBuffer(const DOMBuffer &); + DOMBuffer & operator = (const DOMBuffer &); +}; + +inline void DOMBuffer:: +append (const XMLCh* const chars) +{ + XMLSize_t count = XMLString::stringLen(chars); + if (fIndex + count >= fCapacity) + expandCapacity(count); + + memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh)); + fIndex += count; + + // Keep it null terminated + fBuffer[fIndex] = 0; +} + +inline void DOMBuffer:: +append (const XMLCh* const chars, const XMLSize_t count) +{ + if (fIndex + count >= fCapacity) + expandCapacity(count); + + memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh)); + fIndex += count; + + // Keep it null terminated + fBuffer[fIndex] = 0; +} + +inline void DOMBuffer:: +set (const XMLCh* const chars) +{ + XMLSize_t count = XMLString::stringLen(chars); + fIndex = 0; + if (count >= fCapacity) + expandCapacity(count); + + memcpy(fBuffer, chars, count * sizeof(XMLCh)); + fIndex = count; + + // Keep it null terminated + fBuffer[fIndex] = 0; +} + +inline void DOMBuffer:: +set (const XMLCh* const chars, const XMLSize_t count) +{ + fIndex = 0; + if (count >= fCapacity) + expandCapacity(count); + + memcpy(fBuffer, chars, count * sizeof(XMLCh)); + fIndex = count; + + // Keep it null terminated + fBuffer[fIndex] = 0; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMTextImpl.cpp b/include/xercesc/dom/impl/DOMTextImpl.cpp new file mode 100644 index 0000000..d966d04 --- /dev/null +++ b/include/xercesc/dom/impl/DOMTextImpl.cpp @@ -0,0 +1,331 @@ +/* + * 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: DOMTextImpl.cpp 1027995 2010-10-27 15:09:39Z amassari $ + */ + + +#include + +#include +#include +#include +#include +#include +#include + +#include "DOMDocumentImpl.hpp" +#include "DOMStringPool.hpp" +#include "DOMTextImpl.hpp" +#include "DOMCharacterDataImpl.hpp" +#include "DOMChildNode.hpp" +#include "DOMRangeImpl.hpp" +#include "DOMCasts.hpp" + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMDocument; + +DOMTextImpl::DOMTextImpl(DOMDocument *ownerDoc, const XMLCh *dat) + : fNode(ownerDoc), fCharacterData(ownerDoc, dat) +{ + fNode.setIsLeafNode(true); +} + +DOMTextImpl:: +DOMTextImpl(DOMDocument *ownerDoc, const XMLCh* dat, XMLSize_t n) + : fNode(ownerDoc), fCharacterData(ownerDoc, dat, n) +{ + fNode.setIsLeafNode(true); +} + +DOMTextImpl::DOMTextImpl(const DOMTextImpl &other, bool) + : DOMText(other) + , fNode(other.fNode) + , fCharacterData(other.fCharacterData) +{ + fNode.setIsLeafNode(true); +} + +DOMTextImpl::~DOMTextImpl() +{ +} + + +DOMNode *DOMTextImpl::cloneNode(bool deep) const +{ + DOMNode* newNode = new (getOwnerDocument(), DOMMemoryManager::TEXT_OBJECT) DOMTextImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +const XMLCh * DOMTextImpl::getNodeName() const { + static const XMLCh gtext[] = {chPound, chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull}; + return gtext; +} + +DOMNode::NodeType DOMTextImpl::getNodeType() const { + return DOMNode::TEXT_NODE; +} + + +DOMText *DOMTextImpl::splitText(XMLSize_t offset) +{ + if (fNode.isReadOnly()) + { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + XMLSize_t len = fCharacterData.fDataBuf->getLen(); + if (offset > len) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager); + + DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument(); + DOMText *newText = doc->createTextNode( + this->substringData(offset, len - offset)); + + DOMNode *parent = getParentNode(); + if (parent != 0) + parent->insertBefore(newText, getNextSibling()); + + fCharacterData.fDataBuf->chop(offset); + + if (doc != 0) { + Ranges* ranges = doc->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; ielementAt(i)->updateSplitInfo( this, newText, offset); + } + } + } + } + + return newText; +} + + +bool DOMTextImpl::isIgnorableWhitespace() const +{ + return fNode.ignorableWhitespace(); +} + + + +void DOMTextImpl::setIgnorableWhitespace(bool ignorable) +{ + fNode.ignorableWhitespace(ignorable); +} + + +bool DOMTextImpl::getIsElementContentWhitespace() const +{ + return isIgnorableWhitespace(); +} + +const XMLCh* DOMTextImpl::getWholeText() const +{ + DOMDocument *doc = getOwnerDocument(); + if (!doc) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager); + return 0; + } + DOMNode* root=doc->getDocumentElement(); + DOMTreeWalker* pWalker=doc->createTreeWalker(root!=NULL?root:(DOMNode*)this, DOMNodeFilter::SHOW_ALL, NULL, true); + pWalker->setCurrentNode((DOMNode*)this); + // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in + // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes. + DOMNode* prevNode; + while((prevNode=pWalker->previousNode())!=NULL) + { + if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + } + XMLBuffer buff(1023, GetDOMNodeMemoryManager); + DOMNode* nextNode; + while((nextNode=pWalker->nextNode())!=NULL) + { + if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + if(nextNode->getNodeType()==TEXT_NODE || nextNode->getNodeType()==CDATA_SECTION_NODE) + buff.append(nextNode->getNodeValue()); + } + pWalker->release(); + + XMLCh* wholeString = (XMLCh*)((DOMDocumentImpl*)doc)->allocate((buff.getLen()+1) * sizeof(XMLCh)); + XMLString::copyString(wholeString, buff.getRawBuffer()); + return wholeString; +} + +DOMText* DOMTextImpl::replaceWholeText(const XMLCh* newText) +{ + DOMDocument *doc = getOwnerDocument(); + DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true); + pWalker->setCurrentNode((DOMNode*)this); + // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in + // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes. + DOMNode* pFirstTextNode=this; + DOMNode* prevNode; + while((prevNode=pWalker->previousNode())!=NULL) + { + if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + pFirstTextNode=prevNode; + } + // before doing any change we need to check if we are going to remove an entity reference that doesn't contain just text + DOMNode* pCurrentNode=pWalker->getCurrentNode(); + DOMNode* nextNode; + while((nextNode=pWalker->nextNode())!=NULL) + { + if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + if(nextNode->getNodeType()==ENTITY_REFERENCE_NODE) + { + DOMTreeWalker* pInnerWalker=doc->createTreeWalker(nextNode, DOMNodeFilter::SHOW_ALL, NULL, true); + while(pInnerWalker->nextNode()) + { + short nodeType=pInnerWalker->getCurrentNode()->getNodeType(); + if(nodeType!=ENTITY_REFERENCE_NODE && nodeType!=TEXT_NODE && nodeType!=CDATA_SECTION_NODE) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); + } + pInnerWalker->release(); + } + } + DOMText* retVal=NULL; + // if the first node in the chain is a text node, replace its content, otherwise create a new node + if(newText && *newText) + { + if(!castToNodeImpl(pFirstTextNode)->isReadOnly() && (pFirstTextNode->getNodeType()==TEXT_NODE || pFirstTextNode->getNodeType()==CDATA_SECTION_NODE)) + { + pFirstTextNode->setNodeValue(newText); + retVal=(DOMText*)pFirstTextNode; + } + else + { + if(getNodeType()==TEXT_NODE) + retVal=doc->createTextNode(newText); + else + retVal=doc->createCDATASection(newText); + pFirstTextNode->getParentNode()->insertBefore(retVal, pFirstTextNode); + } + } + // now delete all the following text nodes + pWalker->setCurrentNode(pCurrentNode); + while((nextNode=pWalker->nextNode())!=NULL) + { + if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) + break; + if(nextNode!=retVal) + { + // keep the tree walker valid + pWalker->previousNode(); + nextNode->getParentNode()->removeChild(nextNode); + nextNode->release(); + } + } + pWalker->release(); + return retVal; +} + + +void DOMTextImpl::release() +{ + if (fNode.isOwned() && !fNode.isToBeReleased()) + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + + DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); + if (doc) { + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fCharacterData.releaseBuffer(); + doc->release(this, DOMMemoryManager::TEXT_OBJECT); + } + else { + // shouldn't reach here + throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); + } +} + +// +// Delegation functions +// + DOMNode* DOMTextImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); } + DOMNamedNodeMap* DOMTextImpl::getAttributes() const {return fNode.getAttributes (); } + DOMNodeList* DOMTextImpl::getChildNodes() const {return fNode.getChildNodes (); } + DOMNode* DOMTextImpl::getFirstChild() const {return fNode.getFirstChild (); } + DOMNode* DOMTextImpl::getLastChild() const {return fNode.getLastChild (); } + const XMLCh* DOMTextImpl::getLocalName() const {return fNode.getLocalName (); } + const XMLCh* DOMTextImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } + DOMNode* DOMTextImpl::getNextSibling() const {return fChild.getNextSibling (); } + const XMLCh* DOMTextImpl::getNodeValue() const {return fCharacterData.getNodeValue (); } + DOMDocument* DOMTextImpl::getOwnerDocument() const {return fNode.getOwnerDocument (); } + const XMLCh* DOMTextImpl::getPrefix() const {return fNode.getPrefix (); } + DOMNode* DOMTextImpl::getParentNode() const {return fChild.getParentNode (this); } + DOMNode* DOMTextImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); } + bool DOMTextImpl::hasChildNodes() const {return fNode.hasChildNodes (); } + DOMNode* DOMTextImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) + {return fNode.insertBefore (newChild, refChild); } + void DOMTextImpl::normalize() {fNode.normalize (); } + DOMNode* DOMTextImpl::removeChild(DOMNode *oldChild) {return fNode.removeChild (oldChild); } + DOMNode* DOMTextImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) + {return fNode.replaceChild (newChild, oldChild); } + bool DOMTextImpl::isSupported(const XMLCh *feature, const XMLCh *version) const + {return fNode.isSupported (feature, version); } + void DOMTextImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } + bool DOMTextImpl::hasAttributes() const {return fNode.hasAttributes(); } + bool DOMTextImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } + bool DOMTextImpl::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); } + void* DOMTextImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) + {return fNode.setUserData(key, data, handler); } + void* DOMTextImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } + const XMLCh* DOMTextImpl::getBaseURI() const {return fNode.getBaseURI(); } + short DOMTextImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } + const XMLCh* DOMTextImpl::getTextContent() const {return fNode.getTextContent(); } + void DOMTextImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } + const XMLCh* DOMTextImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } + bool DOMTextImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } + const XMLCh* DOMTextImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } + void* DOMTextImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); } + + + +// +// Delegation of CharacerData functions. +// + + + const XMLCh* DOMTextImpl::getData() const {return fCharacterData.getData();} + XMLSize_t DOMTextImpl::getLength() const {return fCharacterData.getLength();} + const XMLCh* DOMTextImpl::substringData(XMLSize_t offset, XMLSize_t count) const + {return fCharacterData.substringData(this, offset, count);} + void DOMTextImpl::appendData(const XMLCh *arg) {fCharacterData.appendData(this, arg);} + void DOMTextImpl::insertData(XMLSize_t offset, const XMLCh *arg) + {fCharacterData.insertData(this, offset, arg);} + void DOMTextImpl::deleteData(XMLSize_t offset, XMLSize_t count) + {fCharacterData.deleteData(this, offset, count);} + void DOMTextImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg) + {fCharacterData.replaceData(this, offset, count, arg);} + void DOMTextImpl::setData(const XMLCh *data) {fCharacterData.setData(this, data);} + void DOMTextImpl::setNodeValue(const XMLCh *nodeValue) {fCharacterData.setNodeValue (this, nodeValue); } + + void DOMTextImpl::appendData(const XMLCh *arg, XMLSize_t n) {fCharacterData.appendData(this, arg, n);} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMTextImpl.hpp b/include/xercesc/dom/impl/DOMTextImpl.hpp new file mode 100644 index 0000000..deb47ee --- /dev/null +++ b/include/xercesc/dom/impl/DOMTextImpl.hpp @@ -0,0 +1,103 @@ +/* + * 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: DOMTextImpl.hpp 678709 2008-07-22 10:56:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMTEXTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMTEXTIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + + +#include +#include + +#include "DOMChildNode.hpp" +#include "DOMNodeImpl.hpp" +#include "DOMCharacterDataImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMTextImpl: public DOMText { +public: + DOMNodeImpl fNode; + DOMChildNode fChild; + DOMCharacterDataImpl fCharacterData; + +public: + DOMTextImpl(DOMDocument* ownerDoc, const XMLCh* data); + DOMTextImpl(DOMDocument *ownerDoc, const XMLCh* data, XMLSize_t n); + DOMTextImpl(const DOMTextImpl& other, bool deep=false); + + virtual ~DOMTextImpl(); + virtual DOMText* splitText(XMLSize_t offset); + // DOM Level 3 + virtual bool getIsElementContentWhitespace() const; + virtual const XMLCh* getWholeText() const; + virtual DOMText* replaceWholeText(const XMLCh* content); + + // non-standard extension + virtual bool isIgnorableWhitespace() const; + +public: + // Declare the functions coming from DOMNode. + DOMNODE_FUNCTIONS; + +public: + // All of the functions coming from DOMCharacterData + virtual const XMLCh* getData() const; + virtual XMLSize_t getLength() const; + virtual const XMLCh* substringData(XMLSize_t offset, + XMLSize_t count) const; + virtual void appendData(const XMLCh *arg); + virtual void insertData(XMLSize_t offset, const XMLCh *arg); + virtual void deleteData(XMLSize_t offset, + XMLSize_t count); + virtual void replaceData(XMLSize_t offset, + XMLSize_t count, + const XMLCh *arg); + virtual void setData(const XMLCh *data); + + // Non-standard extension. + // + virtual void appendData(const XMLCh *arg, XMLSize_t n); + +protected: + virtual void setIgnorableWhitespace(bool ignorable); + friend class AbstractDOMParser; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMTextImpl & operator = (const DOMTextImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMTreeWalkerImpl.cpp b/include/xercesc/dom/impl/DOMTreeWalkerImpl.cpp new file mode 100644 index 0000000..9fe5dc4 --- /dev/null +++ b/include/xercesc/dom/impl/DOMTreeWalkerImpl.cpp @@ -0,0 +1,484 @@ +/* + * 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: DOMTreeWalkerImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#include "DOMTreeWalkerImpl.hpp" +#include "DOMDocumentImpl.hpp" + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** constructor */ +DOMTreeWalkerImpl::DOMTreeWalkerImpl ( + DOMNode* root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* nodeFilter, + bool expandEntityRef) +: fWhatToShow(whatToShow), + fNodeFilter(nodeFilter), + fCurrentNode(root), + fRoot(root), + fExpandEntityReferences(expandEntityRef) +{ +} + + +DOMTreeWalkerImpl::DOMTreeWalkerImpl (const DOMTreeWalkerImpl& twi) +: DOMTreeWalker(twi), + fWhatToShow(twi.fWhatToShow), + fNodeFilter(twi.fNodeFilter), + fCurrentNode(twi.fCurrentNode), + fRoot(twi.fRoot), + fExpandEntityReferences(twi.fExpandEntityReferences) +{ +} + + +DOMTreeWalkerImpl& DOMTreeWalkerImpl::operator= (const DOMTreeWalkerImpl& twi) { + if (this != &twi) + { + fCurrentNode = twi.fCurrentNode; + fRoot = twi.fRoot; + fWhatToShow = twi.fWhatToShow; + fNodeFilter = twi.fNodeFilter; + fExpandEntityReferences = twi.fExpandEntityReferences; + } + + return *this; +} + + + +/** Return the root node */ +DOMNode* DOMTreeWalkerImpl::getRoot () { + return fRoot; +} + + +/** Return the whatToShow value */ +DOMNodeFilter::ShowType DOMTreeWalkerImpl::getWhatToShow () { + return fWhatToShow; +} + + +/** Return the NodeFilter */ +DOMNodeFilter* DOMTreeWalkerImpl::getFilter () { + return fNodeFilter; +} + +/** Get the expandEntity reference flag. */ +bool DOMTreeWalkerImpl::getExpandEntityReferences() { + return fExpandEntityReferences; +} + + + +/** Return the current Node. */ +DOMNode* DOMTreeWalkerImpl::getCurrentNode () { + + return fCurrentNode; +} + + +/** Return the current Node. */ +void DOMTreeWalkerImpl::setCurrentNode (DOMNode* node) { + + if (!node) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMTreeWalkerMemoryManager); + + fCurrentNode = node; +} + + +/** Return the parent Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ +DOMNode* DOMTreeWalkerImpl::parentNode () { + + if (!fCurrentNode) return 0; + + DOMNode* node = getParentNode(fCurrentNode); + if (node != 0) { + fCurrentNode = node; + } + return node; + +} + + +/** Return the first child Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ +DOMNode* DOMTreeWalkerImpl::firstChild () { + + if (!fCurrentNode) return 0; + + if(!fExpandEntityReferences && fCurrentNode->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE) + return 0; + + DOMNode* node = getFirstChild(fCurrentNode); + + if (node != 0) { + fCurrentNode = node; + } + return node; +} + + +/** Return the last child Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ +DOMNode* DOMTreeWalkerImpl::lastChild () { + + if (!fCurrentNode) return 0; + + if(!fExpandEntityReferences && fCurrentNode->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE) + return 0; + + DOMNode* node = getLastChild(fCurrentNode); + if (node != 0) { + fCurrentNode = node; + } + return node; +} + + +/** Return the previous sibling Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ + +DOMNode* DOMTreeWalkerImpl::previousSibling () { + + if (!fCurrentNode) return 0; + + DOMNode* node = getPreviousSibling(fCurrentNode); + if (node != 0) { + fCurrentNode = node; + } + return node; +} + + +/** Return the next sibling Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ + +DOMNode* DOMTreeWalkerImpl::nextSibling () { + + if (!fCurrentNode) return 0; + + DOMNode* node = getNextSibling(fCurrentNode); + if (node != 0) { + fCurrentNode = node; + } + return node; +} + + +/** Return the previous Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ + +DOMNode* DOMTreeWalkerImpl::previousNode () { + + if (!fCurrentNode) return 0; + + // get sibling + DOMNode* node = getPreviousSibling(fCurrentNode); + if (node == 0) { + node = getParentNode(fCurrentNode); + if ( node != 0) { + fCurrentNode = node; + } + return node; + } + else { + + // get the lastChild of result. + DOMNode* lastChild = getLastChild(node); + + // if there is a lastChild which passes filters return it. + if (lastChild != 0) { + fCurrentNode = lastChild; + } + else { + fCurrentNode = node; + } + return fCurrentNode; + } +} + + +/** Return the next Node from the current node, + * after applying filter, whatToshow. + * If result is not null, set the current Node. + */ + +DOMNode* DOMTreeWalkerImpl::nextNode () { + + if (!fCurrentNode) return 0; + + DOMNode* node = getFirstChild(fCurrentNode); + + if (node != 0) { + fCurrentNode = node; + return node; + } + else { + + node = getNextSibling(fCurrentNode); + + if (node != 0) { + fCurrentNode = node; + return node; + } + else { + + // return parent's 1st sibling. + DOMNode* parent = getParentNode(fCurrentNode); + while ( parent != 0) { + node = getNextSibling(parent); + if (node != 0) { + fCurrentNode = node; + return node; + } else { + parent = getParentNode(parent); + } + } + return node; + } + } +} + + +/** Internal function. + * Return the parent Node, from the input node + * after applying filter, whatToshow. + * The current node is not consulted or set. + */ + +DOMNode* DOMTreeWalkerImpl::getParentNode (DOMNode* node) { + + if (!node || node == fRoot) return 0; + + DOMNode* newNode = node->getParentNode(); + if (!newNode) return 0; + + short accept = acceptNode(newNode); + + if (accept == DOMNodeFilter::FILTER_ACCEPT) + return newNode; + + return getParentNode(newNode); + +} + + +/** Internal function. + * Return the nextSibling Node, from the input node + * after applying filter, whatToshow. + * The current node is not consulted or set. + */ + +DOMNode* DOMTreeWalkerImpl::getNextSibling (DOMNode* node) { + + if (!node || node == fRoot) return 0; + + DOMNode* newNode = node->getNextSibling(); + if (!newNode) { + + newNode = node->getParentNode(); + + if (!newNode || node == fRoot) return 0; + + short parentAccept = acceptNode(newNode); + + if (parentAccept == DOMNodeFilter::FILTER_SKIP) { + return getNextSibling(newNode); + } + + return 0; + } + + short accept = acceptNode(newNode); + + if (accept == DOMNodeFilter::FILTER_ACCEPT) + return newNode; + else + if (accept == DOMNodeFilter::FILTER_SKIP) { + DOMNode* fChild = getFirstChild(newNode); + if (!fChild && !newNode->hasChildNodes()) { + return getNextSibling(newNode); + } + return fChild; + } + return getNextSibling(newNode); + +} + + +/** Internal function. + * Return the previous sibling Node, from the input node + * after applying filter, whatToshow. + * The current node is not consulted or set. + */ + +DOMNode* DOMTreeWalkerImpl::getPreviousSibling (DOMNode* node) { + + if (!node || node == fRoot) return 0; + + DOMNode* newNode = node->getPreviousSibling(); + if (!newNode) { + + newNode = node->getParentNode(); + if (!newNode || node == fRoot) return 0; + + short parentAccept = acceptNode(newNode); + + if (parentAccept == DOMNodeFilter::FILTER_SKIP) { + return getPreviousSibling(newNode); + } + + return 0; + } + + short accept = acceptNode(newNode); + + if (accept == DOMNodeFilter::FILTER_ACCEPT) + return newNode; + else + if (accept == DOMNodeFilter::FILTER_SKIP) { + DOMNode* fChild = getLastChild(newNode); + if (!fChild && !newNode->hasChildNodes()) { + return getPreviousSibling(newNode); + } + return fChild; + } + return getPreviousSibling(newNode); + +} + + +/** Internal function. + * Return the first child Node, from the input node + * after applying filter, whatToshow. + * The current node is not consulted or set. + */ + +DOMNode* DOMTreeWalkerImpl::getFirstChild (DOMNode* node) { + + if (!node) return 0; + + if(!fExpandEntityReferences && node->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE) + return 0; + + DOMNode* newNode = node->getFirstChild(); + if (!newNode) return 0; + + short accept = acceptNode(newNode); + + if (accept == DOMNodeFilter::FILTER_ACCEPT) + return newNode; + else + if (accept == DOMNodeFilter::FILTER_SKIP + && newNode->hasChildNodes()) + { + return getFirstChild(newNode); + } + return getNextSibling(newNode); + +} + + +/** Internal function. + * Return the last child Node, from the input node + * after applying filter, whatToshow. + * The current node is not consulted or set. + */ + +DOMNode* DOMTreeWalkerImpl::getLastChild (DOMNode* node) { + + if (!node) return 0; + + if(!fExpandEntityReferences && node->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE) + return 0; + + DOMNode* newNode = node->getLastChild(); + if (!newNode) return 0; + + short accept = acceptNode(newNode); + + if (accept == DOMNodeFilter::FILTER_ACCEPT) + return newNode; + else + if (accept == DOMNodeFilter::FILTER_SKIP + && newNode->hasChildNodes()) + { + return getLastChild(newNode); + } + return getPreviousSibling(newNode); + +} + + +/** The node is accepted if it passes the whatToShow and the filter. */ + +short DOMTreeWalkerImpl::acceptNode (DOMNode* node) { + + if (fNodeFilter == 0) { + if ( ( fWhatToShow & (1 << (node->getNodeType() - 1))) != 0) + { + return DOMNodeFilter::FILTER_ACCEPT; + } + else + { + return DOMNodeFilter::FILTER_SKIP; + } + } else { + // REVISIT: This logic is unclear from the spec! + if ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0 ) { + return fNodeFilter->acceptNode(node); + } else { + // what to show has failed! + if (fNodeFilter->acceptNode(node) == DOMNodeFilter::FILTER_REJECT) { + return DOMNodeFilter::FILTER_REJECT; + } else { + return DOMNodeFilter::FILTER_SKIP; + } + } + } +} + + +void DOMTreeWalkerImpl::release() +{ + // for performance reason, do not recycle pointer + // chance that this is allocated again and again is not usual +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMTreeWalkerImpl.hpp b/include/xercesc/dom/impl/DOMTreeWalkerImpl.hpp new file mode 100644 index 0000000..c36ba1e --- /dev/null +++ b/include/xercesc/dom/impl/DOMTreeWalkerImpl.hpp @@ -0,0 +1,168 @@ +/* + * 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: DOMTreeWalkerImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMTREEWALKERIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMTREEWALKERIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class CDOM_EXPORT DOMTreeWalkerImpl : public DOMTreeWalker { +protected: + // The whatToShow mask. + DOMNodeFilter::ShowType fWhatToShow; + + // The NodeFilter reference. + DOMNodeFilter* fNodeFilter; + + // The current Node. + DOMNode* fCurrentNode; + + // The root Node. + DOMNode* fRoot; + + // The expandEntity reference flag. + bool fExpandEntityReferences; + +public: + // Implementation Note: No state is kept except the data above + // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that + // setters could be created for these data values and the + // implementation will still work. + + /** Public constructor */ + DOMTreeWalkerImpl ( + DOMNode* root, + DOMNodeFilter::ShowType whatToShow, + DOMNodeFilter* nodeFilter, + bool expandEntityRef); + DOMTreeWalkerImpl (const DOMTreeWalkerImpl& twi); + DOMTreeWalkerImpl& operator= (const DOMTreeWalkerImpl& twi); + + // Return the root node. + virtual DOMNode* getRoot (); + + // Return the whatToShow value. + virtual DOMNodeFilter::ShowType getWhatToShow (); + + // Return the NodeFilter. + virtual DOMNodeFilter* getFilter (); + + + // Return the current DOMNode. + virtual DOMNode* getCurrentNode (); + + // Return the current Node. + virtual void setCurrentNode (DOMNode* node); + + // Return the parent Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + virtual DOMNode* parentNode (); + + // Return the first child Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + virtual DOMNode* firstChild (); + + // Return the last child Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + virtual DOMNode* lastChild (); + + // Return the previous sibling Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + virtual DOMNode* previousSibling (); + + // Return the next sibling Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + + virtual DOMNode* nextSibling (); + // Return the previous Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + virtual DOMNode* previousNode (); + + // Return the next Node from the current node, + // after applying filter, whatToshow. + // If result is not null, set the current Node. + virtual DOMNode* nextNode (); + + // Get the expandEntity reference flag. + virtual bool getExpandEntityReferences(); + + // release the resource + virtual void release(); + +protected: + + // Internal function. + // Return the parent Node, from the input node + // after applying filter, whatToshow. + // The current node is not consulted or set. + DOMNode* getParentNode (DOMNode* node); + + // Internal function. + // Return the nextSibling Node, from the input node + // after applying filter, whatToshow. + // The current node is not consulted or set. + DOMNode* getNextSibling (DOMNode* node); + + // Internal function. + // Return the previous sibling Node, from the input node + // after applying filter, whatToshow. + // The current node is not consulted or set. + DOMNode* getPreviousSibling (DOMNode* node); + + // Internal function. + // Return the first child Node, from the input node + // after applying filter, whatToshow. + // The current node is not consulted or set. + DOMNode* getFirstChild (DOMNode* node); + + // Internal function. + // Return the last child Node, from the input node + // after applying filter, whatToshow. + // The current node is not consulted or set. + DOMNode* getLastChild (DOMNode* node); + + // The node is accepted if it passes the whatToShow and the filter. + short acceptNode (DOMNode* node); + + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMTypeInfoImpl.cpp b/include/xercesc/dom/impl/DOMTypeInfoImpl.cpp new file mode 100644 index 0000000..90786b1 --- /dev/null +++ b/include/xercesc/dom/impl/DOMTypeInfoImpl.cpp @@ -0,0 +1,186 @@ +/* + * 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. + */ + +#include "DOMTypeInfoImpl.hpp" +#include "DOMDocumentImpl.hpp" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedElement; +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdNotValidatedAttribute; +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedCDATAAttribute(XMLUni::fgInfosetURIName, XMLUni::fgCDATAString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedIDAttribute(XMLUni::fgInfosetURIName, XMLUni::fgIDString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedIDREFAttribute(XMLUni::fgInfosetURIName, XMLUni::fgIDRefString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedIDREFSAttribute(XMLUni::fgInfosetURIName, XMLUni::fgIDRefsString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedENTITYAttribute(XMLUni::fgInfosetURIName, XMLUni::fgEntityString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedENTITIESAttribute(XMLUni::fgInfosetURIName, XMLUni::fgEntitiesString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedNMTOKENAttribute(XMLUni::fgInfosetURIName, XMLUni::fgNmTokenString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedNMTOKENSAttribute(XMLUni::fgInfosetURIName, XMLUni::fgNmTokensString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedNOTATIONAttribute(XMLUni::fgInfosetURIName, XMLUni::fgNotationString); +/*static*/ DOMTypeInfoImpl DOMTypeInfoImpl::g_DtdValidatedENUMERATIONAttribute(XMLUni::fgInfosetURIName, XMLUni::fgEnumerationString); + +DOMTypeInfoImpl::DOMTypeInfoImpl(const XMLCh* namespaceUri/*=0*/, const XMLCh* name/*=0*/) +: fBitFields(0), + fTypeName(name), + fTypeNamespace(namespaceUri), + fMemberTypeName(0), + fMemberTypeNamespace(0), + fDefaultValue(0), + fNormalizedValue(0) +{ + // by setting the fBitField to 0 we are also setting: + // - [validity]=VALIDITY_NOTKNOWN + // - [validitation attempted]=VALIDATION_NONE + // - [schema specified]=false +} + +DOMTypeInfoImpl::DOMTypeInfoImpl(DOMDocumentImpl* ownerDoc, const DOMPSVITypeInfo* sourcePSVI) +: fBitFields(0), + fTypeName(0), + fTypeNamespace(0), + fMemberTypeName(0), + fMemberTypeNamespace(0), + fDefaultValue(0), + fNormalizedValue(0) +{ + setNumericProperty(DOMPSVITypeInfo::PSVI_Validity, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Validity)); + setNumericProperty(DOMPSVITypeInfo::PSVI_Validation_Attempted, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Validation_Attempted)); + setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Type, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Type)); + setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Anonymous, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Anonymous)); + setNumericProperty(DOMPSVITypeInfo::PSVI_Nil, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Nil)); + setNumericProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Anonymous, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Anonymous)); + setNumericProperty(DOMPSVITypeInfo::PSVI_Schema_Specified, + sourcePSVI->getNumericProperty(DOMPSVITypeInfo::PSVI_Schema_Specified)); + + setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Name, + ownerDoc->getPooledString(sourcePSVI->getStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Name))); + setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Namespace, + ownerDoc->getPooledString(sourcePSVI->getStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Namespace))); + setStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Name, + ownerDoc->getPooledString(sourcePSVI->getStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Name))); + setStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Namespace, + ownerDoc->getPooledString(sourcePSVI->getStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Namespace))); + setStringProperty(DOMPSVITypeInfo::PSVI_Schema_Default, + ownerDoc->getPooledString(sourcePSVI->getStringProperty(DOMPSVITypeInfo::PSVI_Schema_Default))); + setStringProperty(DOMPSVITypeInfo::PSVI_Schema_Normalized_Value, + ownerDoc->getPooledString(sourcePSVI->getStringProperty(DOMPSVITypeInfo::PSVI_Schema_Normalized_Value))); +} + +const XMLCh* DOMTypeInfoImpl::getTypeName() const { + // if it's a DTD, return the data that was stored + if(!getNumericProperty(PSVI_Schema_Specified)) + return fTypeName; + // if [validity] is "invalid" or "notKnown", the {target namespace} and {name} properties of the declared type if available, otherwise null. + if(!getNumericProperty(PSVI_Validity)) + return fTypeName; + if(fMemberTypeName) + return fMemberTypeName; + return fTypeName; +} + +const XMLCh* DOMTypeInfoImpl::getTypeNamespace() const { + // if it's a DTD, return the data that was stored + if(!getNumericProperty(PSVI_Schema_Specified)) + return fTypeNamespace; + // if [validity] is "invalid" or "notKnown", the {target namespace} and {name} properties of the declared type if available, otherwise null. + if(!getNumericProperty(PSVI_Validity)) + return fTypeNamespace; + if(fMemberTypeName) // we check on the name, as the URI can be NULL + return fMemberTypeNamespace; + return fTypeNamespace; +} + +bool DOMTypeInfoImpl::isDerivedFrom(const XMLCh* typeNamespaceArg, const XMLCh* typeNameArg, DerivationMethods) const +{ + // if it's a DTD, return false + if(!getNumericProperty(PSVI_Schema_Specified)) + return false; + if(XMLString::equals(typeNamespaceArg, getTypeNamespace()) && XMLString::equals(typeNameArg, getTypeName())) + return true; + // TODO: need a pointer to the Grammar object + return false; +} + +const XMLCh* DOMTypeInfoImpl::getStringProperty(PSVIProperty prop) const { + switch(prop) + { + case PSVI_Type_Definition_Name: return fTypeName; + case PSVI_Type_Definition_Namespace: return fTypeNamespace; + case PSVI_Member_Type_Definition_Name: return fMemberTypeName; + case PSVI_Member_Type_Definition_Namespace: return fMemberTypeNamespace; + case PSVI_Schema_Default: return fDefaultValue; + case PSVI_Schema_Normalized_Value: return fNormalizedValue; + default: assert(false); /* it's not a string property */ + } + return 0; +} + +int DOMTypeInfoImpl::getNumericProperty(PSVIProperty prop) const { + switch(prop) + { + case PSVI_Validity: return (PSVIItem::VALIDITY_STATE)(fBitFields & 0x0003); + case PSVI_Validation_Attempted: return (PSVIItem::ASSESSMENT_TYPE)((fBitFields >> 2) & 0x0003); + case PSVI_Type_Definition_Type: return (fBitFields & (1 << 5))?XSTypeDefinition::COMPLEX_TYPE:XSTypeDefinition::SIMPLE_TYPE; + case PSVI_Type_Definition_Anonymous: return (fBitFields & (1 << 6))?true:false; + case PSVI_Nil: return (fBitFields & (1 << 7))?true:false; + case PSVI_Member_Type_Definition_Anonymous: return (fBitFields & (1 << 8))?true:false; + case PSVI_Schema_Specified: return (fBitFields & (1 << 9))?true:false; + default: assert(false); /* it's not a numeric property */ + } + return 0; +} + +void DOMTypeInfoImpl::setStringProperty(PSVIProperty prop, const XMLCh* value) { + switch(prop) + { + case PSVI_Type_Definition_Name: fTypeName=value; break; + case PSVI_Type_Definition_Namespace: fTypeNamespace=value; break; + case PSVI_Member_Type_Definition_Name: fMemberTypeName=value; break; + case PSVI_Member_Type_Definition_Namespace: fMemberTypeNamespace=value; break; + case PSVI_Schema_Default: fDefaultValue=value; break; + case PSVI_Schema_Normalized_Value: fNormalizedValue=value; break; + default: assert(false); /* it's not a string property */ + } +} + +void DOMTypeInfoImpl::setNumericProperty(PSVIProperty prop, int value) { + switch(prop) + { + case PSVI_Validity: fBitFields |= (value & 0x0003); break; + case PSVI_Validation_Attempted: fBitFields |= ((value & 0x0003) << 2); break; + case PSVI_Type_Definition_Type: fBitFields |= (value==XSTypeDefinition::COMPLEX_TYPE)?(1 << 5):0; break; + case PSVI_Type_Definition_Anonymous: fBitFields |= (value!=0)?(1 << 6):0; break; + case PSVI_Nil: fBitFields |= (value!=0)?(1 << 7):0; break; + case PSVI_Member_Type_Definition_Anonymous: fBitFields |= (value!=0)?(1 << 8):0; break; + case PSVI_Schema_Specified: fBitFields |= (value!=0)?(1 << 9):0; break; + default: assert(false); /* it's not a numeric property */ + } +} + + +XERCES_CPP_NAMESPACE_END +/** + * End of file DOMTypeInfo.cpp + */ diff --git a/include/xercesc/dom/impl/DOMTypeInfoImpl.hpp b/include/xercesc/dom/impl/DOMTypeInfoImpl.hpp new file mode 100644 index 0000000..f290fe1 --- /dev/null +++ b/include/xercesc/dom/impl/DOMTypeInfoImpl.hpp @@ -0,0 +1,106 @@ +/* + * 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. + */ + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#if !defined(XERCESC_INCLUDE_GUARD_DOMTYPEINFOIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMTYPEINFOIMPL_HPP + +//------------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------------ +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMDocumentImpl; + +class CDOM_EXPORT DOMTypeInfoImpl : public DOMTypeInfo, public DOMPSVITypeInfo +{ +public: + + //----------------------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------------------- + DOMTypeInfoImpl(const XMLCh* namespaceUri=0, const XMLCh* name=0); + DOMTypeInfoImpl(DOMDocumentImpl* ownerDoc, const DOMPSVITypeInfo* sourcePSVI); + + static DOMTypeInfoImpl g_DtdValidatedElement; + static DOMTypeInfoImpl g_DtdNotValidatedAttribute; + static DOMTypeInfoImpl g_DtdValidatedCDATAAttribute; + static DOMTypeInfoImpl g_DtdValidatedIDAttribute; + static DOMTypeInfoImpl g_DtdValidatedIDREFAttribute; + static DOMTypeInfoImpl g_DtdValidatedIDREFSAttribute; + static DOMTypeInfoImpl g_DtdValidatedENTITYAttribute; + static DOMTypeInfoImpl g_DtdValidatedENTITIESAttribute; + static DOMTypeInfoImpl g_DtdValidatedNMTOKENAttribute; + static DOMTypeInfoImpl g_DtdValidatedNMTOKENSAttribute; + static DOMTypeInfoImpl g_DtdValidatedNOTATIONAttribute; + static DOMTypeInfoImpl g_DtdValidatedENUMERATIONAttribute; + + // ----------------------------------------------------------------------- + // DOMTypeInfo interface + // ----------------------------------------------------------------------- + virtual const XMLCh* getTypeName() const; + virtual const XMLCh* getTypeNamespace() const; + virtual bool isDerivedFrom(const XMLCh* typeNamespaceArg, const XMLCh* typeNameArg, DerivationMethods derivationMethod) const; + + // ----------------------------------------------------------------------- + // DOMPSVITypeInfo interface + // ----------------------------------------------------------------------- + virtual const XMLCh* getStringProperty(PSVIProperty prop) const; + virtual int getNumericProperty(PSVIProperty prop) const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + virtual void setStringProperty(PSVIProperty prop, const XMLCh* value); + virtual void setNumericProperty(PSVIProperty prop, int value); + +protected: + int fBitFields; + const XMLCh* fTypeName; + const XMLCh* fTypeNamespace; + const XMLCh* fMemberTypeName; + const XMLCh* fMemberTypeNamespace; + const XMLCh* fDefaultValue; + const XMLCh* fNormalizedValue; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMTypeInfoImpl (const DOMTypeInfoImpl&); + DOMTypeInfoImpl & operator = (const DOMTypeInfoImpl &); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DOMTypeInfo.hpp + */ diff --git a/include/xercesc/dom/impl/DOMXPathExpressionImpl.cpp b/include/xercesc/dom/impl/DOMXPathExpressionImpl.cpp new file mode 100644 index 0000000..f832d8a --- /dev/null +++ b/include/xercesc/dom/impl/DOMXPathExpressionImpl.cpp @@ -0,0 +1,216 @@ +/* + * 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. + */ + +#include "DOMXPathExpressionImpl.hpp" +#include "DOMXPathResultImpl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class WrapperForXPathNSResolver : public XercesNamespaceResolver +{ +public: + WrapperForXPathNSResolver(XMLStringPool* pool, const DOMXPathNSResolver *resolver, MemoryManager* const manager) : + fStringPool(pool), + fResolver(resolver), + fMemoryManager(manager) + { + } + + virtual unsigned int getNamespaceForPrefix(const XMLCh* const prefix) const + { + if(fResolver==NULL) + throw DOMException(DOMException::NAMESPACE_ERR, 0, fMemoryManager); + const XMLCh* nsUri=fResolver->lookupNamespaceURI(prefix); + if(nsUri==NULL) + throw DOMException(DOMException::NAMESPACE_ERR, 0, fMemoryManager); + return fStringPool->addOrFind(nsUri); + } + +protected: + XMLStringPool* fStringPool; + const DOMXPathNSResolver * fResolver; + MemoryManager* const fMemoryManager; +}; + + +typedef JanitorMemFunCall CleanupType; + +DOMXPathExpressionImpl::DOMXPathExpressionImpl(const XMLCh *expression, const DOMXPathNSResolver *resolver, MemoryManager* const manager) : + fStringPool(NULL), + fParsedExpression(NULL), + fExpression(NULL), + fMoveToRoot(false), + fMemoryManager(manager) +{ + if(expression==NULL || *expression==0) + throw DOMXPathException(DOMXPathException::INVALID_EXPRESSION_ERR, 0, fMemoryManager); + + CleanupType cleanup(this, &DOMXPathExpressionImpl::cleanUp); + fStringPool = new (fMemoryManager) XMLStringPool(109, fMemoryManager); + // XercesPath will complain if the expression starts with '/', add a "." in front of it and start from the document root + if(*expression==chForwardSlash) + { + fExpression=(XMLCh*)fMemoryManager->allocate((XMLString::stringLen(expression)+2)*sizeof(XMLCh)); + *fExpression = chPeriod; + *(fExpression+1) = chNull; + XMLString::catString(fExpression, expression); + fMoveToRoot=true; + } + else + fExpression=XMLString::replicate(expression); + + try + { + WrapperForXPathNSResolver wrappedResolver(fStringPool, resolver, fMemoryManager); + fParsedExpression = new (fMemoryManager) XercesXPath(fExpression, fStringPool, &wrappedResolver, 0, true, fMemoryManager); + } + catch(const XPathException& ) + { + throw DOMXPathException(DOMXPathException::INVALID_EXPRESSION_ERR, 0, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +DOMXPathExpressionImpl::~DOMXPathExpressionImpl() +{ + cleanUp(); +} + +void DOMXPathExpressionImpl::cleanUp() +{ + XMLString::release(&fExpression, fMemoryManager); + delete fParsedExpression; + delete fStringPool; +} + +DOMXPathResult* DOMXPathExpressionImpl::evaluate(const DOMNode *contextNode, + DOMXPathResult::ResultType type, + DOMXPathResult* result) const +{ + if(type!=DOMXPathResult::FIRST_ORDERED_NODE_TYPE && type!=DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE && + type!=DOMXPathResult::ANY_UNORDERED_NODE_TYPE && type!=DOMXPathResult::UNORDERED_NODE_SNAPSHOT_TYPE) + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); + + if(contextNode==NULL || contextNode->getNodeType()!=DOMNode::ELEMENT_NODE) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager); + + JanitorMemFunCall r_cleanup ( + 0, &DOMXPathResultImpl::release); + DOMXPathResultImpl* r=(DOMXPathResultImpl*)result; + if(r==NULL) + { + r=new (fMemoryManager) DOMXPathResultImpl(type, fMemoryManager); + r_cleanup.reset (r); + } + else + r->reset(type); + + XPathMatcher matcher(fParsedExpression, fMemoryManager); + matcher.startDocumentFragment(); + + if(fMoveToRoot) + { + contextNode=contextNode->getOwnerDocument(); + if(contextNode==NULL) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager); + + QName qName(contextNode->getNodeName(), 0, fMemoryManager); + SchemaElementDecl elemDecl(&qName); + RefVectorOf attrList(0, true, fMemoryManager); + matcher.startElement(elemDecl, 0, XMLUni::fgZeroLenString, attrList, 0); + DOMNode* child=contextNode->getFirstChild(); + while(child) + { + if(child->getNodeType()==DOMNode::ELEMENT_NODE) + testNode(&matcher, r, (DOMElement*)child); + child=child->getNextSibling(); + } + matcher.endElement(elemDecl, XMLUni::fgZeroLenString); + } + else + testNode(&matcher, r, (DOMElement*)contextNode); + + r_cleanup.release (); + return r; +} + +bool DOMXPathExpressionImpl::testNode(XPathMatcher* matcher, DOMXPathResultImpl* result, DOMElement *node) const +{ + int uriId=fStringPool->addOrFind(node->getNamespaceURI()); + QName qName(node->getNodeName(), uriId, fMemoryManager); + SchemaElementDecl elemDecl(&qName); + DOMNamedNodeMap* attrMap=node->getAttributes(); + XMLSize_t attrCount = attrMap->getLength(); + RefVectorOf attrList(attrCount, true, fMemoryManager); + for(XMLSize_t i=0;iitem(i); + attrList.addElement(new (fMemoryManager) XMLAttr(fStringPool->addOrFind(attr->getNamespaceURI()), + attr->getNodeName(), + attr->getNodeValue(), + XMLAttDef::CData, + attr->getSpecified(), + fMemoryManager, + NULL, + true)); + } + matcher->startElement(elemDecl, uriId, node->getPrefix(), attrList, attrCount); + unsigned char nMatch=matcher->isMatched(); + if(nMatch!=0 && nMatch!=XPathMatcher::XP_MATCHED_DP) + { + result->addResult(node); + if(result->getResultType()==DOMXPathResult::ANY_UNORDERED_NODE_TYPE || result->getResultType()==DOMXPathResult::FIRST_ORDERED_NODE_TYPE) + return true; // abort navigation, we found one result + } + + if(nMatch==0 || nMatch==XPathMatcher::XP_MATCHED_D || nMatch==XPathMatcher::XP_MATCHED_DP) + { + DOMNode* child=node->getFirstChild(); + while(child) + { + if(child->getNodeType()==DOMNode::ELEMENT_NODE) + if(testNode(matcher, result, (DOMElement*)child)) + return true; + child=child->getNextSibling(); + } + } + matcher->endElement(elemDecl, XMLUni::fgZeroLenString); + return false; +} + +void DOMXPathExpressionImpl::release() +{ + DOMXPathExpressionImpl* me = this; + delete me; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMXPathExpressionImpl.hpp b/include/xercesc/dom/impl/DOMXPathExpressionImpl.hpp new file mode 100644 index 0000000..efeec36 --- /dev/null +++ b/include/xercesc/dom/impl/DOMXPathExpressionImpl.hpp @@ -0,0 +1,69 @@ +/* + * 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: DOMXPathExpressionImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHEXPRESSIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHEXPRESSIONIMPL_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMElement; +class XercesXPath; +class XPathMatcher; +class DOMXPathResultImpl; +class DOMXPathNSResolver; +class XMLStringPool; + +class CDOM_EXPORT DOMXPathExpressionImpl : public XMemory, + public DOMXPathExpression +{ +public: + DOMXPathExpressionImpl(const XMLCh *expression, + const DOMXPathNSResolver *resolver, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual ~DOMXPathExpressionImpl(); + + virtual DOMXPathResult* evaluate(const DOMNode *contextNode, + DOMXPathResult::ResultType type, + DOMXPathResult* result) const; + + virtual void release(); + +protected: + bool testNode(XPathMatcher* matcher, + DOMXPathResultImpl* result, + DOMElement *node) const; + void cleanUp(); + + XMLStringPool* fStringPool; + XercesXPath* fParsedExpression; + XMLCh* fExpression; + bool fMoveToRoot; + + MemoryManager* const fMemoryManager; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/DOMXPathNSResolverImpl.cpp b/include/xercesc/dom/impl/DOMXPathNSResolverImpl.cpp new file mode 100644 index 0000000..960046e --- /dev/null +++ b/include/xercesc/dom/impl/DOMXPathNSResolverImpl.cpp @@ -0,0 +1,109 @@ +/* + * 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. + */ + +#include "DOMXPathNSResolverImpl.hpp" +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMXPathNSResolverImpl::DOMXPathNSResolverImpl(const DOMNode *nodeResolver, MemoryManager* const manager) : + fNamespaceBindings(0), + fResolverNode(nodeResolver), + fManager(manager) +{ + fNamespaceBindings = new (fManager) RefHashTableOf(7, true, fManager); +} + +DOMXPathNSResolverImpl::~DOMXPathNSResolverImpl() +{ + delete fNamespaceBindings; +} + +const XMLCh* DOMXPathNSResolverImpl::lookupNamespaceURI(const XMLCh* prefix) const +{ + if(prefix == 0) prefix = XMLUni::fgZeroLenString; + + if(XMLString::equals(prefix, XMLUni::fgXMLString)) + return XMLUni::fgXMLURIName; + + const KVStringPair *pair = fNamespaceBindings->get((void*)prefix); + if(pair) { + + // An empty namespace URI indicated that this binding was removed + // by the user. + // + if(*pair->getValue() == 0) return NULL; + + return pair->getValue(); + } + + if(fResolverNode) + return fResolverNode->lookupNamespaceURI( + *prefix == 0 ? 0 : prefix); // Expects 0 for default namespace. + + return NULL; +} + +const XMLCh* DOMXPathNSResolverImpl::lookupPrefix(const XMLCh* uri) const +{ + if (uri == 0 || *uri == 0) + return 0; + + if(XMLString::equals(uri, XMLUni::fgXMLURIName)) + return XMLUni::fgXMLString; + + RefHashTableOfEnumerator enumerator((RefHashTableOf*)fNamespaceBindings); + while(enumerator.hasMoreElements()) { + KVStringPair &pair = enumerator.nextElement(); + if(XMLString::equals(pair.getValue(), uri)) { + return pair.getKey(); + } + } + + if(fResolverNode) + { + const XMLCh* r = fResolverNode->lookupPrefix(uri); + + if (r == 0 && fResolverNode->isDefaultNamespace(uri)) + r = XMLUni::fgZeroLenString; + + return r; + } + + return 0; +} + +void DOMXPathNSResolverImpl::addNamespaceBinding(const XMLCh* prefix, const XMLCh* uri) +{ + if(prefix == 0) prefix = XMLUni::fgZeroLenString; + if(uri == 0) uri = XMLUni::fgZeroLenString; + + KVStringPair* pair = new (fManager) KVStringPair(prefix, uri, fManager); + + fNamespaceBindings->put((void*)pair->getKey(), pair); +} + +void DOMXPathNSResolverImpl::release() +{ + DOMXPathNSResolverImpl* me=(DOMXPathNSResolverImpl*)this; + delete me; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMXPathNSResolverImpl.hpp b/include/xercesc/dom/impl/DOMXPathNSResolverImpl.hpp new file mode 100644 index 0000000..c27d88c --- /dev/null +++ b/include/xercesc/dom/impl/DOMXPathNSResolverImpl.hpp @@ -0,0 +1,58 @@ +/* + * 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: DOMXPathNSResolverImpl.hpp 657774 2008-05-19 09:59:33Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHNSRESOLVERIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHNSRESOLVERIMPL_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMNode; + +class CDOM_EXPORT DOMXPathNSResolverImpl : public XMemory, + public DOMXPathNSResolver +{ +public: + DOMXPathNSResolverImpl(const DOMNode* nodeResolver = 0, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~DOMXPathNSResolverImpl(); + + virtual const XMLCh* lookupNamespaceURI(const XMLCh* prefix) const; + virtual const XMLCh* lookupPrefix(const XMLCh* URI) const; + virtual void addNamespaceBinding(const XMLCh* prefix, const XMLCh* uri); + + virtual void release(); + +protected: + RefHashTableOf* fNamespaceBindings; + const DOMNode* fResolverNode; + MemoryManager* fManager; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + + diff --git a/include/xercesc/dom/impl/DOMXPathResultImpl.cpp b/include/xercesc/dom/impl/DOMXPathResultImpl.cpp new file mode 100644 index 0000000..ffaf4f6 --- /dev/null +++ b/include/xercesc/dom/impl/DOMXPathResultImpl.cpp @@ -0,0 +1,138 @@ +/* + * 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. + */ + +#include "DOMXPathResultImpl.hpp" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMXPathResultImpl::DOMXPathResultImpl(ResultType type, + MemoryManager* const manager) + : fType(type), + fMemoryManager(manager), + fIndex (0) +{ + fSnapshot = new (fMemoryManager) RefVectorOf(13, false, fMemoryManager); +} + +DOMXPathResultImpl::~DOMXPathResultImpl() +{ + delete fSnapshot; +} + +// +// +DOMXPathResult::ResultType DOMXPathResultImpl::getResultType() const +{ + return fType; +} + +const DOMTypeInfo* DOMXPathResultImpl::getTypeInfo() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +bool DOMXPathResultImpl::isNode() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +bool DOMXPathResultImpl::getBooleanValue() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +int DOMXPathResultImpl::getIntegerValue() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +double DOMXPathResultImpl::getNumberValue() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +const XMLCh* DOMXPathResultImpl::getStringValue() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +DOMNode* DOMXPathResultImpl::getNodeValue() const +{ + if(fType == ANY_UNORDERED_NODE_TYPE || fType == FIRST_ORDERED_NODE_TYPE) + { + return fSnapshot->size() > 0 ? fSnapshot->elementAt(0) : 0; + } + else if (fType==UNORDERED_NODE_SNAPSHOT_TYPE || fType==ORDERED_NODE_SNAPSHOT_TYPE) + { + return fIndex < fSnapshot->size() ? fSnapshot->elementAt(fIndex) : 0; + } + else + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +bool DOMXPathResultImpl::iterateNext() +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +bool DOMXPathResultImpl::getInvalidIteratorState() const +{ + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +bool DOMXPathResultImpl::snapshotItem(XMLSize_t index) +{ + if(fType==UNORDERED_NODE_SNAPSHOT_TYPE || fType==ORDERED_NODE_SNAPSHOT_TYPE) + { + fIndex = index; + return fIndex < fSnapshot->size(); + } + else + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +XMLSize_t DOMXPathResultImpl::getSnapshotLength() const +{ + if(fType==UNORDERED_NODE_SNAPSHOT_TYPE || fType==ORDERED_NODE_SNAPSHOT_TYPE) + return fSnapshot->size(); + else + throw DOMXPathException(DOMXPathException::TYPE_ERR, 0, fMemoryManager); +} + +void DOMXPathResultImpl::release() +{ + DOMXPathResultImpl* me = this; + delete me; +} + +// +// +void DOMXPathResultImpl::reset(ResultType type) +{ + fType = type; + fSnapshot->removeAllElements(); + fIndex = 0; +} + +void DOMXPathResultImpl::addResult(DOMNode* node) +{ + fSnapshot->addElement(node); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/DOMXPathResultImpl.hpp b/include/xercesc/dom/impl/DOMXPathResultImpl.hpp new file mode 100644 index 0000000..4033f48 --- /dev/null +++ b/include/xercesc/dom/impl/DOMXPathResultImpl.hpp @@ -0,0 +1,66 @@ +/* + * 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: DOMXPathResultImpl.hpp 671894 2008-06-26 13:29:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMXPATHRESULTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMXPATHRESULTIMPL_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class CDOM_EXPORT DOMXPathResultImpl : public XMemory, + public DOMXPathResult +{ +public: + DOMXPathResultImpl(ResultType type, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~DOMXPathResultImpl(); + + virtual ResultType getResultType() const; + virtual const DOMTypeInfo *getTypeInfo() const; + virtual bool isNode() const; + virtual bool getBooleanValue() const; + virtual int getIntegerValue() const; + virtual double getNumberValue() const; + virtual const XMLCh* getStringValue() const; + virtual DOMNode* getNodeValue() const; + virtual bool iterateNext(); + virtual bool getInvalidIteratorState() const; + virtual bool snapshotItem(XMLSize_t); + virtual XMLSize_t getSnapshotLength() const; + + virtual void release(); + +public: + void reset(ResultType type); + void addResult(DOMNode* node); + +protected: + ResultType fType; + MemoryManager* const fMemoryManager; + RefVectorOf* fSnapshot; + XMLSize_t fIndex; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/dom/impl/XSDElementNSImpl.cpp b/include/xercesc/dom/impl/XSDElementNSImpl.cpp new file mode 100644 index 0000000..bdfc35e --- /dev/null +++ b/include/xercesc/dom/impl/XSDElementNSImpl.cpp @@ -0,0 +1,63 @@ +/* + * 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: XSDElementNSImpl.cpp 678381 2008-07-21 10:15:01Z borisk $ + */ +#include +#include + +#include "DOMDocumentImpl.hpp" +#include "XSDElementNSImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +XSDElementNSImpl::XSDElementNSImpl(DOMDocument *ownerDoc, const XMLCh *nam) : + DOMElementNSImpl(ownerDoc, nam) + , fLineNo(0) + , fColumnNo(0) +{ +} + +//Introduced in DOM Level 2 +XSDElementNSImpl::XSDElementNSImpl(DOMDocument *ownerDoc, + const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + const XMLFileLoc lineNo, + const XMLFileLoc columnNo) : + DOMElementNSImpl(ownerDoc, namespaceURI, qualifiedName) + , fLineNo(lineNo) + , fColumnNo(columnNo) +{ +} + +XSDElementNSImpl::XSDElementNSImpl(const XSDElementNSImpl &other, bool deep) : + DOMElementNSImpl(other, deep) +{ + this->fLineNo = other.fLineNo; + this->fColumnNo =other.fColumnNo; +} + +DOMNode * XSDElementNSImpl::cloneNode(bool deep) const { + DOMNode* newNode = new (fParent.fOwnerDocument) XSDElementNSImpl(*this, deep); + fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); + return newNode; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/dom/impl/XSDElementNSImpl.hpp b/include/xercesc/dom/impl/XSDElementNSImpl.hpp new file mode 100644 index 0000000..e746a40 --- /dev/null +++ b/include/xercesc/dom/impl/XSDElementNSImpl.hpp @@ -0,0 +1,71 @@ +/* + * 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: XSDElementNSImpl.hpp 672232 2008-06-27 10:16:38Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSDELEMENTNSIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_XSDELEMENTNSIMPL_HPP + +// +// This file is part of the internal implementation of the C++ XML DOM. +// It is used by TraverseSchema to store line/column information. +// It should NOT be included or used directly by application programs. +// +// Applications should include the file for the entire +// DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class +// name is substituded for the *. +// + + +#include "DOMElementNSImpl.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + + +class CDOM_EXPORT XSDElementNSImpl: public DOMElementNSImpl { +protected: + XMLFileLoc fLineNo; //Line number + XMLFileLoc fColumnNo; //Column number + + +public: + XSDElementNSImpl(DOMDocument *ownerDoc, const XMLCh *name); + XSDElementNSImpl(DOMDocument *ownerDoc, //DOM Level 2 + const XMLCh *namespaceURI, + const XMLCh *qualifiedName, + const XMLFileLoc lineNo, + const XMLFileLoc columnNo); + XSDElementNSImpl(const XSDElementNSImpl &other, bool deep=false); + + virtual DOMNode * cloneNode(bool deep) const; + + XMLFileLoc getLineNo() const { return fLineNo; } + XMLFileLoc getColumnNo() const { return fColumnNo; } + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSDElementNSImpl& operator=(const XSDElementNSImpl&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/BinOutputStream.cpp b/include/xercesc/framework/BinOutputStream.cpp new file mode 100644 index 0000000..16ed997 --- /dev/null +++ b/include/xercesc/framework/BinOutputStream.cpp @@ -0,0 +1,45 @@ +/* + * 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: BinOutputStream.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// BinOutputStream: Virtual destructor! +// --------------------------------------------------------------------------- +BinOutputStream::~BinOutputStream() +{ +} + + +// --------------------------------------------------------------------------- +// BinOutputStream: Hidden Constructors +// --------------------------------------------------------------------------- +BinOutputStream::BinOutputStream() +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/BinOutputStream.hpp b/include/xercesc/framework/BinOutputStream.hpp new file mode 100644 index 0000000..25dddab --- /dev/null +++ b/include/xercesc/framework/BinOutputStream.hpp @@ -0,0 +1,65 @@ +/* + * 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: BinOutputStream.hpp 553915 2007-07-06 14:57:08Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BIN_OUTPUT_STREAM_HPP) +#define XERCESC_INCLUDE_GUARD_BIN_OUTPUT_STREAM_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BinOutputStream : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Virtual destructor for derived classes + // ----------------------------------------------------------------------- + virtual ~BinOutputStream(); + + // ----------------------------------------------------------------------- + // The virtual output stream interface + // ----------------------------------------------------------------------- + virtual XMLFilePos curPos() const = 0; + + virtual void writeBytes + ( + const XMLByte* const toGo + , const XMLSize_t maxToWrite + ) = 0; + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + BinOutputStream(); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented Constructors + // ----------------------------------------------------------------------- + BinOutputStream(const BinOutputStream&); + BinOutputStream& operator=(const BinOutputStream&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/LocalFileFormatTarget.cpp b/include/xercesc/framework/LocalFileFormatTarget.cpp new file mode 100644 index 0000000..2cd2389 --- /dev/null +++ b/include/xercesc/framework/LocalFileFormatTarget.cpp @@ -0,0 +1,154 @@ +/* + * 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: LocalFileFormatTarget.cpp 1662880 2015-02-28 01:55:31Z scantor $ + */ + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +const XMLSize_t MAX_BUFFER_SIZE = 65536; + +LocalFileFormatTarget::LocalFileFormatTarget( const XMLCh* const fileName + , MemoryManager* const manager) +: fSource(0) +, fDataBuf(0) +, fIndex(0) +, fCapacity(1024) +, fMemoryManager(manager) +{ + fSource = XMLPlatformUtils::openFileToWrite(fileName, manager); + + if (fSource == (FileHandle) XERCES_Invalid_File_Handle) + ThrowXMLwithMemMgr1(IOException, XMLExcepts::File_CouldNotOpenFile, fileName, fMemoryManager); + + fDataBuf = (XMLByte*) fMemoryManager->allocate ( + fCapacity * sizeof(XMLByte)); +} + +LocalFileFormatTarget::LocalFileFormatTarget( const char* const fileName + , MemoryManager* const manager) +: fSource(0) +, fDataBuf(0) +, fIndex(0) +, fCapacity(1024) +, fMemoryManager(manager) +{ + fSource = XMLPlatformUtils::openFileToWrite(fileName, manager); + + if (fSource == (FileHandle) XERCES_Invalid_File_Handle) + ThrowXMLwithMemMgr1(IOException, XMLExcepts::File_CouldNotOpenFile, fileName, fMemoryManager); + + fDataBuf = (XMLByte*) fMemoryManager->allocate ( + fCapacity * sizeof(XMLByte)); +} + +LocalFileFormatTarget::~LocalFileFormatTarget() +{ + if (fSource && fSource != (FileHandle) XERCES_Invalid_File_Handle) + { + try + { + // flush remaining buffer before destroy + flush(); + } + catch (...) + { + // There is nothing we can do about it here. + } + // XERCESC-2024: use separate try/catch so that we close the handle + // even when flush() failed (e.g. because of a disk full) + try + { + XMLPlatformUtils::closeFile(fSource, fMemoryManager); + } + catch (...) + { + // There is nothing we can do about it here. + } + } + + fMemoryManager->deallocate(fDataBuf);//delete [] fDataBuf; +} + +void LocalFileFormatTarget::flush() +{ + XMLPlatformUtils::writeBufferToFile(fSource, fIndex, fDataBuf, fMemoryManager); + fIndex = 0; +} + +void LocalFileFormatTarget::writeChars(const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter * const) +{ + if (count == 0) + return; + if (count < MAX_BUFFER_SIZE) + { + // If we don't have enough space, see if we can grow the buffer. + // + if (fIndex + count > fCapacity && fCapacity < MAX_BUFFER_SIZE) + ensureCapacity (count); + + // If still not enough space, flush the buffer. + // + if (fIndex + count > fCapacity) + flush(); + + memcpy(&fDataBuf[fIndex], toWrite, count * sizeof(XMLByte)); + fIndex += count; + } + else + { + // block is too big to cache, flush the current cache... + // + if (fIndex) + flush(); + + //... then write the data directly to disk + // + XMLPlatformUtils::writeBufferToFile(fSource, count, toWrite, fMemoryManager); + } +} + +void LocalFileFormatTarget::ensureCapacity(const XMLSize_t extraNeeded) +{ + XMLSize_t newCap = fCapacity * 2; + + while (fIndex + extraNeeded > newCap) + newCap *= 2; + + XMLByte* newBuf = (XMLByte*) fMemoryManager->allocate ( + newCap * sizeof(XMLByte)); + + // Copy over the old stuff + memcpy(newBuf, fDataBuf, fIndex * sizeof(XMLByte)); + + // Clean up old buffer and store new stuff + fMemoryManager->deallocate(fDataBuf); + fDataBuf = newBuf; + fCapacity = newCap; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/LocalFileFormatTarget.hpp b/include/xercesc/framework/LocalFileFormatTarget.hpp new file mode 100644 index 0000000..e7cc279 --- /dev/null +++ b/include/xercesc/framework/LocalFileFormatTarget.hpp @@ -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: LocalFileFormatTarget.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_LOCALFILEFORMATTARGET_HPP) +#define XERCESC_INCLUDE_GUARD_LOCALFILEFORMATTARGET_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT LocalFileFormatTarget : public XMLFormatTarget { +public: + + /** @name constructors and destructor */ + //@{ + LocalFileFormatTarget + ( + const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + LocalFileFormatTarget + ( + const char* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + ~LocalFileFormatTarget(); + //@} + + // ----------------------------------------------------------------------- + // Implementations of the format target interface + // ----------------------------------------------------------------------- + virtual void writeChars(const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter* const formatter); + + virtual void flush(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented methods. + // ----------------------------------------------------------------------- + LocalFileFormatTarget(const LocalFileFormatTarget&); + LocalFileFormatTarget& operator=(const LocalFileFormatTarget&); + + // ----------------------------------------------------------------------- + // Private helpers + // ----------------------------------------------------------------------- + void ensureCapacity(const XMLSize_t extraNeeded); + + // ----------------------------------------------------------------------- + // Private data members + // + // fSource + // The source file that we represent. The FileHandle type is defined + // per platform. + // + // fDataBuf + // The pointer to the buffer data. Its always + // one larger than fCapacity, to leave room for the null terminator. + // + // fIndex + // The current index into the buffer, as characters are appended + // to it. If its zero, then the buffer is empty. + // + // fCapacity + // The current capacity of the buffer. Its actually always one + // larger, to leave room for the null terminator. + // ----------------------------------------------------------------------- + FileHandle fSource; + XMLByte* fDataBuf; + XMLSize_t fIndex; + XMLSize_t fCapacity; + MemoryManager* fMemoryManager; +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/LocalFileInputSource.cpp b/include/xercesc/framework/LocalFileInputSource.cpp new file mode 100644 index 0000000..f5adce8 --- /dev/null +++ b/include/xercesc/framework/LocalFileInputSource.cpp @@ -0,0 +1,172 @@ +/* + * 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. + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*** + * + * Originated by Chris larsson + * + * Issue: + * + * There is an inconsistency in URI resolution in the case where the file itself is a + * symbolic link to another path (or the path has path segment which is a symbolic + * link to another path). So, is the base path the directory where the symbolic link resides + * or the directory where the real file resides? I'm sure one could argue either way, + * but I think that having the base path be the directory where the symbolic link resides + * is more intuitive. + * + * Defining it this way would then make the behavior consistent with using an absolute + * path as well as with the java behavior. + * + * Proposal: + * + * The URI is resolved within the parser code, and is somewhat independant of the OS. + * + * A relative path is resolved by querying the current directory and appending the + * relative part onto the returned current directory string to obtain the base URI. + * An absolute path is simply used as the base URI. + * Then remove all "./" and "../" path segments using an algorithm like weavepath to obtain + * the resolved base URI. + * + * When you need to access another file such as a dtd, use the resolved base URI and add on + * the relative URI of the dtd file. Then resolve it using the same weavepath algorithm. + * + * Note: + * + * Java parser behaves differently for a path containning symbolic path segment. When + * it is given an absolute path, it can locate the primary instance document, while given + * relative path, it might not. + * + * It is because Java parser uses URI solution where "/segment/../" is required to be removed + * from the resultant path if a relative URI is merged to a baseURI. While this is NOT required + * for an absolute URI. + * + * So if a path segment, which is symbolic link, happen to be followed by the '/../', it is + * NOT removed from the path if it is given in absolute form, and the underlying file system + * will locate the file, if in relative form, that symbolic link path segment together with + * '../' is removed from the resultant path, and the file system may NOT be able to locate + * the file, if there is a one, it is definitely not the one expected, in fact by accident. + * + * Therefore, to keep consistent with Java parser, for now, we do not apply removeDotDotSlash() + * for absolute path. + * + ***/ + +// --------------------------------------------------------------------------- +// LocalFileInputSource: Constructors and Destructor +// --------------------------------------------------------------------------- +LocalFileInputSource::LocalFileInputSource( const XMLCh* const basePath + , const XMLCh* const relativePath + , MemoryManager* const manager) + : InputSource(manager) +{ + // + // If the relative part is really relative, then weave it together + // with the base path. If not, just take the relative path as the + // entire path. + // + if (XMLPlatformUtils::isRelative(relativePath, manager)) + { + XMLCh* tmpBuf = XMLPlatformUtils::weavePaths(basePath, relativePath, manager); + setSystemId(tmpBuf); + manager->deallocate(tmpBuf); //delete [] tmpBuf; + } + else + { + XMLCh* tmpBuf = XMLString::replicate(relativePath, manager); + XMLPlatformUtils::removeDotSlash(tmpBuf, manager); + setSystemId(tmpBuf); + manager->deallocate(tmpBuf);//delete [] tmpBuf; + } + +} + +LocalFileInputSource::LocalFileInputSource(const XMLCh* const filePath, + MemoryManager* const manager) + : InputSource(manager) +{ + + // + // If the path is relative, then complete it acording to the current + // working directory rules of the current platform. Else, just take + // it as is. + // + if (XMLPlatformUtils::isRelative(filePath, manager)) + { + XMLCh* curDir = XMLPlatformUtils::getCurrentDirectory(manager); + + XMLSize_t curDirLen = XMLString::stringLen(curDir); + XMLSize_t filePathLen = XMLString::stringLen(filePath); + XMLCh* fullDir = (XMLCh*) manager->allocate + ( + (curDirLen + filePathLen + 2) * sizeof(XMLCh) + );//new XMLCh [ curDirLen + filePathLen + 2]; + + XMLString::copyString(fullDir, curDir); + fullDir[curDirLen] = chForwardSlash; + XMLString::copyString(&fullDir[curDirLen+1], filePath); + + XMLPlatformUtils::removeDotSlash(fullDir, manager); + XMLPlatformUtils::removeDotDotSlash(fullDir, manager); + + setSystemId(fullDir); + + manager->deallocate(curDir);//delete [] curDir; + manager->deallocate(fullDir);//delete [] fullDir; + } + else + { + XMLCh* tmpBuf = XMLString::replicate(filePath, manager); + XMLPlatformUtils::removeDotSlash(tmpBuf, manager); + setSystemId(tmpBuf); + manager->deallocate(tmpBuf);//delete [] tmpBuf; + } + +} + +LocalFileInputSource::~LocalFileInputSource() +{ +} + + +// --------------------------------------------------------------------------- +// LocalFileInputSource: InputSource interface implementation +// --------------------------------------------------------------------------- +BinInputStream* LocalFileInputSource::makeStream() const +{ + BinFileInputStream* retStrm = new (getMemoryManager()) BinFileInputStream(getSystemId(), getMemoryManager()); + if (!retStrm->getIsOpen()) + { + delete retStrm; + return 0; + } + return retStrm; +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/LocalFileInputSource.hpp b/include/xercesc/framework/LocalFileInputSource.hpp new file mode 100644 index 0000000..4f12117 --- /dev/null +++ b/include/xercesc/framework/LocalFileInputSource.hpp @@ -0,0 +1,152 @@ +/* + * 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: LocalFileInputSource.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + + +#if !defined(XERCESC_INCLUDE_GUARD_LOCALFILEINPUTSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_LOCALFILEINPUTSOURCE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class BinInputStream; + +/** + * This class is a derivative of the standard InputSource class. It provides + * for the parser access to data which is referenced via a local file path, + * as apposed to remote file or URL. This is the most efficacious mechanism + * by which local files can be parsed, since the parse knows that it refers + * to a local file and will make no other attempts to interpret the passed + * path. + * + * The path provided can either be a fully qualified path or a relative path. + * If relative, it will be completed either relative to a passed base path + * or relative to the current working directory of the process. + * + * As with all InputSource derivatives. The primary objective of an input + * source is to create an input stream via which the parser can spool in + * data from the referenced source. + */ +class XMLPARSER_EXPORT LocalFileInputSource : public InputSource +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors */ + //@{ + + /** + * A local file input source requires a path to the file to load. This + * can be provided either as a fully qualified path, a path relative to + * the current working directly, or a path relative to a provided base + * path. + * + * The completed path will become the system id of this input source. + * The constructors don't take any public id for local files, but you + * still set them via the parent class' setPublicId() method of course. + * + * This constructor takes an explicit base path and a possibly relative + * path. If the relative path is seen to be fully qualified, it is used + * as is. Otherwise, it is made relative to the passed base path. + * + * @param basePath The base path from which the passed relative path + * will be based, if the relative part is indeed + * relative. + * + * @param relativePath The relative part of the path. It can actually + * be fully qualified, in which case it is taken + * as is. + * + * @param manager Pointer to the memory manager to be used to + * allocate objects. + * + * @exception XMLException If the path is relative and doesn't properly + * resolve to a file. + */ + LocalFileInputSource + ( + const XMLCh* const basePath + , const XMLCh* const relativePath + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * This constructor takes a single parameter which is the fully qualified + * or relative path. If it is fully qualified, it is taken as is. If it is + * relative, then it is completed relative to the current working directory + * (or the equivalent on the local host machine.) + * + * The completed path will become the system id of this input source. + * The constructors don't take any public id for local files, but you + * still set them via the parent class' setPublicId() method of course. + * + * @param filePath The relative or fully qualified path. + * + * @param manager Pointer to the memory manager to be used to + * allocate objects. + * + * @exception XMLException If the path is relative and doesn't properly + * resolve to a file. + */ + LocalFileInputSource + ( + const XMLCh* const filePath + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + //@} + + /** @name Destructor */ + //@{ + ~LocalFileInputSource(); + //@} + + + // ----------------------------------------------------------------------- + // Virtual input source interface + // ----------------------------------------------------------------------- + + /** @name Virtual methods */ + //@{ + + /** + * This method will return a binary input stream derivative that will + * parse from the local file indicatedby the system id. + * + * @return A dynamically allocated binary input stream derivative that + * can parse from the file indicated by the system id. + */ + virtual BinInputStream* makeStream() const; + + //@} +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + LocalFileInputSource(const LocalFileInputSource&); + LocalFileInputSource& operator=(const LocalFileInputSource&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/MemBufFormatTarget.cpp b/include/xercesc/framework/MemBufFormatTarget.cpp new file mode 100644 index 0000000..512cd87 --- /dev/null +++ b/include/xercesc/framework/MemBufFormatTarget.cpp @@ -0,0 +1,105 @@ +/* + * 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: MemBufFormatTarget.cpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MemBufFormatTarget::MemBufFormatTarget( XMLSize_t initCapacity + , MemoryManager* const manager) + : fMemoryManager(manager) + , fDataBuf(0) + , fIndex(0) + , fCapacity(initCapacity) +{ + // Buffer is one larger than capacity, to allow for zero term + fDataBuf = (XMLByte*) fMemoryManager->allocate + ( + (fCapacity + 4) * sizeof(XMLByte) + );//new XMLByte[fCapacity+4]; + + // Keep it null terminated + fDataBuf[0] = XMLByte(0); +} + +MemBufFormatTarget::~MemBufFormatTarget() +{ + fMemoryManager->deallocate(fDataBuf);//delete [] fDataBuf; +} + +void MemBufFormatTarget::writeChars(const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter * const) +{ + + if (count) + { + if (fIndex + count >= fCapacity) + ensureCapacity(count); + + memcpy(&fDataBuf[fIndex], toWrite, count * sizeof(XMLByte)); + fIndex += count; + } + +} + +const XMLByte* MemBufFormatTarget::getRawBuffer() const +{ + fDataBuf[fIndex] = 0; + fDataBuf[fIndex + 1] = 0; + fDataBuf[fIndex + 2] = 0; + fDataBuf[fIndex + 3] = 0; + return fDataBuf; +} + +void MemBufFormatTarget::reset() +{ + fIndex = 0; + fDataBuf[0] = 0; + fDataBuf[fIndex + 1] = 0; + fDataBuf[fIndex + 2] = 0; + fDataBuf[fIndex + 3] = 0; +} + +// --------------------------------------------------------------------------- +// MemBufFormatTarget: Private helper methods +// --------------------------------------------------------------------------- +void MemBufFormatTarget::ensureCapacity(const XMLSize_t extraNeeded) +{ + // Oops, not enough room. Calc new capacity and allocate new buffer + const XMLSize_t newCap = ((fIndex + extraNeeded) * 2); + XMLByte* newBuf = (XMLByte*) fMemoryManager->allocate + ( + (newCap+4) * sizeof(XMLByte) + );//new XMLByte[newCap+4]; + + // Copy over the old stuff + memcpy(newBuf, fDataBuf, fIndex * sizeof(XMLByte)); + + // Clean up old buffer and store new stuff + fMemoryManager->deallocate(fDataBuf); //delete [] fDataBuf; + fDataBuf = newBuf; + fCapacity = newCap; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/MemBufFormatTarget.hpp b/include/xercesc/framework/MemBufFormatTarget.hpp new file mode 100644 index 0000000..27da938 --- /dev/null +++ b/include/xercesc/framework/MemBufFormatTarget.hpp @@ -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: MemBufFormatTarget.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_MEMBUFFORMATTARGET_HPP) +#define XERCESC_INCLUDE_GUARD_MEMBUFFORMATTARGET_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/* + * The MemBufFormatTarget is a derivative from XMLFormatTarget, which user code + * may plug into DOMLSSerializer to retrieve the serialized XML stream (from DOM Tree) + * in a memory buffer. + * + * The MemBufFormatTarget is initialized to have a memory buffer of 1023 upon + * construction, which grows as needed. The buffer will be deleted when + * MemBufFormatTarget is destructed; or will be reset when the reset() function + * is called. + * + * The MemBufFormatTarget returns a NULL terminated XMLByte stream upon request, + * through the method getRawBuffer(), and user should make its own copy of the + * returned buffer if it intends to keep it independent on the state of the + * MemBufFormatTarget. + */ + +class XMLPARSER_EXPORT MemBufFormatTarget : public XMLFormatTarget { +public: + + /** @name constructors and destructor */ + //@{ + MemBufFormatTarget + ( + XMLSize_t initCapacity = 1023 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ) ; + ~MemBufFormatTarget(); + //@} + + // ----------------------------------------------------------------------- + // Implementations of the format target interface + // ----------------------------------------------------------------------- + virtual void writeChars(const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter* const formatter); + + // ----------------------------------------------------------------------- + // Getter + // ----------------------------------------------------------------------- + /** @name getRawBuffer */ + //@{ + /** + * Returned the internal raw buffer. + * + */ + //@} + const XMLByte* getRawBuffer() const; + + /** @name getLen */ + //@{ + /** + * Returned the length of the raw buffer. + * + */ + //@} + XMLSize_t getLen() const + { + return fIndex; + } + + /** @name reset */ + //@{ + /** + * Reset the internal string buffer. + * + */ + void reset(); + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented methods. + // ----------------------------------------------------------------------- + MemBufFormatTarget(const MemBufFormatTarget&); + MemBufFormatTarget& operator=(const MemBufFormatTarget&); + + // ----------------------------------------------------------------------- + // Private helpers + // ----------------------------------------------------------------------- + void ensureCapacity(const XMLSize_t extraNeeded); + + // ----------------------------------------------------------------------- + // Private data members + // + // fDataBuf + // The pointer to the buffer data. Its grown as needed. Its always + // one larger than fCapacity, to leave room for the null terminator. + // + // fIndex + // The current index into the buffer, as characters are appended + // to it. If its zero, then the buffer is empty. + // + // fCapacity + // The current capacity of the buffer. Its actually always one + // larger, to leave room for the null terminator. + // + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + XMLByte* fDataBuf; + XMLSize_t fIndex; + XMLSize_t fCapacity; + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/framework/MemBufInputSource.cpp b/include/xercesc/framework/MemBufInputSource.cpp new file mode 100644 index 0000000..d39f80b --- /dev/null +++ b/include/xercesc/framework/MemBufInputSource.cpp @@ -0,0 +1,94 @@ +/* + * 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: MemBufInputSource.cpp 553941 2007-07-06 16:14:22Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// MemBufInputSource: Constructors and Destructor +// --------------------------------------------------------------------------- +MemBufInputSource::MemBufInputSource( const XMLByte* const srcDocBytes + , const XMLSize_t byteCount + , const XMLCh* const bufId + , const bool adoptBuffer + , MemoryManager* const manager) : + InputSource(bufId, manager) + , fAdopted(adoptBuffer) + , fByteCount(byteCount) + , fCopyBufToStream(true) + , fSrcBytes(srcDocBytes) +{ +} + +MemBufInputSource::MemBufInputSource( const XMLByte* const srcDocBytes + , const XMLSize_t byteCount + , const char* const bufId + , const bool adoptBuffer + , MemoryManager* const manager) : + InputSource(bufId, manager) + , fAdopted(adoptBuffer) + , fByteCount(byteCount) + , fCopyBufToStream(true) + , fSrcBytes(srcDocBytes) +{ +} + +MemBufInputSource::~MemBufInputSource() +{ + if (fAdopted) + delete [] (XMLByte*)fSrcBytes; +} + +void MemBufInputSource::resetMemBufInputSource(const XMLByte* const srcDocBytes + , const XMLSize_t byteCount) +{ + fByteCount = byteCount; + fSrcBytes = srcDocBytes; +} + +// --------------------------------------------------------------------------- +// MemBufInputSource: InputSource interface implementation +// --------------------------------------------------------------------------- +BinInputStream* MemBufInputSource::makeStream() const +{ + // + // Create a memory input stream over our buffer. According to our + // fCopyBufToStream flag, we either tell it to copy the buffer or to + // just reference it. + // + return new (getMemoryManager()) BinMemInputStream + ( + fSrcBytes + , fByteCount + , fCopyBufToStream ? BinMemInputStream::BufOpt_Copy + : BinMemInputStream::BufOpt_Reference + , getMemoryManager() + ); +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/MemBufInputSource.hpp b/include/xercesc/framework/MemBufInputSource.hpp new file mode 100644 index 0000000..5ccf528 --- /dev/null +++ b/include/xercesc/framework/MemBufInputSource.hpp @@ -0,0 +1,230 @@ +/* + * 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: MemBufInputSource.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + + +#if !defined(XERCESC_INCLUDE_GUARD_MEMBUFINPUTSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_MEMBUFINPUTSOURCE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class BinInputStream; + + +/** + * This class is a derivative of the standard InputSource class. It provides + * for the parser access to data stored in a memory buffer. The type of + * buffer and its host specific attributes are of little concern here. The + * only real requirement is that the memory be readable by the current + * process. + * + * Note that the memory buffer size is expressed in bytes, not in + * characters. If you pass it text data, you must account for the bytes + * per character when indicating the buffer size. + * + * As with all InputSource derivatives. The primary objective of an input + * source is to create an input stream via which the parser can spool in + * data from the referenced source. In this case, there are two options + * available. + * + * The passed buffer can be adopted or merely referenced. If it is adopted, + * then it must be dynamically allocated and will be destroyed when the + * input source is destroyed (no reference counting!.) If not adopted, the + * caller must insure that it remains valid until the input source object + * is destroyed. + * + * The other option indicates whether each stream created for this input + * source should get its own copy of the data, or whether it should just + * stream the data directly from this object's copy of the data. The same + * rules apply here, in that the buffer must either be copied by the + * stream or it must remain valid until the stream is destroyed. + */ +class XMLPARSER_EXPORT MemBufInputSource : public InputSource +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors */ + //@{ + + /** + * A memory buffer input source is constructed from a buffer of byte + * data, and the count of bytes in that buffer. The parser will parse + * from this memory buffer until it has eaten the indicated number of + * bytes. + * + * Note that the system id provided serves two purposes. Firstly it is + * going to be displayed in error messages as the source of the error. + * And secondly, any entities which are referred to from this entity + * via relative paths/URLs will be relative to this fake system id. + * + * @param srcDocBytes The actual data buffer to be parsed from. + * @param byteCount The count of bytes (not characters, bytes!) + * in the buffer. + * @param bufId A fake system id for the buffer. + * @param adoptBuffer Indicates whether this object should adopt + * the buffer (i.e. become responsible for + * deletion) or just + * use it in place. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + MemBufInputSource + ( + const XMLByte* const srcDocBytes + , const XMLSize_t byteCount + , const XMLCh* const bufId + , const bool adoptBuffer = false + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * This constructor is identical to the previous one, except that it takes + * the fake system id in local code page form and transcodes it internally. + */ + MemBufInputSource + ( + const XMLByte* const srcDocBytes + , const XMLSize_t byteCount + , const char* const bufId + , const bool adoptBuffer = false + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + //@} + + /** @name Destructor */ + //@{ + /** + * If the buffer was adopted, the copy made during construction is deleted + * at this point. + */ + ~MemBufInputSource(); + //@} + + + // ----------------------------------------------------------------------- + // Virtual input source interface + // ----------------------------------------------------------------------- + + /** @name Virtual methods */ + //@{ + + /** + * This method will return a binary input stream derivative that will + * parse from the memory buffer. If setCopyBufToStream() has been set, + * then the stream will make its own copy. Otherwise, it will use the + * buffer as is (in which case it must remain valid until the stream + * is no longer in use, i.e. the parse completes.) + * + * @return A dynamically allocated binary input stream derivative that + * can parse from the memory buffer. + */ + BinInputStream* makeStream() const; + + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + + //@{ + + /** + * By default, for safety's sake, each newly created stream from this + * input source will make its own copy of the buffer to stream from. This + * avoids having to deal with aliasing of the buffer for simple work. But, + * for higher performance applications or for large buffers, this is + * obviously not optimal. + * + * In such cases, you can call this method to turn off that default + * action. Once turned off, the streams will just get a pointer to the + * buffer and parse directly from that. In this case, you must insure that + * the buffer remains valid for as long as any parse events are still + * using it. + * + * @param newState The new boolean flag state to set. + */ + void setCopyBufToStream(const bool newState); + + /** + * This methods allows the MemBufInputSource to be used for more than + * one input source, instead of destructing/constructing another + * MemBufInputSource. + * + * @param srcDocBytes The actual data buffer to be parsed from. + * @param byteCount The count of bytes (not characters, bytes!) + * in the buffer. + */ + void resetMemBufInputSource(const XMLByte* const srcDocBytes + , const XMLSize_t byteCount); + //@} + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + MemBufInputSource(const MemBufInputSource&); + MemBufInputSource& operator=(const MemBufInputSource&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fAdopted + // Indicates whether the buffer is adopted or not. If so, then it + // is destroyed when the input source is destroyed. + // + // fByteCount + // The size of the source document. + // + // fCopyBufToStream + // This defaults to true (the safe option), which causes it to + // give a copy of the buffer to any streams it creates. If you set + // it to false, it will allow the streams to just reference the + // buffer (in which case this input source must stay alive as long + // as the buffer is in use by the stream.) + // + // fSrcBytes + // The source memory buffer that is being spooled from. Whether it + // belongs to the this input source or not is controlled by the + // fAdopted flag. + // ----------------------------------------------------------------------- + bool fAdopted; + XMLSize_t fByteCount; + bool fCopyBufToStream; + const XMLByte* fSrcBytes; +}; + + +inline void MemBufInputSource::setCopyBufToStream(const bool newState) +{ + fCopyBufToStream = newState; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/MemoryManager.hpp b/include/xercesc/framework/MemoryManager.hpp new file mode 100644 index 0000000..6b6c186 --- /dev/null +++ b/include/xercesc/framework/MemoryManager.hpp @@ -0,0 +1,125 @@ +/* + * 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: MemoryManager.hpp 673975 2008-07-04 09:23:56Z borisk $ + */ + + +#if !defined(XERCESC_INCLUDE_GUARD_MEMORYMANAGER_HPP) +#define XERCESC_INCLUDE_GUARD_MEMORYMANAGER_HPP + +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * Configurable memory manager + * + *

This interface allows outside applications to plug in their own memory + * manager to be used by Xerces for memory allocation/deallocation.

+ */ +class XMLPARSER_EXPORT MemoryManager +{ +public: + // ----------------------------------------------------------------------- + // Constructors are hidden, only the virtual destructor is exposed + // ----------------------------------------------------------------------- + + /** @name Destructor */ + //@{ + + /** + * Default destructor + */ + virtual ~MemoryManager() + { + } + //@} + + + /** + * This method is called to obtain the memory manager that should be + * used to allocate memory used in exceptions. If the same memory + * manager can be used, simply return 'this' from this function. + * Note, however, that if there is a possibility that an exception + * thrown can outlive the memory manager (for example, because the + * memory manager object is allocated on the stack or is managed by + * a stack-bound object), it is recommended that you return + * XMLPlatformUtils::fgMemoryManager. + * + * @return A pointer to the memory manager + */ + virtual MemoryManager* getExceptionMemoryManager() = 0; + + + // ----------------------------------------------------------------------- + // The virtual memory manager interface + // ----------------------------------------------------------------------- + /** @name The pure virtual methods in this interface. */ + //@{ + + /** + * This method allocates requested memory. + * + * @param size The requested memory size + * + * @return A pointer to the allocated memory + */ + virtual void* allocate(XMLSize_t size) = 0; + + /** + * This method deallocates memory + * + * @param p The pointer to the allocated memory to be deleted + */ + virtual void deallocate(void* p) = 0; + + //@} + + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + /** @name Constructor */ + //@{ + + /** + * Protected default constructor + */ + MemoryManager() + { + } + //@} + + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + MemoryManager(const MemoryManager&); + MemoryManager& operator=(const MemoryManager&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/StdInInputSource.cpp b/include/xercesc/framework/StdInInputSource.cpp new file mode 100644 index 0000000..93ac7fd --- /dev/null +++ b/include/xercesc/framework/StdInInputSource.cpp @@ -0,0 +1,52 @@ +/* + * 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: StdInInputSource.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// StdInInputSource: Implementation of the input source interface +// --------------------------------------------------------------------------- +BinInputStream* StdInInputSource::makeStream() const +{ + // Open a binary file stream for the standard input file handle + BinFileInputStream* retStream = new (getMemoryManager()) BinFileInputStream + ( + XMLPlatformUtils::openStdInHandle(getMemoryManager()) + ); + + if (!retStream->getIsOpen()) + { + delete retStream; + return 0; + } + return retStream; +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/StdInInputSource.hpp b/include/xercesc/framework/StdInInputSource.hpp new file mode 100644 index 0000000..765b963 --- /dev/null +++ b/include/xercesc/framework/StdInInputSource.hpp @@ -0,0 +1,108 @@ +/* + * 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: StdInInputSource.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + + +#if !defined(XERCESC_INCLUDE_GUARD_STDININPUTSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_STDININPUTSOURCE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class BinInputStream; + + +/** + * This class is a derivative of the standard InputSource class. It provides + * for the parser access to data via the standard input. This input source + * is not commonly used, but can be useful when implementing such things + * as pipe based tools which exchange XML data. + * + * As with all InputSource derivatives. The primary objective of an input + * source is to create an input stream via which the parser can spool in + * data from the referenced source. + */ +class XMLPARSER_EXPORT StdInInputSource : public InputSource +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructor */ + //@{ + + /** + * Since the standard input is a canned source, the constructor is very + * simple. It just uses local platform services to open up the standard + * input source as file, a new handleof which it gives to each new stream + * it creates. + */ + StdInInputSource(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + //@} + + /** @name Destructor */ + //@{ + ~StdInInputSource(); + //@} + + + // ----------------------------------------------------------------------- + // Virtual input source interface + // ----------------------------------------------------------------------- + + + /** @name Virtual methods */ + //@{ + + /** + * This method will return a binary input stream derivative that will + * parse from the standard input of the local host. + * + * @return A dynamically allocated binary input stream derivative that + * can parse from the standardinput. + */ + BinInputStream* makeStream() const; + + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + StdInInputSource(const StdInInputSource&); + StdInInputSource& operator=(const StdInInputSource&); + +}; + +inline StdInInputSource::StdInInputSource(MemoryManager* const manager) : + + InputSource("stdin", manager) +{ +} + +inline StdInInputSource::~StdInInputSource() +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/StdOutFormatTarget.cpp b/include/xercesc/framework/StdOutFormatTarget.cpp new file mode 100644 index 0000000..18114ec --- /dev/null +++ b/include/xercesc/framework/StdOutFormatTarget.cpp @@ -0,0 +1,51 @@ +/* + * 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: StdOutFormatTarget.cpp 881225 2009-11-17 10:19:57Z borisk $ + */ + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +StdOutFormatTarget::StdOutFormatTarget() +{} + +StdOutFormatTarget::~StdOutFormatTarget() +{ + flush (); +} + +void StdOutFormatTarget::flush() +{ + fflush(stdout); +} + +void StdOutFormatTarget::writeChars(const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter* const) +{ + XMLSize_t written=fwrite(toWrite, sizeof(XMLByte), count, stdout); + if(written!=count) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile); + fflush(stdout); +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/StdOutFormatTarget.hpp b/include/xercesc/framework/StdOutFormatTarget.hpp new file mode 100644 index 0000000..c58e0d6 --- /dev/null +++ b/include/xercesc/framework/StdOutFormatTarget.hpp @@ -0,0 +1,57 @@ +/* + * 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: StdOutFormatTarget.hpp 553937 2007-07-06 16:02:19Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_STDOUTFORMATTARGET_HPP) +#define XERCESC_INCLUDE_GUARD_STDOUTFORMATTARGET_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT StdOutFormatTarget : public XMLFormatTarget { +public: + + /** @name constructors and destructor */ + //@{ + StdOutFormatTarget() ; + ~StdOutFormatTarget(); + //@} + + // ----------------------------------------------------------------------- + // Implementations of the format target interface + // ----------------------------------------------------------------------- + virtual void writeChars(const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter* const formatter); + + virtual void flush(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented methods. + // ----------------------------------------------------------------------- + StdOutFormatTarget(const StdOutFormatTarget&); + StdOutFormatTarget& operator=(const StdOutFormatTarget&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/URLInputSource.cpp b/include/xercesc/framework/URLInputSource.cpp new file mode 100644 index 0000000..4ab22e6 --- /dev/null +++ b/include/xercesc/framework/URLInputSource.cpp @@ -0,0 +1,100 @@ +/* + * 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: URLInputSource.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// URLInputSource: Constructors and Destructor +// --------------------------------------------------------------------------- +URLInputSource::URLInputSource( const XMLURL& urlId + , MemoryManager* const manager) : + + InputSource(manager) + , fURL(urlId) +{ + setSystemId(fURL.getURLText()); +} + +URLInputSource::URLInputSource( const XMLCh* const baseId + , const XMLCh* const systemId + , MemoryManager* const manager) : + InputSource(manager) + , fURL(baseId, systemId) +{ + // Create a URL that will build up the full URL and store as the system id + setSystemId(fURL.getURLText()); +} + +URLInputSource::URLInputSource( const XMLCh* const baseId + , const XMLCh* const systemId + , const XMLCh* const publicId + , MemoryManager* const manager) : + InputSource(0, publicId, manager) + , fURL(baseId, systemId) +{ + setSystemId(fURL.getURLText()); +} + +URLInputSource::URLInputSource( const XMLCh* const baseId + , const char* const systemId + , MemoryManager* const manager) : + InputSource(manager) + , fURL(baseId, systemId) +{ + setSystemId(fURL.getURLText()); +} + +URLInputSource::URLInputSource( const XMLCh* const baseId + , const char* const systemId + , const char* const publicId + , MemoryManager* const manager) : + InputSource(0, publicId, manager) + , fURL(baseId, systemId) +{ + setSystemId(fURL.getURLText()); +} + +URLInputSource::~URLInputSource() +{ +} + + +// --------------------------------------------------------------------------- +// URLInputSource: Implementation of the input source interface +// --------------------------------------------------------------------------- +BinInputStream* URLInputSource::makeStream() const +{ + // Ask the URL to create us an appropriate input stream + return fURL.makeNewStream(); +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/URLInputSource.hpp b/include/xercesc/framework/URLInputSource.hpp new file mode 100644 index 0000000..f264bcf --- /dev/null +++ b/include/xercesc/framework/URLInputSource.hpp @@ -0,0 +1,236 @@ +/* + * 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: URLInputSource.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_URLINPUTSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_URLINPUTSOURCE_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class BinInputStream; + +/** + * This class is a derivative of the standard InputSource class. It provides + * for the parser access to data which is referenced via a URL, as apposed to + * a local file name. The URL can be provided via an XMLURL class, as a fully + * qualified system id, or a base system id and a system id which may be + * fully qualified or may be relative to the base. + * + * As with all InputSource derivatives. The primary objective of an input + * source is to create an input stream via which the parser can spool in + * data from the referenced source. + * + * Note that the parse system does not necessarily support URL based XML + * entities out of the box. Support for socket based access is optional and + * controlled by the per-platform support. + */ +class XMLPARSER_EXPORT URLInputSource : public InputSource +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors */ + //@{ + + /** + * This constructor accepts an already built URL. It is assumed that + * it is correct and it will be used as is. In this case, no public id + * accepted, but it can still be set via the parent class' setPublicId() + * method. + * + * @param urlId The URL which holds the system id of the entity + * to parse. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + URLInputSource + ( + const XMLURL& urlId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + + /** + * This constructor takes a base system id URL and a possibly relative + * system id. The relative part is parsed and, if it is indeed relative, + * it will be made relative to the passed base id. Otherwise, it will be + * taken as is. + * + * @param baseId The base system id URL which provides the base + * for any relative id part. + * + * @param systemId The possibly relative system id URL. If its relative + * its based on baseId, else its taken as is. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + URLInputSource + ( + const XMLCh* const baseId + , const XMLCh* const systemId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * This constructor is identical to the previous one, except that it also + * allows you to set a public id if you want to. + * + * @param baseId The base system id URL which provides the base + * for any relative id part. + * + * @param systemId The possibly relative system id URL. If its relative + * its based on baseId, else its taken as is. + * + * @param publicId The optional public id to set. This is just passed + * on to the parent class for storage. + * + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + URLInputSource + ( + const XMLCh* const baseId + , const XMLCh* const systemId + , const XMLCh* const publicId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + + /** + * This constructor is identical to the second constructor above, except that + * it accepts the relative system id part as a local code page string and + * just transcodes it internally, as a convenience. + * + * @param baseId The base system id URL which provides the base + * for any relative id part. + * + * @param systemId The possibly relative system id URL. If its relative + * its based on baseId, else its taken as is. + * + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + URLInputSource + ( + const XMLCh* const baseId + , const char* const systemId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * This constructor is identical to the third constructor above, except that + * it accepts the relative and public ids as local code page strings and just + * transcodes them internally, as a convenience. + * + * @param baseId The base system id URL which provides the base + * for any relative id part. + * + * @param systemId The possibly relative system id URL. If its relative + * its based on baseId, else its taken as is. + * + * @param publicId The optional public id to set. This is just passed + * on to the parent class for storage. + * on to the parent class for storage. + * + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + URLInputSource + ( + const XMLCh* const baseId + , const char* const systemId + , const char* const publicId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** @name Destructor */ + //@{ + ~URLInputSource(); + //@} + + + // ----------------------------------------------------------------------- + // Virtual input source interface + // ----------------------------------------------------------------------- + + /** @name Virtual methods */ + //@{ + + /** + * This method will return a binary input stream derivative that will + * parse from the source referred to by the URL system id. + */ + BinInputStream* makeStream() const; + + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** + * This method will return a const reference to the URL member which + * contains the system id in pre-parsed URL form. If you just want the + * string format, call getSystemId() on the parent class. + * + * @return A const reference to a URL object that contains the current + * system id set for this input source. + */ + const XMLURL& urlSrc() const; + + //@} + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + URLInputSource(const URLInputSource&); + URLInputSource& operator=(const URLInputSource&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fURL + // This is the URL created from the passed ids. + // ----------------------------------------------------------------------- + XMLURL fURL; +}; + + +inline const XMLURL& URLInputSource::urlSrc() const +{ + return fURL; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/ValidationContext.hpp b/include/xercesc/framework/ValidationContext.hpp new file mode 100644 index 0000000..b238a14 --- /dev/null +++ b/include/xercesc/framework/ValidationContext.hpp @@ -0,0 +1,139 @@ +/* + * 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: ValidationContext.hpp 729944 2008-12-29 17:03:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_VALIDATION_CONTEXT_HPP) +#define XERCESC_INCLUDE_GUARD_VALIDATION_CONTEXT_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLRefInfo; +class DTDEntityDecl; +class DatatypeValidator; +class ElemStack; +class NamespaceScope; +class XMLScanner; + +class XMLPARSER_EXPORT ValidationContext : public XMemory +{ +public : + // ----------------------------------------------------------------------- + /** @name Virtual destructor for derived classes */ + // ----------------------------------------------------------------------- + //@{ + + /** + * virtual destructor + * + */ + virtual ~ValidationContext(){}; + //@} + + // ----------------------------------------------------------------------- + /** @name The ValidationContext Interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * IDRefList + * + */ + virtual RefHashTableOf* getIdRefList() const = 0; + + virtual void setIdRefList(RefHashTableOf* const) = 0; + + virtual void clearIdRefList() = 0; + + virtual void addId(const XMLCh * const ) = 0; + + virtual void addIdRef(const XMLCh * const ) = 0; + + virtual void toCheckIdRefList(bool) = 0; + + /** + * EntityDeclPool + * + */ + virtual const NameIdPool* getEntityDeclPool() const = 0; + + virtual const NameIdPool* setEntityDeclPool(const NameIdPool* const) = 0; + + virtual void checkEntity(const XMLCh * const ) const = 0 ; + + /** + * Union datatype handling + * + */ + + virtual DatatypeValidator * getValidatingMemberType() const = 0 ; + virtual void setValidatingMemberType(DatatypeValidator * validatingMemberType) = 0 ; + + /** + * QName datatype handling + * Create default implementations for source code compatibility + */ + virtual bool isPrefixUnknown(XMLCh* /* prefix */) { return true; }; + virtual void setElemStack(ElemStack* /* elemStack */) {}; + virtual const XMLCh* getURIForPrefix(XMLCh* /*prefix */) { return 0; }; + virtual void setScanner(XMLScanner* /* scanner */) { }; + virtual void setNamespaceScope(NamespaceScope* /* nsStack */) { }; + + //@} + + +protected : + // ----------------------------------------------------------------------- + /** Hidden Constructors */ + // ----------------------------------------------------------------------- + //@{ + ValidationContext(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager) + :fMemoryManager(memMgr) + { + }; + //@} + + // ----------------------------------------------------------------------- + // Data members + // + // fMemoryManager + // Pluggable memory manager for dynamic allocation/deallocation. + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + ValidationContext(const ValidationContext& ); + ValidationContext& operator=(const ValidationContext& ); + //@} + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/framework/Wrapper4DOMLSInput.cpp b/include/xercesc/framework/Wrapper4DOMLSInput.cpp new file mode 100644 index 0000000..bbaab7f --- /dev/null +++ b/include/xercesc/framework/Wrapper4DOMLSInput.cpp @@ -0,0 +1,160 @@ +/* + * 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: Wrapper4DOMLSInput.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Wrapper4DOMLSInput: Constructor and Destructor +// --------------------------------------------------------------------------- +Wrapper4DOMLSInput::Wrapper4DOMLSInput(DOMLSInput* const inputSource, + DOMLSResourceResolver* entityResolver, + const bool adoptFlag, + MemoryManager* const manager) : + InputSource(manager) + , fAdoptInputSource(adoptFlag) + , fForceXMLChEncoding(false) + , fInputSource(inputSource) + , fEntityResolver(entityResolver) +{ + if (!inputSource) + ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, getMemoryManager()); +} + +Wrapper4DOMLSInput::~Wrapper4DOMLSInput() +{ + if (fAdoptInputSource) + delete fInputSource; +} + + +// --------------------------------------------------------------------------- +// Wrapper4DOMLSInput: Getter methods +// --------------------------------------------------------------------------- +bool Wrapper4DOMLSInput::getIssueFatalErrorIfNotFound() const +{ + return fInputSource->getIssueFatalErrorIfNotFound(); +} + +const XMLCh* Wrapper4DOMLSInput::getEncoding() const +{ + if(fForceXMLChEncoding) + return XMLUni::fgXMLChEncodingString; + return fInputSource->getEncoding(); +} + +const XMLCh* Wrapper4DOMLSInput::getSystemId() const +{ + return fInputSource->getSystemId(); +} + +const XMLCh* Wrapper4DOMLSInput::getPublicId() const +{ + return fInputSource->getPublicId(); +} + + +// --------------------------------------------------------------------------- +// Wrapper4DOMLSInput: Setter methods +// --------------------------------------------------------------------------- +void Wrapper4DOMLSInput::setIssueFatalErrorIfNotFound(const bool flag) +{ + fInputSource->setIssueFatalErrorIfNotFound(flag); +} + + +void Wrapper4DOMLSInput::setEncoding(const XMLCh* const encodingStr) +{ + fInputSource->setEncoding(encodingStr); +} + + +void Wrapper4DOMLSInput::setPublicId(const XMLCh* const publicId) +{ + fInputSource->setPublicId(publicId); +} + + +void Wrapper4DOMLSInput::setSystemId(const XMLCh* const systemId) +{ + fInputSource->setSystemId(systemId); +} + + +// --------------------------------------------------------------------------- +// Wrapper4DOMLSInput: Stream methods +// --------------------------------------------------------------------------- +BinInputStream* Wrapper4DOMLSInput::makeStream() const +{ + // The LSParser will use the LSInput object to determine how to read data. The LSParser will look at the different inputs specified in the + // LSInput in the following order to know which one to read from, the first one that is not null and not an empty string will be used: + // 1. LSInput.characterStream + // 2. LSInput.byteStream + // 3. LSInput.stringData + // 4. LSInput.systemId + // 5. LSInput.publicId + InputSource* binStream=fInputSource->getByteStream(); + if(binStream) + return binStream->makeStream(); + const XMLCh* xmlString=fInputSource->getStringData(); + if(xmlString) + { + MemBufInputSource is((const XMLByte*)xmlString, XMLString::stringLen(xmlString)*sizeof(XMLCh), "", false, getMemoryManager()); + is.setCopyBufToStream(false); + return is.makeStream(); + } + const XMLCh* szSystemId=fInputSource->getSystemId(); + if(szSystemId) + { + XMLURL urlTmp(getMemoryManager()); + if (urlTmp.setURL(szSystemId, fInputSource->getBaseURI(), urlTmp) && !urlTmp.isRelative()) + { + URLInputSource src(urlTmp, getMemoryManager()); + return src.makeStream(); + } + LocalFileInputSource src(szSystemId, getMemoryManager()); + return src.makeStream(); + } + const XMLCh* szPublicId=fInputSource->getPublicId(); + if(szPublicId && fEntityResolver) + { + DOMLSInput* is = fEntityResolver->resolveResource(XMLUni::fgDOMDTDType, 0, szPublicId, 0, fInputSource->getBaseURI()); + if (is) + return Wrapper4DOMLSInput(is, fEntityResolver, true, getMemoryManager()).makeStream(); + } + + return 0; +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/Wrapper4DOMLSInput.hpp b/include/xercesc/framework/Wrapper4DOMLSInput.hpp new file mode 100644 index 0000000..98f2af6 --- /dev/null +++ b/include/xercesc/framework/Wrapper4DOMLSInput.hpp @@ -0,0 +1,230 @@ +/* + * 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: Wrapper4DOMLSInput.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_WRAPPER4DOMLSINPUT_HPP) +#define XERCESC_INCLUDE_GUARD_WRAPPER4DOMLSINPUT_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMLSInput; +class DOMLSResourceResolver; + +/** + * Wrap a DOMLSInput object and make it behave like a SAX InputSource. + */ +class XMLPARSER_EXPORT Wrapper4DOMLSInput: public InputSource +{ +public: + /** @name Constructors and Destructor */ + //@{ + + /** + * Constructor + * + * Wrap a DOMLSInput and make it behave like a SAX InputSource. + * By default, the wrapper will adopt the DOMLSInput that is wrapped. + * + * @param inputSource The DOMLSInput to be wrapped + * @param entityResolver The DOMLSResourceResolver to be used when resolving publicID entries + * @param adoptFlag Indicates if the wrapper should adopt the wrapped + * DOMLSInput. Default is true. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + Wrapper4DOMLSInput + ( + DOMLSInput* const inputSource + , DOMLSResourceResolver* entityResolver = 0 + , const bool adoptFlag = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Destructor + * + */ + virtual ~Wrapper4DOMLSInput(); + //@} + + + // ----------------------------------------------------------------------- + /** @name Virtual input source interface */ + //@{ + /** + * + * Makes the byte stream for this input source. + * + *

The function will call the makeStream of the wrapped input source. + * The returned stream becomes the parser's property.

+ * + * @see BinInputStream + */ + BinInputStream* makeStream() const; + + //@} + + // ----------------------------------------------------------------------- + /** @name Getter methods */ + //@{ + /** + * + * An input source can be set to force the parser to assume a particular + * encoding for the data that input source reprsents, via the setEncoding() + * method. This method will delegate to the wrapped input source to return + * name of the encoding that is to be forced. If the encoding has never + * been forced, it returns a null pointer. + * + * @return The forced encoding, or null if none was supplied. + * @see #setEncoding + */ + const XMLCh* getEncoding() const; + + + /** + * + * Get the public identifier for this input source. Delegated to the + * wrapped input source object. + * + * @return The public identifier, or null if none was supplied. + * @see #setPublicId + */ + const XMLCh* getPublicId() const; + + + /** + * + * Get the system identifier for this input source. Delegated to the + * wrapped input source object. + * + *

If the system ID is a URL, it will be fully resolved.

+ * + * @return The system identifier. + * @see #setSystemId + */ + const XMLCh* getSystemId() const; + + /** + * + * Get the flag that indicates if the parser should issue fatal error if + * this input source is not found. Delegated to the wrapped input source + * object. + * + * @return True if the parser should issue fatal error if this input source + * is not found. + * False if the parser issue warning message instead. + * @see #setIssueFatalErrorIfNotFound + */ + bool getIssueFatalErrorIfNotFound() const; + + //@} + + + // ----------------------------------------------------------------------- + /** @name Setter methods */ + //@{ + + /** + * + * Set the encoding which will be required for use with the XML text read + * via a stream opened by this input source. This will update the wrapped + * input source object. + * + *

This is usually not set, allowing the encoding to be sensed in the + * usual XML way. However, in some cases, the encoding in the file is known + * to be incorrect because of intermediate transcoding, for instance + * encapsulation within a MIME document. + * + * @param encodingStr The name of the encoding to force. + */ + void setEncoding(const XMLCh* const encodingStr); + + + /** + * + * Set the public identifier for this input source. This will update the + * wrapped input source object. + * + *

The public identifier is always optional: if the application writer + * includes one, it will be provided as part of the location information.

+ * + * @param publicId The public identifier as a string. + * @see Locator#getPublicId + * @see SAXParseException#getPublicId + * @see #getPublicId + */ + void setPublicId(const XMLCh* const publicId); + + /** + * + * Set the system identifier for this input source. This will update the + * wrapped input source object. + * + *

The system id is always required. The public id may be used to map + * to another system id, but the system id must always be present as a fall + * back.

+ * + *

If the system ID is a URL, it must be fully resolved.

+ * + * @param systemId The system identifier as a string. + * @see #getSystemId + * @see Locator#getSystemId + * @see SAXParseException#getSystemId + */ + void setSystemId(const XMLCh* const systemId); + + /** + * + * Indicates if the parser should issue fatal error if this input source + * is not found. If set to false, the parser issue warning message instead. + * This will update the wrapped input source object. + * + * @param flag True if the parser should issue fatal error if this input source is not found. + * If set to false, the parser issue warning message instead. (Default: true) + * + * @see #getIssueFatalErrorIfNotFound + */ + void setIssueFatalErrorIfNotFound(const bool flag); + + //@} + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Wrapper4DOMLSInput(const Wrapper4DOMLSInput&); + Wrapper4DOMLSInput& operator=(const Wrapper4DOMLSInput&); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fAdoptInputSource, + fForceXMLChEncoding; + DOMLSInput* fInputSource; + DOMLSResourceResolver* fEntityResolver; +}; + +XERCES_CPP_NAMESPACE_END + + +#endif diff --git a/include/xercesc/framework/Wrapper4InputSource.cpp b/include/xercesc/framework/Wrapper4InputSource.cpp new file mode 100644 index 0000000..4803783 --- /dev/null +++ b/include/xercesc/framework/Wrapper4InputSource.cpp @@ -0,0 +1,121 @@ +/* + * 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: Wrapper4InputSource.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Constructor and Destructor +// --------------------------------------------------------------------------- +Wrapper4InputSource::Wrapper4InputSource(InputSource* const inputSource, + const bool adoptFlag + , MemoryManager* const manager) : + fAdoptInputSource(adoptFlag) + , fInputSource(inputSource) +{ + if (!inputSource) + ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, manager); +} + +Wrapper4InputSource::~Wrapper4InputSource() +{ + if (fAdoptInputSource) + delete fInputSource; +} + + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Getter methods +// --------------------------------------------------------------------------- +bool Wrapper4InputSource::getIssueFatalErrorIfNotFound() const +{ + return fInputSource->getIssueFatalErrorIfNotFound(); +} + +const XMLCh* Wrapper4InputSource::getEncoding() const +{ + return fInputSource->getEncoding(); +} + +const XMLCh* Wrapper4InputSource::getSystemId() const +{ + return fInputSource->getSystemId(); +} + +const XMLCh* Wrapper4InputSource::getPublicId() const +{ + return fInputSource->getPublicId(); +} + + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Setter methods +// --------------------------------------------------------------------------- +void Wrapper4InputSource::setIssueFatalErrorIfNotFound(bool flag) +{ + fInputSource->setIssueFatalErrorIfNotFound(flag); +} + + +void Wrapper4InputSource::setEncoding(const XMLCh* const encodingStr) +{ + fInputSource->setEncoding(encodingStr); +} + + +void Wrapper4InputSource::setPublicId(const XMLCh* const publicId) +{ + fInputSource->setPublicId(publicId); +} + + +void Wrapper4InputSource::setSystemId(const XMLCh* const systemId) +{ + fInputSource->setSystemId(systemId); +} + + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Stream methods +// --------------------------------------------------------------------------- +InputSource* Wrapper4InputSource::getByteStream() const +{ + return fInputSource; +} + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Memory methods +// --------------------------------------------------------------------------- +void Wrapper4InputSource::release() +{ + Wrapper4InputSource* src = (Wrapper4InputSource*) this; + delete src; +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/Wrapper4InputSource.hpp b/include/xercesc/framework/Wrapper4InputSource.hpp new file mode 100644 index 0000000..c7295a1 --- /dev/null +++ b/include/xercesc/framework/Wrapper4InputSource.hpp @@ -0,0 +1,290 @@ +/* + * 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: Wrapper4InputSource.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_WRAPPER4INPUTSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_WRAPPER4INPUTSOURCE_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class InputSource; + + +/** + * Wrap a SAX InputSource object and make it behave like DOMLSInput. + */ +class XMLPARSER_EXPORT Wrapper4InputSource: public DOMLSInput +{ +public: + /** @name Constructors and Destructor */ + //@{ + + /** + * Constructor + * + * Wrap a SAX InputSource and make it behave like a DOMLSInput. + * By default, the wrapper will adopt the SAX InputSource that is wrapped. + * + * @param inputSource The SAX InputSource to be wrapped + * @param adoptFlag Indicates if the wrapper should adopt the wrapped + * SAX InputSource. Default is true. + * @param manager The MemoryManager to use to allocate objects + */ + Wrapper4InputSource(InputSource* const inputSource + , const bool adoptFlag = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Destructor + * + */ + virtual ~Wrapper4InputSource(); + //@} + + + // ----------------------------------------------------------------------- + /** @name Virtual input source interface */ + //@{ + /** + * This wrapper doesn't support string data + * + */ + virtual const XMLCh* getStringData() const; + + /** + * Makes the byte stream for this input source. + * + *

The function will call the makeStream of the wrapped input source. + * The returned stream becomes the parser's property.

+ * + * @see InputSource + */ + virtual InputSource* getByteStream() const; + //@} + + // ----------------------------------------------------------------------- + /** @name Getter methods */ + //@{ + /** + * An input source can be set to force the parser to assume a particular + * encoding for the data that input source represents, via the setEncoding() + * method. This method will delegate to the wrapped input source to return + * name of the encoding that is to be forced. If the encoding has never + * been forced, it returns a null pointer. + * + * @return The forced encoding, or null if none was supplied. + * @see #setEncoding + */ + virtual const XMLCh* getEncoding() const; + + + /** + * Get the public identifier for this input source. Delegated to the + * wrapped input source object. + * + * @return The public identifier, or null if none was supplied. + * @see #setPublicId + */ + const XMLCh* getPublicId() const; + + + /** + * Get the system identifier for this input source. Delegated to the + * wrapped input source object. + * + *

If the system ID is a URL, it will be fully resolved.

+ * + * @return The system identifier. + * @see #setSystemId + */ + const XMLCh* getSystemId() const; + + /** + * Get the base URI to be used for resolving relative URIs to absolute + * URIs. If the baseURI is itself a relative URI, the behavior is + * implementation dependent. Delegated to the wrapped intput source + * object. + * + * @return The base URI. + * @see #setBaseURI + * @since DOM Level 3 + */ + const XMLCh* getBaseURI() const; + + /** + * Get the flag that indicates if the parser should issue fatal error if this input source + * is not found. Delegated to the wrapped input source object. + * + * @return True if the parser should issue fatal error if this input source is not found. + * False if the parser issue warning message instead. + * @see #setIssueFatalErrorIfNotFound + */ + bool getIssueFatalErrorIfNotFound() const; + + //@} + + + // ----------------------------------------------------------------------- + /** @name Setter methods */ + //@{ + /** + * This wrapper only exposes the given InputSource, no setting allowed + * + */ + virtual void setStringData(const XMLCh* data); + + /** + * This wrapper only exposes the given InputSource, no setting allowed + * + */ + virtual void setByteStream(InputSource* stream); + + /** + * Set the encoding which will be required for use with the XML text read + * via a stream opened by this input source. This will update the wrapped + * input source object. + * + *

This is usually not set, allowing the encoding to be sensed in the + * usual XML way. However, in some cases, the encoding in the file is known + * to be incorrect because of intermediate transcoding, for instance + * encapsulation within a MIME document. + * + * @param encodingStr The name of the encoding to force. + */ + void setEncoding(const XMLCh* const encodingStr); + + + /** + * Set the public identifier for this input source. This will update the + * wrapped input source object. + * + *

The public identifier is always optional: if the application writer + * includes one, it will be provided as part of the location information.

+ * + * @param publicId The public identifier as a string. + * @see Locator#getPublicId + * @see SAXParseException#getPublicId + * @see #getPublicId + */ + void setPublicId(const XMLCh* const publicId); + + /** + * Set the system identifier for this input source. This will update the + * wrapped input source object. + * + *

The system id is always required. The public id may be used to map + * to another system id, but the system id must always be present as a fall + * back.

+ * + *

If the system ID is a URL, it must be fully resolved.

+ * + * @param systemId The system identifier as a string. + * @see #getSystemId + * @see Locator#getSystemId + * @see SAXParseException#getSystemId + */ + void setSystemId(const XMLCh* const systemId); + + /** + * Set the base URI to be used for resolving relative URIs to absolute + * URIs. If the baseURI is itself a relative URI, the behavior is + * implementation dependent. This will update the wrapped input source + * object. + * + * @param baseURI The base URI. + * @see #getBaseURI + * @since DOM Level 3 + */ + void setBaseURI(const XMLCh* const baseURI); + + /** + * Indicates if the parser should issue fatal error if this input source + * is not found. If set to false, the parser issue warning message + * instead. This will update the wrapped input source object. + * + * @param flag True if the parser should issue fatal error if this input + * source is not found. + * If set to false, the parser issue warning message instead. + * (Default: true) + * + * @see #getIssueFatalErrorIfNotFound + */ + void setIssueFatalErrorIfNotFound(bool flag); + + /** + * Called to indicate that this DOMInputSource is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + * Access to a released object will lead to unexpected result. + */ + void release(); + + //@} + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Wrapper4InputSource(const Wrapper4InputSource&); + Wrapper4InputSource& operator=(const Wrapper4InputSource&); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fAdoptInputSource; + InputSource* fInputSource; +}; + + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Getter methods +// --------------------------------------------------------------------------- +inline const XMLCh* Wrapper4InputSource::getBaseURI() const +{ + return 0; // REVISIT - should we return an empty string? +} + +inline const XMLCh* Wrapper4InputSource::getStringData() const +{ + return 0; +} + +// --------------------------------------------------------------------------- +// Wrapper4InputSource: Setter methods +// --------------------------------------------------------------------------- +inline void Wrapper4InputSource::setBaseURI(const XMLCh* const) +{ +} + +inline void Wrapper4InputSource::setStringData(const XMLCh*) +{ +} + +inline void Wrapper4InputSource::setByteStream(InputSource*) +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLAttDef.cpp b/include/xercesc/framework/XMLAttDef.cpp new file mode 100644 index 0000000..a250942 --- /dev/null +++ b/include/xercesc/framework/XMLAttDef.cpp @@ -0,0 +1,220 @@ +/* + * 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: XMLAttDef.cpp 679359 2008-07-24 11:15:19Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local const data +// +// gAttTypeStrings +// A list of strings which are used to map attribute type numbers to +// attribute type names. +// +// gDefAttTypesStrings +// A list of strings which are used to map default attribute type +// numbers to default attribute type names. +// --------------------------------------------------------------------------- +const XMLCh* const gAttTypeStrings[XMLAttDef::AttTypes_Count] = +{ + XMLUni::fgCDATAString + , XMLUni::fgIDString + , XMLUni::fgIDRefString + , XMLUni::fgIDRefsString + , XMLUni::fgEntityString + , XMLUni::fgEntitiesString + , XMLUni::fgNmTokenString + , XMLUni::fgNmTokensString + , XMLUni::fgNotationString + , XMLUni::fgEnumerationString + , XMLUni::fgCDATAString + , XMLUni::fgCDATAString + , XMLUni::fgCDATAString + , XMLUni::fgCDATAString + +}; + +const XMLCh* const gDefAttTypeStrings[XMLAttDef::DefAttTypes_Count] = +{ + XMLUni::fgDefaultString + , XMLUni::fgFixedString + , XMLUni::fgRequiredString + , XMLUni::fgImpliedString + , XMLUni::fgImpliedString + , XMLUni::fgImpliedString + , XMLUni::fgImpliedString + , XMLUni::fgImpliedString + , XMLUni::fgImpliedString +}; + + + +// --------------------------------------------------------------------------- +// XMLAttDef: Public, static data members +// --------------------------------------------------------------------------- +const unsigned int XMLAttDef::fgInvalidAttrId = 0xFFFFFFFE; + + +// --------------------------------------------------------------------------- +// XMLAttDef: Public, static methods +// --------------------------------------------------------------------------- +const XMLCh* XMLAttDef::getAttTypeString(const XMLAttDef::AttTypes attrType + , MemoryManager* const manager) +{ + // Check for an invalid attribute type and return a null + if ((attrType < AttTypes_Min) || (attrType > AttTypes_Max)) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::AttDef_BadAttType, manager); + return gAttTypeStrings[attrType]; +} + +const XMLCh* XMLAttDef::getDefAttTypeString(const XMLAttDef::DefAttTypes attrType + , MemoryManager* const manager) +{ + // Check for an invalid attribute type and return a null + if ((attrType < DefAttTypes_Min) || (attrType > DefAttTypes_Max)) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::AttDef_BadDefAttType, manager); + return gDefAttTypeStrings[attrType]; +} + + +// --------------------------------------------------------------------------- +// XMLAttDef: Destructor +// --------------------------------------------------------------------------- +XMLAttDef::~XMLAttDef() +{ + cleanUp(); +} + + +// --------------------------------------------------------------------------- +// XMLAttDef: Hidden constructors +// --------------------------------------------------------------------------- +XMLAttDef::XMLAttDef( const XMLAttDef::AttTypes type + , const XMLAttDef::DefAttTypes defType + , MemoryManager* const manager) : + + fDefaultType(defType) + , fType(type) + , fCreateReason(XMLAttDef::NoReason) + , fExternalAttribute(false) + , fId(XMLAttDef::fgInvalidAttrId) + , fValue(0) + , fEnumeration(0) + , fMemoryManager(manager) +{ +} + +typedef JanitorMemFunCall CleanupType; + +XMLAttDef::XMLAttDef( const XMLCh* const attrValue + , const XMLAttDef::AttTypes type + , const XMLAttDef::DefAttTypes defType + , const XMLCh* const enumValues + , MemoryManager* const manager) : + + fDefaultType(defType) + , fType(type) + , fCreateReason(XMLAttDef::NoReason) + , fExternalAttribute(false) + , fId(XMLAttDef::fgInvalidAttrId) + , fValue(0) + , fEnumeration(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XMLAttDef::cleanUp); + + try + { + fValue = XMLString::replicate(attrValue, fMemoryManager); + fEnumeration = XMLString::replicate(enumValues, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +// --------------------------------------------------------------------------- +// XMLAttDef: Private helper methods +// --------------------------------------------------------------------------- +void XMLAttDef::cleanUp() +{ + if (fEnumeration) + fMemoryManager->deallocate(fEnumeration); + + if (fValue) + fMemoryManager->deallocate(fValue); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLAttDef) + +void XMLAttDef::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<<(int)fDefaultType; + serEng<<(int)fType; + serEng<<(int)fCreateReason; + serEng<>i; + fDefaultType = (DefAttTypes) i; + + serEng>>i; + fType = (AttTypes)i; + + serEng>>i; + fCreateReason = (CreateReasons)i; + + serEng>>fExternalAttribute; + serEng.readSize (fId); + + serEng.readString(fValue); + serEng.readString(fEnumeration); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLAttDef.hpp b/include/xercesc/framework/XMLAttDef.hpp new file mode 100644 index 0000000..f65f96b --- /dev/null +++ b/include/xercesc/framework/XMLAttDef.hpp @@ -0,0 +1,539 @@ +/* + * 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: XMLAttDef.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLATTDEF_HPP) +#define XERCESC_INCLUDE_GUARD_XMLATTDEF_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLAttr; + +/** Represents the core information of an attribute definition + * + * This class defines the basic characteristics of an attribute, no matter + * what type of validator is used. If a particular schema associates more + * information with an attribute it will create a derivative of this class. + * So this class provides an abstract way to get basic information on + * attributes from any type of validator. + * + * This class supports keyed collection semantics on the fully qualified + * attribute name, by providing a getKey() method to extract the key string. + * getKey(), in this case, just calls the virtual method getFullName() to + * get the fully qualified name, as defined by the derived class. + * + * Note that the 'value' of an attribute type definition is the default or + * of fixed value given to it in its definition. If the attribute is of the + * enumerated or notation type, it will have an 'enumeration value' as well + * which is a space separated list of its possible vlaues. + */ +class XMLPARSER_EXPORT XMLAttDef : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Class specific types + // + // AttTypes + // The list of possible types that an attribute can have, according + // to the XML 1.0 spec and schema. + // + // DefAttTypes + // The modifiers that an attribute decl can have, which indicates + // whether instances of that attributes are required, implied, etc.. + // + // CreateReasons + // This type is used to store how an attribute declaration got into + // the elementdecl's attribute pool. + // + // ----------------------------------------------------------------------- + enum AttTypes + { + CData = 0 + , ID = 1 + , IDRef = 2 + , IDRefs = 3 + , Entity = 4 + , Entities = 5 + , NmToken = 6 + , NmTokens = 7 + , Notation = 8 + , Enumeration = 9 + , Simple = 10 + , Any_Any = 11 + , Any_Other = 12 + , Any_List = 13 + + , AttTypes_Count + , AttTypes_Min = 0 + , AttTypes_Max = 13 + , AttTypes_Unknown = -1 + }; + + enum DefAttTypes + { + Default = 0 + , Fixed = 1 + , Required = 2 + , Required_And_Fixed = 3 + , Implied = 4 + , ProcessContents_Skip = 5 + , ProcessContents_Lax = 6 + , ProcessContents_Strict = 7 + , Prohibited = 8 + + , DefAttTypes_Count + , DefAttTypes_Min = 0 + , DefAttTypes_Max = 8 + , DefAttTypes_Unknown = -1 + }; + + enum CreateReasons + { + NoReason + , JustFaultIn + }; + + // ----------------------------------------------------------------------- + // Public static data members + // ----------------------------------------------------------------------- + static const unsigned int fgInvalidAttrId; + + + // ----------------------------------------------------------------------- + // Public, static methods + // ----------------------------------------------------------------------- + + /** @name Public, static methods */ + //@{ + + /** Get a string representation of the passed attribute type enum + * + * This method allows you to get a textual representation of an attribute + * type, mostly for debug or display. + * + * @param attrType The attribute type value to get the string for. + * @param manager The MemoryManager to use to allocate objects + * @return A const pointer to the static string that holds the text + * description of the passed type. + */ + static const XMLCh* getAttTypeString(const AttTypes attrType + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** Get a string representation of the passed def attribute type enum + * + * This method allows you to get a textual representation of an default + * attributetype, mostly for debug or display. + * + * @param attrType The default attribute type value to get the string for. + * @param manager The MemoryManager to use to allocate objects + * @return A const pointer to the static string that holds the text + * description of the passed default type. + */ + static const XMLCh* getDefAttTypeString(const DefAttTypes attrType + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@} + + + // ----------------------------------------------------------------------- + // Destructor + // ----------------------------------------------------------------------- + + /** @name Destructor */ + //@{ + + /** + * Destructor + */ + virtual ~XMLAttDef(); + //@} + + + // ----------------------------------------------------------------------- + // The virtual attribute def interface + // ----------------------------------------------------------------------- + + /** @name Virtual interface */ + //@{ + + /** Get the full name of this attribute type + * + * The derived class should return a const pointer to the full name of + * this attribute. This will vary depending on the type of validator in + * use. + * + * @return A const pointer to the full name of this attribute type. + */ + virtual const XMLCh* getFullName() const = 0; + + /** + * The derived class should implement any cleaning up required between + * each use of an instance of this class for validation + */ + virtual void reset() = 0; + + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** Get the default type of this attribute type + * + * This method returns the 'default type' of the attribute. Default + * type in this case refers to the XML concept of a default type for + * an attribute, i.e. \#FIXED, \#IMPLIED, etc... + * + * @return The default type enum for this attribute type. + */ + DefAttTypes getDefaultType() const; + + /** Get the enumeration value (if any) of this attribute type + * + * If the attribute is of an enumeration or notation type, then this + * method will return a const reference to a string that contains the + * space separated values that can the attribute can have. + * + * @return A const pointer to a string that contains the space separated + * legal values for this attribute. + */ + const XMLCh* getEnumeration() const; + + /** Get the pool id of this attribute type + * + * This method will return the id of this attribute in the validator's + * attribute pool. It was set by the validator when this attribute was + * created. + * + * @return The pool id of this attribute type. + */ + XMLSize_t getId() const; + + /** Get the type of this attribute + * + * Gets the type of this attribute. This type is represented by an enum + * that converts the types of attributes allowed by XML, e.g. CDATA, NMTOKEN, + * NOTATION, etc... + * + * @return The attribute type enumeration value for this type of + * attribute. + */ + AttTypes getType() const; + + /** Get the default/fixed value of this attribute (if any.) + * + * If the attribute defined a default/fixed value, then it is stored + * and this method will retrieve it. If it has non, then a null pointer + * is returned. + * + * @return A const pointer to the default/fixed value for this attribute + * type. + */ + const XMLCh* getValue() const; + + /** Get the create reason for this attribute + * + * This method returns an enumeration which indicates why this attribute + * declaration exists. + * + * @return An enumerated value that indicates the reason why this attribute + * was added to the attribute table. + */ + CreateReasons getCreateReason() const; + + /** Indicate whether this attribute has been declared externally + * + * This method returns a boolean that indicates whether this attribute + * has been declared externally. + * + * @return true if this attribute has been declared externally, else false. + */ + bool isExternal() const; + + /** Get the plugged-in memory manager + * + * This method returns the plugged-in memory manager user for dynamic + * memory allocation/deallocation. + * + * @return the plugged-in memory manager + */ + MemoryManager* getMemoryManager() const; + + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** Set the default attribute type + * + * This method sets the default attribute type for this attribute. + * This setting controls whether the attribute is required, fixed, + * implied, etc... + * + * @param newValue The new default attribute to set + */ + void setDefaultType(const XMLAttDef::DefAttTypes newValue); + + /** Set the pool id for this attribute type. + * + * This method sets the pool id of this attribute type. This is usually + * called by the validator that creates the actual instance (which is of + * a derived type known only by the validator.) + * + * @param newId The new pool id to set. + */ + void setId(const XMLSize_t newId); + + /** Set the type of this attribute type. + * + * This method will set the type of the attribute. The type of an attribute + * controls how it is normalized and what kinds of characters it can hold. + * + * @param newValue The new attribute type to set + */ + void setType(const XMLAttDef::AttTypes newValue); + + /** Set the default/fixed value of this attribute type. + * + * This method set the fixed/default value for the attribute. This value + * will be used when instances of this attribute type are faulted in. It + * must be a valid value for the type set by setType(). If the + * type is enumeration or notation, this must be one of the valid values + * set in the setEnumeration() call. + * + * @param newValue The new fixed/default value to set. + */ + void setValue(const XMLCh* const newValue); + + /** Set the enumerated value of this attribute type. + * + * This method sets the enumerated/notation value list for this attribute + * type. It is a space separated set of possible values. These values must + * meet the constrains of the XML spec for such values of this type of + * attribute. This should only be set if the setType() method is used to + * set the type to the enumeration or notation types. + * + * @param newValue The new enumerated/notation value list to set. + */ + void setEnumeration(const XMLCh* const newValue); + + /** Update the create reason for this attribute type. + * + * This method will update the 'create reason' field for this attribute + * decl object. + * + * @param newReason The new create reason. + */ + void setCreateReason(const CreateReasons newReason); + + /** + * Set the attribute decl to indicate external declaration + * + * @param aValue The new value to indicate external declaration. + */ + void setExternalAttDeclaration(const bool aValue); + + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLAttDef) + +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + XMLAttDef + ( + const AttTypes type = CData + , const DefAttTypes defType= Implied + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + XMLAttDef + ( + const XMLCh* const attValue + , const AttTypes type + , const DefAttTypes defType + , const XMLCh* const enumValues = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLAttDef(const XMLAttDef&); + XMLAttDef& operator=(const XMLAttDef&); + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fDefaultType + // Indicates what, if any, default stuff this attribute has. + // + // fEnumeration + // If its an enumeration, this is the list of values as space + // separated values. + // + // fId + // This is the unique id of this attribute, given to it when its put + // into the validator's attribute decl pool. It defaults to the + // special value XMLAttrDef::fgInvalidAttrId. + // + // fType + // The type of attribute, which is one of the AttTypes values. + // + // fValue + // This is the value of the attribute, which is the default value + // given in the attribute declaration. + // + // fCreateReason + // This flag tells us how this attribute got created. Sometimes even + // the attribute was not declared for the element, we want to fault + // fault it into the pool to avoid lots of redundant errors. + // + // fExternalAttribute + // This flag indicates whether or not the attribute was declared externally. + // ----------------------------------------------------------------------- + DefAttTypes fDefaultType; + AttTypes fType; + CreateReasons fCreateReason; + bool fExternalAttribute; + XMLSize_t fId; + XMLCh* fValue; + XMLCh* fEnumeration; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// Getter methods +// --------------------------------------------------------------------------- +inline XMLAttDef::DefAttTypes XMLAttDef::getDefaultType() const +{ + return fDefaultType; +} + +inline const XMLCh* XMLAttDef::getEnumeration() const +{ + return fEnumeration; +} + +inline XMLSize_t XMLAttDef::getId() const +{ + return fId; +} + +inline XMLAttDef::AttTypes XMLAttDef::getType() const +{ + return fType; +} + +inline const XMLCh* XMLAttDef::getValue() const +{ + return fValue; +} + +inline XMLAttDef::CreateReasons XMLAttDef::getCreateReason() const +{ + return fCreateReason; +} + +inline bool XMLAttDef::isExternal() const +{ + return fExternalAttribute; +} + +inline MemoryManager* XMLAttDef::getMemoryManager() const +{ + return fMemoryManager; +} + +// --------------------------------------------------------------------------- +// XMLAttDef: Setter methods +// --------------------------------------------------------------------------- +inline void XMLAttDef::setDefaultType(const XMLAttDef::DefAttTypes newValue) +{ + fDefaultType = newValue; +} + +inline void XMLAttDef::setEnumeration(const XMLCh* const newValue) +{ + if (fEnumeration) + fMemoryManager->deallocate(fEnumeration); + + fEnumeration = XMLString::replicate(newValue, fMemoryManager); +} + +inline void XMLAttDef::setId(const XMLSize_t newId) +{ + fId = newId; +} + +inline void XMLAttDef::setType(const XMLAttDef::AttTypes newValue) +{ + fType = newValue; +} + +inline void XMLAttDef::setValue(const XMLCh* const newValue) +{ + if (fValue) + fMemoryManager->deallocate(fValue); + + fValue = XMLString::replicate(newValue, fMemoryManager); +} + +inline void +XMLAttDef::setCreateReason(const XMLAttDef::CreateReasons newReason) +{ + fCreateReason = newReason; +} + +inline void XMLAttDef::setExternalAttDeclaration(const bool aValue) +{ + fExternalAttribute = aValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLAttDefList.cpp b/include/xercesc/framework/XMLAttDefList.cpp new file mode 100644 index 0000000..63df5c7 --- /dev/null +++ b/include/xercesc/framework/XMLAttDefList.cpp @@ -0,0 +1,42 @@ +/* + * 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: XMLAttDefList.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLAttDefList) + +void XMLAttDefList::serialize(XSerializeEngine&) +{ + //no data +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/XMLAttDefList.hpp b/include/xercesc/framework/XMLAttDefList.hpp new file mode 100644 index 0000000..142f478 --- /dev/null +++ b/include/xercesc/framework/XMLAttDefList.hpp @@ -0,0 +1,171 @@ +/* + * 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: XMLAttDefList.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLATTDEFLIST_HPP) +#define XERCESC_INCLUDE_GUARD_XMLATTDEFLIST_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLAttDef; + +/** + * This class defines an abstract interface that all validators must support. + * When the scanner scans the attributes in a start tag, it must have a list + * of the defined attributes for that element. This is used to fault in + * defaulted and fixed attributes, to know which ones are required, and to + * know the their types in order to do the correct normalization. + * + * Since each validator will have its own derivatives of XMLAttDef and will + * have its own specialized storage mechanisms for elements and the att + * defs that they own, there must be an abstracted way for the scanner to + * deal with this list. + * + * It does not derive from the generic Enumerator template class, because + * there are portability issues with deriving from a template class in a + * DLL. It does though provide a similar enumerator interface. + */ + +class XMLPARSER_EXPORT XMLAttDefList : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Destructor */ + //@{ + virtual ~XMLAttDefList(); + //@} + + + // ----------------------------------------------------------------------- + // The virtual interface + // ----------------------------------------------------------------------- + + virtual bool isEmpty() const = 0; + virtual XMLAttDef* findAttDef + ( + const unsigned int uriID + , const XMLCh* const attName + ) = 0; + virtual const XMLAttDef* findAttDef + ( + const unsigned int uriID + , const XMLCh* const attName + ) const = 0; + virtual XMLAttDef* findAttDef + ( + const XMLCh* const attURI + , const XMLCh* const attName + ) = 0; + virtual const XMLAttDef* findAttDef + ( + const XMLCh* const attURI + , const XMLCh* const attName + ) const = 0; + + /** + * return total number of attributes in this list + */ + virtual XMLSize_t getAttDefCount() const = 0; + + /** + * return attribute at the index-th position in the list. + */ + virtual XMLAttDef &getAttDef(XMLSize_t index) = 0; + + /** + * return attribute at the index-th position in the list. + */ + virtual const XMLAttDef &getAttDef(XMLSize_t index) const = 0; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLAttDefList) + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** Get the memory manager + * + * This method returns the configurable memory manager used by the + * element declaration for dynamic allocation/deallocation. + * + * @return the memory manager + */ + MemoryManager* getMemoryManager() const; + + //@} + +protected : + // ----------------------------------------------------------------------- + // Hidden constructors and operators + // ----------------------------------------------------------------------- + XMLAttDefList(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // unimplemented + XMLAttDefList(const XMLAttDefList&); + XMLAttDefList& operator=(const XMLAttDefList&); + + MemoryManager* fMemoryManager; +}; + + + +// --------------------------------------------------------------------------- +// XMLAttDefList: Getter methods +// --------------------------------------------------------------------------- + +inline MemoryManager* XMLAttDefList::getMemoryManager() const +{ + return fMemoryManager; +} + +// --------------------------------------------------------------------------- +// XMLAttDefList: Constructors and Destructor +// --------------------------------------------------------------------------- +inline XMLAttDefList::~XMLAttDefList() +{ +} + + +// --------------------------------------------------------------------------- +// XMLAttDefList: Protected Constructor +// --------------------------------------------------------------------------- +inline XMLAttDefList::XMLAttDefList(MemoryManager* const manager): +fMemoryManager(manager) +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLAttr.cpp b/include/xercesc/framework/XMLAttr.cpp new file mode 100644 index 0000000..cee3d05 --- /dev/null +++ b/include/xercesc/framework/XMLAttr.cpp @@ -0,0 +1,172 @@ +/* + * 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: XMLAttr.cpp 901107 2010-01-20 08:45:02Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLAttr: Constructors and Destructor +// --------------------------------------------------------------------------- +XMLAttr::XMLAttr(MemoryManager* const manager) : + + fSpecified(false) + , fType(XMLAttDef::CData) + , fValueBufSz(0) + , fValue(0) + , fAttName(0) + , fMemoryManager(manager) +{ + fAttName = new (fMemoryManager) QName(fMemoryManager); +} + +typedef JanitorMemFunCall CleanupType; + +XMLAttr::XMLAttr( const unsigned int uriId + , const XMLCh* const attrName + , const XMLCh* const attrPrefix + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type + , const bool specified + , MemoryManager* const manager + , DatatypeValidator* + , const bool /*isSchema*/ ): + + fSpecified(specified) + , fType(type) + , fValueBufSz(0) + , fValue(0) + , fAttName(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XMLAttr::cleanUp); + + try + { + // + // Just call the local setters to set up everything. Too much + // work is required to replicate that functionality here. + // + fAttName = new (fMemoryManager) QName(attrPrefix, attrName, uriId, fMemoryManager); + setValue(attrValue); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XMLAttr::XMLAttr( const unsigned int uriId + , const XMLCh* const rawName + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type + , const bool specified + , MemoryManager* const manager + , DatatypeValidator * + , const bool /*isSchema*/ ): + + fSpecified(specified) + , fType(type) + , fValueBufSz(0) + , fValue(0) + , fAttName(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XMLAttr::cleanUp); + + try + { + // Just call the local setters to set up everything. Too much + // work is required to replicate that functionality here. + fAttName = new (fMemoryManager) QName(rawName, uriId, fMemoryManager); + setValue(attrValue); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +// --------------------------------------------------------------------------- +// XMLAttr: Getter methods +// --------------------------------------------------------------------------- +const XMLCh* XMLAttr::getQName() const +{ + return fAttName->getRawName(); +} + + +// --------------------------------------------------------------------------- +// XMLAttr: Setter methods +// --------------------------------------------------------------------------- +void XMLAttr::setName( const unsigned int uriId + , const XMLCh* const attrName + , const XMLCh* const attrPrefix) +{ + fAttName->setName(attrPrefix, attrName, uriId); +} + + +void XMLAttr::setURIId(const unsigned int uriId) +{ + fAttName->setURI(uriId); +} + + +void XMLAttr::setValue(const XMLCh* const newValue) +{ + const XMLSize_t newLen = XMLString::stringLen(newValue); + if (!fValueBufSz || (newLen > fValueBufSz)) + { + fMemoryManager->deallocate(fValue); //delete [] fValue; + fValue = 0; + fValueBufSz = newLen + 8; + fValue = (XMLCh*) fMemoryManager->allocate((fValueBufSz+1) * sizeof(XMLCh)); //new XMLCh[fValueBufSz + 1]; + } + XMLString::moveChars(fValue, newValue, newLen + 1); +} + + +// --------------------------------------------------------------------------- +// XMLAttr: Private, helper methods +// --------------------------------------------------------------------------- +void XMLAttr::cleanUp() +{ + delete fAttName; + fMemoryManager->deallocate(fValue); //delete [] fValue; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLAttr.hpp b/include/xercesc/framework/XMLAttr.hpp new file mode 100644 index 0000000..4db3cf5 --- /dev/null +++ b/include/xercesc/framework/XMLAttr.hpp @@ -0,0 +1,501 @@ +/* + * 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: XMLAttr.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLATTR_HPP) +#define XERCESC_INCLUDE_GUARD_XMLATTR_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class defines the information about an attribute that will come out + * of the scanner during parsing. This information does not depend upon the + * type of validator because it is not tied to any scheme/DTD type info. Its + * just the raw XML 1.0 information that will be reported about an attribute + * in the startElement() callback method of the XMLDocumentHandler class. + * Hence it is not intended to be extended or derived from. Its designed to + * be used as is. + * + * The 'specified' field of this class indicates whether the attribute was + * actually present or whether it was faulted in because it had a fixed or + * default value. + * + * The code receiving this information can ask its validator for more info + * about the attribute, i.e. get its declaration from the DTD/Schema info. + * + * Because of the heavy use (and reuse) of instances of this class, and the + * number of string members it has, this class takes pains to not reallocate + * string members unless it has to. It keeps up with how long each buffer + * is and only reallocates if the new value won't fit. + */ +class XMLPARSER_EXPORT XMLAttr : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor just setsup an empty attribute to be filled + * in the later. Though the initial state is a reasonable one, it is + * not documented because it should not be depended on. + * + * @param manager The configurable memory manager + */ + XMLAttr(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * This is the primary constructor which takes all of the information + * required to construct a complete attribute object. + * + * @param uriId The id into the validator's URI pool of the URI + * that the prefix mapped to. Only used if namespaces + * are enabled/supported. + * + * @param attrName The base name of the attribute, i.e. the part + * after any prefix. + * + * @param attrPrefix The prefix, if any, of this attribute's name. If + * this is empty, then uriID is meaningless as well. + * + * @param attrValue The value string of the attribute, which should + * be fully normalized by XML rules! + * + * @param type The type of the attribute. This will indicate + * the type of normalization done and constrains + * the value content. Make sure that the value + * set meets the constraints! + * + * @param specified Indicates whether the attribute was explicitly + * specified or not. If not, then it was faulted + * in from a FIXED or DEFAULT value. + * + * @param manager The configurable memory manager + * @param datatypeValidator type used to validate the attribute, + * if it was validated by an XML Schema + * @param isSchema true if and only if this attribute was validated + * by an XML Schema + */ + XMLAttr + ( + const unsigned int uriId + , const XMLCh* const attrName + , const XMLCh* const attrPrefix + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type = XMLAttDef::CData + , const bool specified = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , DatatypeValidator * datatypeValidator = 0 + , const bool isSchema = false + ); + + /** + * This is the primary constructor which takes all of the information + * required to construct a complete attribute object. + * + * @param uriId The id into the validator's URI pool of the URI + * that the prefix mapped to. Only used if namespaces + * are enabled/supported. + * + * @param rawName The raw name of the attribute. + * + * @param attrValue The value string of the attribute, which should + * be fully normalized by XML rules! + * + * @param type The type of the attribute. This will indicate + * the type of normalization done and constrains + * the value content. Make sure that the value + * set meets the constraints! + * + * @param specified Indicates whether the attribute was explicitly + * specified or not. If not, then it was faulted + * in from a FIXED or DEFAULT value. + * + * @param manager The configurable memory manager + * @param datatypeValidator type used to validate the attribute, + * if it was validated by an XML Schema + * @param isSchema true if and only if this attribute was validated + * by an XML Schema + */ + XMLAttr + ( + const unsigned int uriId + , const XMLCh* const rawName + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type = XMLAttDef::CData + , const bool specified = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , DatatypeValidator * datatypeValidator = 0 + , const bool isSchema = false + ); + + //@} + + /** @name Destructor */ + //@{ + ~XMLAttr(); + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** + * This method returns the attribute name in a QName format. + */ + QName* getAttName() const; + + /** + * This method gets a const pointer to the name of the attribute. The + * form of this name is defined by the validator in use. + */ + const XMLCh* getName() const; + + /** + * This method will get a const pointer to the prefix string of this + * attribute. Since prefixes are optional, it may be zero. + */ + const XMLCh* getPrefix() const; + + /** + * This method will get the QName of this attribute, which will be the + * prefix if any, then a colon, then the base name. If there was no + * prefix, its the same as the getName() method. + */ + const XMLCh* getQName() const; + + /** + * This method will get the specified flag, which indicates whether + * the attribute was explicitly specified or just faulted in. + */ + bool getSpecified() const; + + /** + * This method will get the type of the attribute. The available types + * are defined by the XML specification. + */ + XMLAttDef::AttTypes getType() const; + + /** + * This method will get the value of the attribute. The value can be + * be an empty string, but never null if the object is correctly + * set up. + */ + const XMLCh* getValue() const; + + /** + * This method will get the id of the URI that this attribute's prefix + * mapped to. If namespaces are not on, then its value is meaningless. + */ + unsigned int getURIId() const; + + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** + * This method is called to set up a default constructed object after + * the fact, or to reuse a previously used object. + * + * @param uriId The id into the validator's URI pool of the URI + * that the prefix mapped to. Only used if namespaces + * are enabled/supported. + * + * @param attrName The base name of the attribute, i.e. the part + * after any prefix. + * + * @param attrPrefix The prefix, if any, of this attribute's name. If + * this is empty, then uriID is meaningless as well. + * + * @param attrValue The value string of the attribute, which should + * be fully normalized by XML rules according to the + * attribute type. + * + * @param type The type of the attribute. This will indicate + * the type of normalization done and constrains + * the value content. Make sure that the value + * set meets the constraints! + * @param datatypeValidator type used to validate the attribute, + * if it was validated by an XML Schema + * @param isSchema true if and only if this attribute was validated + * by an XML Schema + * + */ + void set + ( + const unsigned int uriId + , const XMLCh* const attrName + , const XMLCh* const attrPrefix + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type = XMLAttDef::CData + , DatatypeValidator * datatypeValidator = 0 + , const bool isSchema = false + ); + + /** + * This method is called to set up a default constructed object after + * the fact, or to reuse a previously used object. + * + * @param uriId The id into the validator's URI pool of the URI + * that the prefix mapped to. Only used if namespaces + * are enabled/supported. + * + * @param attrRawName The raw name of the attribute. + * + * @param attrValue The value string of the attribute, which should + * be fully normalized by XML rules according to the + * attribute type. + * + * @param type The type of the attribute. This will indicate + * the type of normalization done and constrains + * the value content. Make sure that the value + * set meets the constraints! + * @param datatypeValidator type used to validate the attribute, + * if it was validated by an XML Schema + * @param isSchema true if and only if this attribute was validated + * by an XML Schema + */ + void set + ( + const unsigned int uriId + , const XMLCh* const attrRawName + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type = XMLAttDef::CData + , DatatypeValidator * datatypeValidator = 0 + , const bool isSchema = false + ); + + /** + * This method will update just the name related fields of the + * attribute object. The other fields are left as is. + * + * @param uriId The id into the validator's URI pool of the URI + * that the prefix mapped to. Only used if namespaces + * are enabled/supported. + * + * @param attrName The base name of the attribute, i.e. the part + * after any prefix. + * + * @param attrPrefix The prefix, if any, of this attribute's name. If + * this is empty, then uriID is meaningless as well. + */ + void setName + ( + const unsigned int uriId + , const XMLCh* const attrName + , const XMLCh* const attrPrefix + ); + + /** + * This method will update the specified state of the object. + * + * @param newValue Indicates whether the attribute was explicitly + * specified or not. If not, then it was faulted + * in from a FIXED or DEFAULT value. + */ + void setSpecified(const bool newValue); + + /** + * This method will update the attribute type of the object. + * + * @param newType The type of the attribute. This will indicate + * the type of normalization done and constrains + * the value content. Make sure that the value + * set meets the constraints! + */ + void setType(const XMLAttDef::AttTypes newType); + + /** + * This method will update the value field of the attribute. + * + * @param newValue The value string of the attribute, which should + * be fully normalized by XML rules according to the + * attribute type. + */ + void setValue(const XMLCh* const newValue); + + /** + * This method will set the URI id field of this attribute. This is + * generally only ever called internally by the parser itself during + * the parsing process. + * + * @param uriId The uriId of the attribute. + */ + void setURIId(const unsigned int uriId); + + //@} + + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLAttr(const XMLAttr&); + XMLAttr& operator=(const XMLAttr&); + + + // ----------------------------------------------------------------------- + // Private, helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + + // ----------------------------------------------------------------------- + // Private instance variables + // + // fAttName + // The Attribute Name; + // + // fSpecified + // True if this attribute appeared in the element; else, false if + // it was defaulted from an AttDef. + // + // fType + // The attribute type enum value for this attribute. Indicates what + // type of attribute it was. + // + // fValue + // fValueBufSz + // The attribute value that was given in the attribute instance, and + // its current buffer size (minus one, where the null is.) + // + // fMemoryManager + // The memory manager used for dynamic memory allocation/deallocation + // ----------------------------------------------------------------------- + bool fSpecified; + XMLAttDef::AttTypes fType; + XMLSize_t fValueBufSz; + XMLCh* fValue; + QName* fAttName; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// XMLAttr: Constructors and Destructor +// --------------------------------------------------------------------------- +inline XMLAttr::~XMLAttr() +{ + cleanUp(); +} + + +// --------------------------------------------------------------------------- +// XMLAttr: Getter methods +// --------------------------------------------------------------------------- +inline QName* XMLAttr::getAttName() const +{ + return fAttName; +} + +inline const XMLCh* XMLAttr::getName() const +{ + return fAttName->getLocalPart(); +} + +inline const XMLCh* XMLAttr::getPrefix() const +{ + return fAttName->getPrefix(); +} + +inline bool XMLAttr::getSpecified() const +{ + return fSpecified; +} + +inline XMLAttDef::AttTypes XMLAttr::getType() const +{ + return fType; +} + +inline const XMLCh* XMLAttr::getValue() const +{ + return fValue; +} + +inline unsigned int XMLAttr::getURIId() const +{ + return fAttName->getURI(); +} + +// --------------------------------------------------------------------------- +// XMLAttr: Setter methods +// --------------------------------------------------------------------------- +inline void XMLAttr::set(const unsigned int uriId + , const XMLCh* const attrName + , const XMLCh* const attrPrefix + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type + , DatatypeValidator * /*datatypeValidator */ + , const bool /*isSchema*/ ) +{ + // Set the name info and the value via their respective calls + fAttName->setName(attrPrefix, attrName, uriId); + setValue(attrValue); + + // And store the type + fType = type; +} + +inline void XMLAttr::set(const unsigned int uriId + , const XMLCh* const attrRawName + , const XMLCh* const attrValue + , const XMLAttDef::AttTypes type + , DatatypeValidator * /*datatypeValidator */ + , const bool /*isSchema*/ ) +{ + // Set the name info and the value via their respective calls + fAttName->setName(attrRawName, uriId); + setValue(attrValue); + + // And store the type + fType = type; +} + +inline void XMLAttr::setType(const XMLAttDef::AttTypes newValue) +{ + fType = newValue; +} + +inline void XMLAttr::setSpecified(const bool newValue) +{ + fSpecified = newValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLBuffer.cpp b/include/xercesc/framework/XMLBuffer.cpp new file mode 100644 index 0000000..22e0f08 --- /dev/null +++ b/include/xercesc/framework/XMLBuffer.cpp @@ -0,0 +1,86 @@ +/* + * 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: XMLBuffer.cpp 932887 2010-04-11 13:04:59Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLBuffer: Buffer management +// --------------------------------------------------------------------------- + +void XMLBuffer::ensureCapacity(const XMLSize_t extraNeeded) +{ + // If we can't handle it, try doubling the buffer size. + XMLSize_t newCap = (fIndex + extraNeeded) * 2; + + // If a maximum size is set, and double the current buffer size exceeds that + // maximum, first check if the maximum size will accomodate the extra needed. + if (fFullHandler && (newCap > fFullSize)) + { + // If the maximum buffer size accomodates the extra needed, resize to + // the maximum + if (fIndex + extraNeeded <= fFullSize) + { + newCap = fFullSize; + } + + // Otherwise, allow the registered full-handler to try to empty the buffer. + // If it claims success, and we can accommodate the extra needed in the buffer + // to be expanded, resize to the maximum + // Note the order of evaluation: bufferFull() has the intentional side-effect + // of modifying fIndex. + else if (fFullHandler->bufferFull(*this) && (fIndex + extraNeeded <= fFullSize)) + { + newCap = fFullSize; + } + + // Finally, if the full-handler failed, or the buffer (of maximum size) + // still can't accomodate the extra needed, we must fail. + else + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Array_BadNewSize, fMemoryManager); + } + + // Note the previous if block can modify newCap, so we may not need to allocate + // at all. + if (newCap > fCapacity) + { + // Allocate new buffer + XMLCh* newBuf = (XMLCh*) fMemoryManager->allocate((newCap+1) * sizeof(XMLCh)); //new XMLCh[newCap+1]; + + // Copy over the old stuff + memcpy(newBuf, fBuffer, fIndex * sizeof(XMLCh)); + + // Clean up old buffer and store new stuff + fMemoryManager->deallocate(fBuffer); //delete [] fBuffer; + fBuffer = newBuf; + fCapacity = newCap; + } +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/XMLBuffer.hpp b/include/xercesc/framework/XMLBuffer.hpp new file mode 100644 index 0000000..7b4c711 --- /dev/null +++ b/include/xercesc/framework/XMLBuffer.hpp @@ -0,0 +1,281 @@ +/* + * 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: XMLBuffer.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLBufferFullHandler; + +/** + * XMLBuffer is a lightweight, expandable Unicode text buffer. Since XML is + * inherently theoretically unbounded in terms of the sizes of things, we + * very often need to have expandable buffers. The primary concern here is + * that appends of characters and other buffers or strings be very fast, so + * it always maintains the current buffer size. + * + * The buffer is not null terminated until some asks to see the raw buffer + * contents. This also avoids overhead during append operations. + */ +class XMLPARSER_EXPORT XMLBuffer : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructor */ + //@{ + XMLBuffer(const XMLSize_t capacity = 1023 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) : + + fIndex(0) + , fCapacity(capacity) + , fFullSize(0) + , fUsed(false) + , fMemoryManager(manager) + , fFullHandler(0) + , fBuffer(0) + { + // Buffer is one larger than capacity, to allow for zero term + fBuffer = (XMLCh*) manager->allocate((capacity+1) * sizeof(XMLCh)); //new XMLCh[fCapacity+1]; + + // Keep it null terminated + fBuffer[0] = XMLCh(0); + } + //@} + + /** @name Destructor */ + //@{ + ~XMLBuffer() + { + fMemoryManager->deallocate(fBuffer); //delete [] fBuffer; + } + //@} + + // ----------------------------------------------------------------------- + // Buffer Full Handler Management + // ----------------------------------------------------------------------- + void setFullHandler(XMLBufferFullHandler* handler, const XMLSize_t fullSize) + { + if (handler && fullSize) { + fFullHandler = handler; + fFullSize = fullSize; + + // Need to consider the case that the fullsize is less than the current capacity. + // For example, say fullSize = 100 and fCapacity is 1023 (the default). + // If the fIndex is less than the fullSize, then no problem. We can just carry + // on by resetting fCapacity to fullsize and proceed business as usual. + // If the fIndex is already bigger than the fullSize then we call ensureCapacity + // to see if it can handle emptying the current buffer (it will throw an + // exception if it can't). + if (fullSize < fCapacity) { + fCapacity = fullSize; + if (fIndex >= fullSize) { + ensureCapacity(0); + } + } + } + else { + // reset fFullHandler to zero because setFullHandler had bad input + fFullHandler = 0; + } + } + + // ----------------------------------------------------------------------- + // Buffer Management + // ----------------------------------------------------------------------- + void append(const XMLCh toAppend) + { + // Put in char and bump the index + if (fIndex == fCapacity) + ensureCapacity(1); + fBuffer[fIndex++] = toAppend; + } + + void append (const XMLCh* const chars, const XMLSize_t count) + { + if (count) { + if (fIndex + count >= fCapacity) { + ensureCapacity(count); + } + memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh)); + fIndex += count; + } + else { + append(chars); + } + } + + void append (const XMLCh* const chars) + { + if (chars != 0 && *chars != 0) { + // get length of chars + XMLSize_t count = 0; + for (; *(chars+count); count++ ) /*noop*/; + + if (fIndex + count >= fCapacity) { + ensureCapacity(count); + } + memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh)); + fIndex += count; + } + } + + void set (const XMLCh* const chars, const XMLSize_t count) + { + fIndex = 0; + append(chars, count); + } + + void set (const XMLCh* const chars) + { + fIndex = 0; + if (chars != 0 && *chars != 0) + append(chars); + } + + const XMLCh* getRawBuffer() const + { + fBuffer[fIndex] = 0; + return fBuffer; + } + + XMLCh* getRawBuffer() + { + fBuffer[fIndex] = 0; + return fBuffer; + } + + void reset() + { + fIndex = 0; + } + + // ----------------------------------------------------------------------- + // Getters + // ----------------------------------------------------------------------- + bool getInUse() const + { + return fUsed; + } + + XMLSize_t getLen() const + { + return fIndex; + } + + bool isEmpty() const + { + return (fIndex == 0); + } + + // ----------------------------------------------------------------------- + // Setters + // ----------------------------------------------------------------------- + void setInUse(const bool newValue) + { + fUsed = newValue; + } + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLBuffer(const XMLBuffer&); + XMLBuffer& operator=(const XMLBuffer&); + + // ----------------------------------------------------------------------- + // Declare our friends + // ----------------------------------------------------------------------- + friend class XMLBufBid; + + // ----------------------------------------------------------------------- + // Private helpers + // ----------------------------------------------------------------------- + void ensureCapacity(const XMLSize_t extraNeeded); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fBuffer + // The pointer to the buffer data. Its grown as needed. Its always + // one larger than fCapacity, to leave room for the null terminator. + // + // fIndex + // The current index into the buffer, as characters are appended + // to it. If its zero, then the buffer is empty. + // + // fCapacity + // The current capacity of the buffer. Its actually always one + // larger, to leave room for the null terminator. + // + // fUsed + // Indicates whether this buffer is in use or not. + // + // fFullHandler, fFullSize + // If fFullHandler is non-null, the buffer has a maximum size + // indicated by fFullSize. If writing to the buffer would exceed the + // buffer's maximum size, fFullHandler's bufferFull callback is + // invoked, to empty the buffer. + // ----------------------------------------------------------------------- + XMLSize_t fIndex; + XMLSize_t fCapacity; + XMLSize_t fFullSize; + bool fUsed; + MemoryManager* const fMemoryManager; + XMLBufferFullHandler* fFullHandler; + XMLCh* fBuffer; +}; + +/** + * XMLBufferFullHandler is a callback interface for clients of + * XMLBuffers that impose a size restriction (e.g. XMLScanner). + * Note that this is intended solely as a mix-in for internal + * use, and therefore does not derive from XMemory (to avoid + * the ambiguous base class problem). + */ +class XMLPARSER_EXPORT XMLBufferFullHandler +{ +public : + + virtual ~XMLBufferFullHandler() {} + + /** + * Callback method, intended to allow clients of an XMLBuffer which has + * become full to empty it appropriately. + * @return true if the handler was able to empty the buffer (either + * partially or completely), otherwise false to indicate an error. + */ + virtual bool bufferFull(XMLBuffer&) = 0; + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLBufferMgr.cpp b/include/xercesc/framework/XMLBufferMgr.cpp new file mode 100644 index 0000000..327f8de --- /dev/null +++ b/include/xercesc/framework/XMLBufferMgr.cpp @@ -0,0 +1,114 @@ +/* + * 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: XMLBufferMgr.cpp 673679 2008-07-03 13:50:10Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +//#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +XMLBufferMgr::XMLBufferMgr(MemoryManager* const manager) : + + fBufCount(32) + , fMemoryManager(manager) + , fBufList(0) +{ + // Allocate the buffer list and zero it out + fBufList = (XMLBuffer**) fMemoryManager->allocate(fBufCount * sizeof(XMLBuffer*)); // new XMLBuffer*[fBufCount]; + for (XMLSize_t index = 0; index < fBufCount; index++) + fBufList[index] = 0; +} + +XMLBufferMgr::~XMLBufferMgr() +{ + // Delete any buffers that got allocated + for (XMLSize_t index = 0; index < fBufCount; index++) + delete fBufList[index]; + + // And then the buffer list + fMemoryManager->deallocate(fBufList); //delete [] fBufList; +} + + +// --------------------------------------------------------------------------- +// Buffer management +// --------------------------------------------------------------------------- +XMLBuffer& XMLBufferMgr::bidOnBuffer() +{ + // + // Look for a buffer that is not in use. If we hit a null entry, then + // we have to add one. + // + for (XMLSize_t index = 0; index < fBufCount; index++) + { + // No more buffers available, so create one and take it + if (!fBufList[index]) + { + fBufList[index] = new (fMemoryManager) XMLBuffer(1023, fMemoryManager); + fBufList[index]->setInUse(true); + return *fBufList[index]; + } + + // + // There's one here, so see if its use. If not, mark it, reset it, + // and take it + // + if (!fBufList[index]->getInUse()) + { + fBufList[index]->reset(); + fBufList[index]->setInUse(true); + return *(fBufList[index]); + } + } + + // We did not find one, so freak out + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::BufMgr_NoMoreBuffers, fMemoryManager); + + // NOTE: Dummy return to make some compilers happy. Never really gets called! + return *fBufList[0]; +} + + +void XMLBufferMgr::releaseBuffer(XMLBuffer& toRelease) +{ + // Look for this buffer in the list + for (XMLSize_t index = 0; index < fBufCount; index++) + { + if (fBufList[index] == &toRelease) + { + // Unmark it + toRelease.setInUse(false); + return; + } + } + + // It was not a legal buffer + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::BufMgr_BufferNotInPool, fMemoryManager); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLBufferMgr.hpp b/include/xercesc/framework/XMLBufferMgr.hpp new file mode 100644 index 0000000..82a5817 --- /dev/null +++ b/include/xercesc/framework/XMLBufferMgr.hpp @@ -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: XMLBufferMgr.hpp 673679 2008-07-03 13:50:10Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFERMGR_HPP) +#define XERCESC_INCLUDE_GUARD_XMLBUFFERMGR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLBufBid; + +/** + * There are many places where XMLBuffer objects are needed. In order to + * avoid either constantly creating and destroying them or maintaining a + * fixed set and worrying about accidental reuse, a buffer manager can + * provide a pool of buffers which can be temporarily used and then put + * back into the pool. This provides a good compromise between performance + * and easier maintenance. + */ +class XMLPARSER_EXPORT XMLBufferMgr : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructor */ + //@{ + XMLBufferMgr(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + //@} + + /** @name Destructor */ + //@{ + ~XMLBufferMgr(); + //@} + + + // ----------------------------------------------------------------------- + // Buffer management + // ----------------------------------------------------------------------- + XMLBuffer& bidOnBuffer(); + void releaseBuffer(XMLBuffer& toRelease); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLSize_t getBufferCount() const; + XMLSize_t getAvailableBufferCount() const; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLBufferMgr(const XMLBufferMgr&); + XMLBufferMgr& operator=(const XMLBufferMgr&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fBufCount + // The count of buffers that have been allocated so far. + // + // fBufList; + // The list of pointers to buffers that are loaned out. There will + // never be a lot of them, so a flat list is good enough. + // ----------------------------------------------------------------------- + XMLSize_t fBufCount; + MemoryManager* fMemoryManager; + XMLBuffer** fBufList; +}; + +inline XMLSize_t XMLBufferMgr::getBufferCount() const +{ + return fBufCount; +} + +inline XMLSize_t XMLBufferMgr::getAvailableBufferCount() const +{ + XMLSize_t available = fBufCount; + for (XMLSize_t index = 0; index < fBufCount && fBufList[index]; index++) + { + if (fBufList[index]->getInUse()) + --available; + } + return available; +} + + +/** + * XMLBufBid is a scoped based janitor that allows the scanner code to ask + * for a buffer on a scoped basis and then insure that it gets freed back + * into the pool no matter how the scope is exited (exception or normal exit.) + */ +class XMLBufBid : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + XMLBufBid(XMLBufferMgr* const srcMgr) : + + fBuffer(srcMgr->bidOnBuffer()) + , fMgr(srcMgr) + { + } + + ~XMLBufBid() + { + fMgr->releaseBuffer(fBuffer); + } + + + + // ----------------------------------------------------------------------- + // Buffer access + // ----------------------------------------------------------------------- + void append(const XMLCh toAppend) + { + fBuffer.append(toAppend); + } + + void append(const XMLCh* const toAppend, const XMLSize_t count = 0) + { + fBuffer.append(toAppend, count); + } + + const XMLBuffer& getBuffer() const + { + return fBuffer; + } + + XMLBuffer& getBuffer() + { + return fBuffer; + } + + const XMLCh* getRawBuffer() const + { + fBuffer.fBuffer[fBuffer.fIndex] = 0; + return fBuffer.fBuffer; + } + + XMLCh* getRawBuffer() + { + fBuffer.fBuffer[fBuffer.fIndex] = 0; + return fBuffer.fBuffer; + } + + XMLSize_t getLen() const + { + return fBuffer.fIndex; + } + + bool isEmpty() const + { + return (fBuffer.fIndex == 0); + } + + void reset() + { + fBuffer.reset(); + } + + void set(const XMLCh* const chars, const XMLSize_t count = 0) + { + fBuffer.set(chars, count); + } + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLBufBid(const XMLBufBid&); + XMLBufBid& operator=(const XMLBufBid&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fBuffer + // This is the buffer we got, and which we will release. + // + // fMgr + // This is the buffer manager we got the buffer from. This is needed + // to release the buffer later. + // ----------------------------------------------------------------------- + XMLBuffer& fBuffer; + XMLBufferMgr* const fMgr; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLContentModel.cpp b/include/xercesc/framework/XMLContentModel.cpp new file mode 100644 index 0000000..0545185 --- /dev/null +++ b/include/xercesc/framework/XMLContentModel.cpp @@ -0,0 +1,38 @@ +/* + * 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: XMLContentModel.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// public static data +// --------------------------------------------------------------------------- +const unsigned int XMLContentModel::gInvalidTrans = 0xFFFFFFFF; +const unsigned int XMLContentModel::gEOCFakeId = 0xFFFFFFF1; +const unsigned int XMLContentModel::gEpsilonFakeId = 0xFFFFFFF2; + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/XMLContentModel.hpp b/include/xercesc/framework/XMLContentModel.hpp new file mode 100644 index 0000000..44fed23 --- /dev/null +++ b/include/xercesc/framework/XMLContentModel.hpp @@ -0,0 +1,145 @@ +/* + * 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: XMLContentModel.hpp 677705 2008-07-17 20:15:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLCONTENTMODEL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLCONTENTMODEL_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class ContentLeafNameTypeVector; +class GrammarResolver; +class XMLStringPool; +class XMLValidator; +class SchemaGrammar; +class SubstitutionGroupComparator; + +/** + * This class defines the abstract interface for all content models. All + * elements have a content model against which (if validating) its content + * is checked. Each type of validator (DTD, Schema, etc...) can have + * different types of content models, and even with each type of validator + * there can be specialized content models. So this simple class provides + * the abstract API via which all the types of contents models are dealt + * with generically. Its pretty simple. + */ +class XMLPARSER_EXPORT XMLContentModel : public XMemory +{ +public: + // --------------------------------------------------------------------------- + // Public static data + // + // gInvalidTrans + // This value represents an invalid transition in each line of the + // transition table. + // + // gEOCFakeId + // gEpsilonFakeId + // We have to put in a couple of special CMLeaf nodes to represent + // special values, using fake element ids that we know won't conflict + // with real element ids. + // + // + // --------------------------------------------------------------------------- + static const unsigned int gInvalidTrans; + static const unsigned int gEOCFakeId; + static const unsigned int gEpsilonFakeId; + + // ----------------------------------------------------------------------- + // Constructors are hidden, only the virtual Destructor is exposed + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + virtual ~XMLContentModel() + { + } + //@} + + + // ----------------------------------------------------------------------- + // The virtual content model interface provided by derived classes + // ----------------------------------------------------------------------- + virtual bool validateContent + ( + QName** const children + , XMLSize_t childCount + , unsigned int emptyNamespaceId + , XMLSize_t* indexFailingChild + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ) const = 0; + + 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 =0; + + virtual void checkUniqueParticleAttribution + ( + SchemaGrammar* const pGrammar + , GrammarResolver* const pGrammarResolver + , XMLStringPool* const pStringPool + , XMLValidator* const pValidator + , unsigned int* const pContentSpecOrgURI + , const XMLCh* pComplexTypeName = 0 + ) =0; + + virtual ContentLeafNameTypeVector* getContentLeafNameTypeVector() + const = 0; + + virtual unsigned int getNextState(unsigned int currentState, + XMLSize_t elementIndex) const = 0; + + 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 = 0; + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + XMLContentModel() + { + } + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLContentModel(const XMLContentModel&); + XMLContentModel& operator=(const XMLContentModel&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLDTDDescription.cpp b/include/xercesc/framework/XMLDTDDescription.cpp new file mode 100644 index 0000000..238a289 --- /dev/null +++ b/include/xercesc/framework/XMLDTDDescription.cpp @@ -0,0 +1,54 @@ +/* + * 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: XMLDTDDescription.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +XMLDTDDescription::~XMLDTDDescription() +{ +} + +XMLDTDDescription::XMLDTDDescription(MemoryManager* const memMgr) +:XMLGrammarDescription(memMgr) +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLDTDDescription) + +void XMLDTDDescription::serialize(XSerializeEngine& serEng) +{ + + XMLGrammarDescription::serialize(serEng); + + //no data +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/XMLDTDDescription.hpp b/include/xercesc/framework/XMLDTDDescription.hpp new file mode 100644 index 0000000..455a1ca --- /dev/null +++ b/include/xercesc/framework/XMLDTDDescription.hpp @@ -0,0 +1,103 @@ +/* + * 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: XMLDTDDescription.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLDTDDESCRIPTION_HPP) +#define XERCESC_INCLUDE_GUARD_XMLDTDDESCRIPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT XMLDTDDescription : public XMLGrammarDescription +{ +public : + // ----------------------------------------------------------------------- + /** @name Virtual destructor for derived classes */ + // ----------------------------------------------------------------------- + //@{ + /** + * virtual destructor + * + */ + virtual ~XMLDTDDescription(); + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of Grammar Description Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * getGrammarType + * + */ + virtual Grammar::GrammarType getGrammarType() const + { + return Grammar::DTDGrammarType; + } + //@} + + // ----------------------------------------------------------------------- + /** @name The DTDDescription Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * Getter + * + */ + virtual const XMLCh* getRootName() const = 0; + virtual const XMLCh* getSystemId() const {return 0;}; + + /** + * Setter + * + */ + virtual void setRootName(const XMLCh* const) = 0; + virtual void setSystemId(const XMLCh* const) {}; + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLDTDDescription) + +protected : + // ----------------------------------------------------------------------- + /** Hidden Constructors */ + // ----------------------------------------------------------------------- + //@{ + XMLDTDDescription(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + //@} + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLDTDDescription(const XMLDTDDescription& ); + XMLDTDDescription& operator=(const XMLDTDDescription& ); + //@} + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLDocumentHandler.hpp b/include/xercesc/framework/XMLDocumentHandler.hpp new file mode 100644 index 0000000..58855aa --- /dev/null +++ b/include/xercesc/framework/XMLDocumentHandler.hpp @@ -0,0 +1,283 @@ +/* + * 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: XMLDocumentHandler.hpp 673679 2008-07-03 13:50:10Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLDOCUMENTHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLDOCUMENTHANDLER_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLElementDecl; +class XMLEntityDecl; + +/** + * This abstract class provides the interface for the scanner to return + * XML document information up to the parser as it scans through the + * document. + * + * The interface is very similar to org.sax.DocumentHandler, but + * has some extra methods required to get all the data out. + */ +class XMLPARSER_EXPORT XMLDocumentHandler +{ +public: + // ----------------------------------------------------------------------- + // Constructors are hidden, just the virtual destructor is exposed + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + virtual ~XMLDocumentHandler() + { + } + //@} + + /** @name The document handler interface */ + //@{ + /** Receive notification of character data. + * + *

The scanner will call this method to report each chunk of + * character data. The scanner may return all contiguous character + * data in a single chunk, or they may split it into several + * chunks; however, all of the characters in any single event + * will come from the same external entity, so that the Locator + * provides useful information.

+ * + *

The parser must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The content (characters) between markup from the XML + * document. + * @param length The number of characters to read from the array. + * @param cdataSection Indicates that this data is inside a CDATA + * section. + * @see #ignorableWhitespace + * @see Locator + */ + virtual void docCharacters + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ) = 0; + + /** Receive notification of comments in the XML content being parsed. + * + * This scanner will call this method for any comments found in the + * content of the document. + * + * @param comment The text of the comment. + */ + virtual void docComment + ( + const XMLCh* const comment + ) = 0; + + /** Receive notification of PI's parsed in the XML content. + * + * The scanner will call this method for any PIs it finds within the + * content of the document. + * + * @param target The name of the PI. + * @param data The body of the PI. This may be an empty string since + * the body is optional. + */ + virtual void docPI + ( + const XMLCh* const target + , const XMLCh* const data + ) = 0; + + /** Receive notification after the scanner has parsed the end of the + * document. + * + * The scanner will call this method when the current document has been + * fully parsed. The handler may use this opportunity to do something with + * the data, clean up temporary data, etc... + */ + virtual void endDocument() = 0; + + /** Receive notification of the end of an element. + * + * This method is called when scanner encounters the end of element tag. + * There will be a corresponding startElement() event for every + * endElement() event, but not necessarily the other way around. For + * empty tags, there is only a startElement() call. + * + * @param elemDecl The name of the element whose end tag was just + * parsed. + * @param uriId The ID of the URI in the URI pool (only valid if + * name spaces is enabled) + * @param isRoot Indicates if this is the root element. + * @param prefixName The string representing the prefix name + */ + virtual void endElement + ( + const XMLElementDecl& elemDecl + , const unsigned int uriId + , const bool isRoot + , const XMLCh* const prefixName = 0 + ) = 0; + + /** Receive notification when a referenced entity's content ends + * + * This method is called when scanner encounters the end of an entity + * reference. + * + * @param entDecl The name of the entity reference just scanned. + */ + virtual void endEntityReference + ( + const XMLEntityDecl& entDecl + ) = 0; + + /** Receive notification of ignorable whitespace in element content. + * + *

Validating Parsers must use this method to report each chunk + * of ignorable whitespace (see the W3C XML 1.0 recommendation, + * section 2.10): non-validating parsers may also use this method + * if they are capable of parsing and using content models.

+ * + *

The scanner may return all contiguous whitespace in a single + * chunk, or it may split it into several chunks; however, all of + * the characters in any single event will come from the same + * external entity, so that the Locator provides useful + * information.

+ * + *

The parser must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The whitespace characters from the XML document. + * @param length The number of characters to read from the array. + * @param cdataSection Indicates that this data is inside a CDATA + * section. + * @see #docCharacters + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ) = 0; + + /** Reset the document handler's state, if required + * + * This method is used to give the registered document handler a + * chance to reset itself. Its called by the scanner at the start of + * every parse. + */ + virtual void resetDocument() = 0; + + /** Receive notification of the start of a new document + * + * This method is the first callback called the scanner at the + * start of every parse. This is before any content is parsed. + */ + virtual void startDocument() = 0; + + /** Receive notification of a new start tag + * + * This method is called when scanner encounters the start of an element tag. + * All elements must always have a startElement() tag. Empty tags will + * only have the startElement() tag and no endElement() tag. + * + * @param elemDecl The name of the element whose start tag was just + * parsed. + * @param uriId The ID of the URI in the URI pool (only valid if + * name spaces is enabled) + * @param prefixName The string representing the prefix name + * @param attrList List of attributes in the element + * @param attrCount Count of the attributes in the element + * @param isEmpty Indicates if the element is empty, in which case + * you should not expect an endElement() event. + * @param isRoot Indicates if this is the root element. + */ + virtual void startElement + ( + const XMLElementDecl& elemDecl + , const unsigned int uriId + , const XMLCh* const prefixName + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot + ) = 0; + + /** Receive notification when the scanner hits an entity reference. + * + * This is currently useful only to DOM parser configurations as SAX + * does not provide any api to return this information. + * + * @param entDecl The name of the entity that was referenced. + */ + virtual void startEntityReference(const XMLEntityDecl& entDecl) = 0; + + /** Receive notification of an XML declaration + * + * Currently neither DOM nor SAX provide API's to return back this + * information. + * + * @param versionStr The value of the version pseudoattribute + * of the XML decl. + * @param encodingStr The value of the encoding pseudoattribute + * of the XML decl. + * @param standaloneStr The value of the standalone + * pseudoattribute of the XML decl. + * @param autoEncodingStr The encoding string auto-detected by the + * scanner. In absence of any 'encoding' attribute in the + * XML decl, the XML standard specifies how a parser can + * auto-detect. If there is no encodingStr + * this is what will be used to try to decode the file. + */ + virtual void XMLDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const autoEncodingStr + ) = 0; + + //@} + + + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + XMLDocumentHandler() + { + } + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLDocumentHandler(const XMLDocumentHandler&); + XMLDocumentHandler& operator=(const XMLDocumentHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLElementDecl.cpp b/include/xercesc/framework/XMLElementDecl.cpp new file mode 100644 index 0000000..2e31c00 --- /dev/null +++ b/include/xercesc/framework/XMLElementDecl.cpp @@ -0,0 +1,170 @@ +/* + * 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: XMLElementDecl.cpp 679359 2008-07-24 11:15:19Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLElementDecl: Public, static data +// --------------------------------------------------------------------------- +const unsigned int XMLElementDecl::fgInvalidElemId = 0xFFFFFFFE; +const unsigned int XMLElementDecl::fgPCDataElemId = 0xFFFFFFFF; +const XMLCh XMLElementDecl::fgPCDataElemName[] = +{ + chPound, chLatin_P, chLatin_C, chLatin_D, chLatin_A + , chLatin_T, chLatin_A, chNull +}; + + + +// --------------------------------------------------------------------------- +// XMLElementDecl: Destructor +// --------------------------------------------------------------------------- +XMLElementDecl::~XMLElementDecl() +{ + delete fElementName; +} + +// --------------------------------------------------------------------------- +// XMLElementDecl: Setter Methods +// --------------------------------------------------------------------------- +void +XMLElementDecl::setElementName(const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId ) +{ + if (fElementName) + fElementName->setName(prefix, localPart, uriId); + else + fElementName = new (fMemoryManager) QName(prefix, localPart, uriId, fMemoryManager); +} + +void +XMLElementDecl::setElementName(const XMLCh* const rawName + , const int uriId ) +{ + if (fElementName) + fElementName->setName(rawName, uriId); + else + fElementName = new (fMemoryManager) QName(rawName, uriId, fMemoryManager); +} + +void +XMLElementDecl::setElementName(const QName* const elementName) +{ + if (fElementName) + fElementName->setValues(*elementName); + else + fElementName = new (fMemoryManager) QName(*elementName); +} + +// --------------------------------------------------------------------------- +// ElementDecl: Hidden constructors +// --------------------------------------------------------------------------- +XMLElementDecl::XMLElementDecl(MemoryManager* const manager) : + + fMemoryManager(manager) + , fElementName(0) + , fCreateReason(XMLElementDecl::NoReason) + , fId(XMLElementDecl::fgInvalidElemId) + , fExternalElement(false) +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLElementDecl) + +void XMLElementDecl::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<>fElementName; + + int i; + serEng>>i; + fCreateReason=(CreateReasons)i; + + serEng.readSize (fId); + serEng>>fExternalElement; + } + +} + +void +XMLElementDecl::storeElementDecl(XSerializeEngine& serEng + , XMLElementDecl* const element) +{ + if (element) + { + serEng<<(int) element->getObjectType(); + serEng<>type; + + switch((XMLElementDecl::objectType)type) + { + case Schema: + SchemaElementDecl* schemaElementDecl; + serEng>>schemaElementDecl; + return schemaElementDecl; + case DTD: + DTDElementDecl* dtdElementDecl; + serEng>>dtdElementDecl; + return dtdElementDecl; + case UnKnown: + //fall through + default: + return 0; + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLElementDecl.hpp b/include/xercesc/framework/XMLElementDecl.hpp new file mode 100644 index 0000000..4589c71 --- /dev/null +++ b/include/xercesc/framework/XMLElementDecl.hpp @@ -0,0 +1,552 @@ +/* + * 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: XMLElementDecl.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLELEMENTDECL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLELEMENTDECL_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class ContentSpecNode; +class XMLContentModel; + +/** + * This class defines the core information of an element declaration. Each + * validator (DTD, Schema, etc...) will have its own information that it + * associations with the declaration of an element, but they must all share + * at least this core information, i.e. they must all derive from this + * class. The set of info enforced at this level is driven by the needs of + * XML 1.0 spec validation and well formedness checks. + * + * This class defines some special element id values for invalid elements + * and PCDATA elements, as well as a string for the special PCDATA element + * name. All validators must honor these special values in order to allow + * content models to work generically (i.e. to let code know when its dealing + * with invalid or PCDATA element ids without having to know what type of + * validator its messing with.) + */ +class XMLPARSER_EXPORT XMLElementDecl : public XSerializable, public XMemory +{ + public: + // ----------------------------------------------------------------------- + // Class specific types + // + // CreateReasons + // This type is used to store how an element declaration got into + // the grammar's element pool. They are faulted in for various + // reasons. + // + // LookupOpts + // These are the values used by the attribute lookup methods. + // + // CharDataOpts + // This is used to indicate how this type of element reacts to + // character data as content. + // ----------------------------------------------------------------------- + enum CreateReasons + { + NoReason + , Declared + , AttList + , InContentModel + , AsRootElem + , JustFaultIn + }; + + enum CharDataOpts + { + NoCharData + , SpacesOk + , AllCharData + }; + + + // ----------------------------------------------------------------------- + // Public static data + // + // fgInvalidElemId + // A value to represent an invalid element node id. + // + // fgPCDataElemId + // This is the value to use to represent a PCDATA node when an + // element id is required. + // + // fgPCDataElemName + // This is the value to use to represent a PCDATA node when an + // element name is required. + // ----------------------------------------------------------------------- + static const unsigned int fgInvalidElemId; + static const unsigned int fgPCDataElemId; + static const XMLCh fgPCDataElemName[]; + + + + // ----------------------------------------------------------------------- + // Destructor + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + virtual ~XMLElementDecl(); + //@} + + + // ----------------------------------------------------------------------- + // The virtual element decl interface + // ----------------------------------------------------------------------- + + /** @name Virual ElementDecl interface */ + //@{ + + /** Get a list of attributes defined for this element. + * + * The derived class should return a reference to some member object which + * implements the XMLAttDefList interface. This object gives the scanner the + * ability to look through the attributes defined for this element. + * + * It is done this way for efficiency, though of course this is not thread + * safe. The scanner guarantees that it won't ever call this method in any + * nested way, but the outside world must be careful about when it calls + * this method, and optimally never would. + */ + virtual XMLAttDefList& getAttDefList() const = 0; + + /** The character data options for this element type + * + * The derived class should return an appropriate character data opts value + * which correctly represents its tolerance towards whitespace or character + * data inside of its instances. This allows the scanner to do all of the + * validation of character data. + */ + virtual CharDataOpts getCharDataOpts() const = 0; + + /** Indicate whether this element type defined any attributes + * + * The derived class should return a boolean that indicates whether this + * element has any attributes defined for it or not. This is an optimization + * that allows the scanner to skip some work if no attributes exist. + */ + virtual bool hasAttDefs() const = 0; + + /** Get a pointer to the content spec node + * + * This method will return a const pointer to the content spec node object + * of this element. + * + * @return A const pointer to the element's content spec node + */ + virtual const ContentSpecNode* getContentSpec() const = 0; + + /** Get a pointer to the content spec node + * + * This method is identical to the previous one, except that it is non + * const. + */ + virtual ContentSpecNode* getContentSpec() = 0; + + /** Set the content spec node object for this element type + * + * This method will adopt the based content spec node object. This is called + * by the actual validator which is parsing its DTD or Schema or whatever + * and store it on the element decl object via this method. + * + * @param toAdopt This method will adopt the passed content node spec + * object. Any previous object is destroyed. + */ + virtual void setContentSpec(ContentSpecNode* toAdopt) = 0; + + /** Get a pointer to the abstract content model + * + * This method will return a const pointer to the content model object + * of this element. This class is a simple abstraction that allows an + * element to define and use multiple, specialized content model types + * internally but still allow the outside world to do simple stuff with + * them. + * + * @return A pointer to the element's content model, via the basic + * abstract content model type. + */ + virtual XMLContentModel* getContentModel() = 0; + + /** Set the content model object for this element type + * + * This method will adopt the based content model object. This is called + * by the actual validator which is parsing its DTD or Schema or whatever + * a creating an element decl. It will build what it feels is the correct + * content model type object and store it on the element decl object via + * this method. + * + * @param newModelToAdopt This method will adopt the passed content model + * object. Any previous object is destroyed. + */ + virtual void setContentModel(XMLContentModel* const newModelToAdopt) = 0; + + /** Geta formatted string of the content model + * + * This method is a convenience method which will create a formatted + * representation of the content model of the element. It will not always + * exactly recreate the original model, since some normalization or + * or reformatting may occur. But, it will be a technically accurate + * representation of the original content model. + * + * @return A pointer to an internal buffer which contains the formatted + * content model. The caller does not own this buffer and should + * copy it if it needs to be kept around. + */ + virtual const XMLCh* getFormattedContentModel () const = 0; + + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** Get the base name of this element type. + * + * Return the base name part of the element's name. This is the + * same regardless of whether namespaces are enabled or not. + * + * @return A const pointer to the base name of the element decl. + */ + const XMLCh* getBaseName() const; + XMLCh* getBaseName(); + + /** Get the URI id of this element type. + * + * Return the URI Id of this element. + * + * @return The URI Id of the element decl, or the emptyNamespaceId if not applicable. + */ + unsigned int getURI() const; + + /** Get the QName of this element type. + * + * Return the QName part of the element's name. This is the + * same regardless of whether namespaces are enabled or not. + * + * @return A const pointer to the QName of the element decl. + */ + const QName* getElementName() const; + QName* getElementName(); + + /** Get the full name of this element type. + * + * Return the full name of the element. If namespaces + * are not enabled, then this is the qName. Else it is the {uri}baseName + * form. For those validators that always require namespace processing, it + * will always be in the latter form because namespace processing will always + * be on. + */ + const XMLCh* getFullName() const; + + /** Get the create reason for this element type + * + * This method returns an enumeration which indicates why this element + * declaration exists. Elements can be used before they are actually + * declared, so they will often be faulted into the pool and marked as + * to why they are there. + * + * @return An enumerated value that indicates the reason why this element + * was added to the element decl pool. + */ + + CreateReasons getCreateReason() const; + + /** Get the element decl pool id for this element type + * + * This method will return the element decl pool id of this element + * declaration. This uniquely identifies this element type within the + * parse event that it is declared within. This value is assigned by the + * grammar whose decl pool this object belongs to. + * + * @return The element decl id of this element declaration. + */ + XMLSize_t getId() const; + + /** Indicate whether this element type has been declared yet + * + * This method returns a boolean that indicates whether this element + * has been declared yet. There are a number of reasons why an element + * declaration can be faulted in, but eventually it must be declared or + * its an error. See the CreateReasons enumeration. + * + * @return true if this element has been declared, else false. + */ + bool isDeclared() const; + + /** Indicate whether this element type has been declared externally + * + * This method returns a boolean that indicates whether this element + * has been declared externally. + * + * @return true if this element has been declared externally, else false. + */ + + bool isExternal() const; + + /** Get the memory manager + * + * This method returns the configurable memory manager used by the + * element declaration for dynamic allocation/deallocation. + * + * @return the memory manager + */ + MemoryManager* getMemoryManager() const; + + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** Set the element name object for this element type + * + * This method will adopt the based content spec node object. This is called + * by the actual validator which is parsing its DTD or Schema or whatever + * and store it on the element decl object via this method. + * + * @param prefix Prefix of the element + * @param localPart Base Name of the element + * @param uriId The uriId of the element + */ + void setElementName(const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId ); + + /** Set the element name object for this element type + * + * This method will adopt the based content spec node object. This is called + * by the actual validator which is parsing its DTD or Schema or whatever + * and store it on the element decl object via this method. + * + * @param rawName Full Name of the element + * @param uriId The uriId of the element + */ + void setElementName(const XMLCh* const rawName + , const int uriId ); + + /** Set the element name object for this element type + * + * This method will adopt the based content spec node object. This is called + * by the actual validator which is parsing its DTD or Schema or whatever + * and store it on the element decl object via this method. + * + * @param elementName QName of the element + */ + void setElementName(const QName* const elementName); + + /** Update the create reason for this element type. + * + * This method will update the 'create reason' field for this element + * decl object. As the validator parses its DTD, Schema, etc... it will + * encounter various references to an element declaration, which will + * cause the element declaration to either be declared or to be faulted + * into the pool in preparation for some future declaration. As it does + * so,it will update this field to indicate the current status of the + * decl object. + */ + void setCreateReason(const CreateReasons newReason); + + /** Set the element decl pool id for this element type + * + * This method will set the pool id of this element decl. This is called + * by the grammar which created this object, and will provide this + * decl object with a unique id within the parse event that created it. + */ + void setId(const XMLSize_t newId); + + + /** Set the element decl to indicate external declaration + * + */ + void setExternalElemDeclaration(const bool aValue); + + //@} + + + // ----------------------------------------------------------------------- + // Miscellaneous methods + // ----------------------------------------------------------------------- + + /** @name Miscellaneous methods */ + //@{ + + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLElementDecl) + + enum objectType + { + Schema + , DTD + , UnKnown + }; + + virtual XMLElementDecl::objectType getObjectType() const = 0; + + static void storeElementDecl(XSerializeEngine& serEng + , XMLElementDecl* const element); + + static XMLElementDecl* loadElementDecl(XSerializeEngine& serEng); + +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + XMLElementDecl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLElementDecl(const XMLElementDecl&); + XMLElementDecl& operator=(const XMLElementDecl&); + + + // ----------------------------------------------------------------------- + // Data members + // + // fElementName + // This is the name of the element decl. + // + // fCreateReason + // We sometimes have to put an element decl object into the elem + // decl pool before the element's declaration is seen, such as when + // its used in another element's content model or an att list is + // seen for it. This flag tells us whether its been declared, and + // if not why it had to be created. + // + // fId + // The unique id of this element. This is created by the derived + // class, or more accurately the grammar that owns the objects + // of the derived types. But, since they all have to have them, we + // let them all store the id here. It is defaulted to have the + // value fgInvalidElem until explicitly set. + // + // fExternalElement + // This flag indicates whether or the element was declared externally. + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + QName* fElementName; + CreateReasons fCreateReason; + XMLSize_t fId; + bool fExternalElement; +}; + + +// --------------------------------------------------------------------------- +// XMLElementDecl: Getter methods +// --------------------------------------------------------------------------- +inline const XMLCh* XMLElementDecl::getBaseName() const +{ + return fElementName->getLocalPart(); +} + +inline XMLCh* XMLElementDecl::getBaseName() +{ + return fElementName->getLocalPart(); +} + +inline unsigned int XMLElementDecl::getURI() const +{ + return fElementName->getURI(); +} + +inline const QName* XMLElementDecl::getElementName() const +{ + return fElementName; +} + +inline QName* XMLElementDecl::getElementName() +{ + return fElementName; +} + +inline const XMLCh* XMLElementDecl::getFullName() const +{ + return fElementName->getRawName(); +} + +inline XMLElementDecl::CreateReasons XMLElementDecl::getCreateReason() const +{ + return fCreateReason; +} + +inline XMLSize_t XMLElementDecl::getId() const +{ + return fId; +} + +inline bool XMLElementDecl::isDeclared() const +{ + return (fCreateReason == Declared); +} + + +inline bool XMLElementDecl::isExternal() const +{ + return fExternalElement; +} + +inline MemoryManager* XMLElementDecl::getMemoryManager() const +{ + return fMemoryManager; +} + + +// --------------------------------------------------------------------------- +// XMLElementDecl: Setter methods +// --------------------------------------------------------------------------- +inline void +XMLElementDecl::setCreateReason(const XMLElementDecl::CreateReasons newReason) +{ + fCreateReason = newReason; +} + +inline void XMLElementDecl::setId(const XMLSize_t newId) +{ + fId = newId; +} + + +inline void XMLElementDecl::setExternalElemDeclaration(const bool aValue) +{ + fExternalElement = aValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLEntityDecl.cpp b/include/xercesc/framework/XMLEntityDecl.cpp new file mode 100644 index 0000000..b0c0cec --- /dev/null +++ b/include/xercesc/framework/XMLEntityDecl.cpp @@ -0,0 +1,200 @@ +/* + * 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: XMLEntityDecl.cpp 679359 2008-07-24 11:15:19Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLEntityDecl: Constructors and Destructor +// --------------------------------------------------------------------------- +XMLEntityDecl::XMLEntityDecl(MemoryManager* const manager) : + + fId(0) + , fValueLen(0) + , fValue(0) + , fName(0) + , fNotationName(0) + , fPublicId(0) + , fSystemId(0) + , fBaseURI(0) + , fIsExternal(false) + , fMemoryManager(manager) +{ +} + +XMLEntityDecl::XMLEntityDecl(const XMLCh* const entName, + MemoryManager* const manager) : + + fId(0) + , fValueLen(0) + , fValue(0) + , fName(0) + , fNotationName(0) + , fPublicId(0) + , fSystemId(0) + , fBaseURI(0) + , fIsExternal(false) + , fMemoryManager(manager) +{ + fName = XMLString::replicate(entName, fMemoryManager); +} + +typedef JanitorMemFunCall CleanupType; + +XMLEntityDecl::XMLEntityDecl(const XMLCh* const entName + , const XMLCh* const value + , MemoryManager* const manager) : + fId(0) + , fValueLen(XMLString::stringLen(value)) + , fValue(0) + , fName(0) + , fNotationName(0) + , fPublicId(0) + , fSystemId(0) + , fBaseURI(0) + , fIsExternal(false) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XMLEntityDecl::cleanUp); + + try + { + fValue = XMLString::replicate(value, fMemoryManager); + fName = XMLString::replicate(entName, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XMLEntityDecl::XMLEntityDecl(const XMLCh* const entName + , const XMLCh value + , MemoryManager* const manager) : + fId(0) + , fValueLen(1) + , fValue(0) + , fName(0) + , fNotationName(0) + , fPublicId(0) + , fSystemId(0) + , fBaseURI(0) + , fIsExternal(false) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XMLEntityDecl::cleanUp); + + try + { + XMLCh dummy[2] = { chNull, chNull }; + dummy[0] = value; + fValue = XMLString::replicate(dummy, fMemoryManager); + fName = XMLString::replicate(entName, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XMLEntityDecl::~XMLEntityDecl() +{ + cleanUp(); +} + + +// --------------------------------------------------------------------------- +// XMLEntityDecl: Setter methods +// --------------------------------------------------------------------------- +void XMLEntityDecl::setName(const XMLCh* const entName) +{ + // Clean up the current name stuff + if (fName) + fMemoryManager->deallocate(fName); + + fName = XMLString::replicate(entName, fMemoryManager); +} + + +// --------------------------------------------------------------------------- +// XMLEntityDecl: Private helper methods +// --------------------------------------------------------------------------- +void XMLEntityDecl::cleanUp() +{ + fMemoryManager->deallocate(fName); + fMemoryManager->deallocate(fNotationName); + fMemoryManager->deallocate(fValue); + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); + fMemoryManager->deallocate(fBaseURI); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLEntityDecl) + +void XMLEntityDecl::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng.writeSize (fId); + serEng.writeSize (fValueLen); + serEng.writeString(fValue); + serEng.writeString(fName); + serEng.writeString(fNotationName); + serEng.writeString(fPublicId); + serEng.writeString(fSystemId); + serEng.writeString(fBaseURI); + serEng<>fIsExternal; + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLEntityDecl.hpp b/include/xercesc/framework/XMLEntityDecl.hpp new file mode 100644 index 0000000..cf00fc1 --- /dev/null +++ b/include/xercesc/framework/XMLEntityDecl.hpp @@ -0,0 +1,512 @@ +/* + * 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: XMLEntityDecl.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLENTITYDECL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLENTITYDECL_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class defines that core information that defines an XML entity, no + * matter what validator is used. Each validator will create a derivative + * of this class which adds any extra information it requires. + * + * This class supports keyed collection semantics via the getKey() method + * which extracts the key field, the entity name in this case. The name will + * have whatever form is deemed appropriate for the type of validator in + * use. + * + * When setting the fields of this class, you must make sure that you do + * not set conflicting values. For instance, an internal entity cannot have + * a notation name. And an external entity cannot have a value string. + * These rules are defined by the XML specification. In most cases, these + * objects are created by validator objects as they parse a DTD or Schema + * or whatever, at which time they confirm the correctness of the data before + * creating the entity decl object. + */ +class XMLPARSER_EXPORT XMLEntityDecl : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors */ + //@{ + + /** + * Default Constructor + */ + XMLEntityDecl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** Constructor with a const entity name + * + * @param entName The new name to give to this entity. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + XMLEntityDecl + ( + const XMLCh* const entName + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Constructor with a const entity name and value + * + * @param entName The new name to give to this entity. + * @param value The new value to give to this entity name. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + XMLEntityDecl + ( + const XMLCh* const entName + , const XMLCh* const value + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Constructor with a const entity name and single XMLCh value + * + * @param entName The new name to give to this entity. + * @param value The new value to give to this entity name. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + XMLEntityDecl + ( + const XMLCh* const entName + , const XMLCh value + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + //@} + + /** @name Destructor */ + //@{ + + /** + * Default destructor + */ + virtual ~XMLEntityDecl(); + + //@} + + + // ----------------------------------------------------------------------- + // Virtual entity decl interface + // ----------------------------------------------------------------------- + + /** @name The pure virtual methods in this interface. */ + //@{ + + /** Get the 'declared in internal subset' flag + * + * Gets the state of the flag which indicates whether the entity was + * declared in the internal or external subset. Some structural + * description languages might not have an internal subset concept, in + * which case this will always return false. + */ + virtual bool getDeclaredInIntSubset() const = 0; + + /** Get the 'is parameter entity' flag + * + * Gets the state of the flag which indicates whether this entity is + * a parameter entity. If not, then its a general entity. + */ + virtual bool getIsParameter() const = 0; + + /** Get the 'is special char entity' flag + * + * Gets the state of the flag that indicates whether this entity is + * one of the special, intrinsically supported character entities. + */ + virtual bool getIsSpecialChar() const = 0; + + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** + * Gets the pool id of this entity. Validators maintain all decls in + * pools, from which they can be quickly extracted via id. + */ + XMLSize_t getId() const; + + /** + * Returns a const pointer to the name of this entity decl. This name + * will be in whatever format is appropriate for the type of validator + * in use. + */ + const XMLCh* getName() const; + + /** + * Gets the notation name, if any, declared for this entity. If this + * entity is not a notation type entity, it will be a null pointer. + */ + const XMLCh* getNotationName() const; + + /** + * Gets the public id declared for this entity. Public ids are optional + * so it can be a null pointer. + */ + const XMLCh* getPublicId() const; + + /** + * Gets the system id declared for this entity. The system id is required + * so this method should never return a null pointers. + */ + const XMLCh* getSystemId() const; + + /** + * Gets the base URI for this entity. + */ + const XMLCh* getBaseURI() const; + + /** + * This method returns the value of an internal entity. If this is not + * an internal entity (i.e. its external), then this will be a null + * pointer. + */ + const XMLCh* getValue() const; + + /** + * This method returns the number of characters in the value returned + * by getValue(). If this entity is external, this will be zero since + * an external entity has no internal value. + */ + XMLSize_t getValueLen() const; + + /** + * Indicates that this entity is an external entity. If not, then it is + * assumed to be an internal entity, surprise. + */ + bool isExternal() const; + + /** + * Indicates whether this entity is unparsed. This is meaningless for + * internal entities. Some external entities are unparsed in that they + * refer to something other than XML source. + */ + bool isUnparsed() const; + + /** Get the plugged-in memory manager + * + * This method returns the plugged-in memory manager user for dynamic + * memory allocation/deallocation. + * + * @return the plugged-in memory manager + */ + MemoryManager* getMemoryManager() const; + + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** + * This method will set the entity name. The format of this name is + * defined by the particular validator in use, since it will be the + * one who creates entity definitions as it parses the DTD, Schema, + * ect... + * + * @param entName The new name to give to this entity. + */ + void setName + ( + const XMLCh* const entName + ); + + /** + * This method will mark whether the entity is external. + * + * @param value The new value for the 'is external' flag. + */ + void setIsExternal(bool value); + + /** + * This method will set the notation name for this entity. By setting + * this, you are indicating that this is an unparsed external entity. + * + * @param newName The new notation name to give to this entity. + */ + void setNotationName(const XMLCh* const newName); + + /** + * This method will set a new public id on this entity. The public id + * has no particular form and is purely for client consumption. + * + * @param newId The new public id to give to this entity. + */ + void setPublicId(const XMLCh* const newId); + + /** + * This method will set a new sysetm id on this entity. This will + * then control where the source for this entity lives. If it is + * an internal entity, then the system id is only for bookkeeping + * purposes, and to allow any external entities referenced from + * within the entity to be correctly resolved. + * + * @param newId The new system id to give to the entity. + */ + void setSystemId(const XMLCh* const newId); + + /** + * This method will set a new baseURI on this entity. This will + * then control the URI used to resolve the relative system Id. + * + * @param newId The new base URI to give to the entity. + */ + void setBaseURI(const XMLCh* const newId); + + /** + * This method will set a new value for this entity. This is only + * valid if the entity is to be an internal entity. By setting this + * field, you are indicating that the entity is internal. + * + * @param newValue The new value to give to this entity. + */ + void setValue(const XMLCh* const newValue); + + //@} + + /* For internal use only */ + void setId(const XMLSize_t newId); + + + // ----------------------------------------------------------------------- + // Support named pool syntax + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** + * This method allows objects of this class to be used within a standard + * keyed collection used commonly within the parser system. The collection + * calls this method to get the key (usually to hash it) by which the + * object is to be stored. + */ + const XMLCh* getKey() const; + + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLEntityDecl) + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLEntityDecl(const XMLEntityDecl&); + XMLEntityDecl& operator=(XMLEntityDecl&); + + + // ----------------------------------------------------------------------- + // XMLEntityDecl: Private helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fId + // This is the unique id given to this entity decl. + // + // fName + // The name of the entity. Entity names are never namespace based. + // + // fNotationName + // The optional notation of the entity. If there was none, then its + // empty. + // + // fPublicId + // The public id of the entity, which can be empty. + // + // fSystemId + // The system id of the entity. + // + // fValue + // fValueLen + // The entity's value and length, which is only valid if its an + // internal style entity. + // + // fBaseURI + // The base URI of the entity. According to XML InfoSet, such value + // is the URI where it is declared (NOT referenced). + // ----------------------------------------------------------------------- + XMLSize_t fId; + XMLSize_t fValueLen; + XMLCh* fValue; + XMLCh* fName; + XMLCh* fNotationName; + XMLCh* fPublicId; + XMLCh* fSystemId; + XMLCh* fBaseURI; + bool fIsExternal; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// XMLEntityDecl: Getter methods +// --------------------------------------------------------------------------- +inline XMLSize_t XMLEntityDecl::getId() const +{ + return fId; +} + +inline const XMLCh* XMLEntityDecl::getName() const +{ + return fName; +} + +inline const XMLCh* XMLEntityDecl::getNotationName() const +{ + return fNotationName; +} + +inline const XMLCh* XMLEntityDecl::getPublicId() const +{ + return fPublicId; +} + +inline const XMLCh* XMLEntityDecl::getSystemId() const +{ + return fSystemId; +} + +inline const XMLCh* XMLEntityDecl::getBaseURI() const +{ + return fBaseURI; +} + +inline const XMLCh* XMLEntityDecl::getValue() const +{ + return fValue; +} + +inline XMLSize_t XMLEntityDecl::getValueLen() const +{ + return fValueLen; +} + +inline bool XMLEntityDecl::isExternal() const +{ + return fIsExternal; +} + +inline bool XMLEntityDecl::isUnparsed() const +{ + // If it has a notation, its unparsed + return (fNotationName != 0); +} + +inline MemoryManager* XMLEntityDecl::getMemoryManager() const +{ + return fMemoryManager; +} + +// --------------------------------------------------------------------------- +// XMLEntityDecl: Setter methods +// --------------------------------------------------------------------------- +inline void XMLEntityDecl::setId(const XMLSize_t newId) +{ + fId = newId; +} + +inline void XMLEntityDecl::setIsExternal(bool value) +{ + fIsExternal = value; +} + +inline void XMLEntityDecl::setNotationName(const XMLCh* const newName) +{ + if (fNotationName) + fMemoryManager->deallocate(fNotationName); + + fNotationName = XMLString::replicate(newName, fMemoryManager); +} + +inline void XMLEntityDecl::setPublicId(const XMLCh* const newId) +{ + if (fPublicId) + fMemoryManager->deallocate(fPublicId); + + fPublicId = XMLString::replicate(newId, fMemoryManager); +} + +inline void XMLEntityDecl::setSystemId(const XMLCh* const newId) +{ + if (fSystemId) + fMemoryManager->deallocate(fSystemId); + + fSystemId = XMLString::replicate(newId, fMemoryManager); +} + +inline void XMLEntityDecl::setBaseURI(const XMLCh* const newId) +{ + if (fBaseURI) + fMemoryManager->deallocate(fBaseURI); + + fBaseURI = XMLString::replicate(newId, fMemoryManager); +} + +inline void XMLEntityDecl::setValue(const XMLCh* const newValue) +{ + if (fValue) + fMemoryManager->deallocate(fValue); + + fValue = XMLString::replicate(newValue, fMemoryManager); + fValueLen = XMLString::stringLen(newValue); +} + + +// --------------------------------------------------------------------------- +// XMLEntityDecl: Support named pool syntax +// --------------------------------------------------------------------------- +inline const XMLCh* XMLEntityDecl::getKey() const +{ + return fName; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLEntityHandler.hpp b/include/xercesc/framework/XMLEntityHandler.hpp new file mode 100644 index 0000000..58ef689 --- /dev/null +++ b/include/xercesc/framework/XMLEntityHandler.hpp @@ -0,0 +1,157 @@ +/* + * 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: XMLEntityHandler.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLENTITYHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLENTITYHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class InputSource; +class XMLBuffer; +class XMLResourceIdentifier; + +/** + * This abstract class is a callback mechanism for the scanner. By creating + * a derivative of this class and plugging into the scanner, the scanner + * will call back on the object's methods to entity events. + * + * This class is primarily for use by those writing their own parser classes. + * If you use the standard parser classes, DOMParser and SAXParser, you won't + * use this API. You will instead use a similar mechanism defined by the SAX + * API, called EntityResolver. + */ +class XMLPARSER_EXPORT XMLEntityHandler +{ +public: + // ----------------------------------------------------------------------- + // Constructors are hidden, only the virtual destructor is exposed + // ----------------------------------------------------------------------- + + /** @name Destructor */ + //@{ + + /** + * Default destructor + */ + virtual ~XMLEntityHandler() + { + } + //@} + + + // ----------------------------------------------------------------------- + // The virtual entity handler interface + // ----------------------------------------------------------------------- + /** @name The pure virtual methods in this interface. */ + //@{ + + /** + * This method get called after the scanner has finished reading from + * the given input source while processing external entity references. + * + * @param inputSource The input source for the entity + */ + virtual void endInputSource(const InputSource& inputSource) = 0; + + /** + * This method allows the passes the scanned systemId to the entity + * handler, thereby giving it a chance to provide any customized + * handling like resolving relative path names. The scanner first + * calls this method before calling resolveEntity. + * + * @param systemId The system id extracted by the scanner from the + * input source. + * @param toFill The buffer in which the fully expanded system id needs + * to be stored. + */ + virtual bool expandSystemId + ( + const XMLCh* const systemId + , XMLBuffer& toFill + ) = 0; + + /** + * This method allows the entity handler to reset itself, so that + * it can be used again. It is called prior to a new document parse + * operation. + */ + virtual void resetEntities() = 0; + + /** + * This method allows the entity handler to provide customized + * application specific entity resolution. + * + * Only one resolveEntity method will be used. If both setEntityResolver and + * setXMLEntityResolver are called, then the last one is used. + * + * @param resourceIdentifier An object containing the type of + * resource to be resolved and the associated data members + * corresponding to this type. + * @return The value returned by the resolveEntity method or + * NULL otherwise to indicate no processing was done. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + */ + virtual InputSource* resolveEntity + ( + XMLResourceIdentifier* resourceIdentifier + ) = 0; + + /** + * This method will be called before the scanner starts reading + * from an input source while processing external entity references. + * + * @param inputSource The external input source. + */ + virtual void startInputSource(const InputSource& inputSource) = 0; + //@} + + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + /** @name Constructor */ + //@{ + + /** + * Protected default constructor + */ + XMLEntityHandler() + { + } + //@} + + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and destructor + // ----------------------------------------------------------------------- + XMLEntityHandler(const XMLEntityHandler&); + XMLEntityHandler& operator=(const XMLEntityHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLErrorCodes.hpp b/include/xercesc/framework/XMLErrorCodes.hpp new file mode 100644 index 0000000..ea3a629 --- /dev/null +++ b/include/xercesc/framework/XMLErrorCodes.hpp @@ -0,0 +1,351 @@ +// This file is generated, don't edit it!! + +#if !defined(XERCESC_INCLUDE_GUARD_ERRHEADER_XMLErrs) +#define XERCESC_INCLUDE_GUARD_ERRHEADER_XMLErrs + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLErrs +{ +public : + enum Codes + { + NoError = 0 + , W_LowBounds = 1 + , NotationAlreadyExists = 2 + , AttListAlreadyExists = 3 + , ContradictoryEncoding = 4 + , UndeclaredElemInCM = 5 + , UndeclaredElemInAttList = 6 + , XMLException_Warning = 7 + , XIncludeResourceErrorWarning = 8 + , XIncludeCannotOpenFile = 9 + , XIncludeIncludeFailedResourceError = 10 + , W_HighBounds = 11 + , E_LowBounds = 12 + , FeatureUnsupported = 13 + , TopLevelNoNameComplexType = 14 + , TopLevelNoNameAttribute = 15 + , NoNameRefAttribute = 16 + , NoNameRefElement = 17 + , NoNameRefGroup = 18 + , NoNameRefAttGroup = 19 + , AnonComplexTypeWithName = 20 + , AnonSimpleTypeWithName = 21 + , InvalidElementContent = 22 + , SimpleTypeContentError = 23 + , ExpectedSimpleTypeInList = 24 + , ListUnionRestrictionError = 25 + , SimpleTypeDerivationByListError = 26 + , ExpectedSimpleTypeInRestriction = 27 + , DuplicateFacet = 28 + , ExpectedSimpleTypeInUnion = 29 + , EmptySimpleTypeContent = 30 + , InvalidSimpleContent = 31 + , UnspecifiedBase = 32 + , InvalidComplexContent = 33 + , SchemaElementContentError = 34 + , ContentError = 35 + , UnknownSimpleType = 36 + , UnknownComplexType = 37 + , UnresolvedPrefix = 38 + , RefElementNotFound = 39 + , TypeNotFound = 40 + , TopLevelAttributeNotFound = 41 + , InvalidChildInComplexType = 42 + , BaseTypeNotFound = 43 + , DatatypeValidatorCreationError = 44 + , InvalidChildFollowingSimpleContent = 45 + , InvalidChildFollowingConplexContent = 46 + , AttributeDefaultFixedValue = 47 + , NotOptionalDefaultAttValue = 48 + , DuplicateAttribute = 49 + , AttributeWithTypeAndSimpleType = 50 + , AttributeSimpleTypeNotFound = 51 + , ElementWithFixedAndDefault = 52 + , InvalidDeclarationName = 53 + , ElementWithTypeAndAnonType = 54 + , NotSimpleOrMixedElement = 55 + , DisallowedSimpleTypeExtension = 56 + , InvalidSimpleContentBase = 57 + , InvalidComplexTypeBase = 58 + , InvalidChildInSimpleContent = 59 + , InvalidChildInComplexContent = 60 + , AnnotationError = 61 + , DisallowedBaseDerivation = 62 + , InvalidBlockValue = 63 + , InvalidFinalValue = 64 + , InvalidSubstitutionGroupElement = 65 + , SubstitutionGroupTypeMismatch = 66 + , DuplicateElementDeclaration = 67 + , InvalidAttValue = 68 + , AttributeRefContentError = 69 + , DuplicateRefAttribute = 70 + , ForbiddenDerivationByRestriction = 71 + , ForbiddenDerivationByExtension = 72 + , BaseNotComplexType = 73 + , ImportNamespaceDifference = 74 + , DeclarationNoSchemaLocation = 75 + , IncludeNamespaceDifference = 76 + , OnlyAnnotationExpected = 77 + , InvalidAttributeContent = 78 + , AttributeRequiredGlobal = 79 + , AttributeRequiredLocal = 80 + , AttributeDisallowedGlobal = 81 + , AttributeDisallowedLocal = 82 + , InvalidMin2MaxOccurs = 83 + , AnyAttributeContentError = 84 + , NoNameGlobalElement = 85 + , NoCircularDefinition = 86 + , DuplicateGlobalType = 87 + , DuplicateGlobalDeclaration = 88 + , WS_CollapseExpected = 89 + , Import_1_1 = 90 + , Import_1_2 = 91 + , ElemIDValueConstraint = 92 + , NoNotationType = 93 + , EmptiableMixedContent = 94 + , EmptyComplexRestrictionDerivation = 95 + , MixedOrElementOnly = 96 + , InvalidContentRestriction = 97 + , ForbiddenDerivation = 98 + , AtomicItemType = 99 + , GroupContentError = 100 + , AttGroupContentError = 101 + , MinMaxOnGroupChild = 102 + , DeclarationNotFound = 103 + , AllContentLimited = 104 + , BadMinMaxAllCT = 105 + , BadMinMaxAllElem = 106 + , DuplicateAttInDerivation = 107 + , NotExpressibleWildCardIntersection = 108 + , BadAttDerivation_1 = 109 + , BadAttDerivation_2 = 110 + , BadAttDerivation_3 = 111 + , BadAttDerivation_4 = 112 + , BadAttDerivation_5 = 113 + , BadAttDerivation_6 = 114 + , BadAttDerivation_7 = 115 + , BadAttDerivation_8 = 116 + , BadAttDerivation_9 = 117 + , AllContentError = 118 + , RedefineNamespaceDifference = 119 + , Redefine_InvalidSimpleType = 120 + , Redefine_InvalidSimpleTypeBase = 121 + , Redefine_InvalidComplexType = 122 + , Redefine_InvalidComplexTypeBase = 123 + , Redefine_InvalidGroupMinMax = 124 + , Redefine_DeclarationNotFound = 125 + , Redefine_GroupRefCount = 126 + , Redefine_AttGroupRefCount = 127 + , Redefine_InvalidChild = 128 + , Notation_DeclNotFound = 129 + , IC_DuplicateDecl = 130 + , IC_BadContent = 131 + , IC_KeyRefReferNotFound = 132 + , IC_KeyRefCardinality = 133 + , IC_XPathExprMissing = 134 + , AttUseCorrect = 135 + , AttDeclPropCorrect3 = 136 + , AttDeclPropCorrect5 = 137 + , AttGrpPropCorrect3 = 138 + , InvalidTargetNSValue = 139 + , XMLException_Error = 140 + , InvalidRedefine = 141 + , InvalidNSReference = 142 + , NotAllContent = 143 + , InvalidAnnotationContent = 144 + , InvalidFacetName = 145 + , InvalidXMLSchemaRoot = 146 + , CircularSubsGroup = 147 + , ELTSchemaNS = 148 + , InvalidAttTNS = 149 + , NSDeclInvalid = 150 + , DOMLevel1Node = 151 + , DuplicateAnyAttribute = 152 + , AnyAttributeBeforeAttribute = 153 + , E_HighBounds = 154 + , F_LowBounds = 155 + , EntityExpansionLimitExceeded = 156 + , ExpectedCommentOrCDATA = 157 + , ExpectedAttrName = 158 + , ExpectedNotationName = 159 + , NoRepInMixed = 160 + , ExpectedDefAttrDecl = 161 + , ExpectedEqSign = 162 + , ExpectedElementName = 163 + , CommentsMustStartWith = 164 + , InvalidDocumentStructure = 165 + , ExpectedDeclString = 166 + , BadXMLVersion = 167 + , UnsupportedXMLVersion = 168 + , UnterminatedXMLDecl = 169 + , BadXMLEncoding = 170 + , BadStandalone = 171 + , UnterminatedComment = 172 + , PINameExpected = 173 + , UnterminatedPI = 174 + , InvalidCharacter = 175 + , UnterminatedStartTag = 176 + , ExpectedAttrValue = 177 + , UnterminatedEndTag = 178 + , ExpectedAttributeType = 179 + , ExpectedEndOfTagX = 180 + , ExpectedMarkup = 181 + , NotValidAfterContent = 182 + , ExpectedComment = 183 + , ExpectedCommentOrPI = 184 + , ExpectedWhitespace = 185 + , NoRootElemInDOCTYPE = 186 + , ExpectedQuotedString = 187 + , ExpectedPublicId = 188 + , InvalidPublicIdChar = 189 + , UnterminatedDOCTYPE = 190 + , InvalidCharacterInIntSubset = 191 + , UnexpectedWhitespace = 192 + , InvalidCharacterInAttrValue = 193 + , ExpectedMarkupDecl = 194 + , TextDeclNotLegalHere = 195 + , ConditionalSectInIntSubset = 196 + , ExpectedPEName = 197 + , UnterminatedEntityDecl = 198 + , InvalidCharacterRef = 199 + , UnterminatedCharRef = 200 + , ExpectedEntityRefName = 201 + , EntityNotFound = 202 + , NoUnparsedEntityRefs = 203 + , UnterminatedEntityRef = 204 + , RecursiveEntity = 205 + , PartialMarkupInEntity = 206 + , UnterminatedElementDecl = 207 + , ExpectedContentSpecExpr = 208 + , ExpectedAsterisk = 209 + , UnterminatedContentModel = 210 + , ExpectedSystemOrPublicId = 211 + , UnterminatedNotationDecl = 212 + , ExpectedSeqChoiceLeaf = 213 + , ExpectedChoiceOrCloseParen = 214 + , ExpectedSeqOrCloseParen = 215 + , ExpectedEnumValue = 216 + , ExpectedEnumSepOrParen = 217 + , UnterminatedEntityLiteral = 218 + , MoreEndThanStartTags = 219 + , ExpectedOpenParen = 220 + , AttrAlreadyUsedInSTag = 221 + , BracketInAttrValue = 222 + , Expected2ndSurrogateChar = 223 + , ExpectedEndOfConditional = 224 + , ExpectedIncOrIgn = 225 + , ExpectedINCLUDEBracket = 226 + , UnexpectedEOE = 227 + , PEPropogated = 228 + , ExtraCloseSquare = 229 + , PERefInMarkupInIntSubset = 230 + , EntityPropogated = 231 + , ExpectedNumericalCharRef = 232 + , ExpectedOpenSquareBracket = 233 + , BadSequenceInCharData = 234 + , IllegalSequenceInComment = 235 + , UnterminatedCDATASection = 236 + , ExpectedNDATA = 237 + , NDATANotValidForPE = 238 + , HexRadixMustBeLowerCase = 239 + , DeclStringRep = 240 + , DeclStringsInWrongOrder = 241 + , NoExtRefsInAttValue = 242 + , XMLDeclMustBeLowerCase = 243 + , ExpectedEntityValue = 244 + , BadDigitForRadix = 245 + , EndedWithTagsOnStack = 246 + , NestedCDATA = 247 + , UnknownPrefix = 248 + , PartialTagMarkupError = 249 + , EmptyMainEntity = 250 + , CDATAOutsideOfContent = 251 + , Unexpected2ndSurrogateChar = 252 + , NoPIStartsWithXML = 253 + , XMLDeclMustBeFirst = 254 + , XMLVersionRequired = 255 + , StandaloneNotLegal = 256 + , EncodingRequired = 257 + , ColonNotLegalWithNS = 258 + , XMLException_Fatal = 259 + , BadSchemaLocation = 260 + , SchemaScanFatalError = 261 + , IllegalRefInStandalone = 262 + , PEBetweenDecl = 263 + , NoEmptyStrNamespace = 264 + , NoUseOfxmlnsAsPrefix = 265 + , NoUseOfxmlnsURI = 266 + , PrefixXMLNotMatchXMLURI = 267 + , XMLURINotMatchXMLPrefix = 268 + , NoXMLNSAsElementPrefix = 269 + , CT_SimpleTypeChildRequired = 270 + , InvalidRootElemInDOCTYPE = 271 + , InvalidElementName = 272 + , InvalidAttrName = 273 + , InvalidEntityRefName = 274 + , DuplicateDocTypeDecl = 275 + , XIncludeOrphanFallback = 276 + , XIncludeNoHref = 277 + , XIncludeXPointerNotSupported = 278 + , XIncludeInvalidParseVal = 279 + , XIncludeMultipleFallbackElems = 280 + , XIncludeIncludeFailedNoFallback = 281 + , XIncludeCircularInclusionLoop = 282 + , XIncludeCircularInclusionDocIncludesSelf = 283 + , XIncludeDisallowedChild = 284 + , XIncludeConflictingNotation = 285 + , XIncludeConflictingEntity = 286 + , F_HighBounds = 287 + }; + + static bool isFatal(const XMLErrs::Codes toCheck) + { + return ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds)); + } + + static bool isWarning(const XMLErrs::Codes toCheck) + { + return ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds)); + } + + static bool isError(const XMLErrs::Codes toCheck) + { + return ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds)); + } + + static XMLErrorReporter::ErrTypes errorType(const XMLErrs::Codes toCheck) + { + if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds)) + return XMLErrorReporter::ErrType_Warning; + else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds)) + return XMLErrorReporter::ErrType_Fatal; + else if ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds)) + return XMLErrorReporter::ErrType_Error; + return XMLErrorReporter::ErrTypes_Unknown; + } + static DOMError::ErrorSeverity DOMErrorType(const XMLErrs::Codes toCheck) + { + if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds)) + return DOMError::DOM_SEVERITY_WARNING; + else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds)) + return DOMError::DOM_SEVERITY_FATAL_ERROR; + else return DOMError::DOM_SEVERITY_ERROR; + } + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLErrs(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/framework/XMLErrorReporter.hpp b/include/xercesc/framework/XMLErrorReporter.hpp new file mode 100644 index 0000000..c29076a --- /dev/null +++ b/include/xercesc/framework/XMLErrorReporter.hpp @@ -0,0 +1,162 @@ +/* + * 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: XMLErrorReporter.hpp 672273 2008-06-27 13:57:00Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLERRORREPORTER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLERRORREPORTER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * This abstract class defines a callback mechanism for the scanner. By + * creating a class that implements this interface and plugging an instance + * of that class into the scanner, the scanner will call back on the object's + * virtual methods to report error events. This class is also used with the + * validator, to allow it to report errors. + * + * This class is primarily for use by those writing their own parser classes. + * If you use the standard parser classes, DOMParser and SAXParser, you won't + * use this API. You will instead use a similar mechanism defined by the SAX + * API, called ErrorHandler. + */ +class XMLPARSER_EXPORT XMLErrorReporter +{ +public: + // ----------------------------------------------------------------------- + // The types of errors we can issue + // ----------------------------------------------------------------------- + enum ErrTypes + { + ErrType_Warning + , ErrType_Error + , ErrType_Fatal + + , ErrTypes_Unknown + }; + + + // ----------------------------------------------------------------------- + // Constructors are hidden, only the virtual destructor is exposed + // ----------------------------------------------------------------------- + + /** @name Destructor */ + //@{ + + /** + * Default destructor + */ + virtual ~XMLErrorReporter() + { + } + //@} + + + // ----------------------------------------------------------------------- + // The error handler interface + // ----------------------------------------------------------------------- + + /** @name Error Handler interface */ + //@{ + + /** Called to report errors from the scanner or validator + * + * This method is called back on by the scanner or validator (or any other + * internal parser component which might need to report an error in the + * future.) It contains all the information that the client code might + * need to report or log the error. + * + * @param errCode The error code of the error being reported. What + * this means is dependent on the domain it is from. + * + * @param errDomain The domain from which the error occured. The domain + * is a means of providing a hierarchical layering to + * the error system, so that a single set of error id + * numbers don't have to be split up. + * + * @param type The error type, which is defined mostly by XML which + * categorizes errors into warning, errors and validity + * constraints. + * + * @param errorText The actual text of the error. This is translatable, + * so can possibly be in the local language if a + * translation has been provided. + * + * @param systemId The system id of the entity where the error occured, + * fully qualified. + * + * @param publicId The optional public id of the entity were the error + * occured. It can be an empty string if non was provided. + * + * @param lineNum The line number within the source XML of the error. + * + * @param colNum The column number within the source XML of the error. + * Because of the parsing style, this is usually just + * after the actual offending text. + */ + virtual void error + ( + const unsigned int errCode + , const XMLCh* const errDomain + , const ErrTypes type + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ) = 0; + + /** Called before a new parse event to allow the handler to reset + * + * This method is called by the scanner before a new parse event is + * about to start. It gives the error handler a chance to reset its + * internal state. + */ + virtual void resetErrors() = 0; + + //@} + + +protected : + + /** @name Constructor */ + //@{ + + /** + * Default constructor + */ + XMLErrorReporter() + { + } + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and destructor + // ----------------------------------------------------------------------- + XMLErrorReporter(const XMLErrorReporter&); + XMLErrorReporter& operator=(const XMLErrorReporter&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLFormatter.cpp b/include/xercesc/framework/XMLFormatter.cpp new file mode 100644 index 0000000..f37ab0a --- /dev/null +++ b/include/xercesc/framework/XMLFormatter.cpp @@ -0,0 +1,705 @@ +/* + * 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: XMLFormatter.cpp 901107 2010-01-20 08:45:02Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local data +// +// gXXXRef +// These are hard coded versions of the char refs we put out for the +// standard char refs. +// +// gEscapeChars +// For each style of escape, we have a list of the chars that must +// be escaped for that style. The first null hit in each list indicates +// no more valid entries in that list. The first entry is a dummy for +// the NoEscapes style. +// --------------------------------------------------------------------------- +static const XMLCh gAmpRef[] = +{ + chAmpersand, chLatin_a, chLatin_m, chLatin_p, chSemiColon, chNull +}; + +static const XMLCh gAposRef[] = +{ + chAmpersand, chLatin_a, chLatin_p, chLatin_o, chLatin_s, chSemiColon, chNull +}; + +static const XMLCh gGTRef[] = +{ + chAmpersand, chLatin_g, chLatin_t, chSemiColon, chNull +}; + +static const XMLCh gLTRef[] = +{ + chAmpersand, chLatin_l, chLatin_t, chSemiColon, chNull +}; + +static const XMLCh gQuoteRef[] = +{ + chAmpersand, chLatin_q, chLatin_u, chLatin_o, chLatin_t, chSemiColon, chNull +}; + +static const unsigned int kEscapeCount = 7; +static const XMLCh gEscapeChars[XMLFormatter::EscapeFlags_Count][kEscapeCount] = +{ + { chNull , chNull , chNull , chNull , chNull , chNull , chNull } + , { chAmpersand , chCloseAngle , chDoubleQuote , chOpenAngle , chSingleQuote , chNull , chNull } + , { chAmpersand , chOpenAngle , chDoubleQuote , chLF , chCR , chHTab , chNull } + , { chAmpersand , chOpenAngle , chCloseAngle , chNull , chNull , chNull , chNull } +}; + +// --------------------------------------------------------------------------- +// Local methods +// --------------------------------------------------------------------------- +bool XMLFormatter::inEscapeList(const XMLFormatter::EscapeFlags escStyle + , const XMLCh toCheck) +{ + const XMLCh* escList = gEscapeChars[escStyle]; + while (*escList) + { + if (*escList++ == toCheck) + return true; + } + + /*** + * XML1.1 + * + * Finally, there is considerable demand to define a standard representation of + * arbitrary Unicode characters in XML documents. Therefore, XML 1.1 allows the + * use of character references to the control characters #x1 through #x1F, + * most of which are forbidden in XML 1.0. For reasons of robustness, however, + * these characters still cannot be used directly in documents. + * In order to improve the robustness of character encoding detection, the + * additional control characters #x7F through #x9F, which were freely allowed in + * XML 1.0 documents, now must also appear only as character references. + * (Whitespace characters are of course exempt.) The minor sacrifice of backward + * compatibility is considered not significant. + * Due to potential problems with APIs, #x0 is still forbidden both directly and + * as a character reference. + * + ***/ + if (fIsXML11) + { + // for XML11 + if ( XMLChar1_1::isControlChar(toCheck, 0) && + !XMLChar1_1::isWhitespace(toCheck, 0) ) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + +} + + +// --------------------------------------------------------------------------- +// XMLFormatter: Constructors and Destructor +// --------------------------------------------------------------------------- +XMLFormatter::XMLFormatter( const char* const outEncoding + , const char* const docVersion + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags + , const UnRepFlags unrepFlags + , MemoryManager* const manager) + : fEscapeFlags(escapeFlags) + , fOutEncoding(0) + , fTarget(target) + , fUnRepFlags(unrepFlags) + , fXCoder(0) + , fAposRef(0) + , fAposLen(0) + , fAmpRef(0) + , fAmpLen(0) + , fGTRef(0) + , fGTLen(0) + , fLTRef(0) + , fLTLen(0) + , fQuoteRef(0) + , fQuoteLen(0) + , fIsXML11(false) + , fMemoryManager(manager) +{ + // Transcode the encoding string + fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager); + + // Try to create a transcoder for this encoding + XMLTransService::Codes resCode; + fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fOutEncoding + , resCode + , kTmpBufSize + , fMemoryManager + ); + + if (!fXCoder) + { + fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding; + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , outEncoding + , fMemoryManager + ); + } + + XMLCh* const tmpDocVer = XMLString::transcode(docVersion, fMemoryManager); + ArrayJanitor jname(tmpDocVer, fMemoryManager); + fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1); +} + + +XMLFormatter::XMLFormatter( const XMLCh* const outEncoding + , const XMLCh* const docVersion + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags + , const UnRepFlags unrepFlags + , MemoryManager* const manager) + : fEscapeFlags(escapeFlags) + , fOutEncoding(0) + , fTarget(target) + , fUnRepFlags(unrepFlags) + , fXCoder(0) + , fAposRef(0) + , fAposLen(0) + , fAmpRef(0) + , fAmpLen(0) + , fGTRef(0) + , fGTLen(0) + , fLTRef(0) + , fLTLen(0) + , fQuoteRef(0) + , fQuoteLen(0) + , fIsXML11(false) + , fMemoryManager(manager) +{ + // Try to create a transcoder for this encoding + XMLTransService::Codes resCode; + fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + outEncoding + , resCode + , kTmpBufSize + , fMemoryManager + ); + + if (!fXCoder) + { + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , outEncoding + , fMemoryManager + ); + } + + // Copy the encoding string + fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager); + + + fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1); +} + +XMLFormatter::XMLFormatter( const char* const outEncoding + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags + , const UnRepFlags unrepFlags + , MemoryManager* const manager) + : fEscapeFlags(escapeFlags) + , fOutEncoding(0) + , fTarget(target) + , fUnRepFlags(unrepFlags) + , fXCoder(0) + , fAposRef(0) + , fAposLen(0) + , fAmpRef(0) + , fAmpLen(0) + , fGTRef(0) + , fGTLen(0) + , fLTRef(0) + , fLTLen(0) + , fQuoteRef(0) + , fQuoteLen(0) + , fIsXML11(false) + , fMemoryManager(manager) +{ + // this constructor uses "1.0" for the docVersion + + // Transcode the encoding string + fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager); + + // Try to create a transcoder for this encoding + XMLTransService::Codes resCode; + fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fOutEncoding + , resCode + , kTmpBufSize + , fMemoryManager + ); + + if (!fXCoder) + { + fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding; + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , outEncoding + , fMemoryManager + ); + } + + //XMLCh* const tmpDocVer = XMLString::transcode("1.0", fMemoryManager); + //ArrayJanitor jname(tmpDocVer, fMemoryManager); + //fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1); + fIsXML11 = false; // docVersion 1.0 is not 1.1! +} + + +XMLFormatter::XMLFormatter( const XMLCh* const outEncoding + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags + , const UnRepFlags unrepFlags + , MemoryManager* const manager) + : fEscapeFlags(escapeFlags) + , fOutEncoding(0) + , fTarget(target) + , fUnRepFlags(unrepFlags) + , fXCoder(0) + , fAposRef(0) + , fAposLen(0) + , fAmpRef(0) + , fAmpLen(0) + , fGTRef(0) + , fGTLen(0) + , fLTRef(0) + , fLTLen(0) + , fQuoteRef(0) + , fQuoteLen(0) + , fIsXML11(false) + , fMemoryManager(manager) +{ + // this constructor uses XMLUni::fgVersion1_0 for the docVersion + + // Try to create a transcoder for this encoding + XMLTransService::Codes resCode; + fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + outEncoding + , resCode + , kTmpBufSize + , fMemoryManager + ); + + if (!fXCoder) + { + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , outEncoding + , fMemoryManager + ); + } + + // Copy the encoding string + fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager); + + //fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1); + fIsXML11 = false; // docVersion 1.0 is not 1.1! +} + +XMLFormatter::~XMLFormatter() +{ + fMemoryManager->deallocate(fAposRef); //delete [] fAposRef; + fMemoryManager->deallocate(fAmpRef); //delete [] fAmpRef; + fMemoryManager->deallocate(fGTRef); //delete [] fGTRef; + fMemoryManager->deallocate(fLTRef); //delete [] fLTRef; + fMemoryManager->deallocate(fQuoteRef); //delete [] fQuoteRef; + fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding; + delete fXCoder; + + // We DO NOT own the target object! +} + + +// --------------------------------------------------------------------------- +// XMLFormatter: Formatting methods +// --------------------------------------------------------------------------- +void +XMLFormatter::formatBuf(const XMLCh* const toFormat + , const XMLSize_t count + , const EscapeFlags escapeFlags + , const UnRepFlags unrepFlags) +{ + // + // Figure out the actual escape flag value. If the parameter is not + // the default, then take it. Else take the current default. + // + const EscapeFlags actualEsc = (escapeFlags == DefaultEscape) + ? fEscapeFlags : escapeFlags; + + // And do the same for the unrep flags + const UnRepFlags actualUnRep = (unrepFlags == DefaultUnRep) + ? fUnRepFlags : unrepFlags; + + // + // If the actual unrep action is that they want to provide char refs + // for unrepresentable chars, then this one is a much more difficult + // one to do cleanly, and we handle it separately. + // + if (actualUnRep == UnRep_CharRef) + { + specialFormat(toFormat, count, actualEsc); + return; + } + + // + // If we don't have any escape flags set, then we can do the most + // efficient loop, else we have to do it the hard way. + // + const XMLCh* srcPtr = toFormat; + const XMLCh* endPtr = toFormat + count; + if (actualEsc == NoEscapes) + { + // + // Just do a whole buffer at a time into the temp buffer, cap + // it off, and send it to the target. + // + if (srcPtr < endPtr) + srcPtr += handleUnEscapedChars(srcPtr, endPtr - srcPtr, actualUnRep); + } + else + { + // + // Escape chars that require it according tot he scale flags + // we were given. For the others, try to accumulate them and + // format them in as big as bulk as we can. + // + while (srcPtr < endPtr) + { + // + // Run a temp pointer up until we hit a character that we have + // to escape. Then we can convert all the chars between our + // current source pointer and here all at once. + // + const XMLCh* tmpPtr = srcPtr; + while ((tmpPtr < endPtr) && !inEscapeList(actualEsc, *tmpPtr)) + tmpPtr++; + + // + // If we got any chars, then lets convert them and write them + // out. + // + if (tmpPtr > srcPtr) + srcPtr += handleUnEscapedChars(srcPtr, tmpPtr - srcPtr, + actualUnRep); + + else if (tmpPtr < endPtr) + { + // + // Ok, so we've hit a char that must be escaped. So do + // this one specially. + // + const XMLByte * theChars; + switch (*srcPtr) { + case chAmpersand : + theChars = getCharRef(fAmpLen, fAmpRef, gAmpRef); + fTarget->writeChars(theChars, fAmpLen, this); + break; + + case chSingleQuote : + theChars = getCharRef(fAposLen, fAposRef, gAposRef); + fTarget->writeChars(theChars, fAposLen, this); + break; + + case chDoubleQuote : + theChars = getCharRef(fQuoteLen, fQuoteRef, gQuoteRef); + fTarget->writeChars(theChars, fQuoteLen, this); + break; + + case chCloseAngle : + theChars = getCharRef(fGTLen, fGTRef, gGTRef); + fTarget->writeChars(theChars, fGTLen, this); + break; + + case chOpenAngle : + theChars = getCharRef(fLTLen, fLTRef, gLTRef); + fTarget->writeChars(theChars, fLTLen, this); + break; + + default: + // control characters + writeCharRef(*srcPtr); + break; + } + srcPtr++; + } + } + } +} + + +XMLSize_t +XMLFormatter::handleUnEscapedChars(const XMLCh * srcPtr, + const XMLSize_t oCount, + const UnRepFlags actualUnRep) +{ + // + // Use that to figure out what I should pass to the transcoder. If we + // are doing character references or failing for unrepresentable chars, + // then we just throw, since we should never get a call for something + // we cannot represent. Else, we tell it to just use the replacement + // char. + // + const XMLTranscoder::UnRepOpts unRepOpts = (actualUnRep == UnRep_Replace) + ? XMLTranscoder::UnRep_RepChar + : XMLTranscoder::UnRep_Throw; + + XMLSize_t charsEaten; + XMLSize_t count = oCount; + + while (count) { + const XMLSize_t srcChars = (count > XMLSize_t (kTmpBufSize)) + ? XMLSize_t (kTmpBufSize) : count; + + const XMLSize_t outBytes + = fXCoder->transcodeTo(srcPtr, srcChars, + fTmpBuf, kTmpBufSize, + charsEaten, unRepOpts); + + if (outBytes) { + fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0; + fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0; + fTarget->writeChars(fTmpBuf, outBytes, this); + } + + srcPtr += charsEaten; + count -= charsEaten; + } + + return oCount; // This should be an assertion that count == 0. +} + + +XMLFormatter& XMLFormatter::operator<<(const XMLCh* const toFormat) +{ + const XMLSize_t len = XMLString::stringLen(toFormat); + formatBuf(toFormat, len); + return *this; +} + +XMLFormatter& XMLFormatter::operator<<(const XMLCh toFormat) +{ + // Make a temp string format that + XMLCh szTmp[2]; + szTmp[0] = toFormat; + szTmp[1] = 0; + + formatBuf(szTmp, 1); + return *this; +} + +/** + * the parameter, count, is needed since stringLen() + * does not work on a BOM like "0xFE0xFF0x000x00" or + * "0x000x000xFF0xFE" + **/ +void XMLFormatter::writeBOM(const XMLByte* const toFormat + , const XMLSize_t count) +{ + fTarget->writeChars(toFormat, count, this); +} + +// --------------------------------------------------------------------------- +// XMLFormatter: Private helper methods +// --------------------------------------------------------------------------- +void XMLFormatter::writeCharRef(const XMLCh &toWrite) +{ + XMLCh tmpBuf[32]; + tmpBuf[0] = chAmpersand; + tmpBuf[1] = chPound; + tmpBuf[2] = chLatin_x; + + // Build a char ref for the current char + XMLString::binToText(toWrite, &tmpBuf[3], 8, 16, fMemoryManager); + const XMLSize_t bufLen = XMLString::stringLen(tmpBuf); + tmpBuf[bufLen] = chSemiColon; + tmpBuf[bufLen+1] = chNull; + + // write it out + formatBuf(tmpBuf + , bufLen + 1 + , XMLFormatter::NoEscapes + , XMLFormatter::UnRep_Fail); + +} + +void XMLFormatter::writeCharRef(XMLSize_t toWrite) +{ + XMLCh tmpBuf[64]; + tmpBuf[0] = chAmpersand; + tmpBuf[1] = chPound; + tmpBuf[2] = chLatin_x; + + // Build a char ref for the current char + XMLString::sizeToText(toWrite, &tmpBuf[3], 32, 16, fMemoryManager); + const XMLSize_t bufLen = XMLString::stringLen(tmpBuf); + tmpBuf[bufLen] = chSemiColon; + tmpBuf[bufLen+1] = chNull; + + // write it out + formatBuf(tmpBuf + , bufLen + 1 + , XMLFormatter::NoEscapes + , XMLFormatter::UnRep_Fail); + +} + + +const XMLByte* XMLFormatter::getCharRef(XMLSize_t &count, + XMLByte* &ref, + const XMLCh * stdRef) +{ + if (!ref) { + + XMLSize_t charsEaten; + const XMLSize_t outBytes = + fXCoder->transcodeTo(stdRef, XMLString::stringLen(stdRef), + fTmpBuf, kTmpBufSize, charsEaten, + XMLTranscoder::UnRep_Throw); + + fTmpBuf[outBytes] = 0; + fTmpBuf[outBytes + 1] = 0; + fTmpBuf[outBytes + 2] = 0; + fTmpBuf[outBytes + 3] = 0; + + ref = (XMLByte*) fMemoryManager->allocate + ( + (outBytes + 4) * sizeof(XMLByte) + );//new XMLByte[outBytes + 4]; + memcpy(ref, fTmpBuf, outBytes + 4); + count = outBytes; + } + + return ref; +} + +void XMLFormatter::specialFormat(const XMLCh* const toFormat + , const XMLSize_t count + , const EscapeFlags escapeFlags) +{ + // + // We have to check each character and see if it could be represented. + // As long as it can, we just keep up with where we started and how + // many chars we've checked. When we hit an unrepresentable one, we + // stop, transcode everything we've collected, then start handling + // the unrepresentables via char refs. We repeat this until we get all + // the chars done. + // + const XMLCh* srcPtr = toFormat; + const XMLCh* endPtr = toFormat + count; + + while (srcPtr < endPtr) + { + const XMLCh* tmpPtr = srcPtr; + while (tmpPtr < endPtr) + { + if (fXCoder->canTranscodeTo(*tmpPtr)) + tmpPtr++; + else + break; + } + + if (tmpPtr > srcPtr) + { + // We got at least some chars that can be done normally + formatBuf + ( + srcPtr + , tmpPtr - srcPtr + , escapeFlags + , XMLFormatter::UnRep_Fail + ); + + // Update the source pointer to our new spot + srcPtr = tmpPtr; + } + else + { + + // We hit something unrepresentable. So continue forward doing + // char refs until we hit something representable again or the + // end of input. + // + while (srcPtr < endPtr) + { + if ((*srcPtr & 0xFC00) == 0xD800) { + // we have encountered a surrogate, need to recombine before printing out + // use writeCharRef that takes XMLSize_t to get values larger than + // hex 0xFFFF printed. + tmpPtr = srcPtr; + tmpPtr++; // point at low surrogate + writeCharRef((XMLSize_t) (0x10000+((*srcPtr-0xD800)<<10)+*tmpPtr-0xDC00)); + srcPtr++; // advance to low surrogate (will advance again below) + } + else { + writeCharRef(*srcPtr); + } + + // Move up the source pointer and break out if needed + srcPtr++; + if (fXCoder->canTranscodeTo(*srcPtr)) + break; + } + } + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLFormatter.hpp b/include/xercesc/framework/XMLFormatter.hpp new file mode 100644 index 0000000..49354da --- /dev/null +++ b/include/xercesc/framework/XMLFormatter.hpp @@ -0,0 +1,538 @@ +/* + * 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: XMLFormatter.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLFORMATTER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLFORMATTER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLFormatTarget; +class XMLTranscoder; + +/** + * This class provides the basic formatting capabilities that are required + * to turn the Unicode based XML data from the parsers into a form that can + * be used on non-Unicode based systems, that is, into local or generic text + * encodings. + * + * A number of flags are provided to control whether various optional + * formatting operations are performed. + */ +class XMLPARSER_EXPORT XMLFormatter : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Class types + // ----------------------------------------------------------------------- + /** @name Public Constants */ + //@{ + /** + * EscapeFlags - Different styles of escape flags to control various formatting. + * + *

NoEscapes: + * No character needs to be escaped. Just write them out as is.

+ *

StdEscapes: + * The following characters need to be escaped:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
charactershould be escaped and written as
&&amp;
>&gt;
"&quot;
<&lt;
'&apos;
+ *

AttrEscapes: + * The following characters need to be escaped:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
charactershould be escaped and written as
&&amp;
>&gt;
"&quot;
+ *

CharEscapes: + * The following characters need to be escaped:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + *
charactershould be escaped and written as
&&amp;
>&gt;
+ *

EscapeFlags_Count: + * Special value, do not use directly.

+ *

DefaultEscape: + * Special value, do not use directly.

+ * + */ + enum EscapeFlags + { + NoEscapes + , StdEscapes + , AttrEscapes + , CharEscapes + + // Special values, don't use directly + , EscapeFlags_Count + , DefaultEscape = 999 + }; + + /** + * UnRepFlags + * + * The unrepresentable flags that indicate how to react when a + * character cannot be represented in the target encoding. + * + *

UnRep_Fail: + * Fail the operation.

+ *

UnRep_CharRef: + * Display the unrepresented character as reference.

+ *

UnRep_Replace: + * Replace the unrepresented character with the replacement character.

+ *

DefaultUnRep: + * Special value, do not use directly.

+ * + */ + enum UnRepFlags + { + UnRep_Fail + , UnRep_CharRef + , UnRep_Replace + + , DefaultUnRep = 999 + }; + //@} + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructor and Destructor */ + //@{ + /** + * @param outEncoding the encoding for the formatted content. + * @param docVersion the document version. + * @param target the formatTarget where the formatted content is written to. + * @param escapeFlags the escape style for certain character. + * @param unrepFlags the reaction to unrepresentable character. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + XMLFormatter + ( + const XMLCh* const outEncoding + , const XMLCh* const docVersion + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags = NoEscapes + , const UnRepFlags unrepFlags = UnRep_Fail + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XMLFormatter + ( + const char* const outEncoding + , const char* const docVersion + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags = NoEscapes + , const UnRepFlags unrepFlags = UnRep_Fail + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XMLFormatter + ( + const XMLCh* const outEncoding + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags = NoEscapes + , const UnRepFlags unrepFlags = UnRep_Fail + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XMLFormatter + ( + const char* const outEncoding + , XMLFormatTarget* const target + , const EscapeFlags escapeFlags = NoEscapes + , const UnRepFlags unrepFlags = UnRep_Fail + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + ~XMLFormatter(); + //@} + + + // ----------------------------------------------------------------------- + // Formatting methods + // ----------------------------------------------------------------------- + /** @name Formatting methods */ + //@{ + /** + * @param toFormat the string to be formatted + * @param count length of the string + * @param escapeFlags the escape style for formatting toFormat + * @param unrepFlags the reaction for any unrepresentable character in toFormat + * + */ + void formatBuf + ( + const XMLCh* const toFormat + , const XMLSize_t count + , const EscapeFlags escapeFlags = DefaultEscape + , const UnRepFlags unrepFlags = DefaultUnRep + ); + + /** + * @see formatBuf + */ + XMLFormatter& operator<< + ( + const XMLCh* const toFormat + ); + + XMLFormatter& operator<< + ( + const XMLCh toFormat + ); + + void writeBOM(const XMLByte* const toFormat + , const XMLSize_t count); + + //@} + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Getter methods */ + //@{ + /** + * @return return the encoding set for the formatted content + */ + + const XMLCh* getEncodingName() const; + + /** + * @return return constant transcoder used internally for transcoding the formatter conent + */ + inline const XMLTranscoder* getTranscoder() const; + + /** + * @return return the transcoder used internally for transcoding the formatter content + */ + inline XMLTranscoder* getTranscoder(); + + //@} + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + /** @name Setter methods */ + //@{ + /** + * @param newFlags set the escape style for the follow-on formatted content + */ + void setEscapeFlags + ( + const EscapeFlags newFlags + ); + + /** + * @param newFlags set the reaction for unrepresentable character + */ + void setUnRepFlags + ( + const UnRepFlags newFlags + ); + + /** + * @param newFlags set the escape style for the follow-on formatted content + * @see setEscapeFlags + */ + XMLFormatter& operator<< + ( + const EscapeFlags newFlags + ); + + /** + * @param newFlags set the reaction for unrepresentable character + * @see setUnRepFlags + */ + XMLFormatter& operator<< + ( + const UnRepFlags newFlags + ); + //@} + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Setter methods */ + //@{ + /** + * @return return the escape style for the formatted content + */ + EscapeFlags getEscapeFlags() const; + + /** + * @return return the reaction for unrepresentable character + */ + UnRepFlags getUnRepFlags() const; + //@} + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLFormatter(); + XMLFormatter(const XMLFormatter&); + XMLFormatter& operator=(const XMLFormatter&); + + + // ----------------------------------------------------------------------- + // Private class constants + // ----------------------------------------------------------------------- + enum Constants + { + kTmpBufSize = 16 * 1024 + }; + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + const XMLByte* getCharRef(XMLSize_t &count, + XMLByte* &ref, + const XMLCh * stdRef); + + void writeCharRef(const XMLCh &toWrite); + void writeCharRef(XMLSize_t toWrite); + + bool inEscapeList(const XMLFormatter::EscapeFlags escStyle + , const XMLCh toCheck); + + + XMLSize_t handleUnEscapedChars(const XMLCh * srcPtr, + const XMLSize_t count, + const UnRepFlags unrepFlags); + + void specialFormat + ( + const XMLCh* const toFormat + , const XMLSize_t count + , const EscapeFlags escapeFlags + ); + + + // ----------------------------------------------------------------------- + // Private, non-virtual methods + // + // fEscapeFlags + // The escape flags we were told to use in formatting. These are + // defaults set in the ctor, which can be overridden on a particular + // call. + // + // fOutEncoding + // This the name of the output encoding. Saved mainly for meaningful + // error messages. + // + // fTarget + // This is the target object for the formatting operation. + // + // fUnRepFlags + // The unrepresentable flags that indicate how to react when a + // character cannot be represented in the target encoding. + // + // fXCoder + // This the transcoder that we will use. It is created using the + // encoding name we were told to use. + // + // fTmpBuf + // An output buffer that we use to transcode chars into before we + // send them off to be output. + // + // fAposRef + // fAmpRef + // fGTRef + // fLTRef + // fQuoteRef + // These are character refs for the standard char refs, in the + // output encoding. They are faulted in as required, by transcoding + // them from fixed Unicode versions. + // + // fIsXML11 + // for performance reason, we do not store the actual version string + // and do the string comparison again and again. + // + // ----------------------------------------------------------------------- + EscapeFlags fEscapeFlags; + XMLCh* fOutEncoding; + XMLFormatTarget* fTarget; + UnRepFlags fUnRepFlags; + XMLTranscoder* fXCoder; + XMLByte fTmpBuf[kTmpBufSize + 4]; + XMLByte* fAposRef; + XMLSize_t fAposLen; + XMLByte* fAmpRef; + XMLSize_t fAmpLen; + XMLByte* fGTRef; + XMLSize_t fGTLen; + XMLByte* fLTRef; + XMLSize_t fLTLen; + XMLByte* fQuoteRef; + XMLSize_t fQuoteLen; + bool fIsXML11; + MemoryManager* fMemoryManager; +}; + + +class XMLPARSER_EXPORT XMLFormatTarget : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + virtual ~XMLFormatTarget() {} + + + // ----------------------------------------------------------------------- + // Virtual interface + // ----------------------------------------------------------------------- + virtual void writeChars + ( + const XMLByte* const toWrite + , const XMLSize_t count + , XMLFormatter* const formatter + ) = 0; + + virtual void flush() {}; + + +protected : + // ----------------------------------------------------------------------- + // Hidden constructors and operators + // ----------------------------------------------------------------------- + XMLFormatTarget() {}; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLFormatTarget(const XMLFormatTarget&); + XMLFormatTarget& operator=(const XMLFormatTarget&); +}; + + +// --------------------------------------------------------------------------- +// XMLFormatter: Getter methods +// --------------------------------------------------------------------------- +inline const XMLCh* XMLFormatter::getEncodingName() const +{ + return fOutEncoding; +} + +inline const XMLTranscoder* XMLFormatter::getTranscoder() const +{ + return fXCoder; +} + +inline XMLTranscoder* XMLFormatter::getTranscoder() +{ + return fXCoder; +} + +// --------------------------------------------------------------------------- +// XMLFormatter: Setter methods +// --------------------------------------------------------------------------- +inline void XMLFormatter::setEscapeFlags(const EscapeFlags newFlags) +{ + fEscapeFlags = newFlags; +} + +inline void XMLFormatter::setUnRepFlags(const UnRepFlags newFlags) +{ + fUnRepFlags = newFlags; +} + + +inline XMLFormatter& XMLFormatter::operator<<(const EscapeFlags newFlags) +{ + fEscapeFlags = newFlags; + return *this; +} + +inline XMLFormatter& XMLFormatter::operator<<(const UnRepFlags newFlags) +{ + fUnRepFlags = newFlags; + return *this; +} + +// --------------------------------------------------------------------------- +// XMLFormatter: Getter methods +// --------------------------------------------------------------------------- +inline XMLFormatter::EscapeFlags XMLFormatter::getEscapeFlags() const +{ + return fEscapeFlags; +} + +inline XMLFormatter::UnRepFlags XMLFormatter::getUnRepFlags() const +{ + return fUnRepFlags; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLGrammarDescription.cpp b/include/xercesc/framework/XMLGrammarDescription.cpp new file mode 100644 index 0000000..43f54d7 --- /dev/null +++ b/include/xercesc/framework/XMLGrammarDescription.cpp @@ -0,0 +1,51 @@ +/* + * 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: XMLGrammarDescription.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +XMLGrammarDescription::~XMLGrammarDescription() +{ +} + +XMLGrammarDescription::XMLGrammarDescription(MemoryManager* const memMgr) +:fMemMgr(memMgr) +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLGrammarDescription) + +void XMLGrammarDescription::serialize(XSerializeEngine&) +{ + //no data +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/XMLGrammarDescription.hpp b/include/xercesc/framework/XMLGrammarDescription.hpp new file mode 100644 index 0000000..55ad60d --- /dev/null +++ b/include/xercesc/framework/XMLGrammarDescription.hpp @@ -0,0 +1,105 @@ +/* + * 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: XMLGrammarDescription.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLGRAMMARDESCRIPTION_HPP) +#define XERCESC_INCLUDE_GUARD_XMLGRAMMARDESCRIPTION_HPP + +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT XMLGrammarDescription : public XSerializable, public XMemory +{ +public : + // ----------------------------------------------------------------------- + /** @name Virtual destructor for derived classes */ + // ----------------------------------------------------------------------- + //@{ + /** + * virtual destructor + * + */ + virtual ~XMLGrammarDescription(); + //@} + + // ----------------------------------------------------------------------- + /** @name The Grammar Description Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * getGrammarType + * + */ + virtual Grammar::GrammarType getGrammarType() const = 0; + + /** + * getGrammarKey + * + */ + virtual const XMLCh* getGrammarKey() const = 0; + //@} + + inline MemoryManager* getMemoryManager() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLGrammarDescription) + +protected : + // ----------------------------------------------------------------------- + /** Hidden Constructors */ + // ----------------------------------------------------------------------- + //@{ + XMLGrammarDescription(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + //@} + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLGrammarDescription(const XMLGrammarDescription& ); + XMLGrammarDescription& operator=(const XMLGrammarDescription& ); + //@} + + // ----------------------------------------------------------------------- + // + // fMemMgr: plugged-in (or defaulted-in) memory manager, + // not owned + // no reset after initialization + // allow derivatives to access directly + // + // ----------------------------------------------------------------------- + MemoryManager* const fMemMgr; +}; + +inline MemoryManager* XMLGrammarDescription::getMemoryManager() const +{ + return fMemMgr; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLGrammarPool.hpp b/include/xercesc/framework/XMLGrammarPool.hpp new file mode 100644 index 0000000..3c2dfc8 --- /dev/null +++ b/include/xercesc/framework/XMLGrammarPool.hpp @@ -0,0 +1,322 @@ +/* + * 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: XMLGrammarPool.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLGRAMMARPOOL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLGRAMMARPOOL_HPP + +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +class Grammar; +class XMLGrammarDescription; +class DTDGrammar; +class SchemaGrammar; +class XMLDTDDescription; +class XMLSchemaDescription; +class XMLStringPool; +class BinInputStream; +class BinOutputStream; + +class XMLPARSER_EXPORT XMLGrammarPool : public XMemory +{ +public : + // ----------------------------------------------------------------------- + /** @name Virtual destructor for derived classes */ + // ----------------------------------------------------------------------- + //@{ + + /** + * virtual destructor + * + */ + virtual ~XMLGrammarPool(){}; + //@} + + // ----------------------------------------------------------------------- + /** @name The Grammar Pool Interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * cacheGrammar + * + * Provide the grammar pool with an opportunity + * to cache the given grammar. If the pool does not choose to do so, + * it should return false; otherwise, it should return true, so that + * the caller knows whether the grammar has been adopted. + * + * @param gramToCache the Grammar to be cached in the grammar pool + * @return true if the grammar pool has elected to cache the grammar (in which case + * it is assumed to have adopted it); false if it does not cache it + * + */ + virtual bool cacheGrammar(Grammar* const gramToCache) = 0; + + /** + * retrieveGrammar + * + * @param gramDesc the Grammar Description used to search for grammar + * cached in the grammar pool + * + */ + virtual Grammar* retrieveGrammar(XMLGrammarDescription* const gramDesc) = 0; + + + /** + * orphanGrammar + * + * grammar removed from the grammar pool and owned by the caller + * + * @param nameSpaceKey Key used to search for grammar in the grammar pool + * @return the grammar that was removed from the pool (0 if none) + */ + virtual Grammar* orphanGrammar(const XMLCh* const nameSpaceKey) = 0; + + + /** + * Get an enumeration of the cached Grammars in the Grammar pool + * + * @return enumeration of the cached Grammars in Grammar pool + */ + virtual RefHashTableOfEnumerator getGrammarEnumerator() const = 0; + + /** + * clear + * + * all grammars are removed from the grammar pool and deleted. + * @return true if the grammar pool was cleared. false if it did not. + */ + virtual bool clear() = 0; + + /** + * lockPool + * + * When this method is called by the application, the + * grammar pool should stop adding new grammars to the cache. + * This should result in the grammar pool being sharable + * among parsers operating in different threads. + * + */ + virtual void lockPool() = 0; + + /** + * unlockPool + * + * After this method has been called, the grammar pool implementation + * should return to its default behaviour when cacheGrammars(...) is called. + * One effect, depending on the underlying implementation, is that the grammar pool + * may no longer be thread-safe (even on read operations). + * + * For PSVI support any previous XSModel that was produced will be deleted. + */ + virtual void unlockPool() = 0; + + //@} + + // ----------------------------------------------------------------------- + /** @name Factory interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * createDTDGrammar + * + */ + virtual DTDGrammar* createDTDGrammar() = 0; + + /** + * createSchemaGrammar + * + */ + virtual SchemaGrammar* createSchemaGrammar() = 0; + + /** + * createDTDDescription + * + */ + virtual XMLDTDDescription* createDTDDescription(const XMLCh* const systemId) = 0; + /** + * createSchemaDescription + * + */ + virtual XMLSchemaDescription* createSchemaDescription(const XMLCh* const targetNamespace) = 0; + + //@} + + // ----------------------------------------------------------------------- + /** @name schema component model support */ + // ----------------------------------------------------------------------- + //@{ + + /*** + * Return an XSModel derived from the components of all SchemaGrammars + * in the grammar pool. If the pool is locked, this should + * be a thread-safe operation. + * + * NOTE: The function should NEVER return NULL. If there are no grammars in + * the pool it should return an XSModel containing the Schema for Schema. + * + * Calling getXSModel() on an unlocked grammar pool may result in the + * creation of a new XSModel with the old XSModel being deleted. + * The bool parameter will indicate if the XSModel was changed. + * + */ + virtual XSModel *getXSModel(bool& XSModelWasChanged) = 0; + + // @} + + // ----------------------------------------------------------------------- + /** @name Getter */ + // ----------------------------------------------------------------------- + //@{ + + /** + * getMemoryManager + * + */ + inline MemoryManager* getMemoryManager() + { + return fMemMgr; + } + + /** + * Return an XMLStringPool for use by validation routines. + * Implementations should not create a string pool on each call to this + * method, but should maintain one string pool for all grammars + * for which this pool is responsible. + */ + virtual XMLStringPool *getURIStringPool() = 0; + //@} + + // ----------------------------------------------------------------------- + /** serialization and deserialization support */ + // ----------------------------------------------------------------------- + + /*** + * + * 1. Context: Serialize/Deserialize All Grammars In One Session + * + * Since it is common that a declaration in one grammar may reference + * to definitions in other grammars, it is required to serialize those + * related (or interdependent) grammars in to one persistent data store + * in one serialization session (storing), and deserialize them from the + * persistent data store in one deserialization session (loading) back + * to the grammar pool. + * + * 2. Multiple serializations + * + * It is acceptable that client application requests more than one + * grammar serialization on a particular grammar pool, to track the + * different grammars cached, or for whatever reasons that client + * application is interested in. + * + * 3. Multiple deserializations + * + * Request for grammar deserialization either after the grammar pool has + * its own cached grammars, or request for more than one grammar + * deserialization, may cause undesired and unpredictable consequence + * and therefore client application shall be aware that individual + * implementationis may NOT support this. + * + * However it is strongly recommended that the client application requests + * no more than one grammar deserialization even a particular implementation + * may allow multiple deserializations. + * + * 4. Locking + * + * Both serialization and deserialization requires to lock the grammar pool + * before operation and unlock after operation. In the case the grammar pool + * is locked by a third party, the request for serialization/deserialization + * will NOT be entertained. + * + * 5. Versioning + * + * The Persistent data store has a version tag to be verified during + * deserialization, thus a grammar pool may decide if it supports + * a binary data created by a different release of Xerces. + * + * 6. Clean up + * + * The client application shall be aware that in the event of an exception + * thrown due to a corrupted data store during deserialization, implementation + * may not be able to clean up all resources allocated, and therefore it is + * client application's responsibility to clean up those unreleased resources. + * + * + */ + virtual void serializeGrammars(BinOutputStream* const) = 0; + virtual void deserializeGrammars(BinInputStream* const) = 0; + + /* + * Set/get a flag to not create XSAnnotations when deserializing the grammar. + * Defaults to false (create XSAnnotations when deserializing the grammar). + */ + inline void setIgnoreSerializedAnnotations(const bool flag) + { + fIgnoreSerializedAnnotations = flag; + }; + inline bool getIgnoreSerializedAnnotations() const + { + return fIgnoreSerializedAnnotations; + }; + +protected : + // ----------------------------------------------------------------------- + /** Hidden Constructors */ + // ----------------------------------------------------------------------- + //@{ + XMLGrammarPool(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager) + :fMemMgr(memMgr) + ,fIgnoreSerializedAnnotations(false) + { + }; + //@} + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLGrammarPool(const XMLGrammarPool& ); + XMLGrammarPool& operator=(const XMLGrammarPool& ); + //@} + + // ----------------------------------------------------------------------- + // + // fMemMgr: plugged-in (or defaulted-in) memory manager + // not owned + // no reset after initialization + // + // ----------------------------------------------------------------------- + + MemoryManager* const fMemMgr; + bool fIgnoreSerializedAnnotations; + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLGrammarPoolImpl.cpp b/include/xercesc/framework/XMLGrammarPoolImpl.cpp new file mode 100644 index 0000000..869e095 --- /dev/null +++ b/include/xercesc/framework/XMLGrammarPoolImpl.cpp @@ -0,0 +1,364 @@ +/* + * 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: XMLGrammarPoolImpl.cpp 676823 2008-07-15 07:57:44Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// private function used to update fXSModel +void XMLGrammarPoolImpl::createXSModel() +{ + delete fXSModel; + fXSModel = 0; + fXSModel = new (getMemoryManager()) XSModel(this, getMemoryManager()); + fXSModelIsValid = true; +} + +// --------------------------------------------------------------------------- +// XMLGrammarPoolImpl: constructor and destructor +// --------------------------------------------------------------------------- +XMLGrammarPoolImpl::~XMLGrammarPoolImpl() +{ + delete fGrammarRegistry; + delete fStringPool; + if(fSynchronizedStringPool) + delete fSynchronizedStringPool; + if(fXSModel) + delete fXSModel; +} + +XMLGrammarPoolImpl::XMLGrammarPoolImpl(MemoryManager* const memMgr) +:XMLGrammarPool(memMgr) +,fGrammarRegistry(0) +,fStringPool(0) +,fSynchronizedStringPool(0) +,fXSModel(0) +,fLocked(false) +,fXSModelIsValid(false) +{ + fGrammarRegistry = new (memMgr) RefHashTableOf(29, true, memMgr); + fStringPool = new (memMgr) XMLStringPool(109, memMgr); +} + +// ----------------------------------------------------------------------- +// Implementation of Grammar Pool Interface +// ----------------------------------------------------------------------- +bool XMLGrammarPoolImpl::cacheGrammar(Grammar* const gramToCache ) +{ + if(fLocked || !gramToCache) + return false; + + const XMLCh* grammarKey = gramToCache->getGrammarDescription()->getGrammarKey(); + + if (fGrammarRegistry->containsKey(grammarKey)) + { + return false; + } + + fGrammarRegistry->put((void*) grammarKey, gramToCache); + + if (fXSModelIsValid && gramToCache->getGrammarType() == Grammar::SchemaGrammarType) + { + fXSModelIsValid = false; + } + return true; +} + +Grammar* XMLGrammarPoolImpl::retrieveGrammar(XMLGrammarDescription* const gramDesc) +{ + if (!gramDesc) + return 0; + + /*** + * This implementation simply use GrammarKey + */ + return fGrammarRegistry->get(gramDesc->getGrammarKey()); +} + +Grammar* XMLGrammarPoolImpl::orphanGrammar(const XMLCh* const nameSpaceKey) +{ + if (!fLocked) + { + Grammar* grammar = fGrammarRegistry->orphanKey(nameSpaceKey); + if (fXSModelIsValid && grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) + { + fXSModelIsValid = false; + } + return grammar; + } + return 0; +} + +RefHashTableOfEnumerator +XMLGrammarPoolImpl::getGrammarEnumerator() const +{ + return RefHashTableOfEnumerator(fGrammarRegistry, false, fGrammarRegistry->getMemoryManager()); +} + + +bool XMLGrammarPoolImpl::clear() +{ + if (!fLocked) + { + fGrammarRegistry->removeAll(); + + fXSModelIsValid = false; + if (fXSModel) + { + delete fXSModel; + fXSModel = 0; + } + return true; + } + return false; +} + +void XMLGrammarPoolImpl::lockPool() +{ + if (!fLocked) + { + fLocked = true; + MemoryManager *memMgr = getMemoryManager(); + if(!fSynchronizedStringPool) + { + fSynchronizedStringPool = new (memMgr) XMLSynchronizedStringPool(fStringPool, 109, memMgr); + } + if (!fXSModelIsValid) + { + createXSModel(); + } + } +} + +void XMLGrammarPoolImpl::unlockPool() +{ + if (fLocked) + { + fLocked = false; + if(fSynchronizedStringPool) + { + fSynchronizedStringPool->flushAll(); + // if user calls Lock again, need to have null fSynchronizedStringPool + delete fSynchronizedStringPool; + fSynchronizedStringPool = 0; + } + fXSModelIsValid = false; + if (fXSModel) + { + delete fXSModel; + fXSModel = 0; + } + } +} + +// ----------------------------------------------------------------------- +// Implementation of Factory Interface +// ----------------------------------------------------------------------- +DTDGrammar* XMLGrammarPoolImpl::createDTDGrammar() +{ + return new (getMemoryManager()) DTDGrammar(getMemoryManager()); +} + +SchemaGrammar* XMLGrammarPoolImpl::createSchemaGrammar() +{ + return new (getMemoryManager()) SchemaGrammar(getMemoryManager()); +} + +XMLDTDDescription* XMLGrammarPoolImpl::createDTDDescription(const XMLCh* const systemId) +{ + return new (getMemoryManager()) XMLDTDDescriptionImpl(systemId, getMemoryManager()); +} + +XMLSchemaDescription* XMLGrammarPoolImpl::createSchemaDescription(const XMLCh* const targetNamespace) +{ + return new (getMemoryManager()) XMLSchemaDescriptionImpl(targetNamespace, getMemoryManager()); +} + +XSModel *XMLGrammarPoolImpl::getXSModel(bool& XSModelWasChanged) +{ + XSModelWasChanged = false; + if (fLocked || fXSModelIsValid) + return fXSModel; + + createXSModel(); + XSModelWasChanged = true; + return fXSModel; +} + +XMLStringPool *XMLGrammarPoolImpl::getURIStringPool() +{ + if(fLocked) + return fSynchronizedStringPool; + return fStringPool; +} + +// ----------------------------------------------------------------------- +// serialization and deserialization support +// ----------------------------------------------------------------------- +/*** + * + * don't serialize + * + * XMLSynchronizedStringPool* fSynchronizedStringPool; + */ + +/*** + * .non-empty gramamrRegistry + ***/ +void XMLGrammarPoolImpl::serializeGrammars(BinOutputStream* const binOut) +{ + RefHashTableOfEnumerator grammarEnum(fGrammarRegistry, false, getMemoryManager()); + if (!(grammarEnum.hasMoreElements())) + { + ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_GrammarPool_Empty, getMemoryManager()); + } + + XSerializeEngine serEng(binOut, this); + + //version information + serEng<<(unsigned int)XERCES_GRAMMAR_SERIALIZATION_LEVEL; + + //lock status + serEng<serialize(serEng); + + /*** + * Serialize RefHashTableOf* fGrammarRegistry; + ***/ + XTemplateSerializer::storeObject(fGrammarRegistry, serEng); +} + +/*** + * .empty stringPool + * .empty gramamrRegistry + ***/ +void XMLGrammarPoolImpl::deserializeGrammars(BinInputStream* const binIn) +{ + MemoryManager *memMgr = getMemoryManager(); + unsigned int stringCount = fStringPool->getStringCount(); + if (stringCount) + { + /*** + * it contains only the four predefined one, that is ok + * but we need to reset the string before deserialize it + * + ***/ + if ( stringCount <= 4 ) + { + fStringPool->flushAll(); + } + else + { + ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_StringPool_NotEmpty, memMgr); + } + } + + RefHashTableOfEnumerator grammarEnum(fGrammarRegistry, false, memMgr); + if (grammarEnum.hasMoreElements()) + { + ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_GrammarPool_NotEmpty, memMgr); + } + + // This object will take care of cleaning up if an exception is + // thrown during deserialization. + JanitorMemFunCall cleanup(this, &XMLGrammarPoolImpl::cleanUp); + + try + { + XSerializeEngine serEng(binIn, this); + + //version information + unsigned int StorerLevel; + serEng>>StorerLevel; + serEng.fStorerLevel = StorerLevel; + + // The storer level must match the loader level. + // + if (StorerLevel != (unsigned int)XERCES_GRAMMAR_SERIALIZATION_LEVEL) + { + XMLCh StorerLevelChar[5]; + XMLCh LoaderLevelChar[5]; + XMLString::binToText(StorerLevel, StorerLevelChar, 4, 10, memMgr); + XMLString::binToText(XERCES_GRAMMAR_SERIALIZATION_LEVEL, LoaderLevelChar, 4, 10, memMgr); + + ThrowXMLwithMemMgr2(XSerializationException + , XMLExcepts::XSer_Storer_Loader_Mismatch + , StorerLevelChar + , LoaderLevelChar + , memMgr); + } + + //lock status + serEng>>fLocked; + + //StringPool, don't use >> + fStringPool->serialize(serEng); + + /*** + * Deserialize RefHashTableOf* fGrammarRegistry; + ***/ + XTemplateSerializer::loadObject(&fGrammarRegistry, 29, true, serEng); + + } + catch(const OutOfMemoryException&) + { + // This is a special case, because we don't want + // to execute cleanup code on out-of-memory + // conditions. + cleanup.release(); + + throw; + } + + // Everything is OK, so we can release the cleanup object. + cleanup.release(); + + if (fLocked) + { + createXSModel(); + } +} + + +void +XMLGrammarPoolImpl::cleanUp() +{ + fLocked = false; + + clear(); +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLGrammarPoolImpl.hpp b/include/xercesc/framework/XMLGrammarPoolImpl.hpp new file mode 100644 index 0000000..7b8b746 --- /dev/null +++ b/include/xercesc/framework/XMLGrammarPoolImpl.hpp @@ -0,0 +1,279 @@ +/* + * 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: XMLGrammarPoolImpl.hpp 671531 2008-06-25 12:38:28Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLGRAMMARPOOLIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLGRAMMARPOOLIMPL_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLSynchronizedStringPool; + +class XMLUTIL_EXPORT XMLGrammarPoolImpl : public XMLGrammarPool +{ +public : + // ----------------------------------------------------------------------- + /** @name constructor and destructor */ + // ----------------------------------------------------------------------- + //@{ + + XMLGrammarPoolImpl(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + + ~XMLGrammarPoolImpl(); + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of Grammar Pool Interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * cacheGrammar + * + * Provide the grammar pool with an opportunity + * to cache the given grammar. If the pool does not choose to do so, + * it should return false; otherwise, it should return true, so that + * the caller knows whether the grammar has been adopted. + * + * @param gramToCache: the Grammar to be cached in the grammar pool + * @return true if the grammar pool has elected to cache the grammar (in which case + * it is assumed to have adopted it); false if it does not cache it + * + */ + virtual bool cacheGrammar(Grammar* const gramToCache); + + + /** + * retrieveGrammar + * + * @param gramDesc: the Grammar Description used to search for grammar + * cached in the grammar pool + * + */ + virtual Grammar* retrieveGrammar(XMLGrammarDescription* const gramDesc); + + + /** + * orphanGrammar + * + * grammar removed from the grammar pool and owned by the caller + * + * @param nameSpaceKey: Key used to search for grammar in the grammar pool + * + */ + virtual Grammar* orphanGrammar(const XMLCh* const nameSpaceKey); + + + /** + * Get an enumeration of the cached Grammars in the Grammar pool + * + * @return enumeration of the cached Grammars in Grammar pool + */ + virtual RefHashTableOfEnumerator getGrammarEnumerator() const; + + /** + * clear + * + * all grammars are removed from the grammar pool and deleted. + * @return true if the grammar pool was cleared. false if it did not. + */ + virtual bool clear(); + + /** + * lockPool + * + * When this method is called by the application, the + * grammar pool should stop adding new grammars to the cache. + */ + virtual void lockPool(); + + /** + * unlockPool + * + * After this method has been called, the grammar pool implementation + * should return to its default behaviour when cacheGrammars(...) is called. + * + * For PSVI support any previous XSModel that was produced will be deleted. + */ + virtual void unlockPool(); + + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of Factory interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * createDTDGrammar + * + */ + virtual DTDGrammar* createDTDGrammar(); + + /** + * createSchemaGrammar + * + */ + virtual SchemaGrammar* createSchemaGrammar(); + + /** + * createDTDDescription + * + */ + virtual XMLDTDDescription* createDTDDescription(const XMLCh* const systemId); + /** + * createSchemaDescription + * + */ + virtual XMLSchemaDescription* createSchemaDescription(const XMLCh* const targetNamespace); + //@} + + // ----------------------------------------------------------------------- + /** @name schema component model support */ + // ----------------------------------------------------------------------- + //@{ + + /*** + * Return an XSModel derived from the components of all SchemaGrammars + * in the grammar pool. If the pool is locked, this should + * be a thread-safe operation. + * + * NOTE: The function should NEVER return NULL. If there are no grammars in + * the pool it should return an XSModel containing the Schema for Schema. + * + * Calling getXSModel() on an unlocked grammar pool may result in the + * creation of a new XSModel with the old XSModel being deleted. + * The bool parameter will indicate if the XSModel was changed. + * + * In this implementation, when the pool is not locked a new XSModel will be + * computed each this time the pool is called if the pool has changed (and the + * previous one will be destroyed at that time). When the lockPool() + * method is called, an XSModel will be generated and returned whenever this method is called + * while the pool is in the locked state. This will be destroyed if the unlockPool() + * operation is called. The XSModel will not be serialized, + * but will be recreated if a deserialized pool is in the + * locked state. + * + */ + virtual XSModel *getXSModel(bool& XSModelWasChanged); + + // @} + // ----------------------------------------------------------------------- + /** @name Getter */ + // ----------------------------------------------------------------------- + //@{ + + /** + * Return an XMLStringPool for use by validation routines. + * Implementations should not create a string pool on each call to this + * method, but should maintain one string pool for all grammars + * for which this pool is responsible. + */ + virtual XMLStringPool *getURIStringPool(); + + // @} + + // ----------------------------------------------------------------------- + // serialization and deserialization support + // ----------------------------------------------------------------------- + + /*** + * + * Multiple serializations + * + * For multiple serializations, if the same file name is given, then the + * last result will be in the file (overwriting mode), if different file + * names are given, then there are multiple data stores for each serialization. + * + * Multiple deserializations + * + * Not supported + * + * Versioning + * + * Only binary data serialized with the current XercesC Version and + * SerializationLevel is supported. + * + * Clean up + * + * In the event of an exception thrown due to a corrupted data store during + * deserialization, this implementation may not be able to clean up all resources + * allocated, and therefore it is the client application's responsibility to + * clean up those unreleased resources. + * + * Coupling of Grammars and StringPool + * + * This implementation assumes that StringPool shall always be + * serialized/deserialized together with the grammars. In the case that such a + * coupling is not desired, client application can modify this behaviour by + * either derivate from this imlementation and overwrite the serializeGrammars() + * and/or deserializeGrammars() to decouple grammars and string pool, or + * Once deserializeGrammars() is done, insert another StringPool through + * setStringPool(). + * + * Client application shall be aware of the unpredicatable/undefined consequence + * of this decoupling. + */ + + virtual void serializeGrammars(BinOutputStream* const); + virtual void deserializeGrammars(BinInputStream* const); + +private: + + virtual void createXSModel(); + + void + cleanUp(); + + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLGrammarPoolImpl(const XMLGrammarPoolImpl& ); + XMLGrammarPoolImpl& operator=(const XMLGrammarPoolImpl& ); + //@} + + // ----------------------------------------------------------------------- + // + // fGrammarRegistry: + // + // container + // fStringPool + // grammars need a string pool for URI -> int mappings + // fSynchronizedStringPool + // When the grammar pool is locked, provide a string pool + // that can be updated in a thread-safe manner. + // fLocked + // whether the pool has been locked + // + // ----------------------------------------------------------------------- + RefHashTableOf* fGrammarRegistry; + XMLStringPool* fStringPool; + XMLSynchronizedStringPool* fSynchronizedStringPool; + XSModel* fXSModel; + bool fLocked; + bool fXSModelIsValid; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLNotationDecl.cpp b/include/xercesc/framework/XMLNotationDecl.cpp new file mode 100644 index 0000000..e6d5d57 --- /dev/null +++ b/include/xercesc/framework/XMLNotationDecl.cpp @@ -0,0 +1,140 @@ +/* + * 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: XMLNotationDecl.cpp 679359 2008-07-24 11:15:19Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLNotationDecl: Constructors and operators +// --------------------------------------------------------------------------- +XMLNotationDecl::XMLNotationDecl(MemoryManager* const manager) : + + fId(0) + , fNameSpaceId(0) + , fName(0) + , fPublicId(0) + , fSystemId(0) + , fBaseURI(0) + , fMemoryManager(manager) +{ +} + +typedef JanitorMemFunCall CleanupType; + +XMLNotationDecl::XMLNotationDecl( const XMLCh* const notName + , const XMLCh* const pubId + , const XMLCh* const sysId + , const XMLCh* const baseURI + , MemoryManager* const manager) : + fId(0) + , fNameSpaceId(0) + , fName(0) + , fPublicId(0) + , fSystemId(0) + , fBaseURI(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XMLNotationDecl::cleanUp); + + try + { + fName = XMLString::replicate(notName, fMemoryManager); + fPublicId = XMLString::replicate(pubId, fMemoryManager); + fSystemId = XMLString::replicate(sysId, fMemoryManager); + fBaseURI = XMLString::replicate(baseURI, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XMLNotationDecl::~XMLNotationDecl() +{ + cleanUp(); +} + + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- +void XMLNotationDecl::setName(const XMLCh* const notName) +{ + // Clean up the current name stuff and replicate the passed name + if (fName) + fMemoryManager->deallocate(fName); + + fName = XMLString::replicate(notName, fMemoryManager); +} + + + +// --------------------------------------------------------------------------- +// XMLNotationDecl: Private helper methods +// --------------------------------------------------------------------------- +void XMLNotationDecl::cleanUp() +{ + fMemoryManager->deallocate(fName); + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); + fMemoryManager->deallocate(fBaseURI); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XMLNotationDecl) + +void XMLNotationDecl::serialize(XSerializeEngine& serEng) +{ + if (serEng.isStoring()) + { + serEng.writeSize (fId); + serEng<>fNameSpaceId; + serEng.readString(fName); + serEng.readString(fPublicId); + serEng.readString(fSystemId); + serEng.readString(fBaseURI); + } +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLNotationDecl.hpp b/include/xercesc/framework/XMLNotationDecl.hpp new file mode 100644 index 0000000..61b4801 --- /dev/null +++ b/include/xercesc/framework/XMLNotationDecl.hpp @@ -0,0 +1,231 @@ +/* + * 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: XMLNotationDecl.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLNOTATIONDECL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLNOTATIONDECL_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class represents the core information about a notation declaration + * that all validators must at least support. Each validator will create a + * derivative of this class which adds any information it requires for its + * own extra needs. + * + * At this common level, the information supported is the notation name + * and the public and sysetm ids indicated in the notation declaration. + */ +class XMLPARSER_EXPORT XMLNotationDecl : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors */ + //@{ + XMLNotationDecl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + XMLNotationDecl + ( + const XMLCh* const notName + , const XMLCh* const pubId + , const XMLCh* const sysId + , const XMLCh* const baseURI = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + //@} + + /** @name Destructor */ + //@{ + ~XMLNotationDecl(); + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLSize_t getId() const; + const XMLCh* getName() const; + const XMLCh* getPublicId() const; + const XMLCh* getSystemId() const; + const XMLCh* getBaseURI() const; + unsigned int getNameSpaceId() const; + MemoryManager* getMemoryManager() const; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setId(const XMLSize_t newId); + void setName + ( + const XMLCh* const notName + ); + void setPublicId(const XMLCh* const newId); + void setSystemId(const XMLCh* const newId); + void setBaseURI(const XMLCh* const newId); + void setNameSpaceId(const unsigned int newId); + + // ----------------------------------------------------------------------- + // Support named collection element semantics + // ----------------------------------------------------------------------- + const XMLCh* getKey() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLNotationDecl) + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLNotationDecl(const XMLNotationDecl&); + XMLNotationDecl& operator=(const XMLNotationDecl&); + + + // ----------------------------------------------------------------------- + // XMLNotationDecl: Private helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fId + // This is the unique id given to this notation decl. + // + // fName + // The notation's name, which identifies the type of notation it + // applies to. + // + // fPublicId + // The text of the notation's public id, if any. + // + // fSystemId + // The text of the notation's system id, if any. + // + // fBaseURI + // The text of the notation's base URI + // ----------------------------------------------------------------------- + XMLSize_t fId; + unsigned int fNameSpaceId; + XMLCh* fName; + XMLCh* fPublicId; + XMLCh* fSystemId; + XMLCh* fBaseURI; + MemoryManager* fMemoryManager; +}; + + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- +inline XMLSize_t XMLNotationDecl::getId() const +{ + return fId; +} + +inline const XMLCh* XMLNotationDecl::getName() const +{ + return fName; +} + +inline unsigned int XMLNotationDecl::getNameSpaceId() const +{ + return fNameSpaceId; +} + +inline const XMLCh* XMLNotationDecl::getPublicId() const +{ + return fPublicId; +} + +inline const XMLCh* XMLNotationDecl::getSystemId() const +{ + return fSystemId; +} + +inline const XMLCh* XMLNotationDecl::getBaseURI() const +{ + return fBaseURI; +} + +inline MemoryManager* XMLNotationDecl::getMemoryManager() const +{ + return fMemoryManager; +} + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- +inline void XMLNotationDecl::setId(const XMLSize_t newId) +{ + fId = newId; +} + +inline void XMLNotationDecl::setNameSpaceId(const unsigned int newId) +{ + fNameSpaceId = newId; +} + +inline void XMLNotationDecl::setPublicId(const XMLCh* const newId) +{ + if (fPublicId) + fMemoryManager->deallocate(fPublicId); + + fPublicId = XMLString::replicate(newId, fMemoryManager); +} + +inline void XMLNotationDecl::setSystemId(const XMLCh* const newId) +{ + if (fSystemId) + fMemoryManager->deallocate(fSystemId); + + fSystemId = XMLString::replicate(newId, fMemoryManager); +} + +inline void XMLNotationDecl::setBaseURI(const XMLCh* const newId) +{ + if (fBaseURI) + fMemoryManager->deallocate(fBaseURI); + + fBaseURI = XMLString::replicate(newId, fMemoryManager); +} + + +// --------------------------------------------------------------------------- +// XMLNotationDecl: Support named pool element semantics +// --------------------------------------------------------------------------- +inline const XMLCh* XMLNotationDecl::getKey() const +{ + return fName; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLPScanToken.hpp b/include/xercesc/framework/XMLPScanToken.hpp new file mode 100644 index 0000000..84adacb --- /dev/null +++ b/include/xercesc/framework/XMLPScanToken.hpp @@ -0,0 +1,151 @@ +/* + * 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: XMLPScanToken.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLPSCANTOKEN_HPP) +#define XERCESC_INCLUDE_GUARD_XMLPSCANTOKEN_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLScanner; + +/** + * This simple class is used as a sanity check when the scanner is used to + * do progressive parsing. It insures that things are not done out of + * sequence and that sequences of scan calls are made correctly to the + * right scanner instances. + * + * To client code, it is just a magic cookie which is obtained when a + * progressive parse is begun, and which is passed back in on each subsequent + * call of the progressive parse. + */ +class XMLPARSER_EXPORT XMLPScanToken : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructor */ + //@{ + XMLPScanToken(); + XMLPScanToken(const XMLPScanToken& toCopy); + //@} + + /** @name Destructor */ + //@{ + ~XMLPScanToken(); + //@} + + + // ----------------------------------------------------------------------- + // Public operators + // ----------------------------------------------------------------------- + XMLPScanToken& operator=(const XMLPScanToken& toCopy); + + +protected : + // ----------------------------------------------------------------------- + // XMLScanner is our friend, can you say friend? Sure... + // ----------------------------------------------------------------------- + friend class XMLScanner; + + + // ----------------------------------------------------------------------- + // Hidden methods for use by XMLScanner + // ----------------------------------------------------------------------- + void set + ( + const XMLUInt32 scannerId + , const XMLUInt32 sequenceId + ); + + +private : + // ----------------------------------------------------------------------- + // Private data members + // + // fScannerId + // This field is set to the id of the scanner, to catch problems + // where a token is gotten from one scanner and passed to another. + // Each scanner is assigned an incrementing id. + // + // fSequenceId + // In order to avoid problems such as calling scanNext() without + // a call to scanFirst() and such, this value is set when scanFirst() + // is called and matches this token to the current sequence id of + // the scanner. + // ----------------------------------------------------------------------- + XMLUInt32 fScannerId; + XMLUInt32 fSequenceId; +}; + + +// --------------------------------------------------------------------------- +// XMLPScanToken: Constructors and Operators +// --------------------------------------------------------------------------- +inline XMLPScanToken::XMLPScanToken() : + + fScannerId(0) + , fSequenceId(0) +{ +} + +inline XMLPScanToken::XMLPScanToken(const XMLPScanToken& toCopy) : + XMemory(toCopy) + , fScannerId(toCopy.fScannerId) + , fSequenceId(toCopy.fSequenceId) +{ +} + +inline XMLPScanToken::~XMLPScanToken() +{ +} + + +// --------------------------------------------------------------------------- +// XMLPScanToken: Public operators +// --------------------------------------------------------------------------- +inline XMLPScanToken& XMLPScanToken::operator=(const XMLPScanToken& toCopy) +{ + if (this == &toCopy) + return *this; + + fScannerId = toCopy.fScannerId; + fSequenceId = toCopy.fSequenceId; + + return *this; +} + + +// --------------------------------------------------------------------------- +// XMLPScanToken: Hidden methods +// --------------------------------------------------------------------------- +inline void XMLPScanToken::set( const XMLUInt32 scannerId + , const XMLUInt32 sequenceId) +{ + fScannerId = scannerId; + fSequenceId = sequenceId; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLRecognizer.cpp b/include/xercesc/framework/XMLRecognizer.cpp new file mode 100644 index 0000000..a569486 --- /dev/null +++ b/include/xercesc/framework/XMLRecognizer.cpp @@ -0,0 +1,270 @@ +/* + * 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: XMLRecognizer.cpp 555320 2007-07-11 16:05:13Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local data +// +// gEncodingNameMap +// This array maps the Encodings enum values to their canonical names. +// Be sure to keep this in sync with that enum! +// --------------------------------------------------------------------------- +static const XMLCh* gEncodingNameMap[XMLRecognizer::Encodings_Count] = +{ + XMLUni::fgEBCDICEncodingString + , XMLUni::fgUCS4BEncodingString + , XMLUni::fgUCS4LEncodingString + , XMLUni::fgUSASCIIEncodingString + , XMLUni::fgUTF8EncodingString + , XMLUni::fgUTF16BEncodingString + , XMLUni::fgUTF16LEncodingString + , XMLUni::fgXMLChEncodingString +}; + + + +// --------------------------------------------------------------------------- +// XMLRecognizer: Public, const static data +// +// gXXXPre +// gXXXPreLen +// The byte sequence prefixes for all of the encodings that we can +// auto sense. Also included is the length of each sequence. +// --------------------------------------------------------------------------- +const char XMLRecognizer::fgASCIIPre[] = { 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20 }; +const XMLSize_t XMLRecognizer::fgASCIIPreLen = 6; +const XMLByte XMLRecognizer::fgEBCDICPre[] = { 0x4C, 0x6F, 0xA7, 0x94, 0x93, 0x40 }; +const XMLSize_t XMLRecognizer::fgEBCDICPreLen = 6; +const XMLByte XMLRecognizer::fgUTF16BPre[] = { 0x00, 0x3C, 0x00, 0x3F, 0x00, 0x78, 0x00, 0x6D, 0x00, 0x6C, 0x00, 0x20 }; +const XMLByte XMLRecognizer::fgUTF16LPre[] = { 0x3C, 0x00, 0x3F, 0x00, 0x78, 0x00, 0x6D, 0x00, 0x6C, 0x00, 0x20, 0x00 }; +const XMLSize_t XMLRecognizer::fgUTF16PreLen = 12; +const XMLByte XMLRecognizer::fgUCS4BPre[] = +{ + 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3F + , 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6D + , 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x20 +}; +const XMLByte XMLRecognizer::fgUCS4LPre[] = +{ + 0x3C, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00 + , 0x78, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00 + , 0x6C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 +}; +const XMLSize_t XMLRecognizer::fgUCS4PreLen = 24; + +const char XMLRecognizer::fgUTF8BOM[] = {(char)0xEF, (char)0xBB, (char)0xBF}; +const XMLSize_t XMLRecognizer::fgUTF8BOMLen = 3; + +// --------------------------------------------------------------------------- +// XMLRecognizer: Encoding recognition methods +// --------------------------------------------------------------------------- +XMLRecognizer::Encodings +XMLRecognizer::basicEncodingProbe( const XMLByte* const rawBuffer + , const XMLSize_t rawByteCount) +{ + // + // As an optimization to check the 90% case, check first for the ASCII + // sequence '= fgASCIIPreLen) + { + if (!memcmp(rawBuffer, fgASCIIPre, fgASCIIPreLen)) + return UTF_8; + } + + // + // If the count of raw bytes is less than 2, it cannot be anything + // we understand, so return UTF-8 as a fallback. + // + if (rawByteCount < 2) + return UTF_8; + + // + // We have two to four bytes, so lets check for a UTF-16 BOM. That + // is quick to check and enough to identify two major encodings. + // + + if (rawByteCount < 4) + { + if ((rawBuffer[0] == 0xFE) && (rawBuffer[1] == 0xFF)) + return UTF_16B; + else if ((rawBuffer[0] == 0xFF) && (rawBuffer[1] == 0xFE)) + return UTF_16L; + else + return UTF_8; + } + + /*** + * F.1 Detection Without External Encoding Information + * + * Because each XML entity not accompanied by external encoding information and + * not in UTF-8 or UTF-16 encoding must begin with an XML encoding declaration, + * in which the first characters must be '= fgUCS4PreLen && !memcmp(rawBuffer, fgUCS4BPre, fgUCS4PreLen)) + return UCS_4B; + else if (rawByteCount >= fgUCS4PreLen && !memcmp(rawBuffer, fgUCS4LPre, fgUCS4PreLen)) + return UCS_4L; + else if (rawByteCount >= fgUTF16PreLen && !memcmp(rawBuffer, fgUTF16BPre, fgUTF16PreLen)) + return UTF_16B; + else if (rawByteCount >= fgUTF16PreLen && !memcmp(rawBuffer, fgUTF16LPre, fgUTF16PreLen)) + return UTF_16L; + } + + // + // See if we have enough bytes to possibly match the EBCDIC prefix. + // If so, try it. + // + if (rawByteCount > fgEBCDICPreLen) + { + if (!memcmp(rawBuffer, fgEBCDICPre, fgEBCDICPreLen)) + return EBCDIC; + } + + // + // Does not seem to be anything we know, so go with UTF-8 to get at + // least through the first line and see what it really is. + // + return UTF_8; +} + + +XMLRecognizer::Encodings +XMLRecognizer::encodingForName(const XMLCh* const encName) +{ + // + // Compare the passed string, assume input string is already uppercased, + // to the variations that we recognize. + // + // !!NOTE: Note that we don't handle EBCDIC here because we don't handle + // that one ourselves. It is allowed to fall into 'other'. + // + if (encName == XMLUni::fgXMLChEncodingString || + !XMLString::compareString(encName, XMLUni::fgXMLChEncodingString)) + { + return XMLRecognizer::XERCES_XMLCH; + } + else if (!XMLString::compareString(encName, XMLUni::fgUTF8EncodingString) + || !XMLString::compareString(encName, XMLUni::fgUTF8EncodingString2)) + { + return XMLRecognizer::UTF_8; + } + else if (!XMLString::compareString(encName, XMLUni::fgUSASCIIEncodingString) + || !XMLString::compareString(encName, XMLUni::fgUSASCIIEncodingString2) + || !XMLString::compareString(encName, XMLUni::fgUSASCIIEncodingString3) + || !XMLString::compareString(encName, XMLUni::fgUSASCIIEncodingString4)) + { + return XMLRecognizer::US_ASCII; + } + else if (!XMLString::compareString(encName, XMLUni::fgUTF16LEncodingString) + || !XMLString::compareString(encName, XMLUni::fgUTF16LEncodingString2)) + { + return XMLRecognizer::UTF_16L; + } + else if (!XMLString::compareString(encName, XMLUni::fgUTF16BEncodingString) + || !XMLString::compareString(encName, XMLUni::fgUTF16BEncodingString2)) + { + return XMLRecognizer::UTF_16B; + } + else if (!XMLString::compareString(encName, XMLUni::fgUTF16EncodingString)) + { + return XMLPlatformUtils::fgXMLChBigEndian?XMLRecognizer::UTF_16B:XMLRecognizer::UTF_16L; + } + else if (!XMLString::compareString(encName, XMLUni::fgUCS4LEncodingString) + || !XMLString::compareString(encName, XMLUni::fgUCS4LEncodingString2)) + { + return XMLRecognizer::UCS_4L; + } + else if (!XMLString::compareString(encName, XMLUni::fgUCS4BEncodingString) + || !XMLString::compareString(encName, XMLUni::fgUCS4BEncodingString2)) + { + return XMLRecognizer::UCS_4B; + } + else if (!XMLString::compareString(encName, XMLUni::fgUCS4EncodingString)) + { + return XMLPlatformUtils::fgXMLChBigEndian?XMLRecognizer::UCS_4B:XMLRecognizer::UCS_4L; + } + + // Return 'other' since we don't recognizer it + return XMLRecognizer::OtherEncoding; +} + + +const XMLCh* +XMLRecognizer::nameForEncoding(const XMLRecognizer::Encodings theEncoding + , MemoryManager* const manager) +{ + if (theEncoding >= Encodings_Count) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::XMLRec_UnknownEncoding, manager); + + return gEncodingNameMap[theEncoding]; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLRecognizer.hpp b/include/xercesc/framework/XMLRecognizer.hpp new file mode 100644 index 0000000..68938e1 --- /dev/null +++ b/include/xercesc/framework/XMLRecognizer.hpp @@ -0,0 +1,138 @@ +/* + * 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: XMLRecognizer.hpp 555320 2007-07-11 16:05:13Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLRECOGNIZER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLRECOGNIZER_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class provides some simple code to recognize the encodings of + * XML files. This recognition only does very basic sensing of the encoding + * in a broad sense. Basically its just enough to let us get started and + * read the XMLDecl line. The scanner, once it reads the XMLDecl, will + * tell the reader any actual encoding string it found and the reader can + * update itself to be more specific at that point. + */ +class XMLPARSER_EXPORT XMLRecognizer +{ +public : + // ----------------------------------------------------------------------- + // Class types + // + // This enum represents the various encoding families that we have to + // deal with individually at the scanner level. This does not indicate + // the exact encoding, just the rough family that would let us scan + // the XML/TextDecl to find the encoding string. + // + // The 'L's and 'B's stand for little or big endian. + // + // OtherEncoding means that its some transcoder based encoding, i.e. not + // one of the ones that we do internally. Its a special case and should + // never be used directly outside of the reader. + // + // NOTE: Keep this in sync with the name map array in the Cpp file!! + // ----------------------------------------------------------------------- + enum Encodings + { + EBCDIC = 0 + , UCS_4B = 1 + , UCS_4L = 2 + , US_ASCII = 3 + , UTF_8 = 4 + , UTF_16B = 5 + , UTF_16L = 6 + , XERCES_XMLCH = 7 + + , Encodings_Count + , Encodings_Min = EBCDIC + , Encodings_Max = XERCES_XMLCH + + , OtherEncoding = 999 + }; + + + // ----------------------------------------------------------------------- + // Public, const static data + // + // These are the byte sequences for each of the encodings that we can + // auto sense, and their lengths. + // ----------------------------------------------------------------------- + static const char fgASCIIPre[]; + static const XMLSize_t fgASCIIPreLen; + static const XMLByte fgEBCDICPre[]; + static const XMLSize_t fgEBCDICPreLen; + static const XMLByte fgUTF16BPre[]; + static const XMLByte fgUTF16LPre[]; + static const XMLSize_t fgUTF16PreLen; + static const XMLByte fgUCS4BPre[]; + static const XMLByte fgUCS4LPre[]; + static const XMLSize_t fgUCS4PreLen; + static const char fgUTF8BOM[]; + static const XMLSize_t fgUTF8BOMLen; + + + // ----------------------------------------------------------------------- + // Encoding recognition methods + // ----------------------------------------------------------------------- + static Encodings basicEncodingProbe + ( + const XMLByte* const rawBuffer + , const XMLSize_t rawByteCount + ); + + static Encodings encodingForName + ( + const XMLCh* const theEncName + ); + + static const XMLCh* nameForEncoding(const Encodings theEncoding + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + +protected : + // ----------------------------------------------------------------------- + // Unimplemented constructors, operators, and destructor + // + // This class is effectively being used as a namespace for some static + // methods. + // + // (these functions are protected rather than private only to get rid of + // some annoying compiler warnings.) + // + // ----------------------------------------------------------------------- + XMLRecognizer(); + ~XMLRecognizer(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLRecognizer(const XMLRecognizer&); + XMLRecognizer& operator=(const XMLRecognizer&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLRefInfo.cpp b/include/xercesc/framework/XMLRefInfo.cpp new file mode 100644 index 0000000..36094c0 --- /dev/null +++ b/include/xercesc/framework/XMLRefInfo.cpp @@ -0,0 +1,60 @@ +/* + * 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: XMLRefInfo.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XMLRefInfo) + +void XMLRefInfo::serialize(XSerializeEngine& serEng) +{ + if (serEng.isStoring()) + { + serEng<>fDeclared; + serEng>>fUsed; + serEng.readString(fRefName); + } + +} + +XMLRefInfo::XMLRefInfo(MemoryManager* const manager) +:fDeclared(false) +,fUsed(false) +,fRefName(0) +,fMemoryManager(manager) +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLRefInfo.hpp b/include/xercesc/framework/XMLRefInfo.hpp new file mode 100644 index 0000000..e2559e5 --- /dev/null +++ b/include/xercesc/framework/XMLRefInfo.hpp @@ -0,0 +1,181 @@ +/* + * 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: XMLRefInfo.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLREFINFO_HPP) +#define XERCESC_INCLUDE_GUARD_XMLREFINFO_HPP + +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class provides a simple means to track ID Ref usage. Since id/idref + * semantics are part of XML 1.0, any validator will likely to be able to + * track them. Instances of this class represent a reference and two markers, + * one for its being declared and another for its being used. When the + * document is done, one can look at each instance and, if used but not + * declared, its an error. + * + * The getKey() method allows it to support keyed collection semantics. It + * returns the referenced name, so these objects will be stored via the hash + * of the name. This name will either be a standard QName if namespaces are + * not enabled/supported by the validator, or it will be in the form + * {url}name if namespace processing is enabled. + */ +class XMLPARSER_EXPORT XMLRefInfo : public XSerializable, public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructor */ + //@{ + XMLRefInfo + ( + const XMLCh* const refName + , const bool fDeclared = false + , const bool fUsed = false + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + //@} + + /** @name Destructor */ + //@{ + ~XMLRefInfo(); + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getDeclared() const; + const XMLCh* getRefName() const; + bool getUsed() const; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setDeclared(const bool newValue); + void setUsed(const bool newValue); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLRefInfo) + + XMLRefInfo + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLRefInfo(const XMLRefInfo&); + XMLRefInfo& operator=(XMLRefInfo&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fDeclared + // The name was declared somewhere as an ID attribute. + // + // fRefName + // The name of the ref that this object represents. This is not a + // name of the attribute, but of the value of an ID or IDREF attr + // in content. + // + // fUsed + // The name was used somewhere in an IDREF/IDREFS attribute. If this + // is true, but fDeclared is false, then the ref does not refer to + // a declared ID. + // ----------------------------------------------------------------------- + bool fDeclared; + bool fUsed; + XMLCh* fRefName; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// XMLRefInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +inline XMLRefInfo::XMLRefInfo( const XMLCh* const refName + , const bool declared + , const bool used + , MemoryManager* const manager) : + fDeclared(declared) + , fUsed(used) + , fRefName(0) + , fMemoryManager(manager) +{ + fRefName = XMLString::replicate(refName, fMemoryManager); +} + +inline XMLRefInfo::~XMLRefInfo() +{ + fMemoryManager->deallocate(fRefName); +} + + +// --------------------------------------------------------------------------- +// XMLRefInfo: Getter methods +// --------------------------------------------------------------------------- +inline bool XMLRefInfo::getDeclared() const +{ + return fDeclared; +} + +inline const XMLCh* XMLRefInfo::getRefName() const +{ + return fRefName; +} + +inline bool XMLRefInfo::getUsed() const +{ + return fUsed; +} + + +// --------------------------------------------------------------------------- +// XMLRefInfo: Setter methods +// --------------------------------------------------------------------------- +inline void XMLRefInfo::setDeclared(const bool newValue) +{ + fDeclared = newValue; +} + +inline void XMLRefInfo::setUsed(const bool newValue) +{ + fUsed = newValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLSchemaDescription.cpp b/include/xercesc/framework/XMLSchemaDescription.cpp new file mode 100644 index 0000000..9a73a8f --- /dev/null +++ b/include/xercesc/framework/XMLSchemaDescription.cpp @@ -0,0 +1,53 @@ +/* + * 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: XMLSchemaDescription.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +XMLSchemaDescription::~XMLSchemaDescription() +{ +} + +XMLSchemaDescription::XMLSchemaDescription(MemoryManager* const memMgr) +:XMLGrammarDescription(memMgr) +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(XMLSchemaDescription) + +void XMLSchemaDescription::serialize(XSerializeEngine& serEng) +{ + XMLGrammarDescription::serialize(serEng); + + //no data +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/framework/XMLSchemaDescription.hpp b/include/xercesc/framework/XMLSchemaDescription.hpp new file mode 100644 index 0000000..bff9f54 --- /dev/null +++ b/include/xercesc/framework/XMLSchemaDescription.hpp @@ -0,0 +1,178 @@ +/* + * 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: XMLSchemaDescription.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLSCHEMADESCRIPTION_HPP) +#define XERCESC_INCLUDE_GUARD_XMLSCHEMADESCRIPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef const XMLCh* const LocationHint; + +class XMLPARSER_EXPORT XMLSchemaDescription : public XMLGrammarDescription +{ +public : + // ----------------------------------------------------------------------- + /** @name Virtual destructor for derived classes */ + // ----------------------------------------------------------------------- + //@{ + /** + * virtual destructor + * + */ + virtual ~XMLSchemaDescription(); + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of Grammar Description Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * getGrammarType + * + */ + virtual Grammar::GrammarType getGrammarType() const + { + return Grammar::SchemaGrammarType; + } + //@} + + // ----------------------------------------------------------------------- + /** @name The SchemaDescription Interface */ + // ----------------------------------------------------------------------- + //@{ + + enum ContextType + { + CONTEXT_INCLUDE, + CONTEXT_REDEFINE, + CONTEXT_IMPORT, + CONTEXT_PREPARSE, + CONTEXT_INSTANCE, + CONTEXT_ELEMENT, + CONTEXT_ATTRIBUTE, + CONTEXT_XSITYPE, + CONTEXT_UNKNOWN + }; + + /** + * getContextType + * + */ + virtual ContextType getContextType() const = 0; + + /** + * getTargetNamespace + * + */ + virtual const XMLCh* getTargetNamespace() const = 0; + + /** + * getLocationHints + * + */ + virtual const RefArrayVectorOf* getLocationHints() const = 0; + + /** + * getTriggeringComponent + * + */ + virtual const QName* getTriggeringComponent() const = 0; + + /** + * getenclosingElementName + * + */ + virtual const QName* getEnclosingElementName() const = 0; + + /** + * getAttributes + * + */ + virtual const XMLAttDef* getAttributes() const = 0; + + /** + * setContextType + * + */ + virtual void setContextType(ContextType) = 0; + + /** + * setTargetNamespace + * + */ + virtual void setTargetNamespace(const XMLCh* const) = 0; + + /** + * setLocationHints + * + */ + virtual void setLocationHints(const XMLCh* const) = 0; + + /** + * setTriggeringComponent + * + */ + virtual void setTriggeringComponent(QName* const) = 0; + + /** + * getenclosingElementName + * + */ + virtual void setEnclosingElementName(QName* const) = 0; + + /** + * setAttributes + * + */ + virtual void setAttributes(XMLAttDef* const) = 0; + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLSchemaDescription) + +protected : + // ----------------------------------------------------------------------- + /** Hidden Constructors */ + // ----------------------------------------------------------------------- + //@{ + XMLSchemaDescription(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + //@} + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLSchemaDescription(const XMLSchemaDescription& ); + XMLSchemaDescription& operator=(const XMLSchemaDescription& ); + //@} + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLValidator.cpp b/include/xercesc/framework/XMLValidator.cpp new file mode 100644 index 0000000..dd032d8 --- /dev/null +++ b/include/xercesc/framework/XMLValidator.cpp @@ -0,0 +1,296 @@ +/* + * 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: XMLValidator.cpp 635560 2008-03-10 14:10:09Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static XMLMsgLoader* sMsgLoader = 0; + +void XMLInitializer::initializeXMLValidator() +{ + sMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgValidityDomain); + + if (!sMsgLoader) + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); +} + +void XMLInitializer::terminateXMLValidator() +{ + delete sMsgLoader; + sMsgLoader = 0; +} + +// --------------------------------------------------------------------------- +// XMLValidator: Error emitting methods +// --------------------------------------------------------------------------- + +// +// These methods are called whenever the scanner wants to emit an error. +// It handles getting the message loaded, doing token replacement, etc... +// and then calling the error handler, if its installed. +// +void XMLValidator::emitError(const XMLValid::Codes toEmit) +{ + // Bump the error count if it is not a warning + if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + fScanner->incrementErrorCount(); + + // Call error reporter if we have one + if (fErrorReporter) + { + // Load the message into a local for display + const XMLSize_t msgSize = 1023; + XMLCh errText[msgSize + 1]; + + // load the text + if (!sMsgLoader->loadMsg(toEmit, errText, msgSize)) + { + // Probably should load a default msg here + } + + // + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + // + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr->getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + toEmit + , XMLUni::fgValidityDomain + , XMLValid::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal()) + || XMLValid::isFatal(toEmit)) + && fScanner->getExitOnFirstFatal() + && !fScanner->getInException()) + { + throw toEmit; + } +} + +void XMLValidator::emitError(const XMLValid::Codes toEmit + , const XMLCh* const text1 + , const XMLCh* const text2 + , const XMLCh* const text3 + , const XMLCh* const text4) +{ + // Bump the error count if it is not a warning + if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + fScanner->incrementErrorCount(); + + // Call error reporter if we have one + if (fErrorReporter) + { + // + // Load the message into alocal and replace any tokens found in + // the text. + // + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + // load the text + if (!sMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fScanner->getMemoryManager())) + { + // Should probably load a default message here + } + + // + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + // + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr->getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + toEmit + , XMLUni::fgValidityDomain + , XMLValid::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal()) + || XMLValid::isFatal(toEmit)) + && fScanner->getExitOnFirstFatal() + && !fScanner->getInException()) + { + throw toEmit; + } +} + +void XMLValidator::emitError(const XMLValid::Codes toEmit + , const char* const text1 + , const char* const text2 + , const char* const text3 + , const char* const text4) +{ + // Bump the error count if it is not a warning + if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + fScanner->incrementErrorCount(); + + // Call error reporter if we have one + if (fErrorReporter) + { + // + // Load the message into alocal and replace any tokens found in + // the text. + // + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + // load the text + if (!sMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fScanner->getMemoryManager())) + { + // Should probably load a default message here + } + + // + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + // + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr->getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + toEmit + , XMLUni::fgValidityDomain + , XMLValid::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal()) + || XMLValid::isFatal(toEmit)) + && fScanner->getExitOnFirstFatal() + && !fScanner->getInException()) + { + throw toEmit; + } +} + +void XMLValidator::emitError(const XMLValid::Codes toEmit + , const XMLExcepts::Codes originalExceptCode + , const XMLCh* const text1 + , const XMLCh* const text2 + , const XMLCh* const text3 + , const XMLCh* const text4) +{ + // Bump the error count if it is not a warning + if (XMLValid::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + fScanner->incrementErrorCount(); + + // Call error reporter if we have one + if (fErrorReporter) + { + // + // Load the message into alocal and replace any tokens found in + // the text. + // + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + // load the text + if (!sMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fScanner->getMemoryManager())) + { + // Should probably load a default message here + } + + // + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + // + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr->getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + originalExceptCode + , XMLUni::fgExceptDomain //XMLUni::fgValidityDomain + , XMLValid::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (((XMLValid::isError(toEmit) && fScanner->getValidationConstraintFatal()) + || XMLValid::isFatal(toEmit)) + && fScanner->getExitOnFirstFatal() + && !fScanner->getInException()) + { + throw toEmit; + } +} + +// --------------------------------------------------------------------------- +// XMLValidator: Hidden Constructors +// --------------------------------------------------------------------------- +XMLValidator::XMLValidator(XMLErrorReporter* const errReporter) : + + fBufMgr(0) + , fErrorReporter(errReporter) + , fReaderMgr(0) + , fScanner(0) +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/XMLValidator.hpp b/include/xercesc/framework/XMLValidator.hpp new file mode 100644 index 0000000..440d7b1 --- /dev/null +++ b/include/xercesc/framework/XMLValidator.hpp @@ -0,0 +1,426 @@ +/* + * 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: XMLValidator.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_XMLVALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class ReaderMgr; +class XMLBufferMgr; +class XMLElementDecl; +class XMLScanner; +class Grammar; + + +/** + * This abstract class provides the interface for all validators. This is + * the simple amount of API that all validators must honor, in order for + * the scanner to use them to do validation. All validators will actually + * contain much more functionality than is accessible via this common API, + * but that functionality requires that you know what type of validator you + * are dealing with. + * + * Basically, at this level, the primary concern is to be able to query + * core information about elements and attributes. Adding decls to the + * validator requires that you go through the derived interface because they + * all have their own decl types. At this level, we can return information + * via the base decl classes, from which each validator derives its own + * decl classes. + */ +class XMLPARSER_EXPORT XMLValidator : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors are hidden, just the virtual destructor is exposed + // ----------------------------------------------------------------------- + + /** @name Destructor */ + //@{ + + /** + * The derived class should clean up its allocated data, then this class + * will do the same for data allocated at this level. + */ + virtual ~XMLValidator() + { + } + //@} + + + // ----------------------------------------------------------------------- + // The virtual validator interface + // ----------------------------------------------------------------------- + + /** @name Virtual validator interface */ + //@{ + + /** + * The derived class should look up its declaration of the passed element + * from its element pool. It should then use the content model description + * contained in that element declaration to validate that the passed list + * of child elements are valid for that content model. The count can be + * zero, indicating no child elements. + * + * Note that whitespace and text content are not validated here. Those are + * handled by the scanner. So only element ids are provided here. + * + * @param elemDecl The element whose content is to be checked. + * + * @param children An array of element QName which represent the elements + * found within the parent element, i.e. the content + * to be validated. + * + * @param childCount The number of elements in the childIds array. It can + * be zero if the element had none. + * + * @param indexFailingChild On return, it will contain the index of the + * children failing validation, if the retun value + * is false + * + */ + virtual bool checkContent + ( + XMLElementDecl* const elemDecl + , QName** const children + , XMLSize_t childCount + , XMLSize_t* indexFailingChild + ) = 0; + + /** + * The derived class should fault in the passed XMLAttr value. It should + * use the passeed attribute definition (which is passed via the base + * type so it must often be downcast to the appropriate type for the + * derived validator class), to fill in the passed attribute. This is done + * as a performance enhancement since the derived class has more direct + * access to the information. + */ + virtual void faultInAttr + ( + XMLAttr& toFill + , const XMLAttDef& attDef + ) const = 0; + + /** + * This method is called by the scanner after a Grammar is scanned. + */ + virtual void preContentValidation(bool reuseGrammar, + bool validateDefAttr = false) = 0; + + /** + * This method is called by the scanner after the parse has completed. It + * gives the validator a chance to check certain things that can only be + * checked after the whole document has been parsed, such as referential + * integrity of ID/IDREF pairs and so forth. The validator should just + * issue errors for any problems it finds. + */ + virtual void postParseValidation() = 0; + + /** + * This method is called by the scanner before a new document is about + * to start. It gives the validator a change to reset itself in preparation + * for another validation pass. + */ + virtual void reset() = 0; + + /** + * The derived class should return a boolean that indicates whether it + * requires namespace processing or not. Some do and some allow it to be + * optional. This flag is used to control whether the client code's + * requests to disable namespace processing can be honored or not. + */ + virtual bool requiresNamespaces() const = 0; + + /** + * The derived class should apply any rules to the passed attribute value + * that are above and beyond those defined by XML 1.0. The scanner itself + * will impose XML 1.0 rules, based on the type of the attribute. This + * will generally be used to check things such as range checks and other + * datatype related validation. + * + * If the value breaks any rules as defined by the derived class, it + * should just issue errors as usual. + */ + virtual void validateAttrValue + ( + const XMLAttDef* attDef + , const XMLCh* const attrValue + , bool preValidation = false + , const XMLElementDecl* elemDecl = 0 + ) = 0; + + /** + * The derived class should apply any rules to the passed element decl + * that are above and beyond those defined by XML 1.0. + * + * If the value breaks any rules as defined by the derived class, it + * should just issue errors as usual. + */ + virtual void validateElement + ( + const XMLElementDecl* elemDef + ) = 0; + + /** + * Retrieve the Grammar used + */ + virtual Grammar* getGrammar() const =0; + + /** + * Set the Grammar + */ + virtual void setGrammar(Grammar* aGrammar) =0; + + + //@} + + // ----------------------------------------------------------------------- + // Virtual DTD handler interface. + // ----------------------------------------------------------------------- + + /** @name Virtual DTD handler interface */ + //@{ + + /** + * This method allows the scanner to ask the validator if it handles + * DTDs or not. + */ + virtual bool handlesDTD() const = 0; + + // ----------------------------------------------------------------------- + // Virtual Schema handler interface. + // ----------------------------------------------------------------------- + + /** @name Virtual Schema handler interface */ + + /** + * This method allows the scanner to ask the validator if it handles + * Schema or not. + */ + virtual bool handlesSchema() const = 0; + + //@} + + // ----------------------------------------------------------------------- + // Setter methods + // + // setScannerInfo() is called by the scanner to tell the validator + // about the stuff it needs to have access to. + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** + * @param owningScanner This is a pointer to the scanner to which the + * validator belongs. The validator will often + * need to query state data from the scanner. + * + * @param readerMgr This is a pointer to the reader manager that is + * being used by the scanner. + * + * @param bufMgr This is the buffer manager of the scanner. This + * is provided as a convenience so that the validator + * doesn't have to create its own buffer manager + * during the parse process. + */ + void setScannerInfo + ( + XMLScanner* const owningScanner + , ReaderMgr* const readerMgr + , XMLBufferMgr* const bufMgr + ); + + /** + * This method is called to set an error reporter on the validator via + * which it will report any errors it sees during parsing or validation. + * This is generally called by the owning scanner. + * + * @param errorReporter A pointer to the error reporter to use. This + * is not adopted, just referenced so the caller + * remains responsible for its cleanup, if any. + */ + void setErrorReporter + ( + XMLErrorReporter* const errorReporter + ); + + //@} + + + // ----------------------------------------------------------------------- + // Error emitter methods + // ----------------------------------------------------------------------- + + /** @name Error emittor methods */ + //@{ + + /** + * This call is a convenience by which validators can emit errors. Most + * of the grunt work of loading the text, getting the current source + * location, ect... is handled here. + * + * If the loaded text has replacement parameters, then text strings can be + * passed. These will be used to replace the tokens {0}, {1}, {2}, and {3} + * in the order passed. So text1 will replace {0}, text2 will replace {1}, + * and so forth. + * + * textX Up to four replacement parameters. They can be provided + * as either XMLCh strings, or local code page strings which + * will be transcoded internally. + * + * @param toEmit The error code to emit. it must be one of the defined + * validator error codes. + * + */ + void emitError(const XMLValid::Codes toEmit); + void emitError + ( + const XMLValid::Codes toEmit + , const XMLCh* const text1 + , const XMLCh* const text2 = 0 + , const XMLCh* const text3 = 0 + , const XMLCh* const text4 = 0 + ); + void emitError + ( + const XMLValid::Codes toEmit + , const char* const text1 + , const char* const text2 = 0 + , const char* const text3 = 0 + , const char* const text4 = 0 + ); + void emitError + ( + const XMLValid::Codes toEmit + , const XMLExcepts::Codes originalErrorCode + , const XMLCh* const text1 = 0 + , const XMLCh* const text2 = 0 + , const XMLCh* const text3 = 0 + , const XMLCh* const text4 = 0 + + ); + + //@} + +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + XMLValidator + ( + XMLErrorReporter* const errReporter = 0 + ); + + + // ----------------------------------------------------------------------- + // Protected getters + // ----------------------------------------------------------------------- + const XMLBufferMgr* getBufMgr() const; + XMLBufferMgr* getBufMgr(); + const ReaderMgr* getReaderMgr() const; + ReaderMgr* getReaderMgr(); + const XMLScanner* getScanner() const; + XMLScanner* getScanner(); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented Constructors and Operators + // ----------------------------------------------------------------------- + XMLValidator(const XMLValidator&); + XMLValidator& operator=(const XMLValidator&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fErrorReporter + // The error reporter we are to use, if any. + // + // ----------------------------------------------------------------------- + XMLBufferMgr* fBufMgr; + XMLErrorReporter* fErrorReporter; + ReaderMgr* fReaderMgr; + XMLScanner* fScanner; +}; + + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- +inline void +XMLValidator::setScannerInfo(XMLScanner* const owningScanner + , ReaderMgr* const readerMgr + , XMLBufferMgr* const bufMgr) +{ + // We don't own any of these, we just reference them + fScanner = owningScanner; + fReaderMgr = readerMgr; + fBufMgr = bufMgr; +} + +inline void +XMLValidator::setErrorReporter(XMLErrorReporter* const errorReporter) +{ + fErrorReporter = errorReporter; +} + + +// --------------------------------------------------------------------------- +// XMLValidator: Protected getter +// --------------------------------------------------------------------------- +inline const XMLBufferMgr* XMLValidator::getBufMgr() const +{ + return fBufMgr; +} + +inline XMLBufferMgr* XMLValidator::getBufMgr() +{ + return fBufMgr; +} + +inline const ReaderMgr* XMLValidator::getReaderMgr() const +{ + return fReaderMgr; +} + +inline ReaderMgr* XMLValidator::getReaderMgr() +{ + return fReaderMgr; +} + +inline const XMLScanner* XMLValidator::getScanner() const +{ + return fScanner; +} + +inline XMLScanner* XMLValidator::getScanner() +{ + return fScanner; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/XMLValidityCodes.hpp b/include/xercesc/framework/XMLValidityCodes.hpp new file mode 100644 index 0000000..aed00fb --- /dev/null +++ b/include/xercesc/framework/XMLValidityCodes.hpp @@ -0,0 +1,147 @@ +// This file is generated, don't edit it!! + +#if !defined(XERCESC_INCLUDE_GUARD_ERRHEADER_XMLValid) +#define XERCESC_INCLUDE_GUARD_ERRHEADER_XMLValid + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLValid +{ +public : + enum Codes + { + NoError = 0 + , E_LowBounds = 1 + , ElementNotDefined = 2 + , AttNotDefined = 3 + , NotationNotDeclared = 4 + , RootElemNotLikeDocType = 5 + , RequiredAttrNotProvided = 6 + , ElementNotValidForContent = 7 + , BadIDAttrDefType = 8 + , InvalidEmptyAttValue = 9 + , ElementAlreadyExists = 10 + , MultipleIdAttrs = 11 + , ReusedIDValue = 12 + , IDNotDeclared = 13 + , UnknownNotRefAttr = 14 + , UndeclaredElemInDocType = 15 + , EmptyNotValidForContent = 16 + , AttNotDefinedForElement = 17 + , BadEntityRefAttr = 18 + , UnknownEntityRefAttr = 19 + , ColonNotValidWithNS = 20 + , NotEnoughElemsForCM = 21 + , NoCharDataInCM = 22 + , DoesNotMatchEnumList = 23 + , AttrValNotName = 24 + , NoMultipleValues = 25 + , NotSameAsFixedValue = 26 + , RepElemInMixed = 27 + , FeatureUnsupported = 28 + , GroupContentRestricted = 29 + , UnknownBaseDatatype = 30 + , NoContentForRef = 31 + , DatatypeError = 32 + , ProhibitedAttributePresent = 33 + , IllegalXMLSpace = 34 + , WrongTargetNamespace = 35 + , SimpleTypeHasChild = 36 + , NoDatatypeValidatorForSimpleType = 37 + , GrammarNotFound = 38 + , DisplayErrorMessage = 39 + , NillNotAllowed = 40 + , NilAttrNotEmpty = 41 + , FixedDifferentFromActual = 42 + , NoDatatypeValidatorForAttribute = 43 + , GenericError = 44 + , ElementNotQualified = 45 + , ElementNotUnQualified = 46 + , VC_IllegalRefInStandalone = 47 + , NoDefAttForStandalone = 48 + , NoAttNormForStandalone = 49 + , NoWSForStandalone = 50 + , VC_EntityNotFound = 51 + , PartialMarkupInPE = 52 + , DatatypeValidationFailure = 53 + , UniqueParticleAttributionFail = 54 + , NoAbstractInXsiType = 55 + , NoDirectUseAbstractElement = 56 + , NoUseAbstractType = 57 + , BadXsiType = 58 + , NonDerivedXsiType = 59 + , ElemNoSubforBlock = 60 + , TypeNoSubforBlock = 61 + , AttributeNotQualified = 62 + , AttributeNotUnQualified = 63 + , IC_FieldMultipleMatch = 64 + , IC_UnknownField = 65 + , IC_AbsentKeyValue = 66 + , IC_KeyNotEnoughValues = 67 + , IC_KeyMatchesNillable = 68 + , IC_DuplicateUnique = 69 + , IC_DuplicateKey = 70 + , IC_KeyRefOutOfScope = 71 + , IC_KeyNotFound = 72 + , NonWSContent = 73 + , EmptyElemNotationAttr = 74 + , EmptyElemHasContent = 75 + , ElemOneNotationAttr = 76 + , AttrDupToken = 77 + , ElemChildrenHasInvalidWS = 78 + , E_HighBounds = 79 + , W_LowBounds = 80 + , W_HighBounds = 81 + , F_LowBounds = 82 + , F_HighBounds = 83 + }; + + static bool isFatal(const XMLValid::Codes toCheck) + { + return ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds)); + } + + static bool isWarning(const XMLValid::Codes toCheck) + { + return ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds)); + } + + static bool isError(const XMLValid::Codes toCheck) + { + return ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds)); + } + + static XMLErrorReporter::ErrTypes errorType(const XMLValid::Codes toCheck) + { + if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds)) + return XMLErrorReporter::ErrType_Warning; + else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds)) + return XMLErrorReporter::ErrType_Fatal; + else if ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds)) + return XMLErrorReporter::ErrType_Error; + return XMLErrorReporter::ErrTypes_Unknown; + } + static DOMError::ErrorSeverity DOMErrorType(const XMLValid::Codes toCheck) + { + if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds)) + return DOMError::DOM_SEVERITY_WARNING; + else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds)) + return DOMError::DOM_SEVERITY_FATAL_ERROR; + else return DOMError::DOM_SEVERITY_ERROR; + } + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLValid(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/framework/psvi/PSVIAttribute.cpp b/include/xercesc/framework/psvi/PSVIAttribute.cpp new file mode 100644 index 0000000..fefb404 --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIAttribute.cpp @@ -0,0 +1,71 @@ +/* + * 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: PSVIAttribute.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +PSVIAttribute::PSVIAttribute( MemoryManager* const manager ): + PSVIItem(manager) + , fAttributeDecl(0) + , fDV(0) +{ +} + +void PSVIAttribute::reset( + const XMLCh * const valContext + , PSVIItem::VALIDITY_STATE state + , PSVIItem::ASSESSMENT_TYPE assessmentType + , XSSimpleTypeDefinition * validatingType + , XSSimpleTypeDefinition * memberType + , const XMLCh * const defaultValue + , const bool isSpecified + , XSAttributeDeclaration * attrDecl + , DatatypeValidator *dv + ) +{ + fValidationContext = valContext; + fValidityState = state; + fAssessmentType = assessmentType; + fType = validatingType; + fMemberType = memberType; + fDefaultValue = defaultValue; + fIsSpecified = isSpecified; + fMemoryManager->deallocate((void *)fCanonicalValue); + fCanonicalValue = 0; + fNormalizedValue = 0; + fAttributeDecl = attrDecl; + fDV = dv; +} + +void PSVIAttribute::setValue(const XMLCh * const normalizedValue) +{ + if(normalizedValue) + { + fNormalizedValue = normalizedValue; + if(fDV && fValidityState == PSVIItem::VALIDITY_VALID) + fCanonicalValue = (XMLCh *)fDV->getCanonicalRepresentation(normalizedValue, fMemoryManager); + } +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/PSVIAttribute.hpp b/include/xercesc/framework/psvi/PSVIAttribute.hpp new file mode 100644 index 0000000..e11b014 --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIAttribute.hpp @@ -0,0 +1,179 @@ +/* + * 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: PSVIAttribute.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PSVIATTRIBUTE_HPP) +#define XERCESC_INCLUDE_GUARD_PSVIATTRIBUTE_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Represent the PSVI contributions for one attribute information item. + * This is *always* owned by the scanner/parser object from which + * it is obtained. The validator will specify + * under what conditions it may be relied upon to have meaningful contents. + */ + +// forward declarations +class XSAttributeDeclaration; + +class XMLPARSER_EXPORT PSVIAttribute : public PSVIItem +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param manager The configurable memory manager + */ + PSVIAttribute( MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@}; + + /** @name Destructor */ + //@{ + ~PSVIAttribute(); + //@} + + //--------------------- + /** @name PSVIAttribute methods */ + + //@{ + + /** + * An item isomorphic to the attribute declaration used to validate + * this attribute. + * + * @return an attribute declaration + */ + XSAttributeDeclaration *getAttributeDeclaration(); + + /** + * An item isomorphic to the type definition used to validate this element. + * + * @return a type declaration + */ + XSTypeDefinition *getTypeDefinition(); + + /** + * If and only if that type definition is a simple type definition + * with {variety} union, or a complex type definition whose {content type} + * is a simple thype definition with {variety} union, then an item isomorphic + * to that member of the union's {member type definitions} which actually + * validated the element item's normalized value. + * + * @return a simple type declaration + */ + XSSimpleTypeDefinition *getMemberTypeDefinition(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + /** + * reset this object. Intended to be called by + * the implementation. + */ + void reset( + const XMLCh * const valContext + , PSVIItem::VALIDITY_STATE state + , PSVIItem::ASSESSMENT_TYPE assessmentType + , XSSimpleTypeDefinition * validatingType + , XSSimpleTypeDefinition * memberType + , const XMLCh * const defaultValue + , const bool isSpecified + , XSAttributeDeclaration * attrDecl + , DatatypeValidator * dv + ); + + /** + * set the schema normalized value (and + * implicitly the canonical value) of this object; intended to be used + * by the implementation. + */ + void setValue(const XMLCh * const normalizedValue); + + /** + * set VALIDITY_STATE to specified value; intended to be + * called by implementation. + */ + void updateValidity(VALIDITY_STATE newValue); + + //@} + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + PSVIAttribute(const PSVIAttribute&); + PSVIAttribute & operator=(const PSVIAttribute &); + + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fAttributeDecl + // attribute declaration component that validated this attribute + // fDV + // implementation-specific datatype validator used to validate this attribute + XSAttributeDeclaration * fAttributeDecl; + DatatypeValidator * fDV; +}; +inline PSVIAttribute::~PSVIAttribute() +{ + fMemoryManager->deallocate((void *)fCanonicalValue); +} + +inline XSAttributeDeclaration *PSVIAttribute::getAttributeDeclaration() +{ + return fAttributeDecl; +} + +inline XSTypeDefinition* PSVIAttribute::getTypeDefinition() +{ + return fType; +} + +inline XSSimpleTypeDefinition* PSVIAttribute::getMemberTypeDefinition() +{ + return fMemberType; +} + +inline void PSVIAttribute::updateValidity(VALIDITY_STATE newValue) +{ + fValidityState = newValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/PSVIAttributeList.cpp b/include/xercesc/framework/psvi/PSVIAttributeList.cpp new file mode 100644 index 0000000..26f2ffa --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIAttributeList.cpp @@ -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: PSVIAttributeList.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +PSVIAttributeList::PSVIAttributeList( MemoryManager* const manager ): + fMemoryManager(manager) + , fAttrList(0) + , fAttrPos(0) +{ + fAttrList= new (fMemoryManager) RefVectorOf (10, true, fMemoryManager); +} + +/* + * Get the number of attributes whose PSVI contributions + * are contained in this list. + */ +XMLSize_t PSVIAttributeList::getLength() const +{ + return fAttrPos; +} + +/* + * Get the PSVI contribution of attribute at position i + * in this list. Indeces start from 0. + * @param index index from which the attribute PSVI contribution + * is to come. + * @return PSVIAttribute containing the attributes PSVI contributions; + * null is returned if the index is out of range. + */ +PSVIAttribute *PSVIAttributeList::getAttributePSVIAtIndex(const XMLSize_t index) +{ + if(index >= fAttrPos) + return 0; + return fAttrList->elementAt(index)->fPSVIAttribute; +} + +/* + * Get local part of attribute name at position index in the list. + * Indeces start from 0. + * @param index index from which the attribute name + * is to come. + * @return local part of the attribute's name; null is returned if the index + * is out of range. + */ +const XMLCh *PSVIAttributeList::getAttributeNameAtIndex(const XMLSize_t index) +{ + + if(index >= fAttrPos) + return 0; + return fAttrList->elementAt(index)->fAttributeName; +} + +/* + * Get namespace of attribute at position index in the list. + * Indeces start from 0. + * @param index index from which the attribute namespace + * is to come. + * @return namespace of the attribute; + * null is returned if the index is out of range. + */ +const XMLCh *PSVIAttributeList::getAttributeNamespaceAtIndex(const XMLSize_t index) +{ + if(index >= fAttrPos) + return 0; + return fAttrList->elementAt(index)->fAttributeNamespace; +} + +/* + * Get the PSVI contribution of attribute with given + * local name and namespace. + * @param attrName local part of the attribute's name + * @param attrNamespace namespace of the attribute + * @return null if the attribute PSVI does not exist + */ +PSVIAttribute *PSVIAttributeList::getAttributePSVIByName(const XMLCh *attrName + , const XMLCh * attrNamespace) +{ + for (XMLSize_t index=0; index < fAttrPos; index++) { + PSVIAttributeStorage* storage = fAttrList->elementAt(index); + if (XMLString::equals(attrName,storage->fAttributeName) && + XMLString::equals(attrNamespace,storage->fAttributeNamespace)) + return storage->fPSVIAttribute; + } + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/PSVIAttributeList.hpp b/include/xercesc/framework/psvi/PSVIAttributeList.hpp new file mode 100644 index 0000000..f5b892c --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIAttributeList.hpp @@ -0,0 +1,215 @@ +/* + * 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: PSVIAttributeList.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PSVIATTRIBUTE_LIST_HPP) +#define XERCESC_INCLUDE_GUARD_PSVIATTRIBUTE_LIST_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * A container for the PSVI contributions to attributes that occur + * on a particular element. + * This is always owned by the parser/validator from + * which it is obtained. The parser/validator will specify + * under what conditions it may be relied upon to have meaningful contents. + */ + +class XMLPARSER_EXPORT PSVIAttributeStorage : public XMemory +{ +public: + PSVIAttributeStorage() : + fPSVIAttribute(0) + , fAttributeName(0) + , fAttributeNamespace(0) + { + } + + ~PSVIAttributeStorage() + { + delete fPSVIAttribute; + } + + PSVIAttribute* fPSVIAttribute; + const XMLCh* fAttributeName; + const XMLCh* fAttributeNamespace; +}; + +class XMLPARSER_EXPORT PSVIAttributeList : public XMemory +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param manager The configurable memory manager + */ + PSVIAttributeList( MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@}; + + /** @name Destructor */ + //@{ + ~PSVIAttributeList(); + //@} + + //--------------------- + /** @name PSVIAttributeList methods */ + + //@{ + + /* + * Get the number of attributes whose PSVI contributions + * are contained in this list. + */ + XMLSize_t getLength() const; + + /* + * Get the PSVI contribution of attribute at position i + * in this list. Indices start from 0. + * @param index index from which the attribute PSVI contribution + * is to come. + * @return PSVIAttribute containing the attributes PSVI contributions; + * null is returned if the index is out of range. + */ + PSVIAttribute *getAttributePSVIAtIndex(const XMLSize_t index); + + /* + * Get local part of attribute name at position index in the list. + * Indices start from 0. + * @param index index from which the attribute name + * is to come. + * @return local part of the attribute's name; null is returned if the index + * is out of range. + */ + const XMLCh *getAttributeNameAtIndex(const XMLSize_t index); + + /* + * Get namespace of attribute at position index in the list. + * Indices start from 0. + * @param index index from which the attribute namespace + * is to come. + * @return namespace of the attribute; + * null is returned if the index is out of range. + */ + const XMLCh *getAttributeNamespaceAtIndex(const XMLSize_t index); + + /* + * Get the PSVI contribution of attribute with given + * local name and namespace. + * @param attrName local part of the attribute's name + * @param attrNamespace namespace of the attribute + * @return null if the attribute PSVI does not exist + */ + PSVIAttribute *getAttributePSVIByName(const XMLCh *attrName + , const XMLCh * attrNamespace); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + /** + * returns a PSVI attribute of undetermined state and given name/namespace and + * makes that object part of the internal list. Intended to be called + * during validation of an element. + * @param attrName name of this attribute + * @param attrNS URI of the attribute + * @return new, uninitialized, PSVIAttribute object + */ + PSVIAttribute *getPSVIAttributeToFill( + const XMLCh * attrName + , const XMLCh * attrNS); + + /** + * reset the list + */ + void reset(); + + //@} + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + PSVIAttributeList(const PSVIAttributeList&); + PSVIAttributeList & operator=(const PSVIAttributeList &); + + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fMemoryManager + // handler to provide dynamically-need memory + // fAttrList + // list of PSVIAttributes contained by this object + // fAttrPos + // current number of initialized PSVIAttributes in fAttrList + MemoryManager* fMemoryManager; + RefVectorOf* fAttrList; + XMLSize_t fAttrPos; +}; + +inline PSVIAttributeList::~PSVIAttributeList() +{ + delete fAttrList; +} + +inline PSVIAttribute *PSVIAttributeList::getPSVIAttributeToFill( + const XMLCh *attrName + , const XMLCh * attrNS) +{ + PSVIAttributeStorage* storage = 0; + if(fAttrPos == fAttrList->size()) + { + storage = new (fMemoryManager) PSVIAttributeStorage(); + storage->fPSVIAttribute = new (fMemoryManager) PSVIAttribute(fMemoryManager); + fAttrList->addElement(storage); + } + else + { + storage = fAttrList->elementAt(fAttrPos); + } + storage->fAttributeName = attrName; + storage->fAttributeNamespace = attrNS; + fAttrPos++; + return storage->fPSVIAttribute; +} + +inline void PSVIAttributeList::reset() +{ + fAttrPos = 0; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/PSVIElement.cpp b/include/xercesc/framework/psvi/PSVIElement.cpp new file mode 100644 index 0000000..adc8edf --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIElement.cpp @@ -0,0 +1,93 @@ +/* + * 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: PSVIElement.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +PSVIElement::PSVIElement(MemoryManager* const manager): + PSVIItem(manager), + fElementDecl(0), + fNotationDecl(0), + fSchemaInfo(0) +{ +} + +PSVIElement::~PSVIElement() +{ + fMemoryManager->deallocate(fCanonicalValue); +} + +XSTypeDefinition* PSVIElement::getTypeDefinition() +{ + return fType; +} + + /** + * If and only if that type definition is a simple type definition + * with {variety} union, or a complex type definition whose {content type} + * is a simple type definition with {variety} union, + + * then an item isomorphic + * to that member of the union's {member type definitions} which actually + * validated the element item's normalized value. + * + * @return a simple type declaration + */ +XSSimpleTypeDefinition* PSVIElement::getMemberTypeDefinition() +{ + return fMemberType; +} + +void PSVIElement::reset( const VALIDITY_STATE validityState + , const ASSESSMENT_TYPE assessmentType + , const XMLCh* const validationContext + , bool isSpecified + , XSElementDeclaration* const elemDecl + , XSTypeDefinition* const typeDef + , XSSimpleTypeDefinition* const memberType + , XSModel* const schemaInfo + , const XMLCh* const defaultValue + , const XMLCh* const normalizedValue + , XMLCh* const canonicalValue + , XSNotationDeclaration* const notationDecl) +{ + fValidationContext = validationContext; + fValidityState = validityState; + fAssessmentType = assessmentType; + fIsSpecified = isSpecified; + fType = typeDef; + fMemberType = memberType; + fElementDecl = elemDecl; + fNotationDecl = notationDecl; + fSchemaInfo = schemaInfo; + fDefaultValue = defaultValue; + fNormalizedValue = normalizedValue; + fMemoryManager->deallocate(fCanonicalValue); + fCanonicalValue = canonicalValue; +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/PSVIElement.hpp b/include/xercesc/framework/psvi/PSVIElement.hpp new file mode 100644 index 0000000..58735c5 --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIElement.hpp @@ -0,0 +1,174 @@ +/* + * 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: PSVIElement.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PSVIELEMENT_HPP) +#define XERCESC_INCLUDE_GUARD_PSVIELEMENT_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Represent the PSVI contributions for one element information item. + * This is *always* owned by the scanner/parser object from which + * it is obtained. The validator will specify + * under what conditions it may be relied upon to have meaningful contents. + */ + +// forward declarations +class XSElementDeclaration; +class XSNotationDeclaration; +class XSModel; + +class XMLPARSER_EXPORT PSVIElement : public PSVIItem +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param manager The configurable memory manager + */ + PSVIElement( MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@}; + + /** @name Destructor */ + //@{ + ~PSVIElement(); + //@} + + //--------------------- + /** @name PSVIElement methods */ + + //@{ + + /** + * An item isomorphic to the element declaration used to validate + * this element. + * + * @return an element declaration + */ + XSElementDeclaration *getElementDeclaration(); + + /** + * [notation] + * @see XML Schema Part 1: Structures [notation] + * @return The notation declaration. + */ + XSNotationDeclaration *getNotationDeclaration(); + + /** + * [schema information] + * @see XML Schema Part 1: Structures [schema information] + * @return The schema information property if it's the validation root, + * null otherwise. + */ + XSModel *getSchemaInformation(); + + /** + * An item isomorphic to the type definition used to validate this element. + * + * @return a type declaration + */ + XSTypeDefinition *getTypeDefinition(); + + /** + * If and only if that type definition is a simple type definition + * with {variety} union, or a complex type definition whose {content type} + * is a simple type definition with {variety} union, then an item isomorphic + * to that member of the union's {member type definitions} which actually + * validated the element item's normalized value. + * + * @return a simple type declaration + */ + XSSimpleTypeDefinition *getMemberTypeDefinition(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + void reset + ( + const VALIDITY_STATE validityState + , const ASSESSMENT_TYPE assessmentType + , const XMLCh* const validationContext + , bool isSpecified + , XSElementDeclaration* const elemDecl + , XSTypeDefinition* const typeDef + , XSSimpleTypeDefinition* const memberType + , XSModel* const schemaInfo + , const XMLCh* const defaultValue + , const XMLCh* const normalizedValue = 0 + , XMLCh* const canonicalValue = 0 + , XSNotationDeclaration* const notationDecl = 0 + ); + + //@} + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + PSVIElement(const PSVIElement&); + PSVIElement & operator=(const PSVIElement &); + + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fElementDecl + // element declaration component that validated this element + // fNotationDecl + // (optional) notation decl associated with this element + // fSchemaInfo + // Schema Information Item with which this validation episode is associated + XSElementDeclaration *fElementDecl; + XSNotationDeclaration *fNotationDecl; + XSModel *fSchemaInfo; +}; + +inline XSElementDeclaration *PSVIElement::getElementDeclaration() +{ + return fElementDecl; +} + +inline XSNotationDeclaration* PSVIElement::getNotationDeclaration() +{ + return fNotationDecl; +} + +inline XSModel* PSVIElement::getSchemaInformation() +{ + return fSchemaInfo; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/PSVIHandler.hpp b/include/xercesc/framework/psvi/PSVIHandler.hpp new file mode 100644 index 0000000..7a85216 --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIHandler.hpp @@ -0,0 +1,148 @@ +/* + * 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: PSVIHandler.hpp 676796 2008-07-15 05:04:13Z dbertoni $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PSVIHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_PSVIHANDLER_HPP + + +XERCES_CPP_NAMESPACE_BEGIN + + +class PSVIElement; +class PSVIAttributeList; + + +/** + * This abstract class provides the interface for the scanner to return + * PSVI information to the application. + * + */ +class XMLPARSER_EXPORT PSVIHandler +{ +public: + // ----------------------------------------------------------------------- + // Constructors are hidden, just the virtual destructor is exposed + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + virtual ~PSVIHandler() + { + } + //@} + + /** @name The PSVI handler interface */ + //@{ + /** Receive notification of the PSVI properties of an element. + * The scanner will issue this call after the XMLDocumentHandler + * endElement call. Since the scanner will issue the psviAttributes + * call immediately after reading the start tag of an element, all element + * content will be effectively bracketed by these two calls. + * @param localName The name of the element whose end tag was just + * parsed. + * @param uri The namespace to which the element is bound + * @param elementInfo Object containing the element's PSVI properties + */ + virtual void handleElementPSVI + ( + const XMLCh* const localName + , const XMLCh* const uri + , PSVIElement * elementInfo + ) = 0; + + /** + * Receive notification of partial PSVI properties of an element. + * This callback is made right after the psviAttributes + * call for non-empty element. + * + * The PSVIElement passed in has all fields properly set and it + * can be safely accessed the same way as the one passed in handleElementPSVI. + * However, fields listed below always have default values. + * + * getValidity() PSVIItem::VALIDITY_NOTKNOWN + * getValidationAttemped() PSVIItem::VALIDATION_NONE + * getMemberTypeDefinition() 0 + * getSchemaNormalizedValue() 0 + * getCanonicalRepresentation() 0 + * getNotationDeclaration() 0 + * + * + * @param localName The name of the element upon which start tag + * these attributes were encountered. + * @param uri The namespace to which the element is bound + * @param elementInfo Object containing the element's partial PSVI properties + */ + virtual void handlePartialElementPSVI + ( + const XMLCh* const localName + , const XMLCh* const uri + , PSVIElement * elementInfo + ); + + /** + * Enables PSVI information about attributes to be passed back to the + * application. This callback will be made on *all* + * elements; on elements with no attributes, the final parameter will + * be null. + * @param localName The name of the element upon which start tag + * these attributes were encountered. + * @param uri The namespace to which the element is bound + * @param psviAttributes Object containing the attributes' PSVI properties + * with information to identify them. + */ + virtual void handleAttributesPSVI + ( + const XMLCh* const localName + , const XMLCh* const uri + , PSVIAttributeList * psviAttributes + ) = 0; + + + //@} + + + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + PSVIHandler() + { + } + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + PSVIHandler(const PSVIHandler&); + PSVIHandler& operator=(const PSVIHandler&); +}; + +inline void PSVIHandler::handlePartialElementPSVI(const XMLCh* const /*localName*/ + , const XMLCh* const /*uri*/ + , PSVIElement * /*elementInfo*/ + ) +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/PSVIItem.cpp b/include/xercesc/framework/psvi/PSVIItem.cpp new file mode 100644 index 0000000..ef4faa9 --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIItem.cpp @@ -0,0 +1,145 @@ +/* + * 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: PSVIItem.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +PSVIItem::PSVIItem( MemoryManager* const manager ): + fMemoryManager(manager), + fValidationContext(0), + fNormalizedValue(0), + fDefaultValue(0), + fCanonicalValue(0), + fValidityState(VALIDITY_NOTKNOWN), + fAssessmentType(VALIDATION_FULL), + fIsSpecified(false), + fType(0), + fMemberType(0) +{ +} + +void PSVIItem::reset( + const XMLCh* const validationContext + , const XMLCh* const normalizedValue + , const VALIDITY_STATE validityState + , const ASSESSMENT_TYPE assessmentType + ) +{ + // this is just a wrapper method; fValidationContext will + // be valid as long as and no longer than the thing to which + // validationContext points + fValidationContext = validationContext; + fNormalizedValue = normalizedValue; + fValidityState = validityState; + fAssessmentType = assessmentType; +} + +void PSVIItem::setValidationAttempted(PSVIItem::ASSESSMENT_TYPE attemptType) +{ + fAssessmentType = attemptType; +} + +void PSVIItem::setValidity(PSVIItem::VALIDITY_STATE validity) +{ + fValidityState = validity; +} + +XSValue* PSVIItem::getActualValue() const +{ + /*** + * assessment + * VALIDATION_PARTIAL + * VALIDATION_FULL + * validity + * VALIDITY_VALID + ***/ + if ((fAssessmentType==VALIDATION_NONE) || (fValidityState!=VALIDITY_VALID)) + return 0; + + /*** + * XSSimpleType or + * XSComplexType's CONTENTTYPE_SIMPLE + * allowed + ***/ + if ((!fType) || + ((fType->getTypeCategory() == XSTypeDefinition::COMPLEX_TYPE) && + (((XSComplexTypeDefinition*)fType)->getContentType() != XSComplexTypeDefinition::CONTENTTYPE_SIMPLE))) + return 0; + + /*** + * Resolve dv + * + * 1. If fMemberType is not null, use the fMemberType->fDataTypeValidator + * 2. If fType is XSSimpleType, use fType->fDataTypeValidator + * 3. If fType is XSComplexType, use fType->fXSSimpleTypeDefinition-> fDataTypeValidator + * + ***/ + + DatatypeValidator *dv = 0; + + if (fMemberType) + { + /*** + * Now that fType is either XSSimpleTypeDefinition or + * XSComlextTypeDefinition with CONTENTTYPE_SIMPLE, the + * fMemberType must be XSSimpleTypeDefinition if present + ***/ + dv=((XSSimpleTypeDefinition*) fMemberType)->getDatatypeValidator(); + } + else if (fType->getTypeCategory() == XSTypeDefinition::SIMPLE_TYPE) + { + dv=((XSSimpleTypeDefinition*) fType)->getDatatypeValidator(); + } + else + { + XSSimpleTypeDefinition* simType = ((XSComplexTypeDefinition*)fType)->getSimpleType(); + if (simType) + dv = simType->getDatatypeValidator(); + } + + if (!dv) return 0; + + /*** + * Get the ultimate base dv in the datatype registry + ***/ + DatatypeValidator *basedv = DatatypeValidatorFactory::getBuiltInBaseValidator(dv); + + if (!basedv) return 0; + + XSValue::Status status=XSValue::st_Init; + + return XSValue::getActualValue(fNormalizedValue + , XSValue::getDataType(basedv->getTypeLocalName()) + , status + , XSValue::ver_10 + , false + , fMemoryManager); + + +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/PSVIItem.hpp b/include/xercesc/framework/psvi/PSVIItem.hpp new file mode 100644 index 0000000..784ceaa --- /dev/null +++ b/include/xercesc/framework/psvi/PSVIItem.hpp @@ -0,0 +1,309 @@ +/* + * 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: PSVIItem.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PSVIITEM_HPP) +#define XERCESC_INCLUDE_GUARD_PSVIITEM_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Represent the PSVI contributions for one element or one attribute information item. + * This is *always* owned by the validator /parser object from which + * it is obtained. It is designed to be subclassed; subclasses will + * specify under what conditions it may be relied upon to have meaningful contents. + */ + +// forward declarations +class XSTypeDefinition; +class XSSimpleTypeDefinition; +class XSValue; + +class XMLPARSER_EXPORT PSVIItem : public XMemory +{ +public: + + enum VALIDITY_STATE { + /** Validity value indicating that validation has either not + been performed or that a strict assessment of validity could + not be performed + */ + VALIDITY_NOTKNOWN = 0, + + /** Validity value indicating that validation has been strictly + assessed and the element in question is invalid according to the + rules of schema validation. + */ + VALIDITY_INVALID = 1, + + /** Validity value indicating that validation has been strictly + assessed and the element in question is valid according to the rules + of schema validation. + */ + VALIDITY_VALID = 2 + }; + + enum ASSESSMENT_TYPE { + /** Validation status indicating that schema validation has been + performed and the element in question has specifically been skipped. + */ + VALIDATION_NONE = 0, + + /** Validation status indicating that schema validation has been + performed on the element in question under the rules of lax validation. + */ + VALIDATION_PARTIAL = 1, + + /** Validation status indicating that full schema validation has been + performed on the element. */ + VALIDATION_FULL = 2 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param manager The configurable memory manager + */ + PSVIItem(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@}; + + /** @name Destructor */ + //@{ + virtual ~PSVIItem(); + //@} + + //--------------------- + /** @name PSVIItem methods */ + + //@{ + + /** + * [validation context] + * + * @return A string identifying the nearest ancestor element + * information item with a [schema information] property + * (or this element item itself if it has such a property) + * (form to be determined) + * @see XML Schema Part 1: Structures [validation context] + */ + const XMLCh *getValidationContext(); + + /** + * Determine the validity of the node with respect + * to the validation being attempted + * + * @return return the [validity] property. Possible values are: + * VALIDITY_UNKNOWN, VALIDITY_INVALID, VALIDITY_VALID + */ + VALIDITY_STATE getValidity() const; + + /** + * Determines the extent to which the item has been validated + * + * @return return the [validation attempted] property. The possible values are + * VALIDATION_NONE, VALIDATION_ORDERED_PARTIAL and VALIDATION_FULL + */ + ASSESSMENT_TYPE getValidationAttempted() const; + + /** + * A list of error codes generated from validation attempts. + * Need to find all the possible sub-clause reports that need reporting + * + * @return list of error codes + */ + /*** + const XMLCh ** getErrorCodes(); + ****/ + + /** + * [schema normalized value] + * + * @see XML Schema Part 1: Structures [schema normalized value] + * @return the normalized value of this item after validation + */ + const XMLCh *getSchemaNormalizedValue(); + + /** + * An item isomorphic to the type definition used to validate this element. + * + * @return a type declaration + */ + virtual XSTypeDefinition *getTypeDefinition() = 0; + + /** + * If and only if that type definition is a simple type definition + * with {variety} union, or a complex type definition whose {content type} + * is a simple thype definition with {variety} union, then an item isomorphic + * to that member of the union's {member type definitions} which actually + * validated the element item's normalized value. + * + * @return a simple type declaration + */ + virtual XSSimpleTypeDefinition *getMemberTypeDefinition() = 0; + + /** + * [schema default] + * + * @return The canonical lexical representation of the declaration's {value constraint} value. + * @see XML Schema Part 1: Structures [schema default] + */ + const XMLCh *getSchemaDefault(); + + /** + * [schema specified] + * @see XML Schema Part 1: Structures [schema specified] + * @return true - value was specified in schema, false - value comes from the infoset + */ + bool getIsSchemaSpecified() const; + + /** + * Return the canonical representation of this value. + * Note that, formally, this is not a PSVI property. + * @return string representing the canonical representation, if this item + * was validated by a simple type definition for which canonical + * representations of values are defined. + */ + const XMLCh *getCanonicalRepresentation() const; + + //@} + + /** + * + * Get actual value in the form of XSValue, + * caller needs to delete the object returned. + * + * @return an XSValue + */ + virtual XSValue *getActualValue() const; + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + void setValidationAttempted(PSVIItem::ASSESSMENT_TYPE attemptType); + void setValidity(PSVIItem::VALIDITY_STATE validity); + + /** reset the object + * @param validationContext corresponds to schema validation context property + * @param normalizedValue corresponds to schema normalized value property + * @param validityState state of item's validity + * @param assessmentType type of assessment carried out on item + */ + void reset( + const XMLCh* const validationContext + , const XMLCh* const normalizedValue + , const VALIDITY_STATE validityState + , const ASSESSMENT_TYPE assessmentType + ); + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + PSVIItem(const PSVIItem&); + PSVIItem & operator=(const PSVIItem &); + + +protected: + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fMemoryManager: + // used for any memory allocations + // fValidationContext + // corresponds to the schema [validation context] property + // fNormalizedValue + // The schema normalized value (when present) + // fDefaultValue + // default value specified in the schema, if any + // fCanonicalValue + // canonicalized version of normalizedValue + // fValidityState + // Whether this item is valid or not + // fAssessmentType + // The kind of assessment that produced the given validity outcome + // fIsSpecified + // Whether this item exists because a default was specified in the schema + // fType + // type responsible for validating this item + // fMemberType + // If fType is a union type, the member type that validated this item + MemoryManager* const fMemoryManager; + const XMLCh* fValidationContext; + const XMLCh* fNormalizedValue; + const XMLCh* fDefaultValue; + XMLCh* fCanonicalValue; + VALIDITY_STATE fValidityState; + ASSESSMENT_TYPE fAssessmentType; + bool fIsSpecified; + XSTypeDefinition * fType; + XSSimpleTypeDefinition* fMemberType; +}; + +inline PSVIItem::~PSVIItem() {} + +inline const XMLCh *PSVIItem::getValidationContext() +{ + return fValidationContext; +} + +inline const XMLCh* PSVIItem::getSchemaNormalizedValue() +{ + return fNormalizedValue; +} + +inline const XMLCh* PSVIItem::getSchemaDefault() +{ + return fDefaultValue; +} + +inline const XMLCh* PSVIItem::getCanonicalRepresentation() const +{ + return fCanonicalValue; +} + +inline PSVIItem::VALIDITY_STATE PSVIItem::getValidity() const +{ + return fValidityState; +} + +inline bool PSVIItem::getIsSchemaSpecified() const +{ + return fIsSpecified; +} + +inline PSVIItem::ASSESSMENT_TYPE PSVIItem::getValidationAttempted() const +{ + return fAssessmentType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSAnnotation.cpp b/include/xercesc/framework/psvi/XSAnnotation.cpp new file mode 100644 index 0000000..6367d4e --- /dev/null +++ b/include/xercesc/framework/psvi/XSAnnotation.cpp @@ -0,0 +1,190 @@ +/* + * 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: XSAnnotation.cpp 679296 2008-07-24 08:13:42Z borisk $ + */ + +#include +#include + +#include + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +XSAnnotation::XSAnnotation(const XMLCh* const content, + MemoryManager * const manager) +:XSObject(XSConstants::ANNOTATION, 0, manager) +,fContents(XMLString::replicate(content, manager)) +,fNext(0) +,fSystemId(0) +,fLine(0) +,fCol(0) +{ +} + +XSAnnotation::XSAnnotation(MemoryManager * const manager) +:XSObject(XSConstants::ANNOTATION, 0, manager) +,fContents(0) +,fNext(0) +,fSystemId(0) +,fLine(0) +,fCol(0) +{ +} + +XSAnnotation::~XSAnnotation() +{ + fMemoryManager->deallocate(fContents); + + if (fNext) + delete fNext; + + fMemoryManager->deallocate(fSystemId); +} + +// XSAnnotation methods +void XSAnnotation::writeAnnotation(DOMNode* node, ANNOTATION_TARGET targetType) +{ + XercesDOMParser *parser = new (fMemoryManager) XercesDOMParser(0, fMemoryManager); + parser->setDoNamespaces(true); + parser->setValidationScheme(XercesDOMParser::Val_Never); + + DOMDocument* futureOwner = (targetType == W3C_DOM_ELEMENT) ? + ((DOMElement*)node)->getOwnerDocument() : + (DOMDocument*)node; + + MemBufInputSource* memBufIS = new (fMemoryManager) MemBufInputSource + ( + (const XMLByte*)fContents + , XMLString::stringLen(fContents)*sizeof(XMLCh) + , "" + , false + , fMemoryManager + ); + memBufIS->setEncoding(XMLUni::fgXMLChEncodingString); + memBufIS->setCopyBufToStream(false); + + try + { + parser->parse(*memBufIS); + } + catch (const XMLException&) + { + // REVISIT: should we really eat this? + } + + DOMNode* newElem = futureOwner->importNode((parser->getDocument())->getDocumentElement(), true); + node->insertBefore(newElem, node->getFirstChild()); + + delete parser; + delete memBufIS; +} + + +void XSAnnotation::writeAnnotation(ContentHandler* handler) +{ + SAX2XMLReader* parser = XMLReaderFactory::createXMLReader(fMemoryManager); + parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); + parser->setFeature(XMLUni::fgSAX2CoreValidation, false); + parser->setContentHandler(handler); + + MemBufInputSource* memBufIS = new (fMemoryManager) MemBufInputSource + ( + (const XMLByte*)fContents + , XMLString::stringLen(fContents)*sizeof(XMLCh) + , "" + , false + , fMemoryManager + ); + memBufIS->setEncoding(XMLUni::fgXMLChEncodingString); + memBufIS->setCopyBufToStream(false); + + try + { + parser->parse(*memBufIS); + } + catch (const XMLException&) + { + } + + delete parser; + delete memBufIS; +} + + +void XSAnnotation::setNext(XSAnnotation* const nextAnnotation) +{ + if (fNext) + fNext->setNext(nextAnnotation); + else + fNext = nextAnnotation; +} + +XSAnnotation* XSAnnotation::getNext() +{ + return fNext; +} + +void XSAnnotation::setSystemId(const XMLCh* const systemId) +{ + if (fSystemId) + { + fMemoryManager->deallocate(fSystemId); + fSystemId = 0; + } + + if (systemId) + fSystemId = XMLString::replicate(systemId, fMemoryManager); + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XSAnnotation) + +void XSAnnotation::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng.writeString(fContents); + serEng<>fNext; + serEng.readString(fSystemId); + + serEng.readUInt64 (fLine); + serEng.readUInt64 (fCol); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSAnnotation.hpp b/include/xercesc/framework/psvi/XSAnnotation.hpp new file mode 100644 index 0000000..0e34401 --- /dev/null +++ b/include/xercesc/framework/psvi/XSAnnotation.hpp @@ -0,0 +1,195 @@ +/* + * 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: XSAnnotation.hpp 672273 2008-06-27 13:57:00Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSANNOTATION_HPP) +#define XERCESC_INCLUDE_GUARD_XSANNOTATION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Annotation + * component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class DOMNode; +class ContentHandler; + +class XMLPARSER_EXPORT XSAnnotation : public XSerializable, public XSObject +{ +public: + + // TargetType + enum ANNOTATION_TARGET { + /** + * The object type is org.w3c.dom.Element. + */ + W3C_DOM_ELEMENT = 1, + /** + * The object type is org.w3c.dom.Document. + */ + W3C_DOM_DOCUMENT = 2 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param contents The string that is to be the content of this XSAnnotation + * @param manager The configurable memory manager + */ + XSAnnotation + ( + const XMLCh* const contents + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSAnnotation(); + //@} + + //--------------------- + /** @name XSAnnotation methods */ + + //@{ + + /** + * Write contents of the annotation to the specified DOM object. In-scope + * namespace declarations for annotation element are added as + * attribute nodes of the serialized annotation. + * @param node A target pointer to the annotation target object, i.e. + * either DOMDocument or DOMElement cast as + * DOMNode. + * @param targetType A target type. + */ + + void writeAnnotation(DOMNode* node, ANNOTATION_TARGET targetType); + + /** + * Write contents of the annotation to the specified object. + * The corresponding events for all in-scope namespace declarations are + * sent via the specified document handler. + * @param handler A target pointer to the annotation target object, i.e. + * ContentHandler. + */ + void writeAnnotation(ContentHandler* handler); + + /** + * A text representation of annotation. + */ + const XMLCh *getAnnotationString() const; + XMLCh *getAnnotationString(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + //@{ + void setNext(XSAnnotation* const nextAnnotation); + XSAnnotation* getNext(); + //@} + + //----------------------------- + /** Getter */ + //@{ + inline void getLineCol(XMLFileLoc& line, XMLFileLoc& col) const; + inline const XMLCh* getSystemId() const; + //@} + + //----------------------------- + /** Setter */ + //@{ + inline void setLineCol(XMLFileLoc line, XMLFileLoc col); + void setSystemId(const XMLCh* const systemId); + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XSAnnotation) + XSAnnotation(MemoryManager* const manager); + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSAnnotation(const XSAnnotation&); + XSAnnotation & operator=(const XSAnnotation &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + XMLCh* fContents; + XSAnnotation* fNext; + +private: + + XMLCh* fSystemId; + XMLFileLoc fLine; + XMLFileLoc fCol; + +}; + +inline const XMLCh *XSAnnotation::getAnnotationString() const +{ + return fContents; +} + +inline XMLCh *XSAnnotation::getAnnotationString() +{ + return fContents; +} + +inline void XSAnnotation::getLineCol(XMLFileLoc& line, XMLFileLoc& col) const +{ + line = fLine; + col = fCol; +} + +inline const XMLCh* XSAnnotation::getSystemId() const +{ + return fSystemId; +} + +inline void XSAnnotation::setLineCol(XMLFileLoc line, XMLFileLoc col) +{ + fLine = line; + fCol = col; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSAttributeDeclaration.cpp b/include/xercesc/framework/psvi/XSAttributeDeclaration.cpp new file mode 100644 index 0000000..e521d67 --- /dev/null +++ b/include/xercesc/framework/psvi/XSAttributeDeclaration.cpp @@ -0,0 +1,112 @@ +/* + * 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: XSAttributeDeclaration.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSAttributeDeclaration: Constructors and Destructor +// --------------------------------------------------------------------------- +XSAttributeDeclaration::XSAttributeDeclaration(SchemaAttDef* const attDef, + XSSimpleTypeDefinition* const typeDef, + XSAnnotation* const annot, + XSModel* const xsModel, + XSConstants::SCOPE scope, + XSComplexTypeDefinition* enclosingCTDefinition, + MemoryManager * const manager) + : XSObject(XSConstants::ATTRIBUTE_DECLARATION, xsModel, manager) + , fAttDef(attDef) + , fTypeDefinition(typeDef) + , fAnnotation(annot) + , fScope(scope) + , fEnclosingCTDefinition(enclosingCTDefinition) +{ +} + +XSAttributeDeclaration::~XSAttributeDeclaration() +{ + // don't delete fTypeDefinition - deleted by XSModel +} + +// --------------------------------------------------------------------------- +// XSAttributeDeclaration: XSObject virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSAttributeDeclaration::getName() const +{ + return fAttDef->getAttName()->getLocalPart(); +} + +const XMLCh *XSAttributeDeclaration::getNamespace() +{ + return fXSModel->getURIStringPool()->getValueForId(fAttDef->getAttName()->getURI()); +} + +XSNamespaceItem *XSAttributeDeclaration::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + +// --------------------------------------------------------------------------- +// XSAttributeDeclaration: access methods +// --------------------------------------------------------------------------- + +XSConstants::VALUE_CONSTRAINT XSAttributeDeclaration::getConstraintType() const +{ + if (fScope != XSConstants::SCOPE_GLOBAL) + return XSConstants::VALUE_CONSTRAINT_NONE; + + if (fAttDef->getDefaultType() == XMLAttDef::Default) + return XSConstants::VALUE_CONSTRAINT_DEFAULT; + + if ((fAttDef->getDefaultType() == XMLAttDef::Fixed) || + (fAttDef->getDefaultType() == XMLAttDef::Required_And_Fixed)) + return XSConstants::VALUE_CONSTRAINT_FIXED; + + return XSConstants::VALUE_CONSTRAINT_NONE; +} + +const XMLCh *XSAttributeDeclaration::getConstraintValue() +{ + if (fScope == XSConstants::SCOPE_GLOBAL) + return fAttDef->getValue(); + + return 0; +} + +bool XSAttributeDeclaration::getRequired() const +{ + if (fAttDef->getDefaultType() == XMLAttDef::Required || + fAttDef->getDefaultType() == XMLAttDef::Required_And_Fixed) + return true; + + return false; +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSAttributeDeclaration.hpp b/include/xercesc/framework/psvi/XSAttributeDeclaration.hpp new file mode 100644 index 0000000..54085c2 --- /dev/null +++ b/include/xercesc/framework/psvi/XSAttributeDeclaration.hpp @@ -0,0 +1,210 @@ +/* + * 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: XSAttributeDeclaration.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSATTRIBUTEDECLARATION_HPP) +#define XERCESC_INCLUDE_GUARD_XSATTRIBUTEDECLARATION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Attribute + * Declaration component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class XSComplexTypeDefinition; +class XSSimpleTypeDefinition; +class SchemaAttDef; + +class XMLPARSER_EXPORT XSAttributeDeclaration : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param attDef + * @param typeDef + * @param annot + * @param xsModel + * @param scope + * @param enclosingCTDefinition + * @param manager The configurable memory manager + */ + XSAttributeDeclaration + ( + SchemaAttDef* const attDef + , XSSimpleTypeDefinition* const typeDef + , XSAnnotation* const annot + , XSModel* const xsModel + , XSConstants::SCOPE scope + , XSComplexTypeDefinition* enclosingCTDefinition + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSAttributeDeclaration(); + //@} + + //--------------------- + /** @name overridden XSObject methods */ + + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem* getNamespaceItem(); + + //@} + + /** @name XSAttributeDeclaration methods **/ + + //@{ + + /** + * [type definition]: A simple type definition + */ + XSSimpleTypeDefinition *getTypeDefinition() const; + + /** + * Optional. One of SCOPE_GLOBAL, SCOPE_LOCAL, + * or SCOPE_ABSENT. If the scope is local, then the + * enclosingCTDefinition is present. + */ + XSConstants::SCOPE getScope() const; + + /** + * The complex type definition for locally scoped declarations (see + * scope). + */ + XSComplexTypeDefinition *getEnclosingCTDefinition(); + + /** + * Value constraint: one of VC_NONE, VC_DEFAULT, VC_FIXED. + */ + XSConstants::VALUE_CONSTRAINT getConstraintType() const; + + /** + * Value constraint: The actual value with respect to the [type definition + * ]. + */ + const XMLCh *getConstraintValue(); + + /** + * Optional. Annotation. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + bool getRequired() const; + //@} + +private: + + void setEnclosingCTDefinition(XSComplexTypeDefinition* const toSet); + friend class XSObjectFactory; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSAttributeDeclaration(const XSAttributeDeclaration&); + XSAttributeDeclaration & operator=(const XSAttributeDeclaration &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + SchemaAttDef* fAttDef; + XSSimpleTypeDefinition* fTypeDefinition; + XSAnnotation* fAnnotation; + XSConstants::SCOPE fScope; + XSComplexTypeDefinition* fEnclosingCTDefinition; +}; + +// --------------------------------------------------------------------------- +// XSAttributeDeclaration: inline methods +// --------------------------------------------------------------------------- +inline XSSimpleTypeDefinition* XSAttributeDeclaration::getTypeDefinition() const +{ + return fTypeDefinition; +} + +inline XSAnnotation *XSAttributeDeclaration::getAnnotation() const +{ + return fAnnotation; +} + +inline XSConstants::SCOPE XSAttributeDeclaration::getScope() const +{ + return fScope; +} + +inline XSComplexTypeDefinition *XSAttributeDeclaration::getEnclosingCTDefinition() +{ + return fEnclosingCTDefinition; +} + +inline void XSAttributeDeclaration::setEnclosingCTDefinition +( + XSComplexTypeDefinition* const toSet +) +{ + fEnclosingCTDefinition = toSet; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSAttributeGroupDefinition.cpp b/include/xercesc/framework/psvi/XSAttributeGroupDefinition.cpp new file mode 100644 index 0000000..6df57af --- /dev/null +++ b/include/xercesc/framework/psvi/XSAttributeGroupDefinition.cpp @@ -0,0 +1,76 @@ +/* + * 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: XSAttributeGroupDefinition.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSAttributeGroupDefinition: Constructors and Destructor +// --------------------------------------------------------------------------- +XSAttributeGroupDefinition::XSAttributeGroupDefinition +( + XercesAttGroupInfo* const xercesAttGroupInfo + , XSAttributeUseList* const xsAttList + , XSWildcard* const xsWildcard + , XSAnnotation* const xsAnnot + , XSModel* const xsModel + , MemoryManager * const manager +) + : XSObject(XSConstants::ATTRIBUTE_GROUP_DEFINITION, xsModel, manager) + , fXercesAttGroupInfo(xercesAttGroupInfo) + , fXSAttributeUseList(xsAttList) + , fXSWildcard(xsWildcard) + , fAnnotation(xsAnnot) +{ +} + +XSAttributeGroupDefinition::~XSAttributeGroupDefinition() +{ + if (fXSAttributeUseList) + delete fXSAttributeUseList; + + // don't delete fXSWildcard - deleted by XSModel +} + +// XSObject methods +const XMLCh *XSAttributeGroupDefinition::getName() const +{ + return fXSModel->getURIStringPool()->getValueForId(fXercesAttGroupInfo->getNameId()); +} + +const XMLCh *XSAttributeGroupDefinition::getNamespace() +{ + return fXSModel->getURIStringPool()->getValueForId(fXercesAttGroupInfo->getNamespaceId()); +} + +XSNamespaceItem *XSAttributeGroupDefinition::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSAttributeGroupDefinition.hpp b/include/xercesc/framework/psvi/XSAttributeGroupDefinition.hpp new file mode 100644 index 0000000..8dfacdb --- /dev/null +++ b/include/xercesc/framework/psvi/XSAttributeGroupDefinition.hpp @@ -0,0 +1,167 @@ +/* + * 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: XSAttributeGroupDefinition.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSATTRIBUTEGROUPDEFINITION_HPP) +#define XERCESC_INCLUDE_GUARD_XSATTRIBUTEGROUPDEFINITION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Attribute + * Group Definition component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class XSAttributeUse; +class XSWildcard; +class XercesAttGroupInfo; + +class XMLPARSER_EXPORT XSAttributeGroupDefinition : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param xercesAttGroupInfo + * @param xsAttList + * @param xsWildcard + * @param xsAnnot + * @param xsModel + * @param manager The configurable memory manager + */ + XSAttributeGroupDefinition + ( + XercesAttGroupInfo* const xercesAttGroupInfo + , XSAttributeUseList* const xsAttList + , XSWildcard* const xsWildcard + , XSAnnotation* const xsAnnot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSAttributeGroupDefinition(); + //@} + + //--------------------- + /** @name overridden XSObject methods */ + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem* getNamespaceItem(); + + //@} + + //--------------------- + /** @name XSAttributeGroupDefinition methods */ + + //@{ + + /** + * A set of [attribute uses]. + */ + XSAttributeUseList *getAttributeUses(); + + /** + * Optional. A [wildcard]. + */ + XSWildcard *getAttributeWildcard() const; + + /** + * Optional. An [annotation]. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSAttributeGroupDefinition(const XSAttributeGroupDefinition&); + XSAttributeGroupDefinition & operator=(const XSAttributeGroupDefinition &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + XercesAttGroupInfo* fXercesAttGroupInfo; + XSAttributeUseList* fXSAttributeUseList; + XSWildcard* fXSWildcard; + XSAnnotation* fAnnotation; +}; + +inline XSAttributeUseList* XSAttributeGroupDefinition::getAttributeUses() +{ + return fXSAttributeUseList; +} + +inline XSWildcard* XSAttributeGroupDefinition::getAttributeWildcard() const +{ + return fXSWildcard; +} + +inline XSAnnotation* XSAttributeGroupDefinition::getAnnotation() const +{ + return fAnnotation; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSAttributeUse.cpp b/include/xercesc/framework/psvi/XSAttributeUse.cpp new file mode 100644 index 0000000..a6ff9fc --- /dev/null +++ b/include/xercesc/framework/psvi/XSAttributeUse.cpp @@ -0,0 +1,61 @@ +/* + * 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: XSAttributeUse.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSAttributeUse: Constructors and Destructor +// --------------------------------------------------------------------------- +XSAttributeUse::XSAttributeUse(XSAttributeDeclaration* const xsAttDecl, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::ATTRIBUTE_USE, xsModel, manager) + , fRequired(false) + , fConstraintType(XSConstants::VALUE_CONSTRAINT_NONE) + , fConstraintValue(0) + , fXSAttributeDeclaration(xsAttDecl) +{ +} + + +XSAttributeUse::~XSAttributeUse() +{ + // don't delete fXSAttributeDeclaration - deleted by XSModel +} + + +// --------------------------------------------------------------------------- +// XSAttributeUse: helper methods +// --------------------------------------------------------------------------- +void XSAttributeUse::set(const bool isRequired, + XSConstants::VALUE_CONSTRAINT constraintType, + const XMLCh* const constraintValue) +{ + fRequired = isRequired; + fConstraintType = constraintType; + fConstraintValue = constraintValue; +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSAttributeUse.hpp b/include/xercesc/framework/psvi/XSAttributeUse.hpp new file mode 100644 index 0000000..5696098 --- /dev/null +++ b/include/xercesc/framework/psvi/XSAttributeUse.hpp @@ -0,0 +1,156 @@ +/* + * 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: XSAttributeUse.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSATTRIBUTEUSE_HPP) +#define XERCESC_INCLUDE_GUARD_XSATTRIBUTEUSE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Attribute + * Use component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAttributeDeclaration; + +class XMLPARSER_EXPORT XSAttributeUse : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * @param xsAttDecl + * @param xsModel + * @param manager The configurable memory manager + */ + XSAttributeUse + ( + XSAttributeDeclaration* const xsAttDecl, + XSModel* const xsModel, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSAttributeUse(); + //@} + + //--------------------- + /** @name XSAttributeUse methods */ + + //@{ + + /** + * [required]: determines whether this use of an attribute declaration + * requires an appropriate attribute information item to be present, or + * merely allows it. + */ + bool getRequired() const; + + /** + * [attribute declaration]: provides the attribute declaration itself, + * which will in turn determine the simple type definition used. + */ + XSAttributeDeclaration *getAttrDeclaration() const; + + /** + * Value Constraint: one of default, fixed. + */ + XSConstants::VALUE_CONSTRAINT getConstraintType() const; + + /** + * Value Constraint: The actual value. + */ + const XMLCh *getConstraintValue(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} + +private: + + // set data + void set + ( + const bool isRequired + , XSConstants::VALUE_CONSTRAINT constraintType + , const XMLCh* const constraintValue + ); + + friend class XSObjectFactory; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSAttributeUse(const XSAttributeUse&); + XSAttributeUse & operator=(const XSAttributeUse &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + bool fRequired; + XSConstants::VALUE_CONSTRAINT fConstraintType; + const XMLCh* fConstraintValue; + XSAttributeDeclaration* fXSAttributeDeclaration; +}; + +inline XSAttributeDeclaration *XSAttributeUse::getAttrDeclaration() const +{ + return fXSAttributeDeclaration; +} + +inline bool XSAttributeUse::getRequired() const +{ + return fRequired; +} + +inline XSConstants::VALUE_CONSTRAINT XSAttributeUse::getConstraintType() const +{ + return fConstraintType; +} + +inline const XMLCh *XSAttributeUse::getConstraintValue() +{ + return fConstraintValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSComplexTypeDefinition.cpp b/include/xercesc/framework/psvi/XSComplexTypeDefinition.cpp new file mode 100644 index 0000000..de6a0ae --- /dev/null +++ b/include/xercesc/framework/psvi/XSComplexTypeDefinition.cpp @@ -0,0 +1,207 @@ +/* + * 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: XSComplexTypeDefinition.cpp 594002 2007-11-12 01:05:09Z cargilld $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSComplexTypeDefinition: Constructors and Destructor +// --------------------------------------------------------------------------- +XSComplexTypeDefinition::XSComplexTypeDefinition +( + ComplexTypeInfo* const complexTypeInfo + , XSWildcard* const xsWildcard + , XSSimpleTypeDefinition* const xsSimpleType + , XSAttributeUseList* const xsAttList + , XSTypeDefinition* const xsBaseType + , XSParticle* const xsParticle + , XSAnnotation* const headAnnot + , XSModel* const xsModel + , MemoryManager* const manager +) + : XSTypeDefinition(COMPLEX_TYPE, xsBaseType, xsModel, manager) + , fComplexTypeInfo(complexTypeInfo) + , fXSWildcard(xsWildcard) + , fXSAttributeUseList(xsAttList) + , fXSSimpleTypeDefinition(xsSimpleType) + , fXSAnnotationList(0) + , fParticle(xsParticle) + , fProhibitedSubstitution(0) +{ + int blockset = fComplexTypeInfo->getBlockSet(); + if (blockset) + { + if (blockset & SchemaSymbols::XSD_EXTENSION) + fProhibitedSubstitution |= XSConstants::DERIVATION_EXTENSION; + + if (blockset & SchemaSymbols::XSD_RESTRICTION) + fProhibitedSubstitution |= XSConstants::DERIVATION_RESTRICTION; + } + + int finalSet = fComplexTypeInfo->getFinalSet(); + if (finalSet) + { + if (finalSet & SchemaSymbols::XSD_EXTENSION) + fFinal |= XSConstants::DERIVATION_EXTENSION; + + if (finalSet & SchemaSymbols::XSD_RESTRICTION) + fFinal |= XSConstants::DERIVATION_RESTRICTION; + } + + if (headAnnot) + { + fXSAnnotationList = new (manager) RefVectorOf(1, false, manager); + XSAnnotation* annot = headAnnot; + + do + { + fXSAnnotationList->addElement(annot); + annot = annot->getNext(); + } while (annot); + } +} + +XSComplexTypeDefinition::~XSComplexTypeDefinition() +{ + // don't delete fXSWildcard - deleted by XSModel + // don't delete fXSSimpleTypeDefinition - deleted by XSModel + if (fXSAttributeUseList) + delete fXSAttributeUseList; + + if (fXSAnnotationList) + delete fXSAnnotationList; + + if (fParticle) + delete fParticle; +} + +// --------------------------------------------------------------------------- +// XSComplexTypeDefinition: access methods +// --------------------------------------------------------------------------- +XSConstants::DERIVATION_TYPE XSComplexTypeDefinition::getDerivationMethod() const +{ + if(fComplexTypeInfo->getDerivedBy() == SchemaSymbols::XSD_EXTENSION) + return XSConstants::DERIVATION_EXTENSION; + return XSConstants::DERIVATION_RESTRICTION; +} + +bool XSComplexTypeDefinition::getAbstract() const +{ + return fComplexTypeInfo->getAbstract(); +} + + +XSComplexTypeDefinition::CONTENT_TYPE XSComplexTypeDefinition::getContentType() const +{ + switch(fComplexTypeInfo->getContentType()) { + case SchemaElementDecl::Simple: + return CONTENTTYPE_SIMPLE; + case SchemaElementDecl::Empty: + case SchemaElementDecl::ElementOnlyEmpty: + return CONTENTTYPE_EMPTY; + case SchemaElementDecl::Children: + return CONTENTTYPE_ELEMENT; + default: + //case SchemaElementDecl::Mixed_Complex: + //case SchemaElementDecl::Mixed_Simple: + //case SchemaElementDecl::Any: + return CONTENTTYPE_MIXED; + } +} + +bool XSComplexTypeDefinition::isProhibitedSubstitution(XSConstants::DERIVATION_TYPE toTest) +{ + if (fProhibitedSubstitution & toTest) + return true; + + return false; +} + +XSAnnotationList *XSComplexTypeDefinition::getAnnotations() +{ + return fXSAnnotationList; +} + +// --------------------------------------------------------------------------- +// XSComplexTypeDefinition: virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSComplexTypeDefinition::getName() const +{ + return fComplexTypeInfo->getTypeLocalName(); +} + +const XMLCh *XSComplexTypeDefinition::getNamespace() +{ + return fComplexTypeInfo->getTypeUri(); +} + +XSNamespaceItem *XSComplexTypeDefinition::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + +bool XSComplexTypeDefinition::getAnonymous() const +{ + return fComplexTypeInfo->getAnonymous(); +} + +XSTypeDefinition *XSComplexTypeDefinition::getBaseType() +{ + return fBaseType; +} + +bool XSComplexTypeDefinition::derivedFromType(const XSTypeDefinition * const ancestorType) +{ + if (!ancestorType) + return false; + + XSTypeDefinition* type = (XSTypeDefinition*) ancestorType; + + if (ancestorType == type->getBaseType()) + { + // ancestor is anytype + return true; + } + + type = this; + XSTypeDefinition* lastType = 0; // anytype has a basetype of anytype so will have infinite loop... + + while (type && (type != ancestorType) && (type != lastType)) + { + lastType = type; + type = type->getBaseType(); + } + + return (type == ancestorType); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSComplexTypeDefinition.hpp b/include/xercesc/framework/psvi/XSComplexTypeDefinition.hpp new file mode 100644 index 0000000..2b0a688 --- /dev/null +++ b/include/xercesc/framework/psvi/XSComplexTypeDefinition.hpp @@ -0,0 +1,294 @@ +/* + * 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: XSComplexTypeDefinition.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSCOMPLEXTYPEDEFINITION_HPP) +#define XERCESC_INCLUDE_GUARD_XSCOMPLEXTYPEDEFINITION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class represents a complexType definition + * schema component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + * + */ + +// forward declarations +class XSAnnotation; +class XSAttributeUse; +class XSSimpleTypeDefinition; +class XSParticle; +class XSWildcard; +class ComplexTypeInfo; + +class XMLPARSER_EXPORT XSComplexTypeDefinition : public XSTypeDefinition +{ +public: + + // Content Model Types + enum CONTENT_TYPE { + /** + * Represents an empty content type. A content type with the distinguished + * value empty validates elements with no character or element + * information item children. + */ + CONTENTTYPE_EMPTY = 0, + /** + * Represents a simple content type. A content type which is a simple + * validates elements with character-only children. + */ + CONTENTTYPE_SIMPLE = 1, + /** + * Represents an element-only content type. An element-only content type + * validates elements with children that conform to the supplied content + * model. + */ + CONTENTTYPE_ELEMENT = 2, + /** + * Represents a mixed content type. + */ + CONTENTTYPE_MIXED = 3 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param complexTypeInfo + * @param xsWildcard + * @param xsSimpleType + * @param xsAttList + * @param xsBaseType + * @param xsParticle + * @param headAnnot + * @param xsModel + * @param manager The configurable memory manager + */ + XSComplexTypeDefinition + ( + ComplexTypeInfo* const complexTypeInfo + , XSWildcard* const xsWildcard + , XSSimpleTypeDefinition* const xsSimpleType + , XSAttributeUseList* const xsAttList + , XSTypeDefinition* const xsBaseType + , XSParticle* const xsParticle + , XSAnnotation* const headAnnot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSComplexTypeDefinition(); + //@} + + //--------------------- + /** @name XSComplexTypeDefinition methods */ + + //@{ + + /** + * [derivation method]: either DERIVATION_EXTENSION, + * DERIVATION_RESTRICTION, or DERIVATION_NONE + * (see XSObject). + */ + XSConstants::DERIVATION_TYPE getDerivationMethod() const; + + /** + * [abstract]: a boolean. Complex types for which abstract is + * true must not be used as the type definition for the validation of + * element information items. + */ + bool getAbstract() const; + + /** + * A set of attribute uses. + */ + XSAttributeUseList *getAttributeUses(); + + /** + * Optional.An attribute wildcard. + */ + XSWildcard *getAttributeWildcard() const; + + /** + * [content type]: one of empty (CONTENTTYPE_EMPTY), a simple + * type definition (CONTENTTYPE_SIMPLE), mixed ( + * CONTENTTYPE_MIXED), or element-only ( + * CONTENTTYPE_ELEMENT). + */ + CONTENT_TYPE getContentType() const; + + /** + * A simple type definition corresponding to simple content model, + * otherwise null + */ + XSSimpleTypeDefinition *getSimpleType() const; + + /** + * A particle for mixed or element-only content model, otherwise + * null + */ + XSParticle *getParticle() const; + + /** + * [prohibited substitutions]: a subset of {extension, restriction} + * @param toTest Extension or restriction constants (see + * XSObject). + * @return True if toTest is a prohibited substitution, otherwise + * false. + */ + bool isProhibitedSubstitution(XSConstants::DERIVATION_TYPE toTest); + + /** + * [prohibited substitutions]: A subset of {extension, restriction} or + * DERIVATION_NONE represented as a bit flag (see + * XSObject). + */ + short getProhibitedSubstitutions() const; + + /** + * A set of [annotations]. + */ + XSAnnotationList *getAnnotations(); + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem *getNamespaceItem(); + + /** + * A boolean that specifies if the type definition is + * anonymous. Convenience attribute. + */ + bool getAnonymous() const; + + /** + * {base type definition}: either a simple type definition or a complex + * type definition. + */ + XSTypeDefinition *getBaseType(); + + /** + * Convenience method: check if this type is derived from the given + * ancestorType. + * @param ancestorType An ancestor type definition. + * @return Return true if this type is derived from + * ancestorType. + */ + bool derivedFromType(const XSTypeDefinition* const ancestorType); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + + //@} + +private: + + /** + * Set the base type + */ + void setBaseType(XSTypeDefinition* const xsBaseType); + friend class XSObjectFactory; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSComplexTypeDefinition(const XSComplexTypeDefinition&); + XSComplexTypeDefinition & operator=(const XSComplexTypeDefinition &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + ComplexTypeInfo* fComplexTypeInfo; + XSWildcard* fXSWildcard; + XSAttributeUseList* fXSAttributeUseList; + XSSimpleTypeDefinition* fXSSimpleTypeDefinition; + XSAnnotationList* fXSAnnotationList; + XSParticle* fParticle; + short fProhibitedSubstitution; +}; + + +inline XSAttributeUseList* XSComplexTypeDefinition::getAttributeUses() +{ + return fXSAttributeUseList; +} + +inline XSWildcard* XSComplexTypeDefinition::getAttributeWildcard() const +{ + return fXSWildcard; +} + +inline XSSimpleTypeDefinition* XSComplexTypeDefinition::getSimpleType() const +{ + return fXSSimpleTypeDefinition; +} + +inline short XSComplexTypeDefinition::getProhibitedSubstitutions() const +{ + return fProhibitedSubstitution; +} + +inline XSParticle *XSComplexTypeDefinition::getParticle() const +{ + return fParticle; +} + +inline void +XSComplexTypeDefinition::setBaseType(XSTypeDefinition* const xsBaseType) +{ + fBaseType = xsBaseType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSConstants.hpp b/include/xercesc/framework/psvi/XSConstants.hpp new file mode 100644 index 0000000..2ae20bc --- /dev/null +++ b/include/xercesc/framework/psvi/XSConstants.hpp @@ -0,0 +1,196 @@ +/* + * 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: XSConstants.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSCONSTANTS_HPP) +#define XERCESC_INCLUDE_GUARD_XSCONSTANTS_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This contains constants needed in the schema component model. + */ + +// forward definitions for typedefs +class XSAnnotation; +class XSAttributeUse; +class XSFacet; +class XSMultiValueFacet; +class XSNamespaceItem; +class XSParticle; +class XSSimpleTypeDefinition; + +// these typedefs are intended to help hide dependence on utility +// classes, as well as to define more intuitive names for commonly +// used concepts. + +typedef RefVectorOf XSAnnotationList; +typedef RefVectorOf XSAttributeUseList; +typedef RefVectorOf XSFacetList; +typedef RefVectorOf XSMultiValueFacetList; +typedef RefVectorOf XSNamespaceItemList; +typedef RefVectorOf XSParticleList; +typedef RefVectorOf XSSimpleTypeDefinitionList; +typedef RefArrayVectorOf StringList; + +class XMLPARSER_EXPORT XSConstants +{ +public: + + // XML Schema Components + enum COMPONENT_TYPE { + /** + * The object describes an attribute declaration. + */ + ATTRIBUTE_DECLARATION = 1, + /** + * The object describes an element declaration. + */ + ELEMENT_DECLARATION = 2, + /** + * The object describes a complex type or simple type definition. + */ + TYPE_DEFINITION = 3, + /** + * The object describes an attribute use definition. + */ + ATTRIBUTE_USE = 4, + /** + * The object describes an attribute group definition. + */ + ATTRIBUTE_GROUP_DEFINITION= 5, + /** + * The object describes a model group definition. + */ + MODEL_GROUP_DEFINITION = 6, + /** + * A model group. + */ + MODEL_GROUP = 7, + /** + * The object describes a particle. + */ + PARTICLE = 8, + /** + * The object describes a wildcard. + */ + WILDCARD = 9, + /** + * The object describes an identity constraint definition. + */ + IDENTITY_CONSTRAINT = 10, + /** + * The object describes a notation declaration. + */ + NOTATION_DECLARATION = 11, + /** + * The object describes an annotation. + */ + ANNOTATION = 12, + /** + * The object describes a constraining facet. + */ + FACET = 13, + + /** + * The object describes enumeration/pattern facets. + */ + MULTIVALUE_FACET = 14 + }; + + // Derivation constants + enum DERIVATION_TYPE { + /** + * No constraint is available. + */ + DERIVATION_NONE = 0, + /** + * XSTypeDefinition final set or + * XSElementDeclaration disallowed substitution group. + */ + DERIVATION_EXTENSION = 1, + /** + * XSTypeDefinition final set or + * XSElementDeclaration disallowed substitution group. + */ + DERIVATION_RESTRICTION = 2, + /** + * XSTypeDefinition final set. + */ + DERIVATION_SUBSTITUTION = 4, + /** + * XSTypeDefinition final set. + */ + DERIVATION_UNION = 8, + /** + * XSTypeDefinition final set. + */ + DERIVATION_LIST = 16 + }; + + // Scope + enum SCOPE { + /** + * The scope of a declaration within named model groups or attribute + * groups is absent. The scope of such declaration is + * determined when it is used in the construction of complex type + * definitions. + */ + SCOPE_ABSENT = 0, + /** + * A scope of global identifies top-level declarations. + */ + SCOPE_GLOBAL = 1, + /** + * Locally scoped declarations are available for use only + * within the complex type. + */ + SCOPE_LOCAL = 2 + }; + + // Value Constraint + enum VALUE_CONSTRAINT { + /** + * Indicates that the component does not have any value constraint. + */ + VALUE_CONSTRAINT_NONE = 0, + /** + * Indicates that there is a default value constraint. + */ + VALUE_CONSTRAINT_DEFAULT = 1, + /** + * Indicates that there is a fixed value constraint for this attribute. + */ + VALUE_CONSTRAINT_FIXED = 2 + }; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSConstants(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSElementDeclaration.cpp b/include/xercesc/framework/psvi/XSElementDeclaration.cpp new file mode 100644 index 0000000..bb9859a --- /dev/null +++ b/include/xercesc/framework/psvi/XSElementDeclaration.cpp @@ -0,0 +1,163 @@ +/* + * 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: XSElementDeclaration.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSElementDeclaration: Constructors and Destructor +// --------------------------------------------------------------------------- +XSElementDeclaration::XSElementDeclaration +( + SchemaElementDecl* const schemaElementDecl + , XSTypeDefinition* const typeDefinition + , XSElementDeclaration* const substitutionGroupAffiliation + , XSAnnotation* const annot + , XSNamedMap* const identityConstraints + , XSModel* const xsModel + , XSConstants::SCOPE elemScope + , XSComplexTypeDefinition* const enclosingTypeDefinition + , MemoryManager* const manager +) + : XSObject(XSConstants::ELEMENT_DECLARATION, xsModel, manager) + , fDisallowedSubstitutions(0) + , fSubstitutionGroupExclusions(0) + , fScope(elemScope) + , fSchemaElementDecl(schemaElementDecl) + , fTypeDefinition(typeDefinition) + , fEnclosingTypeDefinition(enclosingTypeDefinition) + , fSubstitutionGroupAffiliation(substitutionGroupAffiliation) + , fAnnotation(annot) + , fIdentityConstraints(identityConstraints) +{ + // set block and final information + // NOTE: rest of setup will be taken care of in construct() + int blockFinalSet = fSchemaElementDecl->getBlockSet(); + if (blockFinalSet) + { + if (blockFinalSet & SchemaSymbols::XSD_EXTENSION) + fDisallowedSubstitutions |= XSConstants::DERIVATION_EXTENSION; + + if (blockFinalSet & SchemaSymbols::XSD_RESTRICTION) + fDisallowedSubstitutions |= XSConstants::DERIVATION_RESTRICTION; + + if (blockFinalSet & SchemaSymbols::XSD_SUBSTITUTION) + fDisallowedSubstitutions |= XSConstants::DERIVATION_SUBSTITUTION; + } + + if (0 != (blockFinalSet = fSchemaElementDecl->getFinalSet())) + { + if (blockFinalSet & SchemaSymbols::XSD_EXTENSION) + fSubstitutionGroupExclusions |= XSConstants::DERIVATION_EXTENSION; + + if (blockFinalSet & SchemaSymbols::XSD_RESTRICTION) + fSubstitutionGroupExclusions |= XSConstants::DERIVATION_RESTRICTION; + } +} + +XSElementDeclaration::~XSElementDeclaration() +{ + // don't delete fTypeDefinition - deleted by XSModel + // don't delete fSubstitutionGroupAffiliation - deleted by XSModel + if (fIdentityConstraints) + delete fIdentityConstraints; +} + +// --------------------------------------------------------------------------- +// XSElementDeclaration: XSObject virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSElementDeclaration::getName() const +{ + return fSchemaElementDecl->getElementName()->getLocalPart(); +} + +const XMLCh *XSElementDeclaration::getNamespace() +{ + return fXSModel->getURIStringPool()->getValueForId(fSchemaElementDecl->getURI()); +} + +XSNamespaceItem *XSElementDeclaration::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + + +// --------------------------------------------------------------------------- +// XSElementDeclaration: access methods +// --------------------------------------------------------------------------- +XSConstants::VALUE_CONSTRAINT XSElementDeclaration::getConstraintType() const +{ + if (fSchemaElementDecl->getMiscFlags() & SchemaSymbols::XSD_FIXED) + return XSConstants::VALUE_CONSTRAINT_FIXED; + + if (fSchemaElementDecl->getDefaultValue()) + return XSConstants::VALUE_CONSTRAINT_DEFAULT; + + return XSConstants::VALUE_CONSTRAINT_NONE; +} + +const XMLCh *XSElementDeclaration::getConstraintValue() +{ + return fSchemaElementDecl->getDefaultValue(); +} + +bool XSElementDeclaration::getNillable() const +{ + if (fSchemaElementDecl->getMiscFlags() & SchemaSymbols::XSD_NILLABLE) + return true; + + return false; +} + +bool XSElementDeclaration::isSubstitutionGroupExclusion(XSConstants::DERIVATION_TYPE exclusion) +{ + if (fSubstitutionGroupExclusions & exclusion) + return true; + + return false; +} + + +bool XSElementDeclaration::isDisallowedSubstitution(XSConstants::DERIVATION_TYPE disallowed) +{ + if (fDisallowedSubstitutions & disallowed) + return true; + + return false; +} + + +bool XSElementDeclaration::getAbstract() const +{ + if (fSchemaElementDecl->getMiscFlags() & SchemaSymbols::XSD_ABSTRACT) + return true; + + return false; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSElementDeclaration.hpp b/include/xercesc/framework/psvi/XSElementDeclaration.hpp new file mode 100644 index 0000000..472219d --- /dev/null +++ b/include/xercesc/framework/psvi/XSElementDeclaration.hpp @@ -0,0 +1,307 @@ +/* + * 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: XSElementDeclaration.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSELEMENTDECLARATION_HPP) +#define XERCESC_INCLUDE_GUARD_XSELEMENTDECLARATION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Element Declaration + * component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class XSComplexTypeDefinition; +class XSIDCDefinition; +class XSTypeDefinition; +class SchemaElementDecl; + +class XMLPARSER_EXPORT XSElementDeclaration : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param schemaElementDecl + * @param typeDefinition + * @param substitutionGroupAffiliation + * @param annot + * @param identityConstraints + * @param xsModel + * @param elemScope + * @param enclosingTypeDefinition + * @param manager The configurable memory manager + */ + XSElementDeclaration + ( + SchemaElementDecl* const schemaElementDecl + , XSTypeDefinition* const typeDefinition + , XSElementDeclaration* const substitutionGroupAffiliation + , XSAnnotation* const annot + , XSNamedMap* const identityConstraints + , XSModel* const xsModel + , XSConstants::SCOPE elemScope = XSConstants::SCOPE_ABSENT + , XSComplexTypeDefinition* const enclosingTypeDefinition = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSElementDeclaration(); + //@} + + //--------------------- + /** @name overridden XSXSObject methods */ + + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem *getNamespaceItem(); + + //@} + + //--------------------- + /** @name XSElementDeclaration methods */ + + //@{ + + /** + * [type definition]: either a simple type definition or a complex type + * definition. + */ + XSTypeDefinition *getTypeDefinition() const; + + /** + * Optional. One of SCOPE_GLOBAL, SCOPE_LOCAL, + * or SCOPE_ABSENT. If the scope is local, then the + * enclosingCTDefinition is present. + */ + XSConstants::SCOPE getScope() const; + + /** + * The complex type definition for locally scoped declarations (see + * scope). + */ + XSComplexTypeDefinition *getEnclosingCTDefinition() const; + + /** + * [Value constraint]: one of VC_NONE, VC_DEFAULT, VC_FIXED. + */ + XSConstants::VALUE_CONSTRAINT getConstraintType() const; + + /** + * [Value constraint]: the actual value with respect to the [type + * definition]. + */ + const XMLCh *getConstraintValue(); + + /** + * If nillable is true, then an element may also be valid if it carries + * the namespace qualified attribute with local name nil + * from namespace http://www.w3.org/2001/XMLSchema-instance + * and value true (xsi:nil) even if it has no text or + * element content despite a content type which would + * otherwise require content. + */ + bool getNillable() const; + + /** + * identity-constraint definitions: a set of constraint definitions. + */ + XSNamedMap *getIdentityConstraints(); + + /** + * [substitution group affiliation]: optional. A top-level element + * definition. + */ + XSElementDeclaration *getSubstitutionGroupAffiliation() const; + + /** + * Convenience method. Check if exclusion is a substitution + * group exclusion for this element declaration. + * @param exclusion + * DERIVATION_EXTENSION, DERIVATION_RESTRICTION or + * DERIVATION_NONE. Represents final set for the element. + * @return True if exclusion is a part of the substitution + * group exclusion subset. + */ + bool isSubstitutionGroupExclusion(XSConstants::DERIVATION_TYPE exclusion); + + /** + * [substitution group exclusions]: the returned value is a bit + * combination of the subset of { + * DERIVATION_EXTENSION, DERIVATION_RESTRICTION} or + * DERIVATION_NONE. + */ + short getSubstitutionGroupExclusions() const; + + /** + * Convenience method. Check if disallowed is a disallowed + * substitution for this element declaration. + * @param disallowed { + * DERIVATION_SUBSTITUTION, DERIVATION_EXTENSION, DERIVATION_RESTRICTION + * } or DERIVATION_NONE. Represents a block set for the + * element. + * @return True if disallowed is a part of the substitution + * group exclusion subset. + */ + bool isDisallowedSubstitution(XSConstants::DERIVATION_TYPE disallowed); + + /** + * [disallowed substitutions]: the returned value is a bit combination of + * the subset of { + * DERIVATION_SUBSTITUTION, DERIVATION_EXTENSION, DERIVATION_RESTRICTION + * } corresponding to substitutions disallowed by this + * XSElementDeclaration or DERIVATION_NONE. + */ + short getDisallowedSubstitutions() const; + + /** + * {abstract} A boolean. + */ + bool getAbstract() const; + + /** + * Optional. Annotation. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + void setTypeDefinition(XSTypeDefinition* typeDefinition); + + //@} +private: + + void setEnclosingCTDefinition(XSComplexTypeDefinition* const toSet); + friend class XSObjectFactory; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSElementDeclaration(const XSElementDeclaration&); + XSElementDeclaration & operator=(const XSElementDeclaration &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + short fDisallowedSubstitutions; + short fSubstitutionGroupExclusions; + XSConstants::SCOPE fScope; + SchemaElementDecl* fSchemaElementDecl; + XSTypeDefinition* fTypeDefinition; + XSComplexTypeDefinition* fEnclosingTypeDefinition; + XSElementDeclaration* fSubstitutionGroupAffiliation; + XSAnnotation* fAnnotation; + XSNamedMap* fIdentityConstraints; +}; + +inline XSTypeDefinition* XSElementDeclaration::getTypeDefinition() const +{ + return fTypeDefinition; +} + +inline XSNamedMap* XSElementDeclaration::getIdentityConstraints() +{ + return fIdentityConstraints; +} + +inline XSElementDeclaration* XSElementDeclaration::getSubstitutionGroupAffiliation() const +{ + return fSubstitutionGroupAffiliation; +} + +inline short XSElementDeclaration::getSubstitutionGroupExclusions() const +{ + return fSubstitutionGroupExclusions; +} + +inline short XSElementDeclaration::getDisallowedSubstitutions() const +{ + return fDisallowedSubstitutions; +} + +inline XSAnnotation *XSElementDeclaration::getAnnotation() const +{ + return fAnnotation; +} + +inline XSConstants::SCOPE XSElementDeclaration::getScope() const +{ + return fScope; +} + +inline XSComplexTypeDefinition *XSElementDeclaration::getEnclosingCTDefinition() const +{ + return fEnclosingTypeDefinition; +} + +inline void XSElementDeclaration::setTypeDefinition(XSTypeDefinition* typeDefinition) +{ + fTypeDefinition = typeDefinition; +} + +inline void XSElementDeclaration::setEnclosingCTDefinition(XSComplexTypeDefinition* const toSet) +{ + fEnclosingTypeDefinition = toSet; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSFacet.cpp b/include/xercesc/framework/psvi/XSFacet.cpp new file mode 100644 index 0000000..f46962f --- /dev/null +++ b/include/xercesc/framework/psvi/XSFacet.cpp @@ -0,0 +1,49 @@ +/* + * 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: XSFacet.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSFacet: Constructors and Destructor +// --------------------------------------------------------------------------- +XSFacet::XSFacet(XSSimpleTypeDefinition::FACET facetKind, + const XMLCh* const lexicalValue, + bool isFixed, + XSAnnotation* const annot, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::FACET, xsModel, manager) + , fFacetKind(facetKind) + , fIsFixed(isFixed) + , fLexicalValue(lexicalValue) + , fAnnotation(annot) +{ +} + +XSFacet::~XSFacet() +{ +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSFacet.hpp b/include/xercesc/framework/psvi/XSFacet.hpp new file mode 100644 index 0000000..3765fb8 --- /dev/null +++ b/include/xercesc/framework/psvi/XSFacet.hpp @@ -0,0 +1,151 @@ +/* + * 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: XSFacet.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSFACET_HPP) +#define XERCESC_INCLUDE_GUARD_XSFACET_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This represents all Schema Facet components with the exception + * of Enumeration and Pattern Facets, which are represented by the + * XSMultiValueFacet interface. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; + +class XMLPARSER_EXPORT XSFacet : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param facetKind + * @param lexicalValue + * @param isFixed + * @param annot + * @param xsModel + * @param manager The configurable memory manager + */ + XSFacet + ( + XSSimpleTypeDefinition::FACET facetKind + , const XMLCh* const lexicalValue + , bool isFixed + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSFacet(); + //@} + + //--------------------- + /** @name XSFacet methods */ + + //@{ + + /** + * @return An indication as to the facet's type; see XSSimpleTypeDefinition::FACET + */ + XSSimpleTypeDefinition::FACET getFacetKind() const; + + /** + * @return Returns a value of a constraining facet. + */ + const XMLCh *getLexicalFacetValue() const; + + /** + * Check whether a facet value is fixed. + */ + bool isFixed() const; + + /** + * @return an annotation + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSFacet(const XSFacet&); + XSFacet & operator=(const XSFacet &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + XSSimpleTypeDefinition::FACET fFacetKind; + bool fIsFixed; + const XMLCh* fLexicalValue; + XSAnnotation* fAnnotation; +}; + +inline XSSimpleTypeDefinition::FACET XSFacet::getFacetKind() const +{ + return fFacetKind; +} + +inline const XMLCh* XSFacet::getLexicalFacetValue() const +{ + return fLexicalValue; +} + +inline bool XSFacet::isFixed() const +{ + return fIsFixed; +} + +inline XSAnnotation* XSFacet::getAnnotation() const +{ + return fAnnotation; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSIDCDefinition.cpp b/include/xercesc/framework/psvi/XSIDCDefinition.cpp new file mode 100644 index 0000000..ac2e5d4 --- /dev/null +++ b/include/xercesc/framework/psvi/XSIDCDefinition.cpp @@ -0,0 +1,122 @@ +/* + * 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: XSIDCDefinition.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSIDCDefinition: Constructors and Destructor +// --------------------------------------------------------------------------- +XSIDCDefinition::XSIDCDefinition(IdentityConstraint* const identityConstraint, + XSIDCDefinition* const keyIC, + XSAnnotation* const headAnnot, + StringList* const stringList, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::IDENTITY_CONSTRAINT, xsModel, manager) + , fIdentityConstraint(identityConstraint) + , fKey(keyIC) + , fStringList(stringList) + , fXSAnnotationList(0) +{ + if (headAnnot) + { + fXSAnnotationList = new (manager) RefVectorOf(1, false, manager); + + XSAnnotation* annot = headAnnot; + do + { + fXSAnnotationList->addElement(annot); + annot = annot->getNext(); + } while (annot); + } + +} + +XSIDCDefinition::~XSIDCDefinition() +{ + if (fStringList) + delete fStringList; + + // don't delete fKey - deleted by XSModel + if (fXSAnnotationList) + delete fXSAnnotationList; +} + +// --------------------------------------------------------------------------- +// XSIDCDefinition: XSObject virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSIDCDefinition::getName() const +{ + return fIdentityConstraint->getIdentityConstraintName(); +} + +const XMLCh *XSIDCDefinition::getNamespace() +{ + return fXSModel->getURIStringPool()->getValueForId(fIdentityConstraint->getNamespaceURI()); +} + +XSNamespaceItem *XSIDCDefinition::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + +// --------------------------------------------------------------------------- +// XSIDCDefinition: access methods +// --------------------------------------------------------------------------- +XSIDCDefinition::IC_CATEGORY XSIDCDefinition::getCategory() const +{ + switch(fIdentityConstraint->getType()) { + case IdentityConstraint::ICType_UNIQUE: + return IC_UNIQUE; + case IdentityConstraint::ICType_KEY: + return IC_KEY; + case IdentityConstraint::ICType_KEYREF: + return IC_KEYREF; + default: + // REVISIT: + // should never really get here... IdentityConstraint::Unknown is the other + // choice so need a default case for completeness; should issues error? + return IC_KEY; + } +} + +const XMLCh *XSIDCDefinition::getSelectorStr() +{ + return fIdentityConstraint->getSelector()->getXPath()->getExpression(); +} + + +XSAnnotationList *XSIDCDefinition::getAnnotations() +{ + return fXSAnnotationList; +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSIDCDefinition.hpp b/include/xercesc/framework/psvi/XSIDCDefinition.hpp new file mode 100644 index 0000000..813eca3 --- /dev/null +++ b/include/xercesc/framework/psvi/XSIDCDefinition.hpp @@ -0,0 +1,190 @@ +/* + * 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: XSIDCDefinition.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSIDCDEFINITION_HPP) +#define XERCESC_INCLUDE_GUARD_XSIDCDEFINITION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Identity Constraint + * Definition component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class IdentityConstraint; + +class XMLPARSER_EXPORT XSIDCDefinition : public XSObject +{ +public: + + // Identity Constraints + enum IC_CATEGORY { + /** + * + */ + IC_KEY = 1, + /** + * + */ + IC_KEYREF = 2, + /** + * + */ + IC_UNIQUE = 3 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param identityConstraint + * @param keyIC + * @param headAnnot + * @param stringList + * @param xsModel + * @param manager The configurable memory manager + */ + XSIDCDefinition + ( + IdentityConstraint* const identityConstraint + , XSIDCDefinition* const keyIC + , XSAnnotation* const headAnnot + , StringList* const stringList + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSIDCDefinition(); + //@} + + //--------------------- + /** @name overridden XSXSObject methods */ + + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem *getNamespaceItem(); + + //@} + + //--------------------- + /** @name XSIDCDefinition methods */ + + //@{ + + /** + * [identity-constraint category]: one of IC_KEY, IC_KEYREF or IC_UNIQUE. + */ + IC_CATEGORY getCategory() const; + + /** + * [selector]: a restricted XPath expression. + */ + const XMLCh *getSelectorStr(); + + /** + * [fields]: a non-empty list of restricted XPath ([XPath]) expressions. + */ + StringList *getFieldStrs(); + + /** + * [referenced key]: required if [identity-constraint category] is IC_KEYREF, + * forbidden otherwise (when an identity-constraint definition with [ + * identity-constraint category] equal to IC_KEY or IC_UNIQUE). + */ + XSIDCDefinition *getRefKey() const; + + /** + * A set of [annotations]. + */ + XSAnnotationList *getAnnotations(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSIDCDefinition(const XSIDCDefinition&); + XSIDCDefinition & operator=(const XSIDCDefinition &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + IdentityConstraint* fIdentityConstraint; + XSIDCDefinition* fKey; + StringList* fStringList; + XSAnnotationList* fXSAnnotationList; +}; + + +inline StringList* XSIDCDefinition::getFieldStrs() +{ + return fStringList; +} + +inline XSIDCDefinition* XSIDCDefinition::getRefKey() const +{ + return fKey; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSModel.cpp b/include/xercesc/framework/psvi/XSModel.cpp new file mode 100644 index 0000000..6b55a4f --- /dev/null +++ b/include/xercesc/framework/psvi/XSModel.cpp @@ -0,0 +1,799 @@ +/* + * 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: XSModel.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSModel: Constructors and Destructor +// --------------------------------------------------------------------------- +XSModel::XSModel( XMLGrammarPool *grammarPool + , MemoryManager* const manager) + : fMemoryManager(manager) + , fNamespaceStringList(0) + , fXSNamespaceItemList(0) + , fURIStringPool(0) + , fXSAnnotationList(0) + , fHashNamespace(0) + , fObjFactory(0) + , fDeleteNamespace(0) + , fParent(0) + , fDeleteParent(false) + , fAddedS4SGrammar(false) +{ + fURIStringPool = grammarPool->getURIStringPool(); + fObjFactory = new (fMemoryManager) XSObjectFactory(manager); + + // Populate XSNamedMaps by going through the components + for (XMLSize_t i=0; i + ( + 20, // size + 29, // modulus + fURIStringPool, + false, // adoptElems + fMemoryManager + ); + break; + default: + // ATTRIBUTE_USE + // MODEL_GROUP + // PARTICLE + // IDENTITY_CONSTRAINT + // WILDCARD + // ANNOTATION + // FACET + // MULTIVALUE + fComponentMap[i] = 0; + break; + } + fIdVector[i] = new (fMemoryManager) RefVectorOf(30, false, fMemoryManager); + } + + fNamespaceStringList = new (manager) RefArrayVectorOf (10, true, manager); + fXSNamespaceItemList = new (manager) RefVectorOf (10, true, manager); + fXSAnnotationList = new (manager) RefVectorOf (10, false, manager); + fHashNamespace = new (manager) RefHashTableOf (11, false, manager); + + // Loop through all grammars in the grammar pool to create the XSNamespaceItem's + // which will have access to Annotation Information which can be used later when + // we create all the XS components. + XSNamespaceItem* namespaceItem = 0; + RefHashTableOfEnumerator grammarEnum = grammarPool->getGrammarEnumerator(); + while (grammarEnum.hasMoreElements()) + { + SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement(); + if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || + XMLString::equals(sGrammar.getTargetNamespace(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) + continue; + + // NOTE: In the grammarpool, preprocessed grammars without targetnamespace + // will use an empty string... + XMLCh* NameSpace = XMLString::replicate(sGrammar.getTargetNamespace(), manager); + fNamespaceStringList->addElement(NameSpace); + namespaceItem = new (manager) XSNamespaceItem(this, &sGrammar, manager); + fXSNamespaceItemList->addElement(namespaceItem); + fHashNamespace->put(NameSpace, namespaceItem); + } + + // Now loop through all of the NamespaceItem's + // First, we add S4S namespace (irrespective of whether we have any grammars) + namespaceItem = new (manager) XSNamespaceItem + ( + this, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, manager + ); + + fNamespaceStringList->addElement + ( + XMLString::replicate(SchemaSymbols::fgURI_SCHEMAFORSCHEMA,manager) + ); + fXSNamespaceItemList->addElement(namespaceItem); + fHashNamespace->put + ( + (void*) SchemaSymbols::fgURI_SCHEMAFORSCHEMA + , namespaceItem + ); + + DatatypeValidatorFactory dvFactory(manager); + addS4SToXSModel + ( + namespaceItem + , dvFactory.getBuiltInRegistry() + ); + // don't include S4S (thus the -1) + XMLSize_t numberOfNamespaces = fXSNamespaceItemList->size() -1; + for (XMLSize_t j = 0; j < numberOfNamespaces; j++) + addGrammarToXSModel(fXSNamespaceItemList->elementAt(j)); +} + +XSModel::XSModel( XSModel *baseModel + , GrammarResolver *grammarResolver + , MemoryManager* const manager) + : fMemoryManager(manager) + , fNamespaceStringList(0) + , fXSNamespaceItemList(0) + , fURIStringPool(0) + , fXSAnnotationList(0) + , fHashNamespace(0) + , fObjFactory(0) + , fDeleteNamespace(0) + , fParent(baseModel) + , fDeleteParent(true) + , fAddedS4SGrammar(false) +{ + fURIStringPool = grammarResolver->getStringPool(); + fObjFactory = new (manager) XSObjectFactory(manager); + + XMLSize_t i; + // Populate XSNamedMaps by going through the components + for (i=0; i + ( + 20, // size + 29, // modulus + fURIStringPool, + false, // adoptElems + fMemoryManager + ); + break; + default: + // ATTRIBUTE_USE + // MODEL_GROUP + // PARTICLE + // IDENTITY_CONSTRAINT + // WILDCARD + // ANNOTATION + // FACET + // MULTIVALUE + fComponentMap[i] = 0; + break; + } + fIdVector[i] = new (fMemoryManager) RefVectorOf(30, false, fMemoryManager); + } + + fNamespaceStringList = new (manager) RefArrayVectorOf (10, true, manager); + fXSNamespaceItemList = new (manager) RefVectorOf (10, false, manager); + fDeleteNamespace = new (manager) RefVectorOf (10, true, manager); + fXSAnnotationList = new (manager) RefVectorOf (10, false, manager); + fHashNamespace = new (manager) RefHashTableOf (11, false, manager); + + if (fParent) + { + if (fParent->fAddedS4SGrammar) + fAddedS4SGrammar = true; + + // Need to copy information from parent so it can be returned in this object... + for (i=0; ifXSNamespaceItemList->size(); i++) + { + XSNamespaceItem* namespaceItem = fParent->fXSNamespaceItemList->elementAt(i); + fXSNamespaceItemList->addElement(namespaceItem); + fNamespaceStringList->addElement + ( + XMLString::replicate + ( + namespaceItem->getSchemaNamespace(), manager + ) + ); + } + + for (i=0; ifComponentMap[i]->getLength(); j++) + { + XSObject* copyObj = fParent->fComponentMap[i]->item(j); + fComponentMap[i]->addElement(copyObj, + copyObj->getName(), + copyObj->getNamespace()); + } + break; + } + for (XMLSize_t j=0; jfIdVector[i]->size(); j++) + { + fIdVector[i]->addElement(fParent->fIdVector[i]->elementAt(j)); + } + } + + for (i=0; ifXSAnnotationList->size(); i++) + { + fXSAnnotationList->addElement(fParent->fXSAnnotationList->elementAt(i)); + } + + } // end of copying parent info + + // Now add information from the new grammars but first create the + // XSNamespaceItem's so we can have access to the XSAnnotations... + ValueVectorOf* grammarsToAdd = grammarResolver->getGrammarsToAddToXSModel(); + XMLSize_t numberOfNamespaces = fXSNamespaceItemList->size(); + XMLSize_t numberOfNamespacesToAdd = 0; + for (i=0; i < grammarsToAdd->size(); i++) + { + SchemaGrammar* lGrammar = grammarsToAdd->elementAt(i); + if (lGrammar->getGrammarType() != Grammar::SchemaGrammarType || + XMLString::equals(lGrammar->getTargetNamespace(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) + continue; + + XMLCh* NameSpace = XMLString::replicate(lGrammar->getTargetNamespace(), manager); + fNamespaceStringList->addElement(NameSpace); + + XSNamespaceItem* namespaceItem = new (manager) XSNamespaceItem(this, lGrammar, manager); + fXSNamespaceItemList->addElement(namespaceItem); + fHashNamespace->put(NameSpace, namespaceItem); + fDeleteNamespace->addElement(namespaceItem); + ++numberOfNamespacesToAdd; + } + + // Add S4S namespace if needed + if (!fAddedS4SGrammar) + { + DatatypeValidatorFactory dvFactory(manager); + + XSNamespaceItem* namespaceItem = new (manager) XSNamespaceItem + ( + this, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, manager + ); + + fNamespaceStringList->addElement + ( + XMLString::replicate(SchemaSymbols::fgURI_SCHEMAFORSCHEMA,manager) + ); + fXSNamespaceItemList->addElement(namespaceItem); + fHashNamespace->put + ( + (void*) SchemaSymbols::fgURI_SCHEMAFORSCHEMA , namespaceItem + ); + fDeleteNamespace->addElement(namespaceItem); + addS4SToXSModel + ( + namespaceItem + , dvFactory.getBuiltInRegistry() + ); + } + + // Now loop through all of the newly created NamespaceItem's + for (i=numberOfNamespaces; i<(numberOfNamespaces+numberOfNamespacesToAdd); i++) + { + addGrammarToXSModel(fXSNamespaceItemList->elementAt(i)); + } // end of namespaceItem loop +} + +XSModel::~XSModel() +{ + for (XMLSize_t i=0; ifDeleteParent) + delete fParent; +} + +// --------------------------------------------------------------------------- +// XSModel: Helper methods +// --------------------------------------------------------------------------- +void XSModel::addComponentToIdVector(XSObject* const component, + XMLSize_t componentIndex) +{ + component->setId(fIdVector[componentIndex]->size()); + fIdVector[componentIndex]->addElement(component); +} + + +void XSModel::addComponentToNamespace(XSNamespaceItem* const namespaceItem, + XSObject* const component, + XMLSize_t componentIndex, + bool addToXSModel) +{ + namespaceItem->fComponentMap[componentIndex]->addElement + ( + component, component->getName(), namespaceItem->getSchemaNamespace() + ); + namespaceItem->fHashMap[componentIndex]->put + ( + (void *) component->getName(), component + ); + + if (addToXSModel) + { + fComponentMap[componentIndex]->addElement + ( + component, component->getName(), namespaceItem->getSchemaNamespace() + ); + } +} + +void +XSModel::addS4SToXSModel(XSNamespaceItem* const namespaceItem, + RefHashTableOf* const builtInDV) +{ + addComponentToNamespace + ( + namespaceItem + , fObjFactory->addOrFind + ( + ComplexTypeInfo::getAnyType + ( + fURIStringPool->getId(XMLUni::fgZeroLenString) + ) + , this + ) + , XSConstants::TYPE_DEFINITION - 1 + ); + + // Loop through built-in simple types + // First add 'anySimpleType' which is the base for the other built-ins + DatatypeValidator* dv = builtInDV->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + addComponentToNamespace + ( + namespaceItem + , fObjFactory->addOrFind(dv, this, true) + , XSConstants::TYPE_DEFINITION - 1 + ); + + // add remaining built-in + RefHashTableOfEnumerator simpleEnum = + RefHashTableOfEnumerator (builtInDV, false, fMemoryManager); + while (simpleEnum.hasMoreElements()) + { + DatatypeValidator& curSimple = simpleEnum.nextElement(); + if (&curSimple == dv) + continue; + + addComponentToNamespace + ( + namespaceItem + , fObjFactory->addOrFind(&curSimple, this) + , XSConstants::TYPE_DEFINITION - 1 + ); + } + + // Set flag to indicate that we have added S4S grammar info + fAddedS4SGrammar = true; +} + + +void XSModel::addGrammarToXSModel(XSNamespaceItem* namespaceItem) +{ + // Loop through top-level attribute declarations in the grammar... + RefHashTableOf* attDeclRegistry = namespaceItem->fGrammar->getAttributeDeclRegistry(); + if(attDeclRegistry) { + RefHashTableOfEnumerator attrEnum = RefHashTableOfEnumerator (attDeclRegistry, false, fMemoryManager); + while (attrEnum.hasMoreElements()) + { + XSAttributeDeclaration* xsAttrDecl = fObjFactory->addOrFind + ( + (SchemaAttDef*) &(attrEnum.nextElement()), this + ); + + addComponentToNamespace + ( + namespaceItem, xsAttrDecl, XSConstants::ATTRIBUTE_DECLARATION - 1 + ); + } // end of attribute loop + } + + // Loop through top-level elements in the grammar... + RefHash3KeysIdPoolEnumerator elemEnum = namespaceItem->fGrammar->getElemEnumerator(); + while (elemEnum.hasMoreElements()) + { + SchemaElementDecl& curElem = elemEnum.nextElement(); + if (curElem.getEnclosingScope() == Grammar::TOP_LEVEL_SCOPE) + { + XSElementDeclaration* xsElemDecl = fObjFactory->addOrFind + ( + &curElem, this + ); + + addComponentToNamespace + ( + namespaceItem, xsElemDecl, XSConstants::ELEMENT_DECLARATION -1 + ); + } + } // end of element loop + + // Now loop through top-level User Defined simple type definitions in the grammar... + DVHashTable* dvHT = namespaceItem->fGrammar->getDatatypeRegistry()->getUserDefinedRegistry(); + if (dvHT) + { + RefHashTableOfEnumerator simpleUserEnum = RefHashTableOfEnumerator (dvHT, false, fMemoryManager); + while (simpleUserEnum.hasMoreElements()) + { + DatatypeValidator& curSimple = simpleUserEnum.nextElement(); + if (!curSimple.getAnonymous()) + { + addComponentToNamespace + ( + namespaceItem + , fObjFactory->addOrFind(&curSimple, this) + , XSConstants::TYPE_DEFINITION - 1 + ); + } + } // end of simple User loop + } + + // Loop through top-level COMPLEX type definitions in the grammar... + RefHashTableOf* complexTypeRegistry = namespaceItem->fGrammar->getComplexTypeRegistry(); + if(complexTypeRegistry) { + RefHashTableOfEnumerator complexEnum = RefHashTableOfEnumerator (complexTypeRegistry, false, fMemoryManager); + while (complexEnum.hasMoreElements()) + { + ComplexTypeInfo& curComplex = complexEnum.nextElement(); + if (!curComplex.getAnonymous()) + { + addComponentToNamespace + ( + namespaceItem + , fObjFactory->addOrFind(&curComplex, this) + , XSConstants::TYPE_DEFINITION - 1 + ); + } + } // end of type definition loop + } + + // Loop through top-level attribute group definitions in the grammar... + RefHashTableOf* attGroupInfoRegistry = namespaceItem->fGrammar->getAttGroupInfoRegistry(); + if(attGroupInfoRegistry) { + RefHashTableOfEnumerator attrGroupEnum = RefHashTableOfEnumerator (attGroupInfoRegistry, false, fMemoryManager); + while (attrGroupEnum.hasMoreElements()) + { + addComponentToNamespace + ( + namespaceItem + , fObjFactory->createXSAttGroupDefinition + ( + &(attrGroupEnum.nextElement()), this + ) + , XSConstants::ATTRIBUTE_GROUP_DEFINITION - 1 + ); + } // end of attribute group loop + } + + // Loop through top-level model group definitions in the grammar... + RefHashTableOf* groupInfoRegistry = namespaceItem->fGrammar->getGroupInfoRegistry(); + if(groupInfoRegistry) { + RefHashTableOfEnumerator modelGroupEnum = RefHashTableOfEnumerator (groupInfoRegistry, false, fMemoryManager); + while (modelGroupEnum.hasMoreElements()) + { + addComponentToNamespace + ( + namespaceItem + , fObjFactory->createXSModelGroupDefinition + ( + &(modelGroupEnum.nextElement()), this + ) + , XSConstants::MODEL_GROUP_DEFINITION - 1 + ); + } // end of model group loop + } + + // Loop through notations in the grammar... + NameIdPoolEnumerator notationEnum = namespaceItem->fGrammar->getNotationEnumerator(); + while (notationEnum.hasMoreElements()) + { + addComponentToNamespace + ( + namespaceItem + , fObjFactory->addOrFind(&(notationEnum.nextElement()), this) + , XSConstants::NOTATION_DECLARATION - 1 + ); + } // end of notation loop + + // Loop through annotations in the grammar... + // As annotations are already created as XSAnnotations no need to create them + // or store them in the XercesToXSMap. + XSAnnotation* annot = namespaceItem->fGrammar->getAnnotation(); + while (annot) + { + fXSAnnotationList->addElement(annot); + namespaceItem->fXSAnnotationList->addElement(annot); + addComponentToIdVector(annot, XSConstants::ANNOTATION -1); + annot = annot->getNext(); + } // end of annotation loop +} + + + + +// --------------------------------------------------------------------------- +// XSModel: Access methods +// --------------------------------------------------------------------------- +/** + * [schema components]: a list of top-level components, i.e. element + * declarations, attribute declarations, etc. + * @param objectType The type of the declaration, i.e. + * ELEMENT_DECLARATION, + * TYPE_DEFINITION and any other component type that + * may be a property of a schema component. + * @return A list of top-level definition of the specified type in + * objectType or null. + */ +XSNamedMap *XSModel::getComponents(XSConstants::COMPONENT_TYPE objectType) +{ + return fComponentMap[objectType -1]; +} + +/** + * Convenience method. Returns a list of top-level component declarations + * that are defined within the specified namespace, i.e. element + * declarations, attribute declarations, etc. + * @param objectType The type of the declaration, i.e. + * ELEMENT_DECLARATION. + * @param compNamespace The namespace to which declaration belong or + * null (for components with no target namespace). + * @return A list of top-level definitions of the specified type in + * objectType and defined in the specified + * namespace or null. + */ +XSNamedMap *XSModel::getComponentsByNamespace(XSConstants::COMPONENT_TYPE objectType, + const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getComponents(objectType); + + return 0; +} + +/** + * [annotations]: a set of annotations. + */ +XSAnnotationList *XSModel::getAnnotations() +{ + return fXSAnnotationList; +} + +/** + * Convenience method. Returns a top-level element declaration. + * @param name The name of the declaration. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level element declaration or null if such + * declaration does not exist. + */ +XSElementDeclaration *XSModel::getElementDeclaration(const XMLCh *name + , const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getElementDeclaration(name); + + return 0; +} + +/** + * Convenience method. Returns a top-level attribute declaration. + * @param name The name of the declaration. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level attribute declaration or null if such + * declaration does not exist. + */ +XSAttributeDeclaration *XSModel::getAttributeDeclaration(const XMLCh *name + , const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getAttributeDeclaration(name); + + return 0; +} + +/** + * Convenience method. Returns a top-level simple or complex type + * definition. + * @param name The name of the definition. + * @param compNamespace The namespace of the declaration, null if absent. + * @return An XSTypeDefinition or null if such + * definition does not exist. + */ +XSTypeDefinition *XSModel::getTypeDefinition(const XMLCh *name + , const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getTypeDefinition(name); + + return 0; +} + +/** + * Convenience method. Returns a top-level attribute group definition. + * @param name The name of the definition. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level attribute group definition or null if + * such definition does not exist. + */ +XSAttributeGroupDefinition *XSModel::getAttributeGroup(const XMLCh *name + , const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getAttributeGroup(name); + + return 0; +} + +/** + * Convenience method. Returns a top-level model group definition. + * @param name The name of the definition. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level model group definition definition or + * null if such definition does not exist. + */ +XSModelGroupDefinition *XSModel::getModelGroupDefinition(const XMLCh *name + , const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getModelGroupDefinition(name); + + return 0; +} + +/** + * Convenience method. Returns a top-level notation declaration. + * @param name The name of the declaration. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level notation declaration or null if such + * declaration does not exist. + */ +XSNotationDeclaration *XSModel::getNotationDeclaration(const XMLCh *name + , const XMLCh *compNamespace) +{ + XSNamespaceItem* namespaceItem; + if (compNamespace) + namespaceItem = getNamespaceItem(compNamespace); + else + namespaceItem = getNamespaceItem(XMLUni::fgZeroLenString); + + if (namespaceItem) + return namespaceItem->getNotationDeclaration(name); + + return 0; +} + +/** + * Optional. Return a component given a component type and a unique Id. + * May not be supported for all component types. + * @param compId unique Id of the component within its type + * @param compType type of the component + * @return the component of the given type with the given Id, or 0 + * if no such component exists or this is unsupported for + * this type of component. + */ +XSObject *XSModel::getXSObjectById(XMLSize_t compId + , XSConstants::COMPONENT_TYPE compType) +{ + if (compId < fIdVector[compType -1]->size()) + return fIdVector[compType -1]->elementAt(compId); + + return 0; +} + +XSNamespaceItem* XSModel::getNamespaceItem(const XMLCh* const key) +{ + XSNamespaceItem* xsName = fHashNamespace->get(key); + if (xsName) + return xsName; + if (fParent) + return fParent->getNamespaceItem(key); + return 0; +} + +XSObject* XSModel::getXSObject(void* key) +{ + XSObject* xsObj = fObjFactory->getObjectFromMap(key); + + if (!xsObj && fParent) + xsObj = fParent->getXSObject(key); + + return xsObj; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSModel.hpp b/include/xercesc/framework/psvi/XSModel.hpp new file mode 100644 index 0000000..c1cd63a --- /dev/null +++ b/include/xercesc/framework/psvi/XSModel.hpp @@ -0,0 +1,338 @@ +/* + * 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: XSModel.hpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSMODEL_HPP) +#define XERCESC_INCLUDE_GUARD_XSMODEL_HPP + +#include +#include +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class contains all properties of the Schema infoitem as determined + * after an entire validation episode. That is, it contains all the properties + * of all the Schema Namespace Information objects that went into + * the validation episode. + * Since it is not like other components, it does not + * inherit from the XSObject interface. + * This is *always* owned by the validator /parser object from which + * it is obtained. It is designed to be subclassed; subclasses will + * specify under what conditions it may be relied upon to have meaningful contents. + */ + +// forward declarations +class Grammar; +class XMLGrammarPool; +class XSAnnotation; +class XSAttributeDeclaration; +class XSAttributeGroupDefinition; +class XSElementDeclaration; +class XSModelGroupDefinition; +class XSNamespaceItem; +class XSNotationDeclaration; +class XSTypeDefinition; +class XSObjectFactory; + +class XMLPARSER_EXPORT XSModel : public XMemory +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The constructor to be used when a grammar pool contains all needed info + * @param grammarPool the grammar pool containing the underlying data structures + * @param manager The configurable memory manager + */ + XSModel( XMLGrammarPool *grammarPool + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * The constructor to be used when the XSModel must represent all + * components in the union of an existing XSModel and a newly-created + * Grammar(s) from the GrammarResolver + * + * @param baseModel the XSModel upon which this one is based + * @param grammarResolver the grammar(s) whose components are to be merged + * @param manager The configurable memory manager + */ + XSModel( XSModel *baseModel + , GrammarResolver *grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@}; + + /** @name Destructor */ + //@{ + ~XSModel(); + //@} + + //--------------------- + /** @name XSModel methods */ + + //@{ + + /** + * Convenience method. Returns a list of all namespaces that belong to + * this schema. The value null is not a valid namespace + * name, but if there are components that don't have a target namespace, + * null is included in this list. + */ + StringList *getNamespaces(); + + /** + * A set of namespace schema information information items ( of type + * XSNamespaceItem), one for each namespace name which + * appears as the target namespace of any schema component in the schema + * used for that assessment, and one for absent if any schema component + * in the schema had no target namespace. For more information see + * schema information. + */ + XSNamespaceItemList *getNamespaceItems(); + + /** + * [schema components]: a list of top-level components, i.e. element + * declarations, attribute declarations, etc. + * @param objectType The type of the declaration, i.e. + * ELEMENT_DECLARATION, + * TYPE_DEFINITION and any other component type that + * may be a property of a schema component. + * @return A list of top-level definition of the specified type in + * objectType or null. + */ + XSNamedMap *getComponents(XSConstants::COMPONENT_TYPE objectType); + + /** + * Convenience method. Returns a list of top-level component declarations + * that are defined within the specified namespace, i.e. element + * declarations, attribute declarations, etc. + * @param objectType The type of the declaration, i.e. + * ELEMENT_DECLARATION. + * @param compNamespace The namespace to which declaration belongs or + * null (for components with no target namespace). + * @return A list of top-level definitions of the specified type in + * objectType and defined in the specified + * namespace or null. + */ + XSNamedMap *getComponentsByNamespace(XSConstants::COMPONENT_TYPE objectType, + const XMLCh *compNamespace); + + /** + * [annotations]: a set of annotations. + */ + XSAnnotationList *getAnnotations(); + + /** + * Convenience method. Returns a top-level element declaration. + * @param name The name of the declaration. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level element declaration or null if such + * declaration does not exist. + */ + XSElementDeclaration *getElementDeclaration(const XMLCh *name + , const XMLCh *compNamespace); + + /** + * Convenience method. Returns a top-level attribute declaration. + * @param name The name of the declaration. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level attribute declaration or null if such + * declaration does not exist. + */ + XSAttributeDeclaration *getAttributeDeclaration(const XMLCh *name + , const XMLCh *compNamespace); + + /** + * Convenience method. Returns a top-level simple or complex type + * definition. + * @param name The name of the definition. + * @param compNamespace The namespace of the declaration, null if absent. + * @return An XSTypeDefinition or null if such + * definition does not exist. + */ + XSTypeDefinition *getTypeDefinition(const XMLCh *name + , const XMLCh *compNamespace); + + /** + * Convenience method. Returns a top-level attribute group definition. + * @param name The name of the definition. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level attribute group definition or null if + * such definition does not exist. + */ + XSAttributeGroupDefinition *getAttributeGroup(const XMLCh *name + , const XMLCh *compNamespace); + + /** + * Convenience method. Returns a top-level model group definition. + * @param name The name of the definition. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level model group definition definition or + * null if such definition does not exist. + */ + XSModelGroupDefinition *getModelGroupDefinition(const XMLCh *name + , const XMLCh *compNamespace); + + /** + * Convenience method. Returns a top-level notation declaration. + * @param name The name of the declaration. + * @param compNamespace The namespace of the declaration, null if absent. + * @return A top-level notation declaration or null if such + * declaration does not exist. + */ + XSNotationDeclaration *getNotationDeclaration(const XMLCh *name + , const XMLCh *compNamespace); + + /** + * Optional. Return a component given a component type and a unique Id. + * May not be supported for all component types. + * @param compId unique Id of the component within its type + * @param compType type of the component + * @return the component of the given type with the given Id, or 0 + * if no such component exists or this is unsupported for + * this type of component. + */ + XSObject *getXSObjectById(XMLSize_t compId, + XSConstants::COMPONENT_TYPE compType); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + XMLStringPool* getURIStringPool(); + + XSNamespaceItem* getNamespaceItem(const XMLCh* const key); + + /** + * Get the XSObject (i.e. XSElementDeclaration) that corresponds to + * to a schema grammar component (i.e. SchemaElementDecl) + * @param key schema component object + * + * @return the corresponding XSObject + */ + XSObject* getXSObject(void* key); + + //@} +private: + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void addGrammarToXSModel + ( + XSNamespaceItem* namespaceItem + ); + void addS4SToXSModel + ( + XSNamespaceItem* const namespaceItem + , RefHashTableOf* const builtInDV + ); + void addComponentToNamespace + ( + XSNamespaceItem* const namespaceItem + , XSObject* const component + , XMLSize_t componentIndex + , bool addToXSModel = true + ); + + void addComponentToIdVector + ( + XSObject* const component + , XMLSize_t componentIndex + ); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSModel(const XSModel&); + XSModel & operator=(const XSModel &); + +protected: + friend class XSObjectFactory; + friend class XSObject; + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fMemoryManager: + // used for any memory allocations + MemoryManager* const fMemoryManager; + + StringList* fNamespaceStringList; + XSNamespaceItemList* fXSNamespaceItemList; + + RefVectorOf* fIdVector[XSConstants::MULTIVALUE_FACET]; + + /* Need a XSNamedMap for each component top-level? + ATTRIBUTE_DECLARATION = 1, + ELEMENT_DECLARATION = 2, + TYPE_DEFINITION = 3, + ATTRIBUTE_USE = 4, no + ATTRIBUTE_GROUP_DEFINITION= 5, + MODEL_GROUP_DEFINITION = 6, + MODEL_GROUP = 7, no + PARTICLE = 8, no + WILDCARD = 9, no + IDENTITY_CONSTRAINT = 10, no + NOTATION_DECLARATION = 11, + ANNOTATION = 12, no + FACET = 13, no + MULTIVALUE_FACET = 14 no + */ + XSNamedMap* fComponentMap[XSConstants::MULTIVALUE_FACET]; + XMLStringPool* fURIStringPool; + XSAnnotationList* fXSAnnotationList; + RefHashTableOf* fHashNamespace; + XSObjectFactory* fObjFactory; + RefVectorOf* fDeleteNamespace; + XSModel* fParent; + bool fDeleteParent; + bool fAddedS4SGrammar; +}; + +inline XMLStringPool* XSModel::getURIStringPool() +{ + return fURIStringPool; +} + +inline StringList *XSModel::getNamespaces() +{ + return fNamespaceStringList; +} + +inline XSNamespaceItemList *XSModel::getNamespaceItems() +{ + return fXSNamespaceItemList; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSModelGroup.cpp b/include/xercesc/framework/psvi/XSModelGroup.cpp new file mode 100644 index 0000000..d4087cd --- /dev/null +++ b/include/xercesc/framework/psvi/XSModelGroup.cpp @@ -0,0 +1,50 @@ +/* + * 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: XSModelGroup.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSModelGroup: Constructors and Destructor +// --------------------------------------------------------------------------- +XSModelGroup::XSModelGroup(COMPOSITOR_TYPE compositorType, + XSParticleList* const particleList, + XSAnnotation* const annot, + XSModel* const xsModel, + MemoryManager * const manager) + : XSObject(XSConstants::MODEL_GROUP, xsModel, manager) + , fCompositorType(compositorType) + , fParticleList(particleList) + , fAnnotation(annot) +{ +} + +XSModelGroup::~XSModelGroup() +{ + if (fParticleList) + delete fParticleList; +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSModelGroup.hpp b/include/xercesc/framework/psvi/XSModelGroup.hpp new file mode 100644 index 0000000..cac1d70 --- /dev/null +++ b/include/xercesc/framework/psvi/XSModelGroup.hpp @@ -0,0 +1,156 @@ +/* + * 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: XSModelGroup.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSMODELGROUP_HPP) +#define XERCESC_INCLUDE_GUARD_XSMODELGROUP_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Model Group + * component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class XSParticle; + +class XMLPARSER_EXPORT XSModelGroup : public XSObject +{ +public: + + // Content model compositors + enum COMPOSITOR_TYPE { + /** + * This constant value signifies a sequence operator. + */ + COMPOSITOR_SEQUENCE = 1, + /** + * This constant value signifies a choice operator. + */ + COMPOSITOR_CHOICE = 2, + /** + * This content model represents a simplified version of the SGML + * &-Connector and is limited to the top-level of any content model. + * No element in the all content model may appear more than once. + */ + COMPOSITOR_ALL = 3 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param compositorType + * @param particleList + * @param annot + * @param xsModel + * @param manager The configurable memory manager + */ + XSModelGroup + ( + COMPOSITOR_TYPE compositorType + , XSParticleList* const particleList + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSModelGroup(); + //@} + + //--------------------- + /** @name XSModelGroup methods */ + //@{ + + /** + * [compositor]: one of all, choice or sequence. The valid constants + * values are: + * COMPOSITOR_SEQUENCE, COMPOSITOR_CHOICE, COMPOSITOR_ALL. + */ + COMPOSITOR_TYPE getCompositor() const; + + /** + * A list of [particles]. + */ + XSParticleList *getParticles() const; + + /** + * Optional. An [annotation]. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSModelGroup(const XSModelGroup&); + XSModelGroup & operator=(const XSModelGroup &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + COMPOSITOR_TYPE fCompositorType; + XSParticleList* fParticleList; + XSAnnotation* fAnnotation; +}; + +inline XSModelGroup::COMPOSITOR_TYPE XSModelGroup::getCompositor() const +{ + return fCompositorType; +} + +inline XSParticleList* XSModelGroup::getParticles() const +{ + return fParticleList; +} + +inline XSAnnotation* XSModelGroup::getAnnotation() const +{ + return fAnnotation; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSModelGroupDefinition.cpp b/include/xercesc/framework/psvi/XSModelGroupDefinition.cpp new file mode 100644 index 0000000..c184b67 --- /dev/null +++ b/include/xercesc/framework/psvi/XSModelGroupDefinition.cpp @@ -0,0 +1,83 @@ +/* + * 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: XSModelGroupDefinition.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSModelGroupDefinition: Constructors and Destructors +// --------------------------------------------------------------------------- +XSModelGroupDefinition::XSModelGroupDefinition(XercesGroupInfo* const groupInfo, + XSParticle* const groupParticle, + XSAnnotation* const annot, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::MODEL_GROUP_DEFINITION, xsModel, manager) + , fGroupInfo(groupInfo) + , fModelGroupParticle(groupParticle) + , fAnnotation(annot) +{ +} + +XSModelGroupDefinition::~XSModelGroupDefinition() +{ + if (fModelGroupParticle) // Not owned by XSModel + delete fModelGroupParticle; +} + +// --------------------------------------------------------------------------- +// XSModelGroupDefinition: XSModel virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSModelGroupDefinition::getName() const +{ + return fXSModel->getURIStringPool()->getValueForId(fGroupInfo->getNameId()); +} + +const XMLCh *XSModelGroupDefinition::getNamespace() +{ + return fXSModel->getURIStringPool()->getValueForId(fGroupInfo->getNamespaceId()); +} + +XSNamespaceItem *XSModelGroupDefinition::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + +// --------------------------------------------------------------------------- +// XSModelGroupDefinition: access methods +// --------------------------------------------------------------------------- +XSModelGroup* XSModelGroupDefinition::getModelGroup() +{ + if (fModelGroupParticle) + return fModelGroupParticle->getModelGroupTerm(); + + return 0; +} + + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSModelGroupDefinition.hpp b/include/xercesc/framework/psvi/XSModelGroupDefinition.hpp new file mode 100644 index 0000000..ce249e3 --- /dev/null +++ b/include/xercesc/framework/psvi/XSModelGroupDefinition.hpp @@ -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: XSModelGroupDefinition.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSMODELGROUPDEFINITION_HPP) +#define XERCESC_INCLUDE_GUARD_XSMODELGROUPDEFINITION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Model Group + * Definition component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class XSModelGroup; +class XSParticle; +class XercesGroupInfo; + +class XMLPARSER_EXPORT XSModelGroupDefinition : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param groupInfo + * @param groupParticle + * @param annot + * @param xsModel + * @param manager The configurable memory manager + */ + XSModelGroupDefinition + ( + XercesGroupInfo* const groupInfo + , XSParticle* const groupParticle + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSModelGroupDefinition(); + //@} + + //--------------------- + /** @name overridden XSXSObject methods */ + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem *getNamespaceItem(); + + //@} + + //--------------------- + /** @name XSModelGroupDefinition methods */ + + //@{ + + /** + * A model group. + */ + XSModelGroup *getModelGroup(); + + /** + * Optional. An [annotation]. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSModelGroupDefinition(const XSModelGroupDefinition&); + XSModelGroupDefinition & operator=(const XSModelGroupDefinition &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + XercesGroupInfo* fGroupInfo; + XSParticle* fModelGroupParticle; + XSAnnotation* fAnnotation; +}; + +inline XSAnnotation* XSModelGroupDefinition::getAnnotation() const +{ + return fAnnotation; +} + + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSMultiValueFacet.cpp b/include/xercesc/framework/psvi/XSMultiValueFacet.cpp new file mode 100644 index 0000000..a314864 --- /dev/null +++ b/include/xercesc/framework/psvi/XSMultiValueFacet.cpp @@ -0,0 +1,64 @@ +/* + * 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: XSMultiValueFacet.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSMultiValueFacet: Constructors and Destructors +// --------------------------------------------------------------------------- +XSMultiValueFacet::XSMultiValueFacet(XSSimpleTypeDefinition::FACET facetKind, + StringList* lexicalValues, + bool isFixed, + XSAnnotation* const headAnnot, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::MULTIVALUE_FACET, xsModel, manager) + , fFacetKind(facetKind) + , fIsFixed(isFixed) + , fLexicalValues(lexicalValues) + , fXSAnnotationList(0) +{ + if (headAnnot) + { + fXSAnnotationList = new (manager) RefVectorOf(1, false, manager); + + XSAnnotation* annot = headAnnot; + do + { + fXSAnnotationList->addElement(annot); + annot = annot->getNext(); + } while (annot); + } +} + +XSMultiValueFacet::~XSMultiValueFacet() +{ + if (fXSAnnotationList) + delete fXSAnnotationList; +} + + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSMultiValueFacet.hpp b/include/xercesc/framework/psvi/XSMultiValueFacet.hpp new file mode 100644 index 0000000..37de670 --- /dev/null +++ b/include/xercesc/framework/psvi/XSMultiValueFacet.hpp @@ -0,0 +1,152 @@ +/* + * 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: XSMultiValueFacet.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSMULTIVALUEFACET_HPP) +#define XERCESC_INCLUDE_GUARD_XSMULTIVALUEFACET_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class represents all Schema Facets which may possess multiple + * lexical values/annotations (i.e., Pattern and Enumeration facets). + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; + +class XMLPARSER_EXPORT XSMultiValueFacet : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param facetKind + * @param lexicalValues + * @param isFixed + * @param headAnnot + * @param xsModel + * @param manager The configurable memory manager + */ + XSMultiValueFacet + ( + XSSimpleTypeDefinition::FACET facetKind + , StringList* lexicalValues + , bool isFixed + , XSAnnotation* const headAnnot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSMultiValueFacet(); + //@} + + //--------------------- + /** @name XSMultiValueFacet methods */ + + //@{ + + /** + * @return An indication as to the facet's type; see XSSimpleTypeDefinition::FACET + */ + XSSimpleTypeDefinition::FACET getFacetKind() const; + + /** + * @return Returns the values of a constraining facet. + */ + StringList *getLexicalFacetValues(); + + /** + * Check whether a facet value is fixed. + */ + bool isFixed() const; + + /** + * @return the annotations belonging to this facet's values + */ + XSAnnotationList *getAnnotations(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSMultiValueFacet(const XSMultiValueFacet&); + XSMultiValueFacet & operator=(const XSMultiValueFacet &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + XSSimpleTypeDefinition::FACET fFacetKind; + bool fIsFixed; + StringList* fLexicalValues; // not owned by this class + XSAnnotationList* fXSAnnotationList; +}; + + +inline XSSimpleTypeDefinition::FACET XSMultiValueFacet::getFacetKind() const +{ + return fFacetKind; +} + +inline bool XSMultiValueFacet::isFixed() const +{ + return fIsFixed; +} + +inline StringList *XSMultiValueFacet::getLexicalFacetValues() +{ + return fLexicalValues; +} + +inline XSAnnotationList *XSMultiValueFacet::getAnnotations() +{ + return fXSAnnotationList; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSNamedMap.c b/include/xercesc/framework/psvi/XSNamedMap.c new file mode 100644 index 0000000..f0e606f --- /dev/null +++ b/include/xercesc/framework/psvi/XSNamedMap.c @@ -0,0 +1,124 @@ +/* + * 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: XSNamedMap.c 674012 2008-07-04 11:18:21Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Include +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSNamedMap: Constructors and Destructor +// --------------------------------------------------------------------------- +template +XSNamedMap::XSNamedMap(const XMLSize_t maxElems, + const XMLSize_t modulus, + XMLStringPool* uriStringPool, + const bool adoptElems, + MemoryManager* const manager) + : fMemoryManager(manager) + , fURIStringPool(uriStringPool) +{ + // allow one of the Vector or Hash to own the data... but not both... + fVector = new (manager) RefVectorOf (maxElems, false, manager); + fHash = new (manager) RefHash2KeysTableOf (modulus, adoptElems, manager); +} +template XSNamedMap::~XSNamedMap() +{ + delete fVector; + delete fHash; +} + + +/** + * The number of XSObjects in the XSObjectList. + * The range of valid child object indices is 0 to + * mapLength-1 inclusive. + */ +template +XMLSize_t XSNamedMap::getLength() const +{ + return fVector->size(); +} + +/** + * Returns the indexth item in the collection. The index + * starts at 0. If index is greater than or equal to the + * number of objects in the list, this returns null. + * @param index index into the collection. + * @return The XSObject at the indexth + * position in the XSObjectList, or null if + * that is not a valid index. + */ +template +TVal* XSNamedMap::item(XMLSize_t index) +{ + if (index >= fVector->size()) + { + return 0; + } + return fVector->elementAt(index); +} + +template +const TVal* XSNamedMap::item(XMLSize_t index) const +{ + if (index >= fVector->size()) + { + return 0; + } + return fVector->elementAt(index); +} + +/** + * Retrieves a component specified by local name and namespace URI. + *
applications must use the value null as the + * compNamespace parameter for components whose targetNamespace property + * is absent. + * @param compNamespace The namespace URI of the component to retrieve. + * @param localName The local name of the component to retrieve. + * @return A component (of any type) with the specified local + * name and namespace URI, or null if they do not + * identify any node in this map. + */ +template +TVal *XSNamedMap::itemByName(const XMLCh *compNamespace, + const XMLCh *localName) +{ + return fHash->get((void*)localName, fURIStringPool->getId(compNamespace)); +} + + +template +void XSNamedMap::addElement(TVal* const toAdd, const XMLCh* key1, const XMLCh* key2) +{ + fVector->addElement(toAdd); + fHash->put((void*)key1, fURIStringPool->getId(key2), toAdd); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSNamedMap.hpp b/include/xercesc/framework/psvi/XSNamedMap.hpp new file mode 100644 index 0000000..899df91 --- /dev/null +++ b/include/xercesc/framework/psvi/XSNamedMap.hpp @@ -0,0 +1,138 @@ +/* + * 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: XSNamedMap.hpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSNAMEDMAP_HPP) +#define XERCESC_INCLUDE_GUARD_XSNAMEDMAP_HPP + + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLStringPool; + +/* + * This template provides convenient mappings between name,namespace + * pairs and individual components, as well as means to iterate through all the + * named components on some object. + */ + +template class XSNamedMap: public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + XSNamedMap(const XMLSize_t maxElems, + const XMLSize_t modulus, + XMLStringPool* uriStringPool, + const bool adoptElems, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + //@} + + /** @name Destructor */ + //@{ + ~XSNamedMap(); + + //@} + + // ----------------------------------------------------------------------- + // XSNamedMap methods + // ----------------------------------------------------------------------- + /** @name XSNamedMap methods */ + //@{ + + /** + * The number of XSObjects in the XSObjectList. + * The range of valid child object indices is 0 to + * mapLength-1 inclusive. + */ + XMLSize_t getLength() const; + + /** + * Returns the indexth item in the collection. The index + * starts at 0. If index is greater than or equal to the + * number of objects in the list, this returns null. + * @param index index into the collection. + * @return The XSObject at the indexth + * position in the XSObjectList, or null if + * that is not a valid index. + */ + TVal *item(XMLSize_t index); + const TVal *item(XMLSize_t index) const; + + /** + * Retrieves a component specified by local name and namespace URI. + *
applications must use the value null as the + * compNamespace parameter for components whose targetNamespace property + * is absent. + * @param compNamespace The namespace URI of the component to retrieve. + * @param localName The local name of the component to retrieve. + * @return A component (of any type) with the specified local + * name and namespace URI, or null if they do not + * identify any node in this map. + */ + TVal *itemByName(const XMLCh *compNamespace, + const XMLCh *localName); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + void addElement(TVal* const toAdd, const XMLCh* key1, const XMLCh* key2); + //@} + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSNamedMap(const XSNamedMap&); + XSNamedMap& operator=(const XSNamedMap&); + + // ----------------------------------------------------------------------- + // Data members + // + // fMemoryManager + // manager used to allocate memory needed by this object + MemoryManager *const fMemoryManager; + XMLStringPool* fURIStringPool; + RefVectorOf* fVector; + RefHash2KeysTableOf* fHash; +}; + + + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/framework/psvi/XSNamespaceItem.cpp b/include/xercesc/framework/psvi/XSNamespaceItem.cpp new file mode 100644 index 0000000..24538a6 --- /dev/null +++ b/include/xercesc/framework/psvi/XSNamespaceItem.cpp @@ -0,0 +1,218 @@ +/* + * 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: XSNamespaceItem.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSNamespaceItem: Constructors and Destructors +// --------------------------------------------------------------------------- +XSNamespaceItem::XSNamespaceItem(XSModel* const xsModel, + SchemaGrammar* const grammar, + MemoryManager* const manager) + : fMemoryManager(manager) + , fGrammar(grammar) + , fXSModel(xsModel) + , fXSAnnotationList(0) + , fSchemaNamespace(grammar->getTargetNamespace()) +{ + // Populate XSNamedMaps by going through the components + for (XMLSize_t i=0; i + ( + 20, // size + 29, // modulus + fXSModel->getURIStringPool(), + false, // adoptElems + fMemoryManager + ); + fHashMap[i] = new (fMemoryManager) RefHashTableOf + ( + 29, + false, + fMemoryManager + ); + break; + default: + // ATTRIBUTE_USE + // MODEL_GROUP + // PARTICLE + // IDENTITY_CONSTRAINT + // WILDCARD + // ANNOTATION + // FACET + // MULTIVALUE + fComponentMap[i] = 0; + fHashMap[i] = 0; + break; + } + } + + fXSAnnotationList = new (manager) RefVectorOf (5, false, manager); +} + +XSNamespaceItem::XSNamespaceItem(XSModel* const xsModel, + const XMLCh* const schemaNamespace, + MemoryManager* const manager) + : fMemoryManager(manager) + , fGrammar(0) + , fXSModel(xsModel) + , fXSAnnotationList(0) + , fSchemaNamespace(schemaNamespace) +{ + // Populate XSNamedMaps by going through the components + for (XMLSize_t i=0; i + ( + 20, // size + 29, // modulus + fXSModel->getURIStringPool(), + false, // adoptElems + fMemoryManager + ); + fHashMap[i] = new (fMemoryManager) RefHashTableOf + ( + 29, + false, + fMemoryManager + ); + break; + default: + // ATTRIBUTE_USE + // MODEL_GROUP + // PARTICLE + // IDENTITY_CONSTRAINT + // WILDCARD + // ANNOTATION + // FACET + // MULTIVALUE + fComponentMap[i] = 0; + fHashMap[i] = 0; + break; + } + } + + fXSAnnotationList = new (manager) RefVectorOf (5, false, manager); +} + +XSNamespaceItem::~XSNamespaceItem() +{ + for (XMLSize_t i=0; i *XSNamespaceItem::getComponents(XSConstants::COMPONENT_TYPE objectType) +{ + return fComponentMap[objectType -1]; +} + +XSElementDeclaration *XSNamespaceItem::getElementDeclaration(const XMLCh *name) +{ + if (name) + return (XSElementDeclaration*) fHashMap[XSConstants::ELEMENT_DECLARATION -1]->get(name); + return 0; +} + +XSAttributeDeclaration *XSNamespaceItem::getAttributeDeclaration(const XMLCh *name) +{ + if (name) + return (XSAttributeDeclaration*) fHashMap[XSConstants::ATTRIBUTE_DECLARATION -1]->get(name); + return 0; +} + +XSTypeDefinition *XSNamespaceItem::getTypeDefinition(const XMLCh *name) +{ + if (name) + return (XSTypeDefinition*) fHashMap[XSConstants::TYPE_DEFINITION -1]->get(name); + return 0; +} + +XSAttributeGroupDefinition *XSNamespaceItem::getAttributeGroup(const XMLCh *name) +{ + if (name) + return (XSAttributeGroupDefinition*) fHashMap[XSConstants::ATTRIBUTE_GROUP_DEFINITION -1]->get(name); + return 0; +} + +XSModelGroupDefinition *XSNamespaceItem::getModelGroupDefinition(const XMLCh *name) +{ + if (name) + return (XSModelGroupDefinition*) fHashMap[XSConstants::MODEL_GROUP_DEFINITION -1]->get(name); + return 0; +} + +XSNotationDeclaration *XSNamespaceItem::getNotationDeclaration(const XMLCh *name) +{ + if (name) + return (XSNotationDeclaration*) fHashMap[XSConstants::NOTATION_DECLARATION -1]->get(name); + return 0; +} + +const StringList *XSNamespaceItem::getDocumentLocations() +{ + if (fGrammar) + return ((XMLSchemaDescriptionImpl*) fGrammar->getGrammarDescription())->getLocationHints(); + + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSNamespaceItem.hpp b/include/xercesc/framework/psvi/XSNamespaceItem.hpp new file mode 100644 index 0000000..bfc6377 --- /dev/null +++ b/include/xercesc/framework/psvi/XSNamespaceItem.hpp @@ -0,0 +1,245 @@ +/* + * 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: XSNamespaceItem.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSNAMESPACEITEM_HPP) +#define XERCESC_INCLUDE_GUARD_XSNAMESPACEITEM_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class contains all properties of the Schema Namespace Information infoitem. + * These items correspond to the result of processing a schema document + * and all its included/redefined schema documents. It corresponds to the + * schema component discussed in the schema specifications, but since it + * is not like other components does not inherit from the XSObject interface. + * This is *always* owned by the validator /parser object from which + * it is obtained. It is designed to be subclassed; subclasses will + * specify under what conditions it may be relied upon to have meaningful contents. + */ + +// forward declarations +class XSAnnotation; +class XSAttributeDeclaration; +class XSAttributeGroupDefinition; +class XSElementDeclaration; +class XSModelGroupDefinition; +class XSNotationDeclaration; +class XSTypeDefinition; +class SchemaGrammar; +class XSModel; + +class XMLPARSER_EXPORT XSNamespaceItem : public XMemory +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param xsModel + * @param grammar + * @param manager The configurable memory manager + */ + XSNamespaceItem + ( + XSModel* const xsModel + , SchemaGrammar* const grammar + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XSNamespaceItem + ( + XSModel* const xsModel + , const XMLCh* const schemaNamespace + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSNamespaceItem(); + //@} + + //--------------------- + /** @name XSNamespaceItem methods */ + + //@{ + + /** + * [schema namespace]: A namespace name or null + * corresponding to the target namespace of the schema document. + */ + const XMLCh *getSchemaNamespace() const; + + /** + * [schema components]: a list of top-level components, i.e. element + * declarations, attribute declarations, etc. + * @param objectType The type of the declaration, i.e. + * ELEMENT_DECLARATION, + * TYPE_DEFINITION and any other component type that + * may be a property of a schema component. + * @return A list of top-level definition of the specified type in + * objectType or null. + */ + XSNamedMap *getComponents(XSConstants::COMPONENT_TYPE objectType); + + /** + * [annotations]: a set of annotations. + */ + XSAnnotationList *getAnnotations(); + const XSAnnotationList *getAnnotations() const; + + /** + * Convenience method. Returns a top-level element declaration. + * @param name The name of the declaration. + * @return A top-level element declaration or null if such + * declaration does not exist. + */ + XSElementDeclaration *getElementDeclaration(const XMLCh *name); + + /** + * Convenience method. Returns a top-level attribute declaration. + * @param name The name of the declaration. + * @return A top-level attribute declaration or null if such + * declaration does not exist. + */ + XSAttributeDeclaration *getAttributeDeclaration(const XMLCh *name); + + /** + * Convenience method. Returns a top-level simple or complex type + * definition. + * @param name The name of the definition. + * @return An XSTypeDefinition or null if such + * definition does not exist. + */ + XSTypeDefinition *getTypeDefinition(const XMLCh *name); + + /** + * Convenience method. Returns a top-level attribute group definition. + * @param name The name of the definition. + * @return A top-level attribute group definition or null if + * such definition does not exist. + */ + XSAttributeGroupDefinition *getAttributeGroup(const XMLCh *name); + + /** + * Convenience method. Returns a top-level model group definition. + * @param name The name of the definition. + * @return A top-level model group definition definition or + * null if such definition does not exist. + */ + XSModelGroupDefinition *getModelGroupDefinition(const XMLCh *name); + + /** + * Convenience method. Returns a top-level notation declaration. + * @param name The name of the declaration. + * @return A top-level notation declaration or null if such + * declaration does not exist. + */ + XSNotationDeclaration *getNotationDeclaration(const XMLCh *name); + + /** + * [document location] - a list of locations URI for the documents that + * contributed to the XSModel. + */ + const StringList *getDocumentLocations(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSNamespaceItem(const XSNamespaceItem&); + XSNamespaceItem & operator=(const XSNamespaceItem &); + +protected: + friend class XSModel; + friend class XSObjectFactory; + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fMemoryManager: + // used for any memory allocations + MemoryManager* const fMemoryManager; + SchemaGrammar* fGrammar; + XSModel* fXSModel; + + /* Need a XSNamedMap for each component top-level? + that is top level. + ATTRIBUTE_DECLARATION = 1, + ELEMENT_DECLARATION = 2, + TYPE_DEFINITION = 3, + ATTRIBUTE_USE = 4, no + ATTRIBUTE_GROUP_DEFINITION= 5, + MODEL_GROUP_DEFINITION = 6, + MODEL_GROUP = 7, no + PARTICLE = 8, no + WILDCARD = 9, no + IDENTITY_CONSTRAINT = 10, no + NOTATION_DECLARATION = 11, + ANNOTATION = 12, no + FACET = 13, no + MULTIVALUE_FACET = 14 no + */ + XSNamedMap* fComponentMap[XSConstants::MULTIVALUE_FACET]; + XSAnnotationList* fXSAnnotationList; + RefHashTableOf* fHashMap[XSConstants::MULTIVALUE_FACET]; + const XMLCh* fSchemaNamespace; +}; + +inline XSAnnotationList* XSNamespaceItem::getAnnotations() +{ + return fXSAnnotationList; +} + +inline const XSAnnotationList* XSNamespaceItem::getAnnotations() const +{ + return fXSAnnotationList; +} + +inline const XMLCh *XSNamespaceItem::getSchemaNamespace() const +{ + return fSchemaNamespace; +} + + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSNotationDeclaration.cpp b/include/xercesc/framework/psvi/XSNotationDeclaration.cpp new file mode 100644 index 0000000..a6a5b37 --- /dev/null +++ b/include/xercesc/framework/psvi/XSNotationDeclaration.cpp @@ -0,0 +1,83 @@ +/* + * 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: XSNotationDeclaration.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSNotationDeclaration: Constructors and Destructors +// --------------------------------------------------------------------------- +XSNotationDeclaration::XSNotationDeclaration +( + XMLNotationDecl* const xmlNotationDecl + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager * const manager +) + : XSObject(XSConstants::NOTATION_DECLARATION, xsModel, manager) + , fXMLNotationDecl(xmlNotationDecl) + , fAnnotation(annot) +{ +} + +XSNotationDeclaration::~XSNotationDeclaration() +{ +} + +// --------------------------------------------------------------------------- +// XSNotationDeclaration: XSModel virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSNotationDeclaration::getName() const +{ + return fXMLNotationDecl->getName(); +} + +const XMLCh *XSNotationDeclaration::getNamespace() +{ + return fXSModel->getURIStringPool()->getValueForId(fXMLNotationDecl->getNameSpaceId()); +} + +XSNamespaceItem *XSNotationDeclaration::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + + +// --------------------------------------------------------------------------- +// XSNotationDeclaration: access methods +// --------------------------------------------------------------------------- +const XMLCh *XSNotationDeclaration::getSystemId() +{ + return fXMLNotationDecl->getSystemId(); +} + +const XMLCh *XSNotationDeclaration::getPublicId() +{ + return fXMLNotationDecl->getPublicId(); +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSNotationDeclaration.hpp b/include/xercesc/framework/psvi/XSNotationDeclaration.hpp new file mode 100644 index 0000000..6ea267d --- /dev/null +++ b/include/xercesc/framework/psvi/XSNotationDeclaration.hpp @@ -0,0 +1,154 @@ +/* + * 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: XSNotationDeclaration.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSNOTATIONDECLARATION_HPP) +#define XERCESC_INCLUDE_GUARD_XSNOTATIONDECLARATION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Notation Declaration + * component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class XMLNotationDecl; + +class XMLPARSER_EXPORT XSNotationDeclaration : public XSObject +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param xmlNotationDecl + * @param annot + * @param xsModel + * @param manager The configurable memory manager + */ + XSNotationDeclaration + ( + XMLNotationDecl* const xmlNotationDecl + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSNotationDeclaration(); + //@} + + //--------------------- + /** @name overridden XSXSObject methods */ + + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem *getNamespaceItem(); + + //@} + + //--------------------- + /** @name XSNotationDeclaration methods */ + + //@{ + + /** + * The URI reference representing the system identifier for the notation + * declaration, if present, null otherwise. + */ + const XMLCh *getSystemId(); + + /** + * The string representing the public identifier for this notation + * declaration, if present; null otherwise. + */ + const XMLCh *getPublicId(); + + /** + * Optional. An [annotation]. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSNotationDeclaration(const XSNotationDeclaration&); + XSNotationDeclaration & operator=(const XSNotationDeclaration &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + XMLNotationDecl* fXMLNotationDecl; + XSAnnotation* fAnnotation; +}; + +inline XSAnnotation* XSNotationDeclaration::getAnnotation() const +{ + return fAnnotation; +} + + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSObject.cpp b/include/xercesc/framework/psvi/XSObject.cpp new file mode 100644 index 0000000..c602914 --- /dev/null +++ b/include/xercesc/framework/psvi/XSObject.cpp @@ -0,0 +1,76 @@ +/* + * 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: XSObject.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSObject: Constructors and Destructor +// --------------------------------------------------------------------------- +XSObject::XSObject(XSConstants::COMPONENT_TYPE compType, + XSModel* const xsModel, + MemoryManager* const manager) + : fComponentType(compType) + , fXSModel(xsModel) + , fMemoryManager(manager) + , fId(0) +{ + if (xsModel) + { + xsModel->addComponentToIdVector(this, compType-1); + } +} + +XSObject::~XSObject() +{ +} + +// --------------------------------------------------------------------------- +// XSObject: Virtual interface methods +// --------------------------------------------------------------------------- +const XMLCh *XSObject::getName() const +{ + return 0; +} + +const XMLCh *XSObject::getNamespace() +{ + return 0; +} + +XSNamespaceItem *XSObject::getNamespaceItem() +{ + return 0; +} + +XMLSize_t XSObject::getId() const +{ + return fId; +} + +void XSObject::setId(XMLSize_t id) +{ + fId = id; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSObject.hpp b/include/xercesc/framework/psvi/XSObject.hpp new file mode 100644 index 0000000..4e60611 --- /dev/null +++ b/include/xercesc/framework/psvi/XSObject.hpp @@ -0,0 +1,152 @@ +/* + * 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: XSObject.hpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSOBJECT_HPP) +#define XERCESC_INCLUDE_GUARD_XSOBJECT_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * The XSObject forms the base of the Schema Component Model. It contains + * all properties common to the majority of XML Schema components. + * This is *always* owned by the validator /parser object from which + * it is obtained. It is designed to be subclassed; subclasses will + * specify under what conditions it may be relied upon to have meaningful contents. + */ + +// forward declarations +class XSNamespaceItem; +class XSModel; + +class XMLPARSER_EXPORT XSObject : public XMemory +{ +public: + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param compType + * @param xsModel + * @param manager The configurable memory manager + */ + XSObject + ( + XSConstants::COMPONENT_TYPE compType + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + virtual ~XSObject(); + //@} + + //--------------------- + /** @name XSObject methods */ + + //@{ + + /** + * The type of this object, i.e. + * ELEMENT_DECLARATION. + */ + XSConstants::COMPONENT_TYPE getType() const; + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + virtual const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + virtual const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + virtual XSNamespaceItem *getNamespaceItem(); + + /** + * Optional. Return a unique identifier for a component within this XSModel, to + * optimize querying. May not be defined for all types of component. + * @return id unique for this type of component within this XSModel or 0 + * to indicate that this is not supported for this type of component. + */ + virtual XMLSize_t getId() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + /** + * Set the id to be returned on getId(). + */ + void setId(XMLSize_t id); + //@} + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSObject(const XSObject&); + XSObject & operator=(const XSObject &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fMemoryManager: + // used for any memory allocations + // fComponentType + // the type of the actual component + XSConstants::COMPONENT_TYPE fComponentType; + XSModel* fXSModel; + MemoryManager* fMemoryManager; + XMLSize_t fId; +}; + +inline XSConstants::COMPONENT_TYPE XSObject::getType() const +{ + return fComponentType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSParticle.cpp b/include/xercesc/framework/psvi/XSParticle.cpp new file mode 100644 index 0000000..85a8f9b --- /dev/null +++ b/include/xercesc/framework/psvi/XSParticle.cpp @@ -0,0 +1,81 @@ +/* + * 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: XSParticle.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSParticle: Constructors and Destructor +// --------------------------------------------------------------------------- +XSParticle::XSParticle(TERM_TYPE termType, + XSModel* const xsModel, + XSObject* const particleTerm, + XMLSize_t minOccurs, + XMLSize_t maxOccurs, + bool unbounded, + MemoryManager* const manager) + : XSObject(XSConstants::PARTICLE, xsModel, manager) + , fTermType(termType) + , fMinOccurs(minOccurs) + , fMaxOccurs(maxOccurs) + , fUnbounded (unbounded) + , fTerm(particleTerm) +{ +} + +XSParticle::~XSParticle() +{ + if (fTerm && (fTermType == TERM_MODELGROUP)) + delete ((XSModelGroup*) fTerm); +} + +// --------------------------------------------------------------------------- +// XSParticle: methods +// --------------------------------------------------------------------------- +XSElementDeclaration *XSParticle::getElementTerm() +{ + if (fTermType == TERM_ELEMENT) + return (XSElementDeclaration*) fTerm; + + return 0; +} + +XSModelGroup *XSParticle::getModelGroupTerm() +{ + if (fTermType == TERM_MODELGROUP) + return (XSModelGroup*) fTerm; + + return 0; +} + +XSWildcard *XSParticle::getWildcardTerm() +{ + if (fTermType == TERM_WILDCARD) + return (XSWildcard*) fTerm; + + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSParticle.hpp b/include/xercesc/framework/psvi/XSParticle.hpp new file mode 100644 index 0000000..4481c2d --- /dev/null +++ b/include/xercesc/framework/psvi/XSParticle.hpp @@ -0,0 +1,198 @@ +/* + * 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: XSParticle.hpp 883665 2009-11-24 11:41:38Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSPARTICLE_HPP) +#define XERCESC_INCLUDE_GUARD_XSPARTICLE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Particle + * component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSElementDeclaration; +class XSModelGroup; +class XSWildcard; + +class XMLPARSER_EXPORT XSParticle : public XSObject +{ +public: + + // possible terms of this particle + enum TERM_TYPE { + /* + * an empty particle + */ + TERM_EMPTY = 0, + /* + * the particle has element content + */ + TERM_ELEMENT = XSConstants::ELEMENT_DECLARATION, + /* + * the particle's content is a model group + */ + TERM_MODELGROUP = XSConstants::MODEL_GROUP_DEFINITION, + /* + * the particle's content is a wildcard + */ + TERM_WILDCARD = XSConstants::WILDCARD + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param termType + * @param xsModel + * @param particleTerm + * @param minOccurs + * @param maxOccurs + * @param unbounded + * @param manager The configurable memory manager + */ + XSParticle + ( + TERM_TYPE termType + , XSModel* const xsModel + , XSObject* const particleTerm + , XMLSize_t minOccurs + , XMLSize_t maxOccurs + , bool unbounded + , MemoryManager* const manager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSParticle(); + //@} + + //--------------------- + /** @name XSParticle methods */ + //@{ + + /** + * [min occurs]: determines the minimum number of terms that can occur. + */ + XMLSize_t getMinOccurs() const; + + /** + * [max occurs] determines the maximum number of terms that can occur. To + * query for value of unbounded use maxOccursUnbounded. + */ + XMLSize_t getMaxOccurs() const; + + /** + * [max occurs] whether the maxOccurs value is unbounded. + */ + bool getMaxOccursUnbounded() const; + + /** + * Returns the type of the [term]: one of + * TERM_EMPTY, TERM_ELEMENT, TERM_MODELGROUP, or TERM_WILDCARD. + */ + TERM_TYPE getTermType() const; + + /** + * If this particle has an [element declaration] for its term, + * this method returns that declaration; otherwise, it returns 0. + * @returns The element declaration that is the [term] of this Particle + * if and only if getTermType() == TERM_ELEMENT. + */ + XSElementDeclaration *getElementTerm(); + + /** + * If this particle has a [model group] for its term, + * this method returns that definition; otherwise, it returns 0. + * @returns The model group that is the [term] of this Particle + * if and only if getTermType() == TERM_MODELGROUP. + */ + XSModelGroup *getModelGroupTerm(); + + /** + * If this particle has an [wildcard] for its term, + * this method returns that declaration; otherwise, it returns 0. + * @returns The wildcard declaration that is the [term] of this Particle + * if and only if getTermType() == TERM_WILDCARD. + */ + XSWildcard *getWildcardTerm(); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSParticle(const XSParticle&); + XSParticle & operator=(const XSParticle &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + TERM_TYPE fTermType; + XMLSize_t fMinOccurs; + XMLSize_t fMaxOccurs; + bool fUnbounded; + XSObject* fTerm; +}; + +inline XMLSize_t XSParticle::getMinOccurs() const +{ + return fMinOccurs; +} + +inline XMLSize_t XSParticle::getMaxOccurs() const +{ + return fMaxOccurs; +} + +inline bool XSParticle::getMaxOccursUnbounded() const +{ + return fUnbounded; +} + +inline XSParticle::TERM_TYPE XSParticle::getTermType() const +{ + return fTermType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSSimpleTypeDefinition.cpp b/include/xercesc/framework/psvi/XSSimpleTypeDefinition.cpp new file mode 100644 index 0000000..bc53ead --- /dev/null +++ b/include/xercesc/framework/psvi/XSSimpleTypeDefinition.cpp @@ -0,0 +1,249 @@ +/* + * 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: XSSimpleTypeDefinition.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local, static functions +// --------------------------------------------------------------------------- +static bool XSSimpleTypeDefinitionTestFlag(int flag) +{ + if (flag) + return true; + return false; +} + + +// --------------------------------------------------------------------------- +// XSSimpleTypeDefinition: Constructors and Destructors +// --------------------------------------------------------------------------- +XSSimpleTypeDefinition::XSSimpleTypeDefinition +( + DatatypeValidator* const datatypeValidator + , VARIETY stVariety + , XSTypeDefinition* const xsBaseType + , XSSimpleTypeDefinition* const primitiveOrItemType + , XSSimpleTypeDefinitionList* const memberTypes + , XSAnnotation* headAnnot + , XSModel* const xsModel + , MemoryManager* const manager +) + : XSTypeDefinition(SIMPLE_TYPE, xsBaseType, xsModel, manager) + , fDefinedFacets(0) + , fFixedFacets(0) + , fVariety(stVariety) + , fDatatypeValidator(datatypeValidator) + , fXSFacetList(0) + , fXSMultiValueFacetList(0) + , fPatternList(0) + , fPrimitiveOrItemType(primitiveOrItemType) + , fMemberTypes(memberTypes) + , fXSAnnotationList(0) +{ + int finalset = fDatatypeValidator->getFinalSet(); + if (finalset) + { + if (finalset & SchemaSymbols::XSD_EXTENSION) + fFinal |= XSConstants::DERIVATION_EXTENSION; + + if (finalset & SchemaSymbols::XSD_RESTRICTION) + fFinal |= XSConstants::DERIVATION_RESTRICTION; + + if (finalset & SchemaSymbols::XSD_LIST) + fFinal |= XSConstants::DERIVATION_LIST; + + if (finalset & SchemaSymbols::XSD_UNION) + fFinal |= XSConstants::DERIVATION_UNION; + } + + if (headAnnot) + { + XSAnnotation* annot = headAnnot; + + fXSAnnotationList = new (manager) RefVectorOf(3, false, manager); + do + { + fXSAnnotationList->addElement(annot); + annot = annot->getNext(); + } while (annot); + } +} + +XSSimpleTypeDefinition::~XSSimpleTypeDefinition() +{ + if (fXSFacetList) + delete fXSFacetList; + + if (fXSMultiValueFacetList) + delete fXSMultiValueFacetList; + + if (fPatternList) + delete fPatternList; + + // don't delete fPrimitiveOrItemType -> deleted by XSModel + if (fMemberTypes) + delete fMemberTypes; + + if (fXSAnnotationList) + delete fXSAnnotationList; +} + + +// --------------------------------------------------------------------------- +// XSSimpleTypeDefinition: access methods +// --------------------------------------------------------------------------- +bool XSSimpleTypeDefinition::isDefinedFacet(FACET facetName) +{ + return XSSimpleTypeDefinitionTestFlag(fDefinedFacets & facetName); +} + +bool XSSimpleTypeDefinition::isFixedFacet(FACET facetName) +{ + return XSSimpleTypeDefinitionTestFlag(fFixedFacets & facetName); +} + +const XMLCh *XSSimpleTypeDefinition::getLexicalFacetValue(FACET facetName) +{ + XMLSize_t size = fXSFacetList->size(); + for (XMLSize_t i=0; ielementAt(i))->getFacetKind()) == facetName) + return (fXSFacetList->elementAt(i))->getLexicalFacetValue(); + } + return 0; +} + +StringList *XSSimpleTypeDefinition::getLexicalEnumeration() +{ + return (RefArrayVectorOf*) fDatatypeValidator->getEnumString(); +} + +XSSimpleTypeDefinition::ORDERING XSSimpleTypeDefinition::getOrdered() const +{ + return fDatatypeValidator->getOrdered(); +} + +bool XSSimpleTypeDefinition::getFinite() const +{ + return fDatatypeValidator->getFinite(); +} + +bool XSSimpleTypeDefinition::getBounded() const +{ + return fDatatypeValidator->getBounded(); +} + +bool XSSimpleTypeDefinition::getNumeric() const +{ + return fDatatypeValidator->getNumeric(); +} + + +// --------------------------------------------------------------------------- +// XSSimpleTypeDefinition: virtual methods +// --------------------------------------------------------------------------- +const XMLCh *XSSimpleTypeDefinition::getName() const +{ + return fDatatypeValidator->getTypeLocalName(); +} + +const XMLCh *XSSimpleTypeDefinition::getNamespace() +{ + return fDatatypeValidator->getTypeUri(); +} + +XSNamespaceItem *XSSimpleTypeDefinition::getNamespaceItem() +{ + return fXSModel->getNamespaceItem(getNamespace()); +} + +bool XSSimpleTypeDefinition::getAnonymous() const +{ + return fDatatypeValidator->getAnonymous(); +} + +XSTypeDefinition *XSSimpleTypeDefinition::getBaseType() +{ + return fBaseType; +} + +bool XSSimpleTypeDefinition::derivedFromType(const XSTypeDefinition * const ancestorType) +{ + if (!ancestorType) + return false; + + XSTypeDefinition* type; + + if (ancestorType->getTypeCategory() == XSTypeDefinition::COMPLEX_TYPE) + { + type = (XSTypeDefinition*) ancestorType; + if (ancestorType == type->getBaseType()) + { + // ancestor is anytype + return true; + } + return false; + } + + type = this; + XSTypeDefinition* lastType = 0; // anysimple type has a base type of anytype + // anytype has a basetype of anytype so will have infinite loop... + + while (type && (type != ancestorType) && (type != lastType)) + { + lastType = type; + type = type->getBaseType(); + } + + return (type == ancestorType); +} + +// --------------------------------------------------------------------------- +// XSSimpleTypeDefinition: helper methods +// --------------------------------------------------------------------------- +void XSSimpleTypeDefinition::setFacetInfo +( + int definedFacets + , int fixedFacets + , XSFacetList* const xsFacetList + , XSMultiValueFacetList* const xsMultiValueFacetList + , StringList* const patternList +) +{ + fDefinedFacets = definedFacets; + fFixedFacets = fixedFacets; + fXSFacetList = xsFacetList; + fXSMultiValueFacetList = xsMultiValueFacetList; + fPatternList = patternList; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSSimpleTypeDefinition.hpp b/include/xercesc/framework/psvi/XSSimpleTypeDefinition.hpp new file mode 100644 index 0000000..44997ff --- /dev/null +++ b/include/xercesc/framework/psvi/XSSimpleTypeDefinition.hpp @@ -0,0 +1,458 @@ +/* + * 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: XSSimpleTypeDefinition.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSSIMPLETYPEDEFINITION_HPP) +#define XERCESC_INCLUDE_GUARD_XSSIMPLETYPEDEFINITION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class represents a simpleType definition + * schema component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + * + */ + +// forward declarations +class XSAnnotation; +class XSFacet; +class XSMultiValueFacet; +class DatatypeValidator; + +class XMLPARSER_EXPORT XSSimpleTypeDefinition : public XSTypeDefinition +{ +public: + + // Variety definitions + enum VARIETY { + /** + * The variety is absent for the anySimpleType definition. + */ + VARIETY_ABSENT = 0, + /** + * Atomic type. + */ + VARIETY_ATOMIC = 1, + /** + * List type. + */ + VARIETY_LIST = 2, + /** + * Union type. + */ + VARIETY_UNION = 3 + }; + + // Facets + enum FACET { + /** + * No facets defined. + */ + FACET_NONE = 0, + /** + * 4.3.1 Length + */ + FACET_LENGTH = 1, + /** + * 4.3.2 minLength. + */ + FACET_MINLENGTH = 2, + /** + * 4.3.3 maxLength. + */ + FACET_MAXLENGTH = 4, + /** + * 4.3.4 pattern. + */ + FACET_PATTERN = 8, + /** + * 4.3.5 whitespace. + */ + FACET_WHITESPACE = 16, + /** + * 4.3.7 maxInclusive. + */ + FACET_MAXINCLUSIVE = 32, + /** + * 4.3.9 maxExclusive. + */ + FACET_MAXEXCLUSIVE = 64, + /** + * 4.3.9 minExclusive. + */ + FACET_MINEXCLUSIVE = 128, + /** + * 4.3.10 minInclusive. + */ + FACET_MININCLUSIVE = 256, + /** + * 4.3.11 totalDigits . + */ + FACET_TOTALDIGITS = 512, + /** + * 4.3.12 fractionDigits. + */ + FACET_FRACTIONDIGITS = 1024, + /** + * 4.3.5 enumeration. + */ + FACET_ENUMERATION = 2048 + }; + + // possible order relations + enum ORDERING { + /** + * A constant defined for the 'ordered' fundamental facet: Not ordered. + */ + ORDERED_FALSE = 0, + /** + * A constant defined for the 'ordered' fundamental facet: partially + * ordered. + */ + ORDERED_PARTIAL = 1, + /** + * A constant defined for the 'ordered' fundamental facet: total ordered. + */ + ORDERED_TOTAL = 2 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param datatypeValidator + * @param stVariety + * @param xsBaseType + * @param primitiveOrItemType + * @param memberTypes + * @param headAnnot + * @param xsModel + * @param manager The configurable memory manager + */ + XSSimpleTypeDefinition + ( + DatatypeValidator* const datatypeValidator + , VARIETY stVariety + , XSTypeDefinition* const xsBaseType + , XSSimpleTypeDefinition* const primitiveOrItemType + , XSSimpleTypeDefinitionList* const memberTypes + , XSAnnotation* headAnnot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + ~XSSimpleTypeDefinition(); + //@} + + //--------------------- + /** @name XSSimpleTypeDefinition methods */ + + //@{ + + /** + * [variety]: one of {atomic, list, union} or absent + */ + VARIETY getVariety() const; + + /** + * If variety is atomic the primitive type definition (a + * built-in primitive datatype definition or the simple ur-type + * definition) is available, otherwise null. + */ + XSSimpleTypeDefinition *getPrimitiveType(); + + /** + * If variety is list the item type definition (an atomic or + * union simple type definition) is available, otherwise + * null. + */ + XSSimpleTypeDefinition *getItemType(); + + /** + * If variety is union the list of member type definitions (a + * non-empty sequence of simple type definitions) is available, + * otherwise null. + */ + XSSimpleTypeDefinitionList *getMemberTypes() const; + + /** + * [facets]: get all facets defined on this type. The value is a bit + * combination of FACET_XXX constants of all defined facets. + */ + int getDefinedFacets() const; + + /** + * Convenience method. [Facets]: check whether a facet is defined on this + * type. + * @param facetName The name of the facet. + * @return True if the facet is defined, false otherwise. + */ + bool isDefinedFacet(FACET facetName); + + /** + * [facets]: get all facets defined and fixed on this type. + */ + int getFixedFacets() const; + + /** + * Convenience method. [Facets]: check whether a facet is defined and + * fixed on this type. + * @param facetName The name of the facet. + * @return True if the facet is fixed, false otherwise. + */ + bool isFixedFacet(FACET facetName); + + /** + * Convenience method. Returns a value of a single constraining facet for + * this simple type definition. This method must not be used to retrieve + * values for enumeration and pattern facets. + * @param facetName The name of the facet, i.e. + * FACET_LENGTH, FACET_TOTALDIGITS (see + * XSConstants).To retrieve value for pattern or + * enumeration, see enumeration and pattern. + * @return A value of the facet specified in facetName for + * this simple type definition or null. + */ + const XMLCh *getLexicalFacetValue(FACET facetName); + + /** + * Returns a list of enumeration values. + */ + StringList *getLexicalEnumeration(); + + /** + * Returns a list of pattern values. + */ + StringList *getLexicalPattern(); + + /** + * Fundamental Facet: ordered + */ + ORDERING getOrdered() const; + + /** + * Fundamental Facet: cardinality. + */ + bool getFinite() const; + + /** + * Fundamental Facet: bounded. + */ + bool getBounded() const; + + /** + * Fundamental Facet: numeric. + */ + bool getNumeric() const; + + /** + * Optional. A set of [annotation]s. + */ + XSAnnotationList *getAnnotations(); + /** + * @return list of constraining facets. + * This method must not be used to retrieve + * values for enumeration and pattern facets. + */ + XSFacetList *getFacets(); + + /** + * @return list of enumeration and pattern facets. + */ + XSMultiValueFacetList *getMultiValueFacets(); + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + const XMLCh* getName() const; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + const XMLCh* getNamespace(); + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + XSNamespaceItem *getNamespaceItem(); + + /** + * A boolean that specifies if the type definition is + * anonymous. Convenience attribute. + */ + bool getAnonymous() const; + + /** + * {base type definition}: either a simple type definition or a complex + * type definition. + */ + XSTypeDefinition *getBaseType(); + + /** + * Convenience method: check if this type is derived from the given + * ancestorType. + * @param ancestorType An ancestor type definition. + * @return Return true if this type is derived from + * ancestorType. + */ + bool derivedFromType(const XSTypeDefinition* const ancestorType); + + /** + * + */ + inline DatatypeValidator* getDatatypeValidator() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + + //@} + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSSimpleTypeDefinition(const XSSimpleTypeDefinition&); + XSSimpleTypeDefinition & operator=(const XSSimpleTypeDefinition &); + + /** + * Helper method for construct + */ + void setFacetInfo + ( + int definedFacets + , int fixedFacets + , XSFacetList* const xsFacetList + , XSMultiValueFacetList* const xsMultiValueFacetList + , StringList* const patternList + ); + void setPrimitiveType(XSSimpleTypeDefinition* const toSet); + + friend class XSObjectFactory; + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + int fDefinedFacets; + int fFixedFacets; + VARIETY fVariety; + DatatypeValidator* fDatatypeValidator; + XSFacetList* fXSFacetList; + XSMultiValueFacetList* fXSMultiValueFacetList; + StringList* fPatternList; + XSSimpleTypeDefinition* fPrimitiveOrItemType; + XSSimpleTypeDefinitionList* fMemberTypes; + XSAnnotationList* fXSAnnotationList; +}; + +inline XSSimpleTypeDefinition::VARIETY XSSimpleTypeDefinition::getVariety() const +{ + return fVariety; +} + +inline XSSimpleTypeDefinition* XSSimpleTypeDefinition::getPrimitiveType() +{ + if (fVariety == VARIETY_ATOMIC) + return fPrimitiveOrItemType; + + return 0; +} + +inline XSSimpleTypeDefinition* XSSimpleTypeDefinition::getItemType() +{ + if (fVariety == VARIETY_LIST) + return fPrimitiveOrItemType; + + return 0; +} + +inline XSSimpleTypeDefinitionList* XSSimpleTypeDefinition::getMemberTypes() const +{ + return fMemberTypes; +} + +inline int XSSimpleTypeDefinition::getDefinedFacets() const +{ + return fDefinedFacets; +} + +inline int XSSimpleTypeDefinition::getFixedFacets() const +{ + return fFixedFacets; +} + +inline StringList* XSSimpleTypeDefinition::getLexicalPattern() +{ + return fPatternList; +} + +inline XSFacetList* XSSimpleTypeDefinition::getFacets() +{ + return fXSFacetList; +} + +inline XSMultiValueFacetList* XSSimpleTypeDefinition::getMultiValueFacets() +{ + return fXSMultiValueFacetList; +} + +inline XSAnnotationList *XSSimpleTypeDefinition::getAnnotations() +{ + return fXSAnnotationList; +} + +inline void +XSSimpleTypeDefinition::setPrimitiveType(XSSimpleTypeDefinition* const toSet) +{ + fPrimitiveOrItemType = toSet; +} + +inline DatatypeValidator* +XSSimpleTypeDefinition::getDatatypeValidator() const +{ + return fDatatypeValidator; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSTypeDefinition.cpp b/include/xercesc/framework/psvi/XSTypeDefinition.cpp new file mode 100644 index 0000000..505d983 --- /dev/null +++ b/include/xercesc/framework/psvi/XSTypeDefinition.cpp @@ -0,0 +1,74 @@ +/* + * 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: XSTypeDefinition.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSTypeDefinition: Constructors and Destructor +// --------------------------------------------------------------------------- +XSTypeDefinition::XSTypeDefinition(TYPE_CATEGORY typeCategory, + XSTypeDefinition* const xsBaseType, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::TYPE_DEFINITION, xsModel, manager) + , fTypeCategory(typeCategory) + , fFinal(0) + , fBaseType(xsBaseType) +{ +} + +XSTypeDefinition::~XSTypeDefinition() +{ +} + +// --------------------------------------------------------------------------- +// XSTypeDefinition: access methods +// --------------------------------------------------------------------------- +bool XSTypeDefinition::isFinal(short toTest) +{ + if (fFinal & toTest) + return true; + + return false; + +} + +bool XSTypeDefinition::derivedFrom(const XMLCh *typeNamespace, + const XMLCh *name) +{ + if (!name) + return false; + + XSTypeDefinition* type = fXSModel->getTypeDefinition(name, typeNamespace); + + if (!type) + return false; + + return derivedFromType(type); +} + +XERCES_CPP_NAMESPACE_END + + diff --git a/include/xercesc/framework/psvi/XSTypeDefinition.hpp b/include/xercesc/framework/psvi/XSTypeDefinition.hpp new file mode 100644 index 0000000..81236fe --- /dev/null +++ b/include/xercesc/framework/psvi/XSTypeDefinition.hpp @@ -0,0 +1,214 @@ +/* + * 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: XSTypeDefinition.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSTYPEDEFINITION_HPP) +#define XERCESC_INCLUDE_GUARD_XSTYPEDEFINITION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// forward declarations +class XSNamespaceItem; + +/** + * This class represents a complexType or simpleType definition. + * This is *always* owned by the validator /parser object from which + * it is obtained. + * + */ + +class XMLPARSER_EXPORT XSTypeDefinition : public XSObject +{ +public: + + enum TYPE_CATEGORY { + /** + * This constant value signifies a complex type. + */ + COMPLEX_TYPE = 15, + /** + * This constant value signifies a simple type. + */ + SIMPLE_TYPE = 16 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param typeCategory + * @param xsBaseType + * @param xsModel + * @param manager The configurable memory manager + */ + XSTypeDefinition + ( + TYPE_CATEGORY typeCategory + , XSTypeDefinition* const xsBaseType + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + /** @name Destructor */ + //@{ + virtual ~XSTypeDefinition(); + //@} + + //--------------------- + /** @name overloaded XSObject methods */ + //@{ + + /** + * The name of type NCName of this declaration as defined in + * XML Namespaces. + */ + virtual const XMLCh* getName() const = 0; + + /** + * The [target namespace] of this object, or null if it is + * unspecified. + */ + virtual const XMLCh* getNamespace() = 0; + + /** + * A namespace schema information item corresponding to the target + * namespace of the component, if it's globally declared; or null + * otherwise. + */ + virtual XSNamespaceItem *getNamespaceItem() = 0; + + //@} + + //--------------------- + /** @name XSTypeDefinition methods */ + + //@{ + + /** + * Return whether this type definition is a simple type or complex type. + */ + TYPE_CATEGORY getTypeCategory() const; + + /** + * {base type definition}: either a simple type definition or a complex + * type definition. + */ + virtual XSTypeDefinition *getBaseType() = 0; + + /** + * {final}. For complex type definition it is a subset of {extension, + * restriction}. For simple type definition it is a subset of + * {extension, list, restriction, union}. + * @param toTest Extension, restriction, list, union constants + * (defined in XSObject). + * @return True if toTest is in the final set, otherwise false. + */ + bool isFinal(short toTest); + + /** + * For complex types the returned value is a bit combination of the subset + * of {DERIVATION_EXTENSION, DERIVATION_RESTRICTION} + * corresponding to final set of this type or + * DERIVATION_NONE. For simple types the returned value is + * a bit combination of the subset of { + * DERIVATION_RESTRICTION, DERIVATION_EXTENSION, DERIVATION_UNION, DERIVATION_LIST + * } corresponding to final set of this type or + * DERIVATION_NONE. + */ + short getFinal() const; + + /** + * A boolean that specifies if the type definition is + * anonymous. Convenience attribute. + */ + virtual bool getAnonymous() const = 0; + + /** + * Convenience method: check if this type is derived from the given + * ancestorType. + * @param ancestorType An ancestor type definition. + * @return Return true if this type is derived from + * ancestorType. + */ + virtual bool derivedFromType(const XSTypeDefinition* const ancestorType) = 0; + + /** + * Convenience method: check if this type is derived from the given + * ancestor type. + * @param typeNamespace An ancestor type namespace. + * @param name An ancestor type name. + * @return Return true if this type is derived from + * the ancestor defined by typeNamespace and name. + */ + bool derivedFrom(const XMLCh* typeNamespace, + const XMLCh* name); + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSTypeDefinition(const XSTypeDefinition&); + XSTypeDefinition & operator=(const XSTypeDefinition &); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + // fTypeCategory + // whether this is a simpleType or complexType + // fFinal + // the final properties which is set by the derived class. + TYPE_CATEGORY fTypeCategory; + short fFinal; + XSTypeDefinition* fBaseType; // owned by XSModel +}; + +inline XSTypeDefinition::TYPE_CATEGORY XSTypeDefinition::getTypeCategory() const +{ + return fTypeCategory; +} + +inline short XSTypeDefinition::getFinal() const +{ + return fFinal; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSValue.cpp b/include/xercesc/framework/psvi/XSValue.cpp new file mode 100644 index 0000000..5a0028a --- /dev/null +++ b/include/xercesc/framework/psvi/XSValue.cpp @@ -0,0 +1,1689 @@ +/* + * 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: XSValue.cpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*** issues + * + * 1. For float, double, datetime family, the validation is almost similar to getActualValue + * + * + * DataType DataGroup + * num dtm str validation canonical actual-value + * ====================================================================================================== + * dt_string str [2] Char NA content + * dt_boolean str {true, false, 1, 0} {true, false} bool + * dt_decimal num lexical only yes double + * dt_float num lexical/value yes double + * dt_double num lexical/value yes double + * --------------------------------------------------------------------------------------------------------- + * 5 dt_duration dtm yes NA struct datetime + * dt_dateTime dtm yes yes struct datetime + * dt_time dtm yes yes struct datetime + * dt_date dtm yes NA struct datetime + * dt_gYearMonth dtm yes NA struct datetime + * --------------------------------------------------------------------------------------------------------- + * 10 dt_gYear dtm yes NA struct datetime + * dt_gMonthDay dtm yes NA struct datetime + * dt_gDay dtm yes NA struct datetime + * dt_gMonth dtm yes NA struct datetime + * dt_hexBinary str decoding ([a-f]) unsigned long ? + * --------------------------------------------------------------------------------------------------------- + * 15 dt_base64Binary str decoding NA (errata?) unsigned long ? + * dt_anyURI str yes NA content + * dt_QName str a:b , [6]QName NA content + * dt_NOTATION str [6]QName NA content + * dt_normalizedString str no #xD #xA #x9 NA content + * --------------------------------------------------------------------------------------------------------- + * 20 dt_token str no #xD #xA #x9 traling NA content + * dt_language str language id NA content + * dt_NMTOKEN str [7] Nmtoken NA content + * dt_NMTOKENS str [8] Nmtokens NA content + * dt_Name str [5] Name NA content + * --------------------------------------------------------------------------------------------------------- + * 25 dt_NCName str [4] NCName NA content + * dt_ID str [4] NCName NA content + * dt_IDREF str [4] NCName NA content + * dt_IDREFS str ws seped IDREF NA content + * dt_ENTITY str [4] NCName NA content + * --------------------------------------------------------------------------------------------------------- + * 30 dt_ENTITIES str ws seped ENTITY NA content + * dt_integer num lexical yes long + * dt_nonPositiveInteger num lexical yes long + * dt_negativeInteger num lexical yes long + * dt_long num lexical yes long + * --------------------------------------------------------------------------------------------------------- + * 35 dt_int num lexical yes int + * dt_short num lexical yes short + * dt_byte num lexical yes char + * dt_nonNegativeInteger num lexical yes unsigned long + * dt_unsignedLong num lexical yes unsigned long + * --------------------------------------------------------------------------------------------------------- + * 40 dt_unsignedInt num lexical yes unsigned int + * dt_unsignedShort num lexical yes unsigned short + * dt_unsignedByte num lexical yes unsigned char + * dt_positiveInteger num lexical yes unsigned long + * + ***/ + +const XSValue::DataGroup XSValue::inGroup[XSValue::dt_MAXCOUNT] = +{ + dg_strings, dg_strings, dg_numerics, dg_numerics, dg_numerics, + dg_datetimes, dg_datetimes, dg_datetimes, dg_datetimes, dg_datetimes, + dg_datetimes, dg_datetimes, dg_datetimes, dg_datetimes, dg_strings, + dg_strings, dg_strings, dg_strings, dg_strings, dg_strings, + dg_strings, dg_strings, dg_strings, dg_strings, dg_strings, + dg_strings, dg_strings, dg_strings, dg_strings, dg_strings, + dg_strings, dg_numerics, dg_numerics, dg_numerics, dg_numerics, + dg_numerics, dg_numerics, dg_numerics, dg_numerics, dg_numerics, + dg_numerics, dg_numerics, dg_numerics, dg_numerics +}; + +const bool XSValue::numericSign[XSValue::dt_MAXCOUNT] = +{ + true, true, true, true, true, + true, true, true, true, true, + true, true, true, true, true, + true, true, true, true, true, + true, true, true, true, true, + true, true, true, true, true, + true, true, true, true, true, + true, true, true, false, false, + false, false, false, false +}; + +// --------------------------------------------------------------------------- +// Local static functions +// --------------------------------------------------------------------------- +static RegularExpression* sXSValueRegEx = 0; +ValueHashTableOf* XSValue::fDataTypeRegistry = 0; + +void XMLInitializer::initializeXSValue() +{ + sXSValueRegEx = new RegularExpression( + XMLUni::fgLangPattern, SchemaSymbols::fgRegEx_XOption); + + XSValue::initializeRegistry(); +} + +void XMLInitializer::terminateXSValue() +{ + delete XSValue::fDataTypeRegistry; + XSValue::fDataTypeRegistry = 0; + + delete sXSValueRegEx; + sXSValueRegEx = 0; +} + +XSValue::DataType XSValue::getDataType(const XMLCh* const dtString) +{ + if (fDataTypeRegistry->containsKey(dtString)) { + return fDataTypeRegistry->get(dtString); + } + + return dt_MAXCOUNT; +} + +void XSValue::initializeRegistry() +{ + //using the XMLPlatformUtils::fgMemoryManager + fDataTypeRegistry = new ValueHashTableOf(43); + + if (fDataTypeRegistry) { + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_STRING, XSValue::dt_string); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_BOOLEAN, XSValue::dt_boolean); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DECIMAL, XSValue::dt_decimal); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_FLOAT, XSValue::dt_float); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DOUBLE, XSValue::dt_double); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DURATION, XSValue::dt_duration); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DATETIME, XSValue::dt_dateTime); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_TIME, XSValue::dt_time); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DATE, XSValue::dt_date); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_YEARMONTH, XSValue::dt_gYearMonth); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_YEAR, XSValue::dt_gYear); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_MONTHDAY, XSValue::dt_gMonthDay); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_DAY, XSValue::dt_gDay); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_MONTH, XSValue::dt_gMonth); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_HEXBINARY, XSValue::dt_hexBinary); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_BASE64BINARY, XSValue::dt_base64Binary); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_ANYURI, XSValue::dt_anyURI); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_QNAME, XSValue::dt_QName); + fDataTypeRegistry->put((void*) XMLUni::fgNotationString, XSValue::dt_NOTATION); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NORMALIZEDSTRING, XSValue::dt_normalizedString); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_TOKEN, XSValue::dt_token); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_LANGUAGE, XSValue::dt_language); + fDataTypeRegistry->put((void*) XMLUni::fgNmTokenString, XSValue::dt_NMTOKEN); + fDataTypeRegistry->put((void*) XMLUni::fgNmTokensString, XSValue::dt_NMTOKENS); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NAME, XSValue::dt_Name); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NCNAME, XSValue::dt_NCName); + fDataTypeRegistry->put((void*) XMLUni::fgIDString, XSValue::dt_ID); + fDataTypeRegistry->put((void*) XMLUni::fgIDRefString, XSValue::dt_IDREF); + fDataTypeRegistry->put((void*) XMLUni::fgIDRefsString, XSValue::dt_IDREFS); + fDataTypeRegistry->put((void*) XMLUni::fgEntityString, XSValue::dt_ENTITY); + fDataTypeRegistry->put((void*) XMLUni::fgEntitiesString, XSValue::dt_ENTITIES); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_INTEGER, XSValue::dt_integer); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NONPOSITIVEINTEGER, XSValue::dt_nonPositiveInteger); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NEGATIVEINTEGER, XSValue::dt_negativeInteger); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_LONG, XSValue::dt_long); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_INT, XSValue::dt_int); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_SHORT, XSValue::dt_short); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_BYTE, XSValue::dt_byte); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_NONNEGATIVEINTEGER, XSValue::dt_nonNegativeInteger); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_ULONG, XSValue::dt_unsignedLong); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_UINT, XSValue::dt_unsignedInt); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_USHORT, XSValue::dt_unsignedShort); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_UBYTE, XSValue::dt_unsignedByte); + fDataTypeRegistry->put((void*) SchemaSymbols::fgDT_POSITIVEINTEGER, XSValue::dt_positiveInteger); + } +} + +static bool checkTimeZoneError(XSValue::DataType const &datatype + , SchemaDateTimeException const &e ) +{ + return (((datatype == XSValue::dt_dateTime) || (datatype == XSValue::dt_time) || (datatype == XSValue::dt_date)) && + ((e.getCode() == XMLExcepts::DateTime_tz_noUTCsign) || + (e.getCode() == XMLExcepts::DateTime_tz_stuffAfterZ) || + (e.getCode() == XMLExcepts::DateTime_tz_invalid) || + (e.getCode() == XMLExcepts::DateTime_tz_hh_invalid))); +} + +// --------------------------------------------------------------------------- +// Local Data +// --------------------------------------------------------------------------- + +static const XMLCh Separator_20[] = {chSpace, chNull}; +static const XMLCh Separator_ws[] = {chSpace, chLF, chCR, chHTab, chNull}; + +// --------------------------------------------------------------------------- +// XSValue: Constructors and Destructor +// --------------------------------------------------------------------------- +XSValue::XSValue(DataType const dt + , MemoryManager* const manager) + :fMemAllocated(false) + ,fMemoryManager(manager) +{ + fData.f_datatype = dt; +} + +XSValue::~XSValue() +{ + if (fMemAllocated) + fMemoryManager->deallocate(fData.fValue.f_byteVal); +} + +// --------------------------------------------------------------------------- +// XSValue: Public Interface +// +// No exception is thrown from these methods +// +// --------------------------------------------------------------------------- +bool XSValue::validate(const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , MemoryManager* const manager) +{ + if (!content || + !*content || + ((version == ver_10) && (XMLChar1_0::isAllSpaces(content, XMLString::stringLen(content)))) || + ((version == ver_11) && (XMLChar1_1::isAllSpaces(content, XMLString::stringLen(content)))) ) { + + switch (datatype) { + case XSValue::dt_string: + case XSValue::dt_normalizedString: + case XSValue::dt_token: + case XSValue::dt_anyURI: + case XSValue::dt_hexBinary: + case XSValue::dt_base64Binary: + status = st_Init; + return true; + break; + default: + status = st_NoContent; + return false; + break; + } + } + + status = st_Init; + + switch (inGroup[datatype]) { + case XSValue::dg_numerics: + return validateNumerics(content, datatype, status, manager); + break; + case XSValue::dg_datetimes: + return validateDateTimes(content, datatype, status, manager); + break; + case XSValue::dg_strings: + return validateStrings(content, datatype, status, version, manager); + break; + default: + status = st_UnknownType; + + return false; + break; + } + return false; +} + +XMLCh* +XSValue::getCanonicalRepresentation(const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , bool toValidate + , MemoryManager* const manager) +{ + if (!content || + !*content || + ((version == ver_10) && (XMLChar1_0::isAllSpaces(content, XMLString::stringLen(content)))) || + ((version == ver_11) && (XMLChar1_1::isAllSpaces(content, XMLString::stringLen(content)))) ) { + status = st_NoContent; + return 0; + } + + status = st_Init; + + switch (inGroup[datatype]) { + case XSValue::dg_numerics: + return getCanRepNumerics(content, datatype, status, toValidate, manager); + break; + case XSValue::dg_datetimes: + return getCanRepDateTimes(content, datatype, status, toValidate, manager); + break; + case XSValue::dg_strings: + return getCanRepStrings(content, datatype, status, version, toValidate, manager); + break; + default: + status = st_UnknownType; + + return 0; + break; + } + return 0; +} + +XSValue* XSValue::getActualValue(const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , bool toValidate + , MemoryManager* const manager) +{ + if (!content || + !*content || + ((version == ver_10) && (XMLChar1_0::isAllSpaces(content, XMLString::stringLen(content)))) || + ((version == ver_11) && (XMLChar1_1::isAllSpaces(content, XMLString::stringLen(content)))) ) { + status = st_NoContent; + return 0; + } + + status = st_Init; + + switch (inGroup[datatype]) { + case XSValue::dg_numerics: + return getActValNumerics(content, datatype, status, toValidate, manager); + break; + case XSValue::dg_datetimes: + return getActValDateTimes(content, datatype, status, manager); + break; + case XSValue::dg_strings: + return getActValStrings(content, datatype, status, version, toValidate, manager); + break; + default: + status = st_UnknownType; + return 0; + break; + } + return 0; +} + +// --------------------------------------------------------------------------- +// XSValue: Helpers +// --------------------------------------------------------------------------- + +/*** + * + * Boundary checking is done against Schema Type's lexcial space + ***/ +bool +XSValue::validateNumerics(const XMLCh* const content + , DataType datatype + , Status& status + , MemoryManager* const manager) +{ + + try { + + switch (datatype) { + case XSValue::dt_decimal: + XMLBigDecimal::parseDecimal(content, manager); + break; + case XSValue::dt_float: + { + //XMLFloat takes care of 0, -0, -INF, INF and NaN + //XMLFloat::checkBoundary() handles error and outofbound issues + XMLFloat data(content, manager); + break; + } + case XSValue::dt_double: + { + //XMLDouble takes care of 0, -0, -INF, INF and NaN + //XMLDouble::checkBoundary() handles error and outofbound issues + XMLDouble data(content, manager); + break; + } + /*** + * For all potentially unrepresentable types + * + * For dt_long, dt_unsignedLong, doing lexical space + * checking ensures consistent behaviour on 32/64 boxes + * + ***/ + case XSValue::dt_integer: + case XSValue::dt_negativeInteger: + case XSValue::dt_nonPositiveInteger: + case XSValue::dt_nonNegativeInteger: + case XSValue::dt_positiveInteger: + case XSValue::dt_long: + case XSValue::dt_unsignedLong: + { + XMLCh* compareData = (XMLCh*) manager->allocate((XMLString::stringLen(content) + 1) * sizeof(XMLCh)); + ArrayJanitor janName(compareData, manager); + int signValue = 0; + XMLBigInteger::parseBigInteger(content, compareData, signValue, manager); + + switch (datatype) { + case XSValue::dt_integer: + //error: no + break; + case XSValue::dt_negativeInteger: + // error: > -1 + if (XMLBigInteger::compareValues(compareData + , signValue + , &(XMLUni::fgNegOne[1]) + , -1 + , manager) + == XMLNumber::GREATER_THAN) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_nonPositiveInteger: + // error: > 0 + if (XMLBigInteger::compareValues(compareData + , signValue + , XMLUni::fgValueZero + , 0 + , manager) + == XMLNumber::GREATER_THAN) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_nonNegativeInteger: + // error: < 0 + if (XMLBigInteger::compareValues(compareData + , signValue + , XMLUni::fgValueZero + , 0 + , manager) + == XMLNumber::LESS_THAN) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_positiveInteger: + // error: < 1 + if (XMLBigInteger::compareValues(compareData + , signValue + , XMLUni::fgValueOne + , 1 + , manager) + == XMLNumber::LESS_THAN) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_long: + // error: < -9223372036854775808 || > 9223372036854775807 + if ((XMLBigInteger::compareValues(compareData + , signValue + , &(XMLUni::fgLongMinInc[1]) + , -1 + , manager) + == XMLNumber::LESS_THAN) || + (XMLBigInteger::compareValues(compareData + , signValue + , XMLUni::fgLongMaxInc + , 1 + , manager) + == XMLNumber::GREATER_THAN)) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_unsignedLong: + // error: < 0 || > 18446744073709551615 + if ((XMLBigInteger::compareValues(compareData + , signValue + , XMLUni::fgValueZero + , 0 + , manager) + == XMLNumber::LESS_THAN) || + (XMLBigInteger::compareValues(compareData + , signValue + , XMLUni::fgULongMaxInc + , 1 + , manager) + == XMLNumber::GREATER_THAN)) + { + status = st_FOCA0002; + return false; + } + break; + default: + status = st_NotSupported; + return false; + break; + } + break; + } + case XSValue::dt_int: + case XSValue::dt_short: + case XSValue::dt_byte: + case XSValue::dt_unsignedInt: + case XSValue::dt_unsignedShort: + case XSValue::dt_unsignedByte: + { + t_value actVal; + + if ( !getActualNumericValue( + content + , status + , actVal + , manager + , datatype + ) + ) + { + return false; + } + break; + } + default: + return false; + } // end switch + } + catch (const NumberFormatException&) + { + //getActValue()/getCanonical() need to know the failure details + //if validation is required + status = st_FOCA0002; + return false; + } + return true; //both valid chars and within boundary +} + +bool XSValue::validateDateTimes(const XMLCh* const input_content + , DataType datatype + , Status& status + , MemoryManager* const manager) +{ + XMLCh* content = XMLString::replicate(input_content, manager); + ArrayJanitor janTmpName(content, manager); + XMLString::trim(content); + try + { + XMLDateTime coreDate = XMLDateTime(content, manager); + + switch (datatype) { + case XSValue::dt_duration: + coreDate.parseDuration(); + break; + case XSValue::dt_dateTime: + coreDate.parseDateTime(); + break; + case XSValue::dt_time: + coreDate.parseTime(); + break; + case XSValue::dt_date: + coreDate.parseDate(); + break; + case XSValue::dt_gYearMonth: + coreDate.parseYearMonth(); + break; + case XSValue::dt_gYear: + coreDate.parseYear(); + break; + case XSValue::dt_gMonthDay: + coreDate.parseMonthDay(); + break; + case XSValue::dt_gDay: + coreDate.parseDay(); + break; + case XSValue::dt_gMonth: + coreDate.parseMonth(); + break; + default: + return false; + break; + } + } + + catch (const SchemaDateTimeException &e) + { + status = checkTimeZoneError(datatype, e)? XSValue::st_FODT0003 : st_FOCA0002; + return false; + } + catch (const NumberFormatException&) + { + //getActValue()/getCanonical() need to know the failure details + //if validation is required + status = st_FOCA0002; + return false; + } + + return true; //parsing succeed +} + +bool XSValue::validateStrings(const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , MemoryManager* const manager) +{ + bool isValid = true; + + switch (datatype) { + case XSValue::dt_boolean: + { + XMLSize_t i = 0; + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + for (; i < XMLUni::fgBooleanValueSpaceArraySize; i++) { + if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[i])) + break; + } + + if (XMLUni::fgBooleanValueSpaceArraySize == i) { + isValid = false; + } + break; + } + case XSValue::dt_hexBinary: + { + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + if (HexBin::getDataLength(tmpStrValue) == -1) { + isValid = false; + } + } + break; + case XSValue::dt_base64Binary: + if (Base64::getDataLength(content, manager) == -1) { + isValid = false; + } + break; + case XSValue::dt_anyURI: + if (XMLUri::isValidURI(true, content, true) == false) { + isValid = false; + } + break; + case XSValue::dt_QName: + { + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + isValid = (version == ver_10) ? + XMLChar1_0::isValidQName(tmpStrValue, XMLString::stringLen(tmpStrValue)) : + XMLChar1_1::isValidQName(tmpStrValue, XMLString::stringLen(tmpStrValue)); + } + break; + case XSValue::dt_NOTATION: + { + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + if ( XMLString::isValidNOTATION(tmpStrValue, manager) == false) { + isValid = false; + } + } + break; + case XSValue::dt_string: + { + const XMLCh* rawPtr = content; + + if (version == ver_10) { + while (*rawPtr) + if (!XMLChar1_0::isXMLChar(*rawPtr++)) { + isValid = false; + break; + } + } + else { + while (*rawPtr) + if (!XMLChar1_1::isXMLChar(*rawPtr++)) { + isValid = false; + break; + } + } + break; + } + case XSValue::dt_normalizedString: + { + const XMLCh* rawPtr = content; + + if (version == ver_10) { + while (*rawPtr) { + if (!XMLChar1_0::isXMLChar(*rawPtr)) { + isValid = false; + break; + } + else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) { + isValid = false; + break; + } + else { + rawPtr++; + } + } + } + else { + while (*rawPtr) { + if (!XMLChar1_1::isXMLChar(*rawPtr)) { + isValid = false; + break; + } + else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) { + isValid = false; + break; + } + else { + rawPtr++; + } + + } + } + break; + } + case XSValue::dt_token: + case XSValue::dt_language: + { + XMLSize_t strLen = XMLString::stringLen(content); + const XMLCh* rawPtr = content; + bool inWS = false; + + if (version == ver_10) { + // Check leading/Trailing white space + if (XMLChar1_0::isWhitespace(content[0]) || + XMLChar1_0::isWhitespace(content[strLen - 1]) ) { + isValid = false; + } + else { + while (*rawPtr) { + if (!XMLChar1_0::isXMLChar(*rawPtr)) { + isValid = false; + break; + } + else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) { + isValid = false; + break; + } + else if (XMLChar1_0::isWhitespace(*rawPtr)) { + if (inWS) { + isValid = false; + break; + } + else { + inWS = true; + } + } + else { + inWS = false; + } + + rawPtr++; + } + } + } + else { + // Check leading/Trailing white space + if (XMLChar1_1::isWhitespace(content[0]) || + XMLChar1_1::isWhitespace(content[strLen - 1]) ) { + isValid = false; + } + else { + while (*rawPtr) { + if (!XMLChar1_1::isXMLChar(*rawPtr)) { + isValid = false; + break; + } + else if (*rawPtr == chCR || *rawPtr == chLF || *rawPtr == chHTab) { + isValid = false; + break; + } + else if (XMLChar1_1::isWhitespace(*rawPtr)) { + if (inWS) { + isValid = false; + break; + } + else { + inWS = true; + } + } + else { + inWS = false; + } + rawPtr++; + } + } + } + if (isValid == true && datatype == XSValue::dt_language) { + if (!sXSValueRegEx) { + status = st_CantCreateRegEx; + isValid = false; + } + else + { + if (sXSValueRegEx->matches(content, manager) == false) + { + isValid = false; + } + } + } + break; + } + case XSValue::dt_NMTOKEN: + isValid = (version == ver_10) ? + XMLChar1_0::isValidNmtoken(content, XMLString::stringLen(content)) : + XMLChar1_1::isValidNmtoken(content, XMLString::stringLen(content)); + break; + case XSValue::dt_NMTOKENS: + // [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* + { + XMLStringTokenizer tokenizer(content, Separator_20, manager); + + if (version == ver_10) { + while (tokenizer.hasMoreTokens()) { + const XMLCh* token = tokenizer.nextToken(); + + if (!XMLChar1_0::isValidNmtoken(token, XMLString::stringLen(token))) { + isValid = false; + break; + } + } + } + else { + while (tokenizer.hasMoreTokens()) { + const XMLCh* token = tokenizer.nextToken(); + + if (!XMLChar1_1::isValidNmtoken(token, XMLString::stringLen(token))) { + isValid = false; + break; + } + } + } + break; + } + case XSValue::dt_Name: + isValid = (version == ver_10) ? + XMLChar1_0::isValidName(content) : + XMLChar1_1::isValidName(content); + break; + case XSValue::dt_NCName: + case XSValue::dt_ID: + case XSValue::dt_IDREF: + case XSValue::dt_ENTITY: + isValid = (version == ver_10) ? + XMLChar1_0::isValidNCName(content, XMLString::stringLen(content)) : + XMLChar1_1::isValidNCName(content, XMLString::stringLen(content)); + break; + case XSValue::dt_ENTITIES: + case XSValue::dt_IDREFS: + { + XMLStringTokenizer tokenizer(content, Separator_ws, manager); + + if (version == ver_10 ) { + while (tokenizer.hasMoreTokens()) { + const XMLCh* token = tokenizer.nextToken(); + + if (!XMLChar1_0::isValidNCName(token, XMLString::stringLen(token))) { + isValid = false; + break; + } + } + } + else { + while (tokenizer.hasMoreTokens()) { + const XMLCh* token = tokenizer.nextToken(); + + if (!XMLChar1_1::isValidNCName(token, XMLString::stringLen(token))) { + isValid = false; + break; + } + } + } + } + break; + default: + status = st_NotSupported; + isValid = false; + break; + } + + + if (isValid == false && status == st_Init) { + status = st_FOCA0002; + } + + return isValid; +} + + +XMLCh* XSValue::getCanRepNumerics(const XMLCh* const content + , DataType datatype + , Status& status + , bool toValidate + , MemoryManager* const manager) +{ + try + { + + // getCanonicalRepresentation does lexical space validation only + // (no range checking), therefore if validation is required, + // we need to pass the content to the validate interface for complete checking + if (toValidate && !validateNumerics(content, datatype, status, manager)) + return 0; + + XMLCh* retVal = 0; + + if (datatype == XSValue::dt_decimal) + { + retVal = XMLBigDecimal::getCanonicalRepresentation(content, manager); + + if (!retVal) + status = st_FOCA0002; + + return retVal; + + } + else if (datatype == XSValue::dt_float || datatype == XSValue::dt_double ) + { + // In XML4C, no float or double is treated as out of range + // it gets converted to INF, -INF or zero. + // The getCanonical method should treat double & float the + // same way as the rest of XML4C for consistentcy so need + // to getActualValue and see if it was converted. + XSValue* xsval = getActValNumerics(content, datatype, status, false, manager); + if (!xsval) { + status = st_FOCA0002; + return retVal; + } + + DoubleFloatType enumVal; + if (datatype == XSValue::dt_float) { + enumVal = xsval->fData.fValue.f_floatType.f_floatEnum; + } + else { + enumVal = xsval->fData.fValue.f_doubleType.f_doubleEnum; + } + delete xsval; + + switch(enumVal) { + case DoubleFloatType_NegINF: + retVal = XMLString::replicate(XMLUni::fgNegINFString, manager); + break; + case DoubleFloatType_PosINF: + retVal = XMLString::replicate(XMLUni::fgPosINFString, manager); + break; + case DoubleFloatType_NaN: + retVal = XMLString::replicate(XMLUni::fgNaNString, manager); + break; + case DoubleFloatType_Zero: + retVal = XMLString::replicate(XMLUni::fgPosZeroString, manager); + break; + default: //DoubleFloatType_Normal + retVal = XMLAbstractDoubleFloat::getCanonicalRepresentation(content, manager); + + if (!retVal) + status = st_FOCA0002; + break; + } + return retVal; + } + else + { + retVal = XMLBigInteger::getCanonicalRepresentation(content, manager, datatype == XSValue::dt_nonPositiveInteger); + + if (!retVal) + status = st_FOCA0002; + + return retVal; + } + } + catch (const NumberFormatException&) + { + status = st_FOCA0002; + } + + return 0; +} + +XMLCh* XSValue::getCanRepDateTimes(const XMLCh* const input_content + , DataType datatype + , Status& status + , bool toValidate + , MemoryManager* const manager) +{ + XMLCh* content = XMLString::replicate(input_content, manager); + ArrayJanitor janTmpName(content, manager); + XMLString::trim(content); + try + { + + XMLDateTime coreDate = XMLDateTime(content, manager); + + switch (datatype) { + case XSValue::dt_dateTime: + //we need this parsing + coreDate.parseDateTime(); + return coreDate.getDateTimeCanonicalRepresentation(manager); + break; + case XSValue::dt_time: + // we need this parsing + coreDate.parseTime(); + return coreDate.getTimeCanonicalRepresentation(manager); + break; + case XSValue::dt_date: + // we need this parsing + coreDate.parseDate(); + return coreDate.getDateCanonicalRepresentation(manager); + break; + case XSValue::dt_duration: + case XSValue::dt_gYearMonth: + case XSValue::dt_gYear: + case XSValue::dt_gMonthDay: + case XSValue::dt_gDay: + case XSValue::dt_gMonth: + { + if (!(toValidate && !validateDateTimes(content, datatype, status, manager))) + status = st_NoCanRep; + + return 0; + } + break; + default: + return 0; + break; + } + } + catch (SchemaDateTimeException &e) + { + status = checkTimeZoneError(datatype, e)? XSValue::st_FODT0003 : st_FOCA0002; + } + catch (const NumberFormatException&) + { + status = st_FOCA0002; + } + return 0; +} + +XMLCh* XSValue::getCanRepStrings(const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , bool toValidate + , MemoryManager* const manager) +{ + switch (datatype) { + case XSValue::dt_boolean: + { + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + //always validate before getting canRep + if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[0]) || + XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[2]) ) + { + return XMLString::replicate(XMLUni::fgBooleanValueSpace[0], manager); + } + else if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[1]) || + XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[3]) ) + { + return XMLString::replicate(XMLUni::fgBooleanValueSpace[1], manager); + } + else + { + status = st_FOCA0002; + return 0; + } + } + break; + case XSValue::dt_hexBinary: + { + //HexBin::getCanonicalRepresentation does validation automatically + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + + XMLCh* canRep = HexBin::getCanonicalRepresentation(tmpStrValue, manager); + if (!canRep) + status = st_FOCA0002; + + return canRep; + break; + } + case XSValue::dt_base64Binary: + { + //Base64::getCanonicalRepresentation does validation automatically + XMLCh* canRep = Base64::getCanonicalRepresentation(content, manager); + if (!canRep) + status = st_FOCA0002; + + return canRep; + break; + } + case XSValue::dt_anyURI: + case XSValue::dt_QName: + case XSValue::dt_NOTATION: + case XSValue::dt_string: + case XSValue::dt_normalizedString: + case XSValue::dt_token: + case XSValue::dt_language: + case XSValue::dt_NMTOKEN: + case XSValue::dt_NMTOKENS: + case XSValue::dt_Name: + case XSValue::dt_NCName: + case XSValue::dt_ID: + case XSValue::dt_IDREF: + case XSValue::dt_ENTITY: + case XSValue::dt_ENTITIES: + case XSValue::dt_IDREFS: + if (toValidate && !validateStrings(content, datatype, status, version, manager)) + status = st_FOCA0002; + else + status = st_NoCanRep; + + return 0; + break; + default: + return 0; + break; + } + + return 0; +} + +XSValue* +XSValue::getActValNumerics(const XMLCh* const content + , DataType datatype + , Status& status + , bool toValidate + , MemoryManager* const manager) +{ + + try { + + switch (datatype) { + case XSValue::dt_decimal: + { + if (toValidate) { + XMLBigDecimal::parseDecimal(content, manager); + } + //Prepare the double value + XMLDouble data(content, manager); + if (data.isDataConverted()) + { + status = st_FOCA0001; + return 0; + } + + XSValue* retVal = new (manager) XSValue(dt_decimal, manager); + retVal->fData.fValue.f_decimal.f_dvalue = data.getValue(); + + return retVal; + break; + } + case XSValue::dt_float: + { + //XMLFloat takes care of 0, -0, -INF, INF and NaN + //XMLFloat::checkBoundary() handles error and outofbound issues + XMLFloat data(content, manager); + XSValue* retVal = new (manager) XSValue(dt_float, manager); + + if (data.isDataConverted()) + { + retVal->fData.fValue.f_floatType.f_float = 0.0; + retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_Zero; + + switch(data.getType()) { + case XMLAbstractDoubleFloat::NegINF: + retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_NegINF; + break; + case XMLAbstractDoubleFloat::PosINF: + retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_PosINF; + break; + case XMLAbstractDoubleFloat::NaN: + retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_NaN; + break; + default: + break; + } + } + else { + retVal->fData.fValue.f_floatType.f_floatEnum = DoubleFloatType_Normal; + retVal->fData.fValue.f_floatType.f_float = (float) data.getValue(); + } + return retVal; + break; + } + case XSValue::dt_double: + { + //XMLDouble takes care of 0, -0, -INF, INF and NaN + //XMLDouble::checkBoundary() handles error and outofbound issues + XMLDouble data(content, manager); + XSValue* retVal = new (manager) XSValue(dt_double, manager); + + if (data.isDataConverted()) + { + retVal->fData.fValue.f_doubleType.f_double = 0.0; + retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_Zero; + + switch(data.getType()) { + case XMLAbstractDoubleFloat::NegINF: + retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_NegINF; + break; + case XMLAbstractDoubleFloat::PosINF: + retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_PosINF; + break; + case XMLAbstractDoubleFloat::NaN: + retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_NaN; + break; + default: + break; + } + } + else { + retVal->fData.fValue.f_doubleType.f_doubleEnum = DoubleFloatType_Normal; + retVal->fData.fValue.f_doubleType.f_double = data.getValue(); + } + return retVal; + break; + } + case XSValue::dt_integer: + case XSValue::dt_negativeInteger: + case XSValue::dt_nonPositiveInteger: + case XSValue::dt_nonNegativeInteger: + case XSValue::dt_positiveInteger: + case XSValue::dt_long: + case XSValue::dt_int: + case XSValue::dt_short: + case XSValue::dt_byte: + case XSValue::dt_unsignedLong: + case XSValue::dt_unsignedInt: + case XSValue::dt_unsignedShort: + case XSValue::dt_unsignedByte: + { + t_value actVal; + + if ( !getActualNumericValue( + content + , status + , actVal + , manager + , datatype + ) + ) + { + //status has been set by getActualNumericValue + return 0; + } + + XSValue* retVal = new (manager) XSValue(datatype, manager); + + switch (datatype) { + case XSValue::dt_integer: + retVal->fData.fValue.f_long = actVal.f_long; + break; + case XSValue::dt_negativeInteger: + retVal->fData.fValue.f_long = actVal.f_long; + break; + case XSValue::dt_nonPositiveInteger: + retVal->fData.fValue.f_long = actVal.f_long; + break; + case XSValue::dt_nonNegativeInteger: + retVal->fData.fValue.f_long = actVal.f_ulong; + break; + case XSValue::dt_positiveInteger: + retVal->fData.fValue.f_long = actVal.f_ulong; + break; + case XSValue::dt_long: + retVal->fData.fValue.f_long = actVal.f_long; + break; + case XSValue::dt_int: + retVal->fData.fValue.f_int = (int) actVal.f_long; + break; + case XSValue::dt_short: + retVal->fData.fValue.f_short = (short) actVal.f_long; + break; + case XSValue::dt_byte: + retVal->fData.fValue.f_char = (char) actVal.f_long; + break; + case XSValue::dt_unsignedLong: + retVal->fData.fValue.f_ulong = actVal.f_ulong; + break; + case XSValue::dt_unsignedInt: + retVal->fData.fValue.f_uint = (unsigned int) actVal.f_ulong; + break; + case XSValue::dt_unsignedShort: + retVal->fData.fValue.f_ushort = (unsigned short) actVal.f_ulong; + break; + case XSValue::dt_unsignedByte: + retVal->fData.fValue.f_uchar = (unsigned char) actVal.f_ulong; + break; + default: + return 0; + break; + } + return retVal; + break; + } + default: + return 0; + break; + } // end switch + } + catch (const NumberFormatException&) + { + status = st_FOCA0002; + } + return 0; +} + +XSValue* +XSValue::getActValDateTimes(const XMLCh* const input_content + , DataType datatype + , Status& status + , MemoryManager* const manager) +{ + XMLCh* content = XMLString::replicate(input_content, manager); + ArrayJanitor janTmpName(content, manager); + XMLString::trim(content); + try + { + //Need not check if validation is requested since + //parsing functions below does the validation automatically + XMLDateTime coreDate = XMLDateTime(content, manager); + + switch (datatype) { + case XSValue::dt_duration: + coreDate.parseDuration(); + break; + case XSValue::dt_dateTime: + coreDate.parseDateTime(); + break; + case XSValue::dt_time: + coreDate.parseTime(); + coreDate.fValue[XMLDateTime::CentYear] = 0; + coreDate.fValue[XMLDateTime::Month] = 0; + coreDate.fValue[XMLDateTime::Day] = 0; + break; + case XSValue::dt_date: + coreDate.parseDate(); + coreDate.fValue[XMLDateTime::Hour] = 0; + coreDate.fValue[XMLDateTime::Minute] = 0; + break; + case XSValue::dt_gYearMonth: + coreDate.parseYearMonth(); + coreDate.fValue[XMLDateTime::Day] = 0; + coreDate.fValue[XMLDateTime::Hour] = 0; + coreDate.fValue[XMLDateTime::Minute] = 0; + break; + case XSValue::dt_gYear: + coreDate.parseYear(); + coreDate.fValue[XMLDateTime::Month] = 0; + coreDate.fValue[XMLDateTime::Day] = 0; + coreDate.fValue[XMLDateTime::Hour] = 0; + coreDate.fValue[XMLDateTime::Minute] = 0; + break; + case XSValue::dt_gMonthDay: + coreDate.parseMonthDay(); + coreDate.fValue[XMLDateTime::CentYear] = 0; + coreDate.fValue[XMLDateTime::Hour] = 0; + coreDate.fValue[XMLDateTime::Minute] = 0; + break; + case XSValue::dt_gDay: + coreDate.parseDay(); + coreDate.fValue[XMLDateTime::CentYear] = 0; + coreDate.fValue[XMLDateTime::Month] = 0; + coreDate.fValue[XMLDateTime::Hour] = 0; + coreDate.fValue[XMLDateTime::Minute] = 0; + break; + case XSValue::dt_gMonth: + coreDate.parseMonth(); + coreDate.fValue[XMLDateTime::CentYear] = 0; + coreDate.fValue[XMLDateTime::Day] = 0; + coreDate.fValue[XMLDateTime::Hour] = 0; + coreDate.fValue[XMLDateTime::Minute] = 0; + break; + default: + return 0; + break; + } + + XSValue* retVal = new (manager) XSValue(datatype, manager); + + retVal->fData.fValue.f_datetime.f_year = coreDate.fValue[XMLDateTime::CentYear]; + retVal->fData.fValue.f_datetime.f_month = coreDate.fValue[XMLDateTime::Month]; + retVal->fData.fValue.f_datetime.f_day = coreDate.fValue[XMLDateTime::Day]; + retVal->fData.fValue.f_datetime.f_hour = coreDate.fValue[XMLDateTime::Hour]; + retVal->fData.fValue.f_datetime.f_min = coreDate.fValue[XMLDateTime::Minute]; + retVal->fData.fValue.f_datetime.f_second = coreDate.fValue[XMLDateTime::Second]; + retVal->fData.fValue.f_datetime.f_milisec = coreDate.fMilliSecond; + + return retVal; + } + catch (SchemaDateTimeException const &e) + { + status = checkTimeZoneError(datatype, e)? XSValue::st_FODT0003 : st_FOCA0002; + } + catch (const NumberFormatException&) + { + status = st_FOCA0002; + } + return 0; + +} + +XSValue* +XSValue::getActValStrings(const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , bool toValidate + , MemoryManager* const manager) +{ + switch (datatype) { + case XSValue::dt_boolean: + { + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + //do validation here more efficiently + if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[0]) || + XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[2]) ) + { + XSValue* retVal = new (manager) XSValue(dt_boolean, manager); + retVal->fData.fValue.f_bool = false; + return retVal; + } + else if (XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[1]) || + XMLString::equals(tmpStrValue, XMLUni::fgBooleanValueSpace[3]) ) + { + XSValue* retVal = new (manager) XSValue(dt_boolean, manager); + retVal->fData.fValue.f_bool = true; + return retVal; + } + else + { + status = st_FOCA0002; + return 0; + } + } + break; + case XSValue::dt_hexBinary: + { + XMLCh* tmpStrValue = XMLString::replicate(content, manager); + ArrayJanitor janTmpName(tmpStrValue, manager); + XMLString::trim(tmpStrValue); + + XMLByte* decodedData = HexBin::decodeToXMLByte(tmpStrValue, manager); + + if (!decodedData) + { + status = st_FOCA0002; + return 0; + } + + XSValue* retVal = new (manager) XSValue(dt_hexBinary, manager); + retVal->fData.fValue.f_byteVal = decodedData; + retVal->fMemAllocated = true; + return retVal; + break; + } + case XSValue::dt_base64Binary: + { + XMLSize_t len = 0; + XMLByte* decodedData = Base64::decodeToXMLByte(content, &len, manager); + + if (!decodedData) + { + status = st_FOCA0002; + return 0; + } + + XSValue* retVal = new (manager) XSValue(dt_base64Binary, manager); + retVal->fData.fValue.f_byteVal = decodedData; + retVal->fMemAllocated = true; + return retVal; + break; + } + case XSValue::dt_anyURI: + case XSValue::dt_QName: + case XSValue::dt_NOTATION: + case XSValue::dt_string: + case XSValue::dt_normalizedString: + case XSValue::dt_token: + case XSValue::dt_language: + case XSValue::dt_NMTOKEN: + case XSValue::dt_NMTOKENS: + case XSValue::dt_Name: + case XSValue::dt_NCName: + case XSValue::dt_ID: + case XSValue::dt_IDREF: + case XSValue::dt_ENTITY: + case XSValue::dt_ENTITIES: + case XSValue::dt_IDREFS: + if (toValidate && !validateStrings(content, datatype, status, version, manager)) + status = st_FOCA0002; + else + status = st_NoActVal; + + return 0; + break; + default: + return 0; + break; + } + + return 0; +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- +bool XSValue::getActualNumericValue(const XMLCh* const content + , Status& status + , t_value& retVal + , MemoryManager* const manager + , DataType datatype) +{ + char *nptr = XMLString::transcode(content, manager); + ArrayJanitor jan(nptr, manager); + char *endptr = 0; + errno = 0; + + if (XSValue::numericSign[datatype]) + { + retVal.f_long = strtol(nptr, &endptr, (int)10); + } + else + { + if (XMLString::indexOf(content, chDash) != -1) + { + status = st_FOCA0002; //invalid lexcial value + return false; + } + + retVal.f_ulong = strtoul(nptr, &endptr, (int)10); + } + + // need to check out-of-bounds before checking erange... + switch (datatype) { + case XSValue::dt_nonPositiveInteger: + if (retVal.f_long > 0) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_negativeInteger: + if (retVal.f_long >= 0) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_int: + // strtol will set value to LONG_MIN/LONG_MAX if ERANGE error + if ((retVal.f_long < INT_MIN) || + (retVal.f_long > INT_MAX) || + (errno == ERANGE)) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_short: + if ((retVal.f_long < SHRT_MIN) || + (retVal.f_long > SHRT_MAX)) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_byte: + if ((retVal.f_long < SCHAR_MIN) || + (retVal.f_long > SCHAR_MAX)) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_unsignedInt: + // strtoul will set value to LONG_INT if ERANGE error + if ((retVal.f_ulong > UINT_MAX) || + (errno == ERANGE)) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_unsignedShort: + if (retVal.f_ulong > USHRT_MAX) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_unsignedByte: + if (retVal.f_ulong > UCHAR_MAX) + { + status = st_FOCA0002; + return false; + } + break; + case XSValue::dt_positiveInteger: + if (retVal.f_ulong == 0) + { + status = st_FOCA0002; + return false; + } + break; + default: + break; + } // end switch + // check if overflow/underflow occurs + if (errno == ERANGE) + { + status = st_FOCA0003; + return false; + } + + // check if all chars are valid char. If they are, endptr will + // pointer to the null terminator, or all of the remaining + // characters will be whitespace characters. + while (*endptr != '\0') + { + const char ch = *endptr; + + if (ch == '\t' || ch == '\n' || ch == '\r' || ch == ' ') + { + ++endptr; + } + else + { + status = st_FOCA0002; + return false; + } + + } + return true; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSValue.hpp b/include/xercesc/framework/psvi/XSValue.hpp new file mode 100644 index 0000000..ac987ee --- /dev/null +++ b/include/xercesc/framework/psvi/XSValue.hpp @@ -0,0 +1,406 @@ +/* + * 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: XSValue.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSVALUE_HPP) +#define XERCESC_INCLUDE_GUARD_XSVALUE_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class RegularExpression; + +class XMLPARSER_EXPORT XSValue : public XMemory +{ +public: + + enum DataType { + dt_string = 0, + dt_boolean = 1, + dt_decimal = 2, + dt_float = 3, + dt_double = 4, + dt_duration = 5, + dt_dateTime = 6, + dt_time = 7, + dt_date = 8, + dt_gYearMonth = 9, + dt_gYear = 10, + dt_gMonthDay = 11, + dt_gDay = 12, + dt_gMonth = 13, + dt_hexBinary = 14, + dt_base64Binary = 15, + dt_anyURI = 16, + dt_QName = 17, + dt_NOTATION = 18, + dt_normalizedString = 19, + dt_token = 20, + dt_language = 21, + dt_NMTOKEN = 22, + dt_NMTOKENS = 23, + dt_Name = 24, + dt_NCName = 25, + dt_ID = 26, + dt_IDREF = 27, + dt_IDREFS = 28, + dt_ENTITY = 29, + dt_ENTITIES = 30, + dt_integer = 31, + dt_nonPositiveInteger = 32, + dt_negativeInteger = 33, + dt_long = 34, + dt_int = 35, + dt_short = 36, + dt_byte = 37, + dt_nonNegativeInteger = 38, + dt_unsignedLong = 39, + dt_unsignedInt = 40, + dt_unsignedShort = 41, + dt_unsignedByte = 42, + dt_positiveInteger = 43, + dt_MAXCOUNT = 44 + }; + + enum XMLVersion { + ver_10, + ver_11 + }; + + enum Status { + st_Init, + st_NoContent, + st_NoCanRep, + st_NoActVal, + st_NotSupported, + st_CantCreateRegEx, + st_FOCA0002, //invalid lexical value + st_FOCA0001, //input value too large/too small for decimal + st_FOCA0003, //input value too large for integer + st_FODT0003, //invalid timezone value + st_UnknownType + }; + + enum DataGroup { + dg_numerics, + dg_datetimes, + dg_strings + }; + + enum DoubleFloatType + { + DoubleFloatType_NegINF, + DoubleFloatType_PosINF, + DoubleFloatType_NaN, + DoubleFloatType_Zero, + DoubleFloatType_Normal + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + ~XSValue(); + //@} + + //--------------------------------- + /** @name Externalization methods */ + //@{ + + /** + * Validate a given string of the data type specified + * + * @param content data to be validated + * @param datatype schema datatype + * @param status validation status which is set upon validation fails + * @param version xml version + * @param manager memory manager provided + */ + static + bool validate + ( + const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version = ver_10 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Get the canonical representation for a given string of the + * data type specified + * + * @param content raw data + * @param datatype schema datatype + * @param status validation status which is set upon validation fails + * @param version xml version + * @param toValidate to validate the content before generate canonical representation + * @param manager memory manager provided + */ + static + XMLCh* getCanonicalRepresentation + ( + const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version = ver_10 + , bool toValidate = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Get the actual value, in the form of XSValue, for a given string of the + * data type specified + * + * Client application is responsible for the deletion of the XSValue returned. + * + * @param content raw data + * @param datatype schema datatype + * @param status validation status which is set upon validation fails + * @param version xml version + * @param toValidate to validate the content before generate actual value + * @param manager memory manager provided + */ + static + XSValue* getActualValue + ( + const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version = ver_10 + , bool toValidate = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + static + DataType getDataType (const XMLCh* const dtString); + + //@} + + //---------------------------------- + /** public data */ + + struct XSValue_Data { + + DataType f_datatype; + + union { + bool f_bool; + char f_char; + unsigned char f_uchar; + short f_short; + unsigned short f_ushort; + int f_int; + unsigned int f_uint; + long f_long; + unsigned long f_ulong; + float f_float; + double f_double; + XMLCh* f_strVal; + XMLByte* f_byteVal; + + struct decimal { + double f_dvalue; + } f_decimal; + + struct datetime { + int f_year; + int f_month; + int f_day; + int f_hour; + int f_min; + int f_second; + double f_milisec; + + } f_datetime; + + struct doubletype { + double f_double; + DoubleFloatType f_doubleEnum; + } f_doubleType; + + struct floattype { + float f_float; + DoubleFloatType f_floatEnum; + } f_floatType; + + + + } fValue; + + } fData; + +private: + + typedef union + { + long f_long; + unsigned long f_ulong; + } t_value; + + /** @name Constructors */ + //@{ + /** + * The default constructor + * + */ + XSValue( + DataType const dt + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@}; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSValue(const XSValue&); + XSValue & operator=(const XSValue &); + + //--------------------------------- + /** @name Helpers */ + + //@{ + + static const XSValue::DataGroup inGroup[]; + static const bool numericSign[]; + + //@} + + static + bool validateNumerics + ( + const XMLCh* const content + , DataType datatype + , Status& status + , MemoryManager* const manager + ); + + static + bool validateDateTimes + ( + const XMLCh* const content + , DataType datatype + , Status& status + , MemoryManager* const manager + ); + + static + bool validateStrings + ( + const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , MemoryManager* const manager + ); + + static + XMLCh* getCanRepNumerics + ( + const XMLCh* const content + , DataType datatype + , Status& status + , bool toValidate + , MemoryManager* const manager + ); + + static + XMLCh* getCanRepDateTimes + ( + const XMLCh* const content + , DataType datatype + , Status& status + , bool toValidate + , MemoryManager* const manager + ); + + static + XMLCh* getCanRepStrings + ( + const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , bool toValidate + , MemoryManager* const manager + ); + + static + XSValue* getActValNumerics + ( + const XMLCh* const content + , DataType datatype + , Status& status + , bool toValidate + , MemoryManager* const manager + ); + + static + XSValue* getActValDateTimes + ( + const XMLCh* const content + , DataType datatype + , Status& status + , MemoryManager* const manager + ); + + static + XSValue* getActValStrings + ( + const XMLCh* const content + , DataType datatype + , Status& status + , XMLVersion version + , bool toValidate + , MemoryManager* const manager + ); + + static + bool getActualNumericValue + ( + const XMLCh* const content + , Status& status + , t_value& retVal + , MemoryManager* const manager + , DataType datatype + ); + + static ValueHashTableOf* fDataTypeRegistry; + + // ----------------------------------------------------------------------- + // static helper methods + // ----------------------------------------------------------------------- + static void initializeRegistry(); + friend class XMLInitializer; + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + bool fMemAllocated; + MemoryManager* fMemoryManager; + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/framework/psvi/XSWildcard.cpp b/include/xercesc/framework/psvi/XSWildcard.cpp new file mode 100644 index 0000000..65858a6 --- /dev/null +++ b/include/xercesc/framework/psvi/XSWildcard.cpp @@ -0,0 +1,181 @@ +/* + * 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: XSWildcard.cpp 674012 2008-07-04 11:18:21Z borisk $ + */ + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSWildcard: Constructors and Destructor +// --------------------------------------------------------------------------- +XSWildcard::XSWildcard(SchemaAttDef* const attWildCard, + XSAnnotation* const annot, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::WILDCARD, xsModel, manager) + , fConstraintType(NSCONSTRAINT_ANY) + , fProcessContents(PC_STRICT) + , fNsConstraintList(0) + , fAnnotation(annot) +{ + XMLAttDef::AttTypes attType = attWildCard->getType(); + if (attType == XMLAttDef::Any_Other) + { + fConstraintType = NSCONSTRAINT_NOT; + fNsConstraintList = new (manager) RefArrayVectorOf(1, true, manager); + fNsConstraintList->addElement + ( + XMLString::replicate(fXSModel->getURIStringPool()->getValueForId( + attWildCard->getAttName()->getURI()), manager) + ); + } + else if (attType == XMLAttDef::Any_List) + { + fConstraintType = NSCONSTRAINT_DERIVATION_LIST; + ValueVectorOf* nsList = attWildCard->getNamespaceList(); + if (nsList) + { + XMLSize_t nsListSize = nsList->size(); + if (nsListSize) + { + fNsConstraintList = new (manager) RefArrayVectorOf(nsListSize, true, manager); + for (XMLSize_t i=0; i < nsListSize; i++) + { + fNsConstraintList->addElement + ( + XMLString::replicate + ( + fXSModel->getURIStringPool()->getValueForId + ( + nsList->elementAt(i) + ) + , manager + ) + ); + } + } + } + } + + XMLAttDef::DefAttTypes attDefType = attWildCard->getDefaultType(); + if (attDefType == XMLAttDef::ProcessContents_Skip) + fProcessContents = PC_SKIP; + else if (attDefType == XMLAttDef::ProcessContents_Lax) + fProcessContents = PC_LAX; +} + +XSWildcard::XSWildcard(const ContentSpecNode* const elmWildCard, + XSAnnotation* const annot, + XSModel* const xsModel, + MemoryManager* const manager) + : XSObject(XSConstants::WILDCARD, xsModel, manager) + , fConstraintType(NSCONSTRAINT_ANY) + , fProcessContents(PC_STRICT) + , fNsConstraintList(0) + , fAnnotation(annot) +{ + ContentSpecNode::NodeTypes nodeType = elmWildCard->getType(); + if ((nodeType & 0x0f) == ContentSpecNode::Any_Other) + { + fConstraintType = NSCONSTRAINT_NOT; + if (nodeType == ContentSpecNode::Any_Other_Lax) + fProcessContents = PC_LAX; + else if (nodeType == ContentSpecNode::Any_Other_Skip) + fProcessContents = PC_SKIP; + } + else if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) + { + fConstraintType = NSCONSTRAINT_DERIVATION_LIST; + if (nodeType == ContentSpecNode::Any_NS_Lax) + fProcessContents = PC_LAX; + else if (nodeType == ContentSpecNode::Any_NS_Skip) + fProcessContents = PC_SKIP; + } + else if (nodeType == ContentSpecNode::Any_NS_Choice) + { + fConstraintType = NSCONSTRAINT_DERIVATION_LIST; + // inspect the second child, not the first one, as the first could hold another Any_NS_Choice wrapper + // if the choices are more than 2, while the second child is always a leaf node + ContentSpecNode::NodeTypes anyType = elmWildCard->getSecond()->getType(); + + if (anyType == ContentSpecNode::Any_NS_Lax) + fProcessContents = PC_LAX; + else if (anyType == ContentSpecNode::Any_NS_Skip) + fProcessContents = PC_SKIP; + + fNsConstraintList = new (manager) RefArrayVectorOf(4, true, manager); + buildNamespaceList(elmWildCard); + } + // must be any + else + { + if (nodeType == ContentSpecNode::Any_Lax) + fProcessContents = PC_LAX; + else if (nodeType == ContentSpecNode::Any_Skip) + fProcessContents = PC_SKIP; + } + + if (fConstraintType == NSCONSTRAINT_NOT + || (fConstraintType == NSCONSTRAINT_DERIVATION_LIST + && !fNsConstraintList)) + { + fNsConstraintList = new (manager) RefArrayVectorOf(1, true, manager); + fNsConstraintList->addElement + ( + XMLString::replicate(fXSModel->getURIStringPool()->getValueForId( + elmWildCard->getElement()->getURI()), manager) + ); + } +} + +XSWildcard::~XSWildcard() +{ + if (fNsConstraintList) + delete fNsConstraintList; +} + +// --------------------------------------------------------------------------- +// XSWildcard: helper methods +// --------------------------------------------------------------------------- +void XSWildcard::buildNamespaceList(const ContentSpecNode* const rootNode) +{ + ContentSpecNode::NodeTypes nodeType = rootNode->getType(); + if (nodeType == ContentSpecNode::Any_NS_Choice) + { + buildNamespaceList(rootNode->getFirst()); + buildNamespaceList(rootNode->getSecond()); + } + else + { + fNsConstraintList->addElement + ( + XMLString::replicate(fXSModel->getURIStringPool()->getValueForId( + rootNode->getElement()->getURI()), fMemoryManager) + ); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/framework/psvi/XSWildcard.hpp b/include/xercesc/framework/psvi/XSWildcard.hpp new file mode 100644 index 0000000..c1c3fbd --- /dev/null +++ b/include/xercesc/framework/psvi/XSWildcard.hpp @@ -0,0 +1,201 @@ +/* + * 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: XSWildcard.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSWILDCARD_HPP) +#define XERCESC_INCLUDE_GUARD_XSWILDCARD_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class describes all properties of a Schema Wildcard + * component. + * This is *always* owned by the validator /parser object from which + * it is obtained. + */ + +// forward declarations +class XSAnnotation; +class SchemaAttDef; +class ContentSpecNode; + +class XMLPARSER_EXPORT XSWildcard : public XSObject +{ +public: + + // Namespace Constraint + enum NAMESPACE_CONSTRAINT { + /** + * Namespace Constraint: any namespace is allowed. + */ + NSCONSTRAINT_ANY = 1, + /** + * Namespace Constraint: namespaces in the list are not allowed. + */ + NSCONSTRAINT_NOT = 2, + /** + * Namespace Constraint: namespaces in the list are allowed. + */ + NSCONSTRAINT_DERIVATION_LIST = 3 + }; + + // Process contents + enum PROCESS_CONTENTS { + /** + * There must be a top-level declaration for the item available, or the + * item must have an xsi:type, and the item must be valid as appropriate. + */ + PC_STRICT = 1, + /** + * No constraints at all: the item must simply be well-formed XML. + */ + PC_SKIP = 2, + /** + * If the item, or any items among its [children] is an element + * information item, has a uniquely determined declaration available, it + * must be valid with respect to that definition, that is, validate + * where you can, don't worry when you can't. + */ + PC_LAX = 3 + }; + + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * The default constructor + * + * @param attWildCard + * @param annot + * @param xsModel + * @param manager The configurable memory manager + */ + XSWildcard + ( + SchemaAttDef* const attWildCard + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XSWildcard + ( + const ContentSpecNode* const elmWildCard + , XSAnnotation* const annot + , XSModel* const xsModel + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** @name Destructor */ + //@{ + ~XSWildcard(); + //@} + + //--------------------- + /** @name XSWildcard methods */ + + //@{ + + /** + * Namespace constraint: A constraint type: any, not, list. + */ + NAMESPACE_CONSTRAINT getConstraintType() const; + + /** + * Namespace constraint. For constraintType + * NSCONSTRAINT_DERIVATION_LIST, the list contains allowed namespaces. + * For constraintType NSCONSTRAINT_NOT, the + * list contains disallowed namespaces. + */ + StringList *getNsConstraintList(); + + /** + * [process contents]: one of skip, lax or strict. Valid constants values + * are: PC_SKIP, PC_LAX, PC_STRICT. + */ + PROCESS_CONTENTS getProcessContents() const; + + /** + * Optional. An [annotation]. + */ + XSAnnotation *getAnnotation() const; + + //@} + + //---------------------------------- + /** methods needed by implementation */ + + //@{ + + //@} +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSWildcard(const XSWildcard&); + XSWildcard & operator=(const XSWildcard &); + + /** + * Build namespace list + */ + void buildNamespaceList(const ContentSpecNode* const rootNode); + +protected: + + // ----------------------------------------------------------------------- + // data members + // ----------------------------------------------------------------------- + NAMESPACE_CONSTRAINT fConstraintType; + PROCESS_CONTENTS fProcessContents; + StringList* fNsConstraintList; + XSAnnotation* fAnnotation; +}; + +inline XSAnnotation *XSWildcard::getAnnotation() const +{ + return fAnnotation; +} + +inline XSWildcard::PROCESS_CONTENTS XSWildcard::getProcessContents() const +{ + return fProcessContents; +} + +inline StringList* XSWildcard::getNsConstraintList() +{ + return fNsConstraintList; +} + +inline XSWildcard::NAMESPACE_CONSTRAINT XSWildcard::getConstraintType() const +{ + return fConstraintType; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/BinFileOutputStream.cpp b/include/xercesc/internal/BinFileOutputStream.cpp new file mode 100644 index 0000000..e3e6d6b --- /dev/null +++ b/include/xercesc/internal/BinFileOutputStream.cpp @@ -0,0 +1,104 @@ +/* + * 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: BinFileOutputStream.cpp 1662880 2015-02-28 01:55:31Z scantor $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// BinFileOutputStream: Constructors and Destructor +// --------------------------------------------------------------------------- +BinFileOutputStream::BinFileOutputStream(const XMLCh* const fileName + , MemoryManager* const manager) + +:fSource(XMLPlatformUtils::openFileToWrite(fileName, manager)) +,fMemoryManager(manager) +{ +} + +BinFileOutputStream::BinFileOutputStream(const char* const fileName + , MemoryManager* const manager) +:fSource(XMLPlatformUtils::openFileToWrite(fileName, manager)) +,fMemoryManager(manager) +{ +} + +BinFileOutputStream::~BinFileOutputStream() +{ + if (getIsOpen()) + { + try + { + XMLPlatformUtils::closeFile(fSource, fMemoryManager); + } + catch (...) + { + // There is nothing we can do about it here. + } + } +} + +// --------------------------------------------------------------------------- +// BinFileOutputStream: Getter methods +// --------------------------------------------------------------------------- +XMLFilePos BinFileOutputStream::getSize() const +{ + return XMLPlatformUtils::fileSize(fSource, fMemoryManager); +} + + +// --------------------------------------------------------------------------- +// BinFileOutputStream: Stream management methods +// --------------------------------------------------------------------------- +void BinFileOutputStream::reset() +{ + XMLPlatformUtils::resetFile(fSource, fMemoryManager); +} + + +// --------------------------------------------------------------------------- +// BinFileOutputStream: Implementation of the input stream interface +// --------------------------------------------------------------------------- +XMLFilePos BinFileOutputStream::curPos() const +{ + return XMLPlatformUtils::curFilePos(fSource, fMemoryManager); +} + + +void BinFileOutputStream::writeBytes( const XMLByte* const toGo + , const XMLSize_t maxToWrite) +{ + // + // Write up to the maximum bytes requested. + // + + XMLPlatformUtils::writeBufferToFile(fSource, maxToWrite, toGo, fMemoryManager); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/BinFileOutputStream.hpp b/include/xercesc/internal/BinFileOutputStream.hpp new file mode 100644 index 0000000..00daf8e --- /dev/null +++ b/include/xercesc/internal/BinFileOutputStream.hpp @@ -0,0 +1,100 @@ +/* + * 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: BinFileOutputStream.hpp 553915 2007-07-06 14:57:08Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BINFILEOUTPUTSTREAM_HPP) +#define XERCESC_INCLUDE_GUARD_BINFILEOUTPUTSTREAM_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BinFileOutputStream : public BinOutputStream +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + ~BinFileOutputStream(); + + BinFileOutputStream + ( + const XMLCh* const fileName + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + BinFileOutputStream + ( + const char* const fileName + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getIsOpen() const; + XMLFilePos getSize() const; + void reset(); + + + // ----------------------------------------------------------------------- + // Implementation of the input stream interface + // ----------------------------------------------------------------------- + virtual XMLFilePos curPos() const; + + virtual void writeBytes + ( + const XMLByte* const toGo + , const XMLSize_t maxToWrite + ); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + BinFileOutputStream(const BinFileOutputStream&); + BinFileOutputStream& operator=(const BinFileOutputStream&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fSource + // The source file that we represent. The FileHandle type is defined + // per platform. + // ----------------------------------------------------------------------- + FileHandle fSource; + MemoryManager* const fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// BinFileOutputStream: Getter methods +// --------------------------------------------------------------------------- +inline bool BinFileOutputStream::getIsOpen() const +{ + return (fSource != (FileHandle) XERCES_Invalid_File_Handle); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/BinMemOutputStream.cpp b/include/xercesc/internal/BinMemOutputStream.cpp new file mode 100644 index 0000000..ad8371e --- /dev/null +++ b/include/xercesc/internal/BinMemOutputStream.cpp @@ -0,0 +1,120 @@ +/* + * 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: BinMemOutputStream.cpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +BinMemOutputStream::BinMemOutputStream( XMLSize_t initCapacity + , MemoryManager* const manager) +: fMemoryManager(manager) +, fDataBuf(0) +, fIndex(0) +, fCapacity(initCapacity) +{ + // Buffer is one larger than capacity, to allow for zero term + fDataBuf = (XMLByte*) fMemoryManager->allocate + ( + (fCapacity + 4) * sizeof(XMLByte) + ); + + // Keep it null terminated + fDataBuf[0] = XMLByte(0); +} + +BinMemOutputStream::~BinMemOutputStream() +{ + fMemoryManager->deallocate(fDataBuf); +} + +void BinMemOutputStream::writeBytes( const XMLByte* const toGo + , const XMLSize_t maxToWrite) +{ + + if (maxToWrite) + { + ensureCapacity(maxToWrite); + memcpy(&fDataBuf[fIndex], toGo, maxToWrite * sizeof(XMLByte)); + fIndex += maxToWrite; + } + +} + +const XMLByte* BinMemOutputStream::getRawBuffer() const +{ + fDataBuf[fIndex] = 0; + fDataBuf[fIndex + 1] = 0; + fDataBuf[fIndex + 2] = 0; + fDataBuf[fIndex + 3] = 0; + return fDataBuf; +} + +void BinMemOutputStream::reset() +{ + fIndex = 0; + for (int i = 0; i < 4; i++) + { + fDataBuf[fIndex + i] = 0; + } +} + +XMLFilePos BinMemOutputStream::curPos() const +{ + return fIndex; +} + +XMLFilePos BinMemOutputStream::getSize() const +{ + return fCapacity; +} + +// --------------------------------------------------------------------------- +// BinMemOutputStream: Private helper methods +// --------------------------------------------------------------------------- +void BinMemOutputStream::ensureCapacity(const XMLSize_t extraNeeded) +{ + // If we can handle it, do nothing yet + if (fIndex + extraNeeded < fCapacity) + return; + + // Oops, not enough room. Calc new capacity and allocate new buffer + const XMLSize_t newCap = ((fIndex + extraNeeded) * 2); + XMLByte* newBuf = (XMLByte*) fMemoryManager->allocate + ( + (newCap+4) * sizeof(XMLByte) + ); + + memset(newBuf, 0, (newCap+4) * sizeof(XMLByte)); + + // Copy over the old stuff + memcpy(newBuf, fDataBuf, fCapacity * sizeof(XMLByte) + 4); + + // Clean up old buffer and store new stuff + fMemoryManager->deallocate(fDataBuf); + fDataBuf = newBuf; + fCapacity = newCap; +} + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/internal/BinMemOutputStream.hpp b/include/xercesc/internal/BinMemOutputStream.hpp new file mode 100644 index 0000000..861c485 --- /dev/null +++ b/include/xercesc/internal/BinMemOutputStream.hpp @@ -0,0 +1,103 @@ +/* + * 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: BinMemOutputStream.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BINMEMOUTPUTSTREAM_HPP) +#define XERCESC_INCLUDE_GUARD_BINMEMOUTPUTSTREAM_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BinMemOutputStream : public BinOutputStream +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + ~BinMemOutputStream(); + + BinMemOutputStream + ( + XMLSize_t initCapacity = 1023 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // ----------------------------------------------------------------------- + // Implementation of the output stream interface + // ----------------------------------------------------------------------- + virtual XMLFilePos curPos() const; + + virtual void writeBytes + ( + const XMLByte* const toGo + , const XMLSize_t maxToWrite + ) ; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + const XMLByte* getRawBuffer() const; + + XMLFilePos getSize() const; + void reset(); + +private : + // ----------------------------------------------------------------------- + // Unimplemented methods. + // ----------------------------------------------------------------------- + BinMemOutputStream(const BinMemOutputStream&); + BinMemOutputStream& operator=(const BinMemOutputStream&); + + // ----------------------------------------------------------------------- + // Private helpers + // ----------------------------------------------------------------------- + void ensureCapacity(const XMLSize_t extraNeeded); + + // ----------------------------------------------------------------------- + // Private data members + // + // fDataBuf + // The pointer to the buffer data. Its grown as needed. Its always + // one larger than fCapacity, to leave room for the null terminator. + // + // fIndex + // The current index into the buffer, as characters are appended + // to it. If its zero, then the buffer is empty. + // + // fCapacity + // The current capacity of the buffer. Its actually always one + // larger, to leave room for the null terminator. + // + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + XMLByte* fDataBuf; + XMLSize_t fIndex; + XMLSize_t fCapacity; + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/internal/CharTypeTables.hpp b/include/xercesc/internal/CharTypeTables.hpp new file mode 100644 index 0000000..aa5c45f --- /dev/null +++ b/include/xercesc/internal/CharTypeTables.hpp @@ -0,0 +1,255 @@ +/* + * 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: CharTypeTables.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_CHARTYPETABLES_HPP) +#define XERCESC_INCLUDE_GUARD_CHARTYPETABLES_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// These are character type lookup tables. They are included into XMLReader +// but are in their own private header in order to keep from making that +// file unreadable. +// +// THE RANGES and SINGLES MUST BE IN NUMERICAL ORDER, because the lookup +// method will use this info to short circuit the search! +// --------------------------------------------------------------------------- +static const XMLCh gBaseChars[] = +{ + // Ranges + 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, 0x00D8, 0x00F6 + , 0x00F8, 0x00FF + , 0x0100, 0x0131, 0x0134, 0x013E, 0x0141, 0x0148, 0x014A, 0x017E + , 0x0180, 0x01C3, 0x01CD, 0x01F0, 0x01F4, 0x01F5, 0x01FA, 0x0217 + , 0x0250, 0x02A8, 0x02BB, 0x02C1, 0x0388, 0x038A, 0x038E, 0x03A1 + , 0x03A3, 0x03CE, 0x03D0, 0x03D6, 0x03E2, 0x03F3, 0x0401, 0x040C + , 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 0x0490, 0x04C4 + , 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5 + , 0x04F8, 0x04F9, 0x0531, 0x0556, 0x0561, 0x0586, 0x05D0, 0x05EA + , 0x05F0, 0x05F2, 0x0621, 0x063A, 0x0641, 0x064A, 0x0671, 0x06B7 + , 0x06BA, 0x06BE, 0x06C0, 0x06CE, 0x06D0, 0x06D3, 0x06E5, 0x06E6 + , 0x0905, 0x0939, 0x0958, 0x0961, 0x0985, 0x098C, 0x098F, 0x0990 + , 0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B6, 0x09B9, 0x09DC, 0x09DD + , 0x09DF, 0x09E1, 0x09F0, 0x09F1, 0x0A05, 0x0A0A, 0x0A0F, 0x0A10 + , 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36 + , 0x0A38, 0x0A39, 0x0A59, 0x0A5C, 0x0A72, 0x0A74, 0x0A85, 0x0A8B + , 0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3 + , 0x0AB5, 0x0AB9, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28 + , 0x0B2A, 0x0B30, 0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B5C, 0x0B5D + , 0x0B5F, 0x0B61, 0x0B85, 0x0B8A, 0x0B8E, 0x0B90, 0x0B92, 0x0B95 + , 0x0B99, 0x0B9A, 0x0B9E, 0x0B9F, 0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA + , 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10 + , 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C60, 0x0C61 + , 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3 + , 0x0CB5, 0x0CB9, 0x0CE0, 0x0CE1, 0x0D05, 0x0D0C, 0x0D0E, 0x0D10 + , 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D60, 0x0D61, 0x0E01, 0x0E2E + , 0x0E32, 0x0E33, 0x0E40, 0x0E45, 0x0E81, 0x0E82, 0x0E87, 0x0E88 + , 0x0E94, 0x0E97, 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EAA, 0x0EAB + , 0x0EAD, 0x0EAE, 0x0EB2, 0x0EB3, 0x0EC0, 0x0EC4, 0x0F40, 0x0F47 + , 0x0F49, 0x0F69, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1102, 0x1103 + , 0x1105, 0x1107, 0x110B, 0x110C, 0x110E, 0x1112, 0x1154, 0x1155 + , 0x115F, 0x1161, 0x116D, 0x116E, 0x1172, 0x1173, 0x11AE, 0x11AF + , 0x11B7, 0x11B8, 0x11BC, 0x11C2, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9 + , 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D + , 0x1F50, 0x1F57, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 0x1FB6, 0x1FBC + , 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 0x1FD6, 0x1FDB + , 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x212A, 0x212B + , 0x2180, 0x2182, 0x3041, 0x3094, 0x30A1, 0x30FA, 0x3105, 0x312C + , 0xAC00, 0xD7A3 + , 0x00 + + // Singles + , 0x0386, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x0559, 0x06D5 + , 0x093D, 0x09B2, 0x0A5E, 0x0A8D, 0x0ABD, 0x0AE0, 0x0B3D, 0x0B9C + , 0x0CDE, 0x0E30, 0x0E84, 0x0E8A, 0x0E8D, 0x0EA5, 0x0EA7, 0x0EB0 + , 0x0EBD, 0x1100, 0x1109, 0x113C, 0x113E, 0x1140, 0x114C, 0x114E + , 0x1150, 0x1159, 0x1163, 0x1165, 0x1167, 0x1169, 0x1175, 0x119E + , 0x11A8, 0x11AB, 0x11BA, 0x11EB, 0x11F0, 0x11F9, 0x1F59, 0x1F5B + , 0x1F5D, 0x1FBE, 0x2126, 0x212E + , 0x00 +}; + + +static const XMLCh gCombiningChars[] = +{ + // Ranges + 0x0300, 0x0345, 0x0360, 0x0361, 0x0483, 0x0486, 0x0591, 0x05A1 + , 0x05A3, 0x05B9, 0x05BB, 0x05BD, 0x05C1, 0x05C2, 0x064B, 0x0652 + , 0x06D6, 0x06DC, 0x06DD, 0x06DF, 0x06E0, 0x06E4 + , 0x06E7, 0x06E8, 0x06EA, 0x06ED, 0x0901, 0x0903, 0x093E, 0x094C + , 0x0951, 0x0954, 0x0962, 0x0963, 0x0981, 0x0983, 0x09C0, 0x09C4 + , 0x09C7, 0x09C8, 0x09CB, 0x09CD, 0x09E2, 0x09E3, 0x0A40, 0x0A42 + , 0x0A47, 0x0A48, 0x0A4B, 0x0A4D, 0x0A70, 0x0A71, 0x0A81, 0x0A83 + , 0x0ABE, 0x0AC5, 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0B01, 0x0B03 + , 0x0B3E, 0x0B43, 0x0B47, 0x0B48, 0x0B4B, 0x0B4D, 0x0B56, 0x0B57 + , 0x0B82, 0x0B83, 0x0BBE, 0x0BC2, 0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD + , 0x0C01, 0x0C03, 0x0C3E, 0x0C44, 0x0C46, 0x0C48, 0x0C4A, 0x0C4D + , 0x0C55, 0x0C56, 0x0C82, 0x0C83, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8 + , 0x0CCA, 0x0CCD, 0x0CD5, 0x0CD6, 0x0D02, 0x0D03, 0x0D3E, 0x0D43 + , 0x0D46, 0x0D48, 0x0D4A, 0x0D4D, 0x0E34, 0x0E3A, 0x0E47, 0x0E4E + , 0x0EB4, 0x0EB9, 0x0EBB, 0x0EBC, 0x0EC8, 0x0ECD, 0x0F18, 0x0F19 + , 0x0F71, 0x0F84, 0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F99, 0x0FAD + , 0x0FB1, 0x0FB7, 0x20D0, 0x20DC, 0x302A, 0x302F + , 0x00 + + // Singles + , 0x05BF, 0x05C4, 0x0670 + , 0x093C, 0x094D, 0x09BC, 0x09BE, 0x09BF, 0x09D7, 0x0A02 + , 0x0A3C, 0x0A3E, 0x0A3F, 0x0ABC, 0x0B3C, 0x0BD7, 0x0D57, 0x0E31 + , 0x0EB1, 0x0F35, 0x0F37, 0x0F39, 0x0F3E, 0x0F3F, 0x0F97, 0x0FB9 + , 0x20E1, 0x3099, 0x309A + , 0x00 +}; + + +static const XMLCh gDigitChars[] = +{ + // Ranges + 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F + , 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F + , 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F + , 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29 + , 0x00 + + // Singles + , 0x00 +}; + + +static const XMLCh gIdeographicChars[] = +{ + // Ranges + 0x3021, 0x3029, 0x4E00, 0x9FA5 + , 0x00 + + // Singles + , 0x3007 + , 0x00 +}; + +static const XMLCh gExtenderChars[] = +{ + // Ranges + 0x3031, 0x3035, 0x309D, 0x309E, 0x30FC, 0x30FE + , 0x00 + + // Singles + , 0x00B7, 0x02D0, 0x02D1, 0x0387, 0x0640, 0x0E46, 0x0EC6, 0x3005 + , 0x00 +}; + + +static const XMLCh gPublicIdChars[] = +{ + // Ranges + 0x0023, 0x0025, 0x0027, 0x003B, 0x003F, 0x005A, 0x0061, 0x007A + , 0x00 + + // Singles + , 0x000A, 0x000D, 0x0020, 0x0021, 0x003D, 0x005F + , 0x00 +}; + + +static const XMLCh gWhitespaceChars[] = +{ + // Ranges + 0x00 + + , 0x0020, 0x0009, 0x000D, 0x000A + , 0x00 +}; + + +static const XMLCh gXMLChars[] = +{ + // Ranges + 0x0020, 0xD7FF, 0xE000, 0xFFFD + , 0x00 + + , 0x0009, 0x000D, 0x000A + , 0x00 +}; + +// The following are for XML 1.1 +static const XMLCh gWhitespaceChars1_1[] = +{ + // Ranges + 0x00 + + , 0x0020, 0x0009, 0x000D, 0x000A, 0x0085, 0x2028 + , 0x00 +}; + +static const XMLCh gFirstNameChars1_1[] = +{ + // Ranges + // Note: 0x10000 to 0xEFFFF are also allowed, need to separately check + 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, 0x00D8, 0x00F6 + , 0x00F8, 0x02FF, 0x0370, 0x037D, 0x037F, 0x1FFF, 0x200C, 0x200D + , 0x2070, 0x218F, 0x2C00, 0x2FEF, 0x3001, 0xD7FF, 0xF900, 0xFDCF + , 0xFDF0, 0xFFFD + , 0x00 + + , 0x003A, 0x005F + , 0x00 + +}; + +static const XMLCh gNameChars1_1[] = +{ + // Ranges + // Note: 0x10000 to 0xEFFFF are also allowed, need to separately check + 0x0030, 0x0039, 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6 + , 0x00D8, 0x00F6, 0x00F8, 0x037D, 0x037F, 0x1FFF, 0x200C, 0x200D + , 0x203F, 0x2040, 0x2070, 0x218F, 0x2C00, 0x2FEF, 0x3001, 0xD7FF + , 0xF900, 0xFDCF, 0xFDF0, 0xFFFD + , 0x00 + + , 0x002D, 0x002E, 0x003A, 0x005F, 0x00B7 + , 0x00 +}; + +static const XMLCh gXMLChars1_1[] = +{ + // Ranges + 0x0020, 0x007E, 0x00A0, 0xD7FF, 0xE000, 0xFFFD + , 0x00 + + , 0x0009, 0x000D, 0x000A, 0x0085 + , 0x00 +}; + +static const XMLCh gControl_Chars1_1[] = +{ + // Ranges + 0x0001, 0x001F, 0x007F, 0x009F + , 0x00 + + , 0x00 +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/DGXMLScanner.cpp b/include/xercesc/internal/DGXMLScanner.cpp new file mode 100644 index 0000000..3f0c73e --- /dev/null +++ b/include/xercesc/internal/DGXMLScanner.cpp @@ -0,0 +1,3572 @@ +/* + * 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: DGXMLScanner.cpp 833045 2009-11-05 13:21:27Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ReaderMgrResetType; + + +// --------------------------------------------------------------------------- +// DGXMLScanner: Constructors and Destructor +// --------------------------------------------------------------------------- +DGXMLScanner::DGXMLScanner(XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(valToAdopt, grammarResolver, manager) + , fAttrNSList(0) + , fDTDValidator(0) + , fDTDGrammar(0) + , fDTDElemNonDeclPool(0) + , fElemCount(0) + , fAttDefRegistry(0) + , fUndeclaredAttrRegistry(0) +{ + CleanupType cleanup(this, &DGXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +DGXMLScanner::DGXMLScanner( XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errHandler + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager) + , fAttrNSList(0) + , fDTDValidator(0) + , fDTDGrammar(0) + , fDTDElemNonDeclPool(0) + , fElemCount(0) + , fAttDefRegistry(0) + , fUndeclaredAttrRegistry(0) +{ + CleanupType cleanup(this, &DGXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +DGXMLScanner::~DGXMLScanner() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Getter methods +// --------------------------------------------------------------------------- +NameIdPool* DGXMLScanner::getEntityDeclPool() +{ + if(!fGrammar) + return 0; + return ((DTDGrammar*)fGrammar)->getEntityDeclPool(); +} + +const NameIdPool* DGXMLScanner::getEntityDeclPool() const +{ + if(!fGrammar) + return 0; + return ((DTDGrammar*)fGrammar)->getEntityDeclPool(); +} + +// --------------------------------------------------------------------------- +// DGXMLScanner: Main entry point to scan a document +// --------------------------------------------------------------------------- +void DGXMLScanner::scanDocument(const InputSource& src) +{ + // Bump up the sequence id for this parser instance. This will invalidate + // any previous progressive scan tokens. + fSequenceId++; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + // Reset the scanner and its plugged in stuff for a new run. This + // resets all the data structures, creates the initial reader and + // pushes it on the stack, and sets up the base document path. + scanReset(src); + + // If we have a document handler, then call the start document + if (fDocHandler) + fDocHandler->startDocument(); + + // Scan the prolog part, which is everything before the root element + // including the DTD subsets. + scanProlog(); + + // If we got to the end of input, then its not a valid XML file. + // Else, go on to scan the content. + if (fReaderMgr.atEOF()) + { + emitError(XMLErrs::EmptyMainEntity); + } + else + { + // Scan content, and tell it its not an external entity + if (scanContent()) + { + // Do post-parse validation if required + if (fValidate) + { + // We handle ID reference semantics at this level since + // its required by XML 1.0. + checkIDRefs(); + + // Then allow the validator to do any extra stuff it wants +// fValidator->postParseValidation(); + } + + // That went ok, so scan for any miscellaneous stuff + if (!fReaderMgr.atEOF()) + scanMiscellaneous(); + } + } + + // If we have a document handler, then call the end document + if (fDocHandler) + fDocHandler->endDocument(); + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } +} + + +bool DGXMLScanner::scanNext(XMLPScanToken& token) +{ + // Make sure this token is still legal + if (!isLegalToken(token)) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager); + + // Find the next token and remember the reader id + XMLSize_t orgReader; + XMLTokens curToken; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + bool retVal = true; + + try + { + while (true) + { + // We have to handle any end of entity exceptions that happen here. + // We could be at the end of X nested entities, each of which will + // generate an end of entity exception as we try to move forward. + try + { + curToken = senseNextToken(orgReader); + break; + } + catch(const EndOfEntityException& toCatch) + { + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + if (curToken == Token_CharData) + { + scanCharData(fCDataBuf); + } + else if (curToken == Token_EOF) + { + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + retVal = false; + } + else + { + // Its some sort of markup + bool gotData = true; + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + if (fDoNamespaces) + scanStartTagNS(gotData); + else + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // If we hit the end, then do the miscellaneous part + if (!gotData) + { + // Do post-parse validation if required + if (fValidate) + { + // We handle ID reference semantics at this level since + // its required by XML 1.0. + checkIDRefs(); + + // Then allow the validator to do any extra stuff it wants +// fValidator->postParseValidation(); + } + + // That went ok, so scan for any miscellaneous stuff + scanMiscellaneous(); + + if (fDocHandler) + fDocHandler->endDocument(); + } + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so return failure + retVal = false; + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so return failure + retVal = false; + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + retVal = false; + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + // If we are not at the end, release the object that will + // reset the ReaderMgr. + if (retVal) + resetReaderMgr.release(); + + return retVal; +} + + +// --------------------------------------------------------------------------- +// DGXMLScanner: Private scanning methods +// --------------------------------------------------------------------------- + +// This method will kick off the scanning of the primary content of the +// document, i.e. the elements. +bool DGXMLScanner::scanContent() +{ + // Go into a loop until we hit the end of the root element, or we fall + // out because there is no root element. + // + // We have to do kind of a deeply nested double loop here in order to + // avoid doing the setup/teardown of the exception handler on each + // round. Doing it this way we only do it when an exception actually + // occurs. + bool gotData = true; + bool inMarkup = false; + while (gotData) + { + try + { + while (gotData) + { + // Sense what the next top level token is. According to what + // this tells us, we will call something to handle that kind + // of thing. + XMLSize_t orgReader; + const XMLTokens curToken = senseNextToken(orgReader); + + // Handle character data and end of file specially. Char data + // is not markup so we don't want to handle it in the loop + // below. + if (curToken == Token_CharData) + { + // Scan the character data and call appropriate events. Let + // him use our local character data buffer for efficiency. + scanCharData(fCDataBuf); + continue; + } + else if (curToken == Token_EOF) + { + // The element stack better be empty at this point or we + // ended prematurely before all elements were closed. + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + // Its the end of file, so clear the got data flag + gotData = false; + continue; + } + + // We are in some sort of markup now + inMarkup = true; + + // According to the token we got, call the appropriate + // scanning method. + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + if (fDoNamespaces) + scanStartTagNS(gotData); + else + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // And we are back out of markup again + inMarkup = false; + } + } + catch(const EndOfEntityException& toCatch) + { + // If we were in some markup when this happened, then its a + // partial markup error. + if (inMarkup) + emitError(XMLErrs::PartialMarkupInEntity); + + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + + inMarkup = false; + } + } + + // It went ok, so return success + return true; +} + + +void DGXMLScanner::scanEndTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the end of the root element. + gotData = true; + + // Check if the element stack is empty. If so, then this is an unbalanced + // element (i.e. more ends than starts, perhaps because of bad text + // causing one to be skipped.) + if (fElemStack.isEmpty()) + { + emitError(XMLErrs::MoreEndThanStartTags); + fReaderMgr.skipPastChar(chCloseAngle); + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager); + } + + // Pop the stack of the element we are supposed to be ending. Remember + // that we don't own this. The stack just keeps them and reuses them. + unsigned int uriId = (fDoNamespaces) + ? fElemStack.getCurrentURI() : fEmptyNamespaceId; + + // Pop the stack of the element we are supposed to be ending. Remember + // that we don't own this. The stack just keeps them and reuses them. + const ElemStack::StackElem* topElem = fElemStack.popTop(); + XMLElementDecl *tempElement = topElem->fThisElement; + + // See if it was the root element, to avoid multiple calls below + const bool isRoot = fElemStack.isEmpty(); + + // Make sure that its the end of the element that we expect + if (!fReaderMgr.skippedStringLong(tempElement->getFullName())) + { + emitError + ( + XMLErrs::ExpectedEndOfTagX + , tempElement->getFullName() + ); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Make sure we are back on the same reader as where we started + if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialTagMarkupError); + + // Skip optional whitespace + fReaderMgr.skipPastSpaces(); + + // Make sure we find the closing bracket + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError + ( + XMLErrs::UnterminatedEndTag + , topElem->fThisElement->getFullName() + ); + } + + // If validation is enabled, then lets pass him the list of children and + // this element and let him validate it. + if (fValidate) + { + + // + // XML1.0-3rd + // Validity Constraint: + // The declaration matches EMPTY and the element has no content (not even + // entity references, comments, PIs or white space). + // + if ( (topElem->fCommentOrPISeen) && + (((DTDElementDecl*) topElem->fThisElement)->getModelType() == DTDElementDecl::Empty)) + { + fValidator->emitError + ( + XMLValid::EmptyElemHasContent + , topElem->fThisElement->getFullName() + ); + } + + // + // XML1.0-3rd + // Validity Constraint: + // + // The declaration matches children and the sequence of child elements + // belongs to the language generated by the regular expression in the + // content model, with optional white space, comments and PIs + // (i.e. markup matching production [27] Misc) between the start-tag and + // the first child element, between child elements, or between the last + // child element and the end-tag. + // + // Note that + // a CDATA section containing only white space or + // a reference to an entity whose replacement text is character references + // expanding to white space do not match the nonterminal S, and hence + // cannot appear in these positions; however, + // a reference to an internal entity with a literal value consisting + // of character references expanding to white space does match S, + // since its replacement text is the white space resulting from expansion + // of the character references. + // + if ( (topElem->fReferenceEscaped) && + (((DTDElementDecl*) topElem->fThisElement)->getModelType() == DTDElementDecl::Children)) + { + fValidator->emitError + ( + XMLValid::ElemChildrenHasInvalidWS + , topElem->fThisElement->getFullName() + ); + } + + XMLSize_t failure; + bool res = fValidator->checkContent + ( + topElem->fThisElement + , topElem->fChildren + , topElem->fChildCount + , &failure + ); + + if (!res) + { + // One of the elements is not valid for the content. NOTE that + // if no children were provided but the content model requires + // them, it comes back with a zero value. But we cannot use that + // to index the child array in this case, and have to put out a + // special message. + if (!topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::EmptyNotValidForContent + , topElem->fThisElement->getFormattedContentModel() + ); + } + else if (failure >= topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::NotEnoughElemsForCM + , topElem->fThisElement->getFormattedContentModel() + ); + } + else + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , topElem->fChildren[failure]->getRawName() + , topElem->fThisElement->getFormattedContentModel() + ); + } + } + } + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + fDocHandler->endElement + ( + *topElem->fThisElement + , uriId + , isRoot + , (fDoNamespaces) + ? topElem->fThisElement->getElementName()->getPrefix() + : XMLUni::fgZeroLenString + ); + } + + // If this was the root, then done with content + gotData = !isRoot; +} + + +// This method handles the high level logic of scanning the DOCType +// declaration. This calls the DTDScanner and kicks off both the scanning of +// the internal subset and the scanning of the external subset, if any. +// +// When we get here the 'resetDocType(); + + // There must be some space after DOCTYPE + bool skippedSomething; + fReaderMgr.skipPastSpaces(skippedSomething); + if (!skippedSomething) + { + emitError(XMLErrs::ExpectedWhitespace); + + // Just skip the Doctype declaration and return + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Get a buffer for the root element + XMLBufBid bbRootName(&fBufMgr); + + // Get a name from the input, which should be the name of the root + // element of the upcoming content. + int colonPosition; + bool validName = fDoNamespaces ? fReaderMgr.getQName(bbRootName.getBuffer(), &colonPosition) : + fReaderMgr.getName(bbRootName.getBuffer()); + if (!validName) + { + if (bbRootName.isEmpty()) + emitError(XMLErrs::NoRootElemInDOCTYPE); + else + emitError(XMLErrs::InvalidRootElemInDOCTYPE, bbRootName.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Store the root element name for later check + setRootElemName(bbRootName.getRawBuffer()); + + // This element obviously is not going to exist in the element decl + // pool yet, but we need to call docTypeDecl. So force it into + // the element decl pool, marked as being there because it was in + // the DOCTYPE. Later, when its declared, the status will be updated. + // + // Only do this if we are not reusing the validator! If we are reusing, + // then look it up instead. It has to exist! + MemoryManager* const rootDeclMgr = + fUseCachedGrammar ? fMemoryManager : fGrammarPoolMemoryManager; + + DTDElementDecl* rootDecl = new (rootDeclMgr) DTDElementDecl + ( + bbRootName.getRawBuffer() + , fEmptyNamespaceId + , DTDElementDecl::Any + , rootDeclMgr + ); + + Janitor rootDeclJanitor(rootDecl); + rootDecl->setCreateReason(DTDElementDecl::AsRootElem); + rootDecl->setExternalElemDeclaration(true); + if(!fUseCachedGrammar) + { + fGrammar->putElemDecl(rootDecl); + rootDeclJanitor.release(); + } else + { + // put this in the undeclared pool so it gets deleted... + XMLElementDecl* elemDecl = fDTDElemNonDeclPool->getByKey(bbRootName.getRawBuffer()); + if (elemDecl) + { + rootDecl->setId(elemDecl->getId()); + } + else + { + rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl)); + rootDeclJanitor.release(); + } + } + + // Skip any spaces after the name + fReaderMgr.skipPastSpaces(); + + // And now if we are looking at a >, then we are done. It is not + // required to have an internal or external subset, though why you + // would not escapes me. + if (fReaderMgr.skippedChar(chCloseAngle)) { + + // If we have a doc type handler and advanced callbacks are enabled, + // call the doctype event. + if (fDocTypeHandler) + fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false); + return; + } + + // either internal/external subset + if (fValScheme == Val_Auto && !fValidate) + fValidate = true; + + bool hasIntSubset = false; + bool hasExtSubset = false; + XMLCh* sysId = 0; + XMLCh* pubId = 0; + + DTDScanner dtdScanner + ( + (DTDGrammar*) fGrammar + , fDocTypeHandler + , fGrammarPoolMemoryManager + , fMemoryManager + ); + dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr); + + // If the next character is '[' then we have no external subset cause + // there is no system id, just the opening character of the internal + // subset. Else, has to be an id. + // + // Just look at the next char, don't eat it. + if (fReaderMgr.peekNextChar() == chOpenSquare) + { + hasIntSubset = true; + } + else + { + // Indicate we have an external subset + hasExtSubset = true; + fHasNoDTD = false; + + // Get buffers for the ids + XMLBufBid bbPubId(&fBufMgr); + XMLBufBid bbSysId(&fBufMgr); + + // Get the external subset id + if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External)) + { + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Get copies of the ids we got + pubId = XMLString::replicate(bbPubId.getRawBuffer(), fMemoryManager); + sysId = XMLString::replicate(bbSysId.getRawBuffer(), fMemoryManager); + + // Skip spaces and check again for the opening of an internal subset + fReaderMgr.skipPastSpaces(); + + // Just look at the next char, don't eat it. + if (fReaderMgr.peekNextChar() == chOpenSquare) { + hasIntSubset = true; + } + } + + // Insure that the ids get cleaned up, if they got allocated + ArrayJanitor janSysId(sysId, fMemoryManager); + ArrayJanitor janPubId(pubId, fMemoryManager); + + // If we have a doc type handler and advanced callbacks are enabled, + // call the doctype event. + if (fDocTypeHandler) + fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset); + + // Ok, if we had an internal subset, we are just past the [ character + // and need to parse that first. + if (hasIntSubset) + { + // Eat the opening square bracket + fReaderMgr.getNextChar(); + + checkInternalDTD(hasExtSubset, sysId, pubId); + + // And try to scan the internal subset. If we fail, try to recover + // by skipping forward tot he close angle and returning. + if (!dtdScanner.scanInternalSubset()) + { + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Do a sanity check that some expanded PE did not propogate out of + // the doctype. This could happen if it was terminated early by bad + // syntax. + if (fReaderMgr.getReaderDepth() > 1) + { + emitError(XMLErrs::PEPropogated); + + // Ask the reader manager to pop back down to the main level + fReaderMgr.cleanStackBackTo(1); + } + + fReaderMgr.skipPastSpaces(); + } + + // And that should leave us at the closing > of the DOCTYPE line + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + // Do a special check for the common scenario of an extra ] char at + // the end. This is easy to recover from. + if (fReaderMgr.skippedChar(chCloseSquare) + && fReaderMgr.skippedChar(chCloseAngle)) + { + emitError(XMLErrs::ExtraCloseSquare); + } + else + { + emitError(XMLErrs::UnterminatedDOCTYPE); + fReaderMgr.skipPastChar(chCloseAngle); + } + } + + // If we had an external subset, then we need to deal with that one + // next. If we are reusing the validator, then don't scan it. + if (hasExtSubset) { + + InputSource* srcUsed=0; + Janitor janSrc(srcUsed); + // If we had an internal subset and we're using the cached grammar, it + // means that the ignoreCachedDTD is set, so we ignore the cached + // grammar + if (fUseCachedGrammar && !hasIntSubset) + { + srcUsed = resolveSystemId(sysId, pubId); + if (srcUsed) { + janSrc.reset(srcUsed); + Grammar* grammar = fGrammarResolver->getGrammar(srcUsed->getSystemId()); + + if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType) { + + fDTDGrammar = (DTDGrammar*) grammar; + fGrammar = fDTDGrammar; + fValidator->setGrammar(fGrammar); + // If we don't report at least the external subset boundaries, + // an advanced document handler cannot know when the DTD end, + // since we've already sent a doctype decl that indicates there's + // there's an external subset. + if (fDocTypeHandler) + { + fDocTypeHandler->startExtSubset(); + fDocTypeHandler->endExtSubset(); + } + + return; + } + } + } + + if (fLoadExternalDTD || fValidate) + { + // And now create a reader to read this entity + XMLReader* reader; + if(srcUsed) { + reader = fReaderMgr.createReader + ( + *srcUsed + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + } + else { + reader = fReaderMgr.createReader + ( + sysId + , pubId + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , srcUsed + , fCalculateSrcOfs + , fLowWaterMark + , fDisableDefaultEntityResolution + ); + janSrc.reset(srcUsed); + } + // If it failed then throw an exception + if (!reader) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed ? srcUsed->getSystemId() : sysId, fMemoryManager); + + if (fToCacheGrammar) { + + unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId()); + const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId); + + fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString); + ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr); + fGrammarResolver->putGrammar(fGrammar); + } + + // In order to make the processing work consistently, we have to + // make this look like an external entity. So create an entity + // decl and fill it in and push it with the reader, as happens + // with an external entity. Put a janitor on it to insure it gets + // cleaned up. The reader manager does not adopt them. + const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull }; + DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); + declDTD->setSystemId(sysId); + declDTD->setIsExternal(true); + Janitor janDecl(declDTD); + + // Mark this one as a throw at end + reader->setThrowAtEnd(true); + + // And push it onto the stack, with its pseudo name + fReaderMgr.pushReader(reader, declDTD); + + // Tell it its not in an include section + dtdScanner.scanExtSubsetDecl(false, true); + } + } +} + +bool DGXMLScanner::scanStartTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Get the QName. In this case, we are not doing namespaces, so we just + // use it as is and don't have to break it into parts. + + bool validName = fReaderMgr.getName(fQNameBuf); + if (!validName) + { + if (fQNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedElementName); + else + emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer()); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // Assume it won't be an empty tag + bool isEmpty = false; + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Lets try to look up the element in the validator's element decl pool + // We can pass bogus values for the URI id and the base name. We know that + // this can only be called if we are doing a DTD style validator and that + // he will only look at the QName. + // + // We *do not* tell him to fault in a decl if he does not find one - NG. + bool wasAdded = false; + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + + XMLElementDecl* elemDecl = fGrammar->getElemDecl + ( + fEmptyNamespaceId + , 0 + , qnameRawBuf + , Grammar::TOP_LEVEL_SCOPE + ); + // look in the undeclared pool: + if(!elemDecl) + { + elemDecl = fDTDElemNonDeclPool->getByKey(qnameRawBuf); + } + if(!elemDecl) + { + wasAdded = true; + elemDecl = new (fMemoryManager) DTDElementDecl + ( + qnameRawBuf + , fEmptyNamespaceId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } + + if (fValidate) { + + if (wasAdded) + { + // This is to tell the reuse Validator that this element was + // faulted-in, was not an element in the validator pool originally + elemDecl->setCreateReason(XMLElementDecl::JustFaultIn); + + fValidator->emitError + ( + XMLValid::ElementNotDefined + , qnameRawBuf + ); + } + // If its not marked declared, then emit an error + else if (!elemDecl->isDeclared()) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , qnameRawBuf + ); + } + + + fValidator->validateElement(elemDecl); + } + + // Expand the element stack and add the new element + fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum()); + + // If this is the first element and we are validating, check the root + // element. + if (isRoot) + { + fRootGrammar = fGrammar; + + if (fValidate) + { + // If a DocType exists, then check if it matches the root name there. + if (fRootElemName && !XMLString::equals(qnameRawBuf, fRootElemName)) + fValidator->emitError(XMLValid::RootElemNotLikeDocType); + } + } + else if (fValidate) + { + // If the element stack is not empty, then add this element as a + // child of the previous top element. If its empty, this is the root + // elem and is not the child of anything. + fElemStack.addChild(elemDecl->getElementName(), true); + } + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // We loop until we either see a /> or >, handling attribute/value + // pairs until we get there. + XMLSize_t attCount = 0; + XMLSize_t curAttListSize = fAttrList->size(); + wasAdded = false; + + fElemCount++; + + while (true) + { + // And get the next non-space character + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + // Ok, skip by them and peek another char + fReaderMgr.skipPastSpaces(); + nextCh = fReaderMgr.peekNextChar(); + } + else + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume its going to be an attribute, so get a name from + // the input. + + validName = fReaderMgr.getName(fAttNameBuf); + if (!validName) + { + if (fAttNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedAttrName); + else + emitError(XMLErrs::InvalidAttrName, fAttNameBuf.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return false; + } + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // See if this attribute is declared for this element. If we are + // not validating of course it will not be at first, but we will + // fault it into the pool (to avoid lots of redundant errors.) + XMLCh * namePtr = fAttNameBuf.getRawBuffer(); + XMLAttDef* attDef = ((DTDElementDecl *)elemDecl)->getAttDef(namePtr); + + // Skip any whitespace before the value and then scan the att + // value. This will come back normalized with entity refs and + // char refs expanded. + fReaderMgr.skipPastSpaces(); + if (!scanAttValue(attDef, namePtr, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // Add this attribute to the attribute list that we use to + // pass them to the handler. We reuse its existing elements + // but expand it as required. + // Note that we want to this first since this will + // make a copy of the namePtr; we can then make use of + // that copy in the hashtable lookup that checks + // for duplicates. This will mean we may have to update + // the type of the XMLAttr later. + XMLAttr* curAtt; + const XMLCh* attrValue = fAttValueBuf.getRawBuffer(); + + if (attCount >= curAttListSize) { + curAtt = new (fMemoryManager) XMLAttr(fMemoryManager); + fAttrList->addElement(curAtt); + } + else { + curAtt = fAttrList->elementAt(attCount); + } + + curAtt->setSpecified(true); + + // NO NAMESPACE CODE + { + curAtt->set( + 0, namePtr, XMLUni::fgZeroLenString, XMLUni::fgZeroLenString + , (attDef)?attDef->getType():XMLAttDef::CData + ); + + // now need to prepare for duplicate detection + if (attDef) { + unsigned int *curCountPtr = fAttDefRegistry->get(attDef); + if (!curCountPtr) { + curCountPtr = getNewUIntPtr(); + *curCountPtr = fElemCount; + fAttDefRegistry->put(attDef, curCountPtr); + } + else if (*curCountPtr < fElemCount) { + *curCountPtr = fElemCount; + } + else { + emitError( + XMLErrs::AttrAlreadyUsedInSTag + , attDef->getFullName(), elemDecl->getFullName() + ); + } + } + else + { + // reset namePtr so it refers to newly-allocated memory + namePtr = (XMLCh *)curAtt->getQName(); + if (!fUndeclaredAttrRegistry->putIfNotPresent(namePtr, 0)) + { + emitError( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr, elemDecl->getFullName() + ); + } + } + } + + if (fValidate) + { + if (attDef) { + // Let the validator pass judgement on the attribute value + fValidator->validateAttrValue( + attDef, fAttValueBuf.getRawBuffer(), false, elemDecl + ); + } + else + { + fValidator->emitError + ( + XMLValid::AttNotDefinedForElement + , fAttNameBuf.getRawBuffer(), qnameRawBuf + ); + } + } + + // must set the newly-minted value on the XMLAttr: + curAtt->setValue(attrValue); + attCount++; + + // And jump back to the top of the loop + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + if(attCount) + { + // clean up after ourselves: + // clear the map used to detect duplicate attributes + fUndeclaredAttrRegistry->removeAll(); + } + + // Now lets get the fAttrList filled in. This involves faulting in any + // defaulted and fixed attributes and normalizing the values of any that + // we got explicitly. + // + // We update the attCount value with the total number of attributes, but + // it goes in with the number of values we got during the raw scan of + // explictly provided attrs above. + attCount = buildAttList(attCount, elemDecl, *fAttrList); + + // If we have a document handler, then tell it about this start tag. We + // don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send + // any prefix since its just one big name if we are not doing namespaces. + unsigned int uriId = fEmptyNamespaceId; + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl + , uriId + , 0 + , *fAttrList + , attCount + , isEmpty + , isRoot + ); + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // If validating, then insure that its legal to have no content + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent(elemDecl, 0, 0, &failure); + if (!res) + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , qnameRawBuf + , elemDecl->getFormattedContentModel() + ); + } + } + + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + } + + return true; +} + + +bool DGXMLScanner::scanStartTagNS(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Get the QName. In this case, we are not doing namespaces, so we just + // use it as is and don't have to break it into parts. + + int colonPosition; + bool validName = fReaderMgr.getQName(fQNameBuf, &colonPosition); + if (!validName) + { + if (fQNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedElementName); + else + emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer()); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // Assume it won't be an empty tag + bool isEmpty = false; + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Lets try to look up the element in the validator's element decl pool + // We can pass bogus values for the URI id and the base name. We know that + // this can only be called if we are doing a DTD style validator and that + // he will only look at the QName. + // + // We *do not* tell him to fault in a decl if he does not find one - NG. + bool wasAdded = false; + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + + XMLElementDecl* elemDecl = fGrammar->getElemDecl + ( + fEmptyNamespaceId + , 0 + , qnameRawBuf + , Grammar::TOP_LEVEL_SCOPE + ); + // look in the undeclared pool: + if(!elemDecl) + { + elemDecl = fDTDElemNonDeclPool->getByKey(qnameRawBuf); + } + if(!elemDecl) + { + wasAdded = true; + elemDecl = new (fMemoryManager) DTDElementDecl + ( + qnameRawBuf + , fEmptyNamespaceId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } + + if (fValidate) { + + if (wasAdded) + { + // This is to tell the reuse Validator that this element was + // faulted-in, was not an element in the validator pool originally + elemDecl->setCreateReason(XMLElementDecl::JustFaultIn); + + fValidator->emitError + ( + XMLValid::ElementNotDefined + , qnameRawBuf + ); + } + // If its not marked declared, then emit an error + else if (!elemDecl->isDeclared()) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , qnameRawBuf + ); + } + + + fValidator->validateElement(elemDecl); + } + + // Expand the element stack and add the new element + fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum()); + + // If this is the first element and we are validating, check the root + // element. + if (isRoot) + { + fRootGrammar = fGrammar; + + if (fValidate) + { + // If a DocType exists, then check if it matches the root name there. + if (fRootElemName && !XMLString::equals(qnameRawBuf, fRootElemName)) + fValidator->emitError(XMLValid::RootElemNotLikeDocType); + } + } + else if (fValidate) + { + // If the element stack is not empty, then add this element as a + // child of the previous top element. If its empty, this is the root + // elem and is not the child of anything. + fElemStack.addChild(elemDecl->getElementName(), true); + } + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // We loop until we either see a /> or >, handling attribute/value + // pairs until we get there. + XMLSize_t attCount = 0; + XMLSize_t curAttListSize = fAttrList->size(); + wasAdded = false; + + fElemCount++; + + while (true) + { + // And get the next non-space character + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + // Ok, skip by them and peek another char + fReaderMgr.skipPastSpaces(); + nextCh = fReaderMgr.peekNextChar(); + } + else + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume its going to be an attribute, so get a name from + // the input. + + validName = fReaderMgr.getQName(fAttNameBuf, &colonPosition); + if (!validName) + { + if (fAttNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedAttrName); + else + emitError(XMLErrs::InvalidAttrName, fAttNameBuf.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return false; + } + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // See if this attribute is declared for this element. If we are + // not validating of course it will not be at first, but we will + // fault it into the pool (to avoid lots of redundant errors.) + XMLCh * namePtr = fAttNameBuf.getRawBuffer(); + XMLAttDef* attDef = ((DTDElementDecl *)elemDecl)->getAttDef(namePtr); + + // Skip any whitespace before the value and then scan the att + // value. This will come back normalized with entity refs and + // char refs expanded. + fReaderMgr.skipPastSpaces(); + if (!scanAttValue(attDef, namePtr, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // Add this attribute to the attribute list that we use to + // pass them to the handler. We reuse its existing elements + // but expand it as required. + // Note that we want to this first since this will + // make a copy of the namePtr; we can then make use of + // that copy in the hashtable lookup that checks + // for duplicates. This will mean we may have to update + // the type of the XMLAttr later. + XMLAttr* curAtt; + const XMLCh* attrValue = fAttValueBuf.getRawBuffer(); + + if (attCount >= curAttListSize) { + curAtt = new (fMemoryManager) XMLAttr(fMemoryManager); + fAttrList->addElement(curAtt); + } + else { + curAtt = fAttrList->elementAt(attCount); + } + + curAtt->setSpecified(true); + // DO NAMESPACES + { + curAtt->set( + fEmptyNamespaceId, namePtr, XMLUni::fgZeroLenString + , (attDef)? attDef->getType() : XMLAttDef::CData + ); + + // each attribute has the prefix:suffix="value" + const XMLCh* attPrefix = curAtt->getPrefix(); + const XMLCh* attLocalName = curAtt->getName(); + + if (attPrefix && *attPrefix) { + if (XMLString::equals(attPrefix, XMLUni::fgXMLString)) { + curAtt->setURIId(fXMLNamespaceId); + } + else if (XMLString::equals(attPrefix, XMLUni::fgXMLNSString)) { + curAtt->setURIId(fXMLNSNamespaceId); + updateNSMap(attPrefix, attLocalName, attrValue); + } + else { + fAttrNSList->addElement(curAtt); + } + } + else if (XMLString::equals(XMLUni::fgXMLNSString, attLocalName)) + { + updateNSMap(attPrefix, XMLUni::fgZeroLenString, attrValue); + } + + // NOTE: duplicate attribute check will be done, when we map + // namespaces to all attributes + if (attDef) { + unsigned int *curCountPtr = fAttDefRegistry->get(attDef); + if (!curCountPtr) { + curCountPtr = getNewUIntPtr(); + *curCountPtr = fElemCount; + fAttDefRegistry->put(attDef, curCountPtr); + } + else if (*curCountPtr < fElemCount) { + *curCountPtr = fElemCount; + } + } + } + + if (fValidate) + { + if (attDef) { + // Let the validator pass judgement on the attribute value + fValidator->validateAttrValue( + attDef, fAttValueBuf.getRawBuffer(), false, elemDecl + ); + } + else + { + fValidator->emitError + ( + XMLValid::AttNotDefinedForElement + , fAttNameBuf.getRawBuffer(), qnameRawBuf + ); + } + } + + // must set the newly-minted value on the XMLAttr: + curAtt->setValue(attrValue); + attCount++; + + // And jump back to the top of the loop + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + // Make an initial pass through the list and find any xmlns attributes. + if (attCount) + scanAttrListforNameSpaces(fAttrList, attCount, elemDecl); + + if(attCount) + { + // clean up after ourselves: + // clear the map used to detect duplicate attributes + fUndeclaredAttrRegistry->removeAll(); + } + + // Now lets get the fAttrList filled in. This involves faulting in any + // defaulted and fixed attributes and normalizing the values of any that + // we got explicitly. + // + // We update the attCount value with the total number of attributes, but + // it goes in with the number of values we got during the raw scan of + // explictly provided attrs above. + attCount = buildAttList(attCount, elemDecl, *fAttrList); + + // If we have a document handler, then tell it about this start tag. We + // don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send + // any prefix since its just one big name if we are not doing namespaces. + if (fDocHandler) + { + unsigned int uriId = resolvePrefix + ( + elemDecl->getElementName()->getPrefix() + , ElemStack::Mode_Element + ); + + fDocHandler->startElement + ( + *elemDecl + , uriId + , elemDecl->getElementName()->getPrefix() + , *fAttrList + , attCount + , isEmpty + , isRoot + ); + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // If validating, then insure that its legal to have no content + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent(elemDecl, 0, 0, &failure); + if (!res) + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , qnameRawBuf + , elemDecl->getFormattedContentModel() + ); + } + } + + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + } + + return true; +} + +// --------------------------------------------------------------------------- +// DGXMLScanner: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* DGXMLScanner::loadGrammar(const InputSource& src + , const short grammarType + , const bool toCache) +{ + Grammar* loadedGrammar = 0; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + fGrammarResolver->cacheGrammarFromParse(false); + fGrammarResolver->useCachedGrammarInParse(false); + fRootGrammar = 0; + + if (fValScheme == Val_Auto) { + fValidate = true; + } + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + + if (grammarType == Grammar::DTDGrammarType) { + loadedGrammar = loadDTDGrammar(src, toCache); + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + return loadedGrammar; +} + +Grammar* DGXMLScanner::loadDTDGrammar(const InputSource& src, + const bool toCache) +{ + // Reset the validators + fDTDValidator->reset(); + if (fValidatorFromUser) + fValidator->reset(); + + fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager); + fGrammarResolver->putGrammar(fDTDGrammar); + fGrammar = fDTDGrammar; + fValidator->setGrammar(fGrammar); + + // And for all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Clear out the id reference list + resetValidationContext(); + + if (toCache) { + + unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId()); + const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId); + + fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString); + ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr); + fGrammarResolver->putGrammar(fGrammar); + } + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // In order to make the processing work consistently, we have to + // make this look like an external entity. So create an entity + // decl and fill it in and push it with the reader, as happens + // with an external entity. Put a janitor on it to insure it gets + // cleaned up. The reader manager does not adopt them. + const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull }; + DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); + declDTD->setSystemId(src.getSystemId()); + declDTD->setIsExternal(true); + Janitor janDecl(declDTD); + + // Mark this one as a throw at end + newReader->setThrowAtEnd(true); + + // And push it onto the stack, with its pseudo name + fReaderMgr.pushReader(newReader, declDTD); + + // If we have a doc type handler and advanced callbacks are enabled, + // call the doctype event. + if (fDocTypeHandler) { + + // Create a dummy root + DTDElementDecl* rootDecl = new (fGrammarPoolMemoryManager) DTDElementDecl + ( + gDTDStr + , fEmptyNamespaceId + , DTDElementDecl::Any + , fGrammarPoolMemoryManager + ); + rootDecl->setCreateReason(DTDElementDecl::AsRootElem); + rootDecl->setExternalElemDeclaration(true); + Janitor janSrc(rootDecl); + + fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true); + } + + // Create DTDScanner + DTDScanner dtdScanner + ( + (DTDGrammar*)fGrammar + , fDocTypeHandler + , fGrammarPoolMemoryManager + , fMemoryManager + ); + dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr); + + // Tell it its not in an include section + dtdScanner.scanExtSubsetDecl(false, true); + + if (fValidate) { + // validate the DTD scan so far + fValidator->preContentValidation(false, true); + } + + if (toCache) + fGrammarResolver->cacheGrammars(); + + return fDTDGrammar; +} + + +// --------------------------------------------------------------------------- +// DGXMLScanner: Private helper methods +// --------------------------------------------------------------------------- +// This method handles the common initialization, to avoid having to do +// it redundantly in multiple constructors. +void DGXMLScanner::commonInit() +{ + // And we need one for the raw attribute scan. This just stores key/ + // value string pairs (prior to any processing.) + fAttrNSList = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + + // Create the Validator and init them + fDTDValidator = new (fMemoryManager) DTDValidator(); + initValidator(fDTDValidator); + fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool(29, 128, fMemoryManager); + fAttDefRegistry = new (fMemoryManager) RefHashTableOf + ( + 131, false, fMemoryManager + ); + fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf(7, fMemoryManager); + + if (fValidator) + { + if (!fValidator->handlesDTD()) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager); + } + else + { + fValidator = fDTDValidator; + } +} + +void DGXMLScanner::cleanUp() +{ + delete fAttrNSList; + delete fDTDValidator; + delete fDTDElemNonDeclPool; + delete fAttDefRegistry; + delete fUndeclaredAttrRegistry; +} + + +// This method is called from scanStartTagNS() to build up the list of +// XMLAttr objects that will be passed out in the start tag callout. We +// get the key/value pairs from the raw scan of explicitly provided attrs, +// which have not been normalized. And we get the element declaration from +// which we will get any defaulted or fixed attribute defs and add those +// in as well. +XMLSize_t +DGXMLScanner::buildAttList(const XMLSize_t attCount + , XMLElementDecl* elemDecl + , RefVectorOf& toFill) +{ + // Ask the element to clear the 'provided' flag on all of the att defs + // that it owns, and to return us a boolean indicating whether it has + // any defs. + const bool hasDefs = elemDecl->hasAttDefs(); + + // If there are no expliclitily provided attributes and there are no + // defined attributes for the element, the we don't have anything to do. + // So just return zero in this case. + if (!hasDefs && !attCount) + return 0; + + // Keep up with how many attrs we end up with total + XMLSize_t retCount = attCount; + + // And get the current size of the output vector. This lets us use + // existing elements until we fill it, then start adding new ones. + const XMLSize_t curAttListSize = toFill.size(); + + // Ok, so lets get an enumerator for the attributes of this element + // and run through them for well formedness and validity checks. But + // make sure that we had any attributes before we do it, since the list + // would have have gotten faulted in anyway. + if (hasDefs) + { + XMLAttDefList& attDefList = elemDecl->getAttDefList(); + for(XMLSize_t i=0; iget(&curDef); + if (!attCountPtr || *attCountPtr < fElemCount) + { // did not occur + const XMLAttDef::DefAttTypes defType = curDef.getDefaultType(); + + if (fValidate) + { + // If we are validating and its required, then an error + if (defType == XMLAttDef::Required) + { + fValidator->emitError + ( + XMLValid::RequiredAttrNotProvided + , curDef.getFullName() + ); + } + else if ((defType == XMLAttDef::Default) || + (defType == XMLAttDef::Fixed) ) + { + if (fStandalone && curDef.isExternal()) + { + // XML 1.0 Section 2.9 + // Document is standalone, so attributes must not be defaulted. + fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName()); + } + } + } + + // Fault in the value if needed, and bump the att count + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + // Let the validator pass judgement on the attribute value + if (fValidate) + { + fValidator->validateAttrValue + ( + &curDef + , curDef.getValue() + , false + , elemDecl + ); + } + + XMLAttr* curAtt; + if (retCount >= curAttListSize) + { + if (fDoNamespaces) + { + curAtt = new (fMemoryManager) XMLAttr + ( + fEmptyNamespaceId + , curDef.getFullName() + , curDef.getValue() + , curDef.getType() + , false + , fMemoryManager + ); + } + else + { + curAtt = new (fMemoryManager) XMLAttr + ( + 0 + , curDef.getFullName() + , XMLUni::fgZeroLenString + , curDef.getValue() + , curDef.getType() + , false + , fMemoryManager + ); + } + + fAttrList->addElement(curAtt); + } + else + { + curAtt = fAttrList->elementAt(retCount); + if (fDoNamespaces) + { + curAtt->set + ( + fEmptyNamespaceId + , curDef.getFullName() + , curDef.getValue() + , curDef.getType() + ); + } + else + { + curAtt->set + ( + 0 + , curDef.getFullName() + , XMLUni::fgZeroLenString + , curDef.getValue() + , curDef.getType() + ); + } + curAtt->setSpecified(false); + } + + if (fDoNamespaces) + { + // Map the new attribute's prefix to a URI id and store + // that in the attribute object. + const XMLCh* attPrefix = curAtt->getPrefix(); + if (attPrefix && *attPrefix) { + curAtt->setURIId + ( + resolvePrefix(attPrefix, ElemStack::Mode_Attribute) + ); + } + } + + retCount++; + } + } + } + } + + return retCount; +} + + +// This method will reset the scanner data structures, and related plugged +// in stuff, for a new scan session. We get the input source for the primary +// XML entity, create the reader for it, and push it on the stack so that +// upon successful return from here we are ready to go. +void DGXMLScanner::scanReset(const InputSource& src) +{ + + // This call implicitly tells us that we are going to reuse the scanner + // if it was previously used. So tell the validator to reset itself. + // + // But, if the fUseCacheGrammar flag is set, then don't reset it. + // + // NOTE: The ReaderMgr is flushed on the way out, because that is + // required to insure that files are closed. + fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar); + fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar); + + fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager); + fGrammarResolver->putGrammar(fDTDGrammar); + fGrammar = fDTDGrammar; + fRootGrammar = 0; + fValidator->setGrammar(fGrammar); + + // Reset validation + fValidate = (fValScheme == Val_Always) ? true : false; + + // And for all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Clear out the id reference list + resetValidationContext(); + + // Reset the Root Element Name + fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName; + fRootElemName = 0; + + // Reset the element stack, and give it the latest ids for the special + // URIs it has to know about. + fElemStack.reset + ( + fEmptyNamespaceId + , fUnknownNamespaceId + , fXMLNamespaceId + , fXMLNSNamespaceId + ); + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + + // Reset the validators + fDTDValidator->reset(); + fDTDValidator->setErrorReporter(fErrorReporter); + if (fValidatorFromUser) + fValidator->reset(); + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , true + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // Push this read onto the reader manager + fReaderMgr.pushReader(newReader, 0); + + // and reset security-related things if necessary: + if(fSecurityManager != 0) + { + fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit(); + fEntityExpansionCount = 0; + } + if(fUIntPoolRowTotal >= 32) + { // 8 KB tied up with validating attributes... + fAttDefRegistry->removeAll(); + recreateUIntPool(); + } + else + { + // note that this will implicitly reset the values of the hashtables, + // though their buckets will still be tied up + resetUIntPool(); + } + fUndeclaredAttrRegistry->removeAll(); + fAttrNSList->removeAllElements(); +} + + +// This method is called between markup in content. It scans for character +// data that is sent to the document handler. It watches for any markup +// characters that would indicate that the character data has ended. It also +// handles expansion of general and character entities. +// +// sendData() is a local static helper for this method which handles some +// code that must be done in three different places here. +void DGXMLScanner::sendCharData(XMLBuffer& toSend) +{ + // If no data in the buffer, then nothing to do + if (toSend.isEmpty()) + return; + + // We do different things according to whether we are validating or + // not. If not, its always just characters; else, it depends on the + // current element's content model. + if (fValidate) + { + // Get the raw data we need for the callback + const XMLCh* const rawBuf = toSend.getRawBuffer(); + const XMLSize_t len = toSend.getLen(); + + // And see if the current element is a 'Children' style content model + const ElemStack::StackElem* topElem = fElemStack.topElement(); + + // Get the character data opts for the current element + XMLElementDecl::CharDataOpts charOpts = topElem->fThisElement->getCharDataOpts(); + + if (charOpts == XMLElementDecl::NoCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + } + else if (fReaderMgr.getCurrentReader()->isAllSpaces(rawBuf, len)) + { + // Its all spaces. So, if they can take spaces, then send it + // as ignorable whitespace. If they can handle any char data + // send it as characters. + if (charOpts == XMLElementDecl::SpacesOk) { + if (fDocHandler) + fDocHandler->ignorableWhitespace(rawBuf, len, false); + } + else if (charOpts == XMLElementDecl::AllCharData) + { + if (fDocHandler) + fDocHandler->docCharacters(rawBuf, len, false); + } + } + else + { + // If they can take any char data, then send it. Otherwise, they + // can only handle whitespace and can't handle this stuff so + // issue an error. + if (charOpts == XMLElementDecl::AllCharData) + { + if (fDocHandler) + fDocHandler->docCharacters(rawBuf, len, false); + } + else + { + fValidator->emitError(XMLValid::NoCharDataInCM); + } + } + } + else + { + // Always assume its just char data if not validating + if (fDocHandler) + fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false); + } + + // Reset buffer + toSend.reset(); +} + + + +// This method is called with a key/value string pair that represents an +// xmlns="yyy" or xmlns:xxx="yyy" attribute. This method will update the +// current top of the element stack based on this data. We know that when +// we get here, that it is one of these forms, so we don't bother confirming +// it. +// +// But we have to ensure +// 1. xxx is not xmlns +// 2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa +// 3. yyy is not XMLUni::fgXMLNSURIName +// 4. if xxx is not null, then yyy cannot be an empty string. +void DGXMLScanner::updateNSMap(const XMLCh* const attrPrefix + , const XMLCh* const attrLocalName + , const XMLCh* const attrValue) +{ + // We either have the default prefix (""), or we point it into the attr + // name parameter. Note that the xmlns is not the prefix we care about + // here. To us, the 'prefix' is really the local part of the attrName + // parameter. + // + // Check 1. xxx is not xmlns + // 2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa + // 3. yyy is not XMLUni::fgXMLNSURIName + // 4. if xxx is not null, then yyy cannot be an empty string. + if (attrPrefix && *attrPrefix) { + + if (XMLString::equals(attrLocalName, XMLUni::fgXMLNSString)) + emitError(XMLErrs::NoUseOfxmlnsAsPrefix); + else if (XMLString::equals(attrLocalName, XMLUni::fgXMLString)) { + if (!XMLString::equals(attrValue, XMLUni::fgXMLURIName)) + emitError(XMLErrs::PrefixXMLNotMatchXMLURI); + } + + if (!attrValue) + emitError(XMLErrs::NoEmptyStrNamespace, attrLocalName); + else if(!*attrValue && fXMLVersion == XMLReader::XMLV1_0) + emitError(XMLErrs::NoEmptyStrNamespace, attrLocalName); + } + + if (XMLString::equals(attrValue, XMLUni::fgXMLNSURIName)) + emitError(XMLErrs::NoUseOfxmlnsURI); + else if (XMLString::equals(attrValue, XMLUni::fgXMLURIName)) { + if (!XMLString::equals(attrLocalName, XMLUni::fgXMLString)) + emitError(XMLErrs::XMLURINotMatchXMLPrefix); + } + + // Ok, we have to get the unique id for the attribute value, which is the + // URI that this value should be mapped to. The validator has the + // namespace string pool, so we ask him to find or add this new one. Then + // we ask the element stack to add this prefix to URI Id mapping. + fElemStack.addPrefix + ( + attrLocalName + , fURIStringPool->addOrFind(attrValue) + ); +} + +void DGXMLScanner::scanAttrListforNameSpaces(RefVectorOf* theAttrList, XMLSize_t attCount, + XMLElementDecl* elemDecl) +{ + // Map prefixes to uris + for (XMLSize_t i=0; i < fAttrNSList->size(); i++) { + XMLAttr* providedAttr = fAttrNSList->elementAt(i); + providedAttr->setURIId( + resolvePrefix(providedAttr->getPrefix(), ElemStack::Mode_Attribute) + ); + } + + fAttrNSList->removeAllElements(); + + // Decide if to use hash table to do duplicate checking + bool toUseHashTable = false; + + setAttrDupChkRegistry(attCount, toUseHashTable); + for (XMLSize_t index = 0; index < attCount; index++) + { + // check for duplicate namespace attributes: + // by checking for qualified names with the same local part and with prefixes + // which have been bound to namespace names that are identical. + XMLAttr* curAttr = theAttrList->elementAt(index); + if (!toUseHashTable) + { + XMLAttr* loopAttr; + for (XMLSize_t attrIndex=0; attrIndex < index; attrIndex++) { + loopAttr = theAttrList->elementAt(attrIndex); + if (loopAttr->getURIId() == curAttr->getURIId() && + XMLString::equals(loopAttr->getName(), curAttr->getName())) { + emitError( + XMLErrs::AttrAlreadyUsedInSTag, curAttr->getName() + , elemDecl->getFullName() + ); + } + } + } + else + { + if (fAttrDupChkRegistry->containsKey((void*)curAttr->getName(), curAttr->getURIId())) + { + emitError( + XMLErrs::AttrAlreadyUsedInSTag + , curAttr->getName(), elemDecl->getFullName() + ); + } + + fAttrDupChkRegistry->put((void*)curAttr->getName(), curAttr->getURIId(), curAttr); + } + } +} + +InputSource* DGXMLScanner::resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId) +{ + //Normalize sysId + XMLBufBid nnSys(&fBufMgr); + XMLBuffer& normalizedSysId = nnSys.getBuffer(); + XMLString::removeChar(sysId, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the normalized system id + XMLBufBid bbSys(&fBufMgr); + XMLBuffer& expSysId = bbSys.getBuffer(); + + // Allow the entity handler to expand the system id if they choose + // to do so. + InputSource* srcToFill = 0; + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity, + expSysId.getRawBuffer(), 0, pubId, lastInfo.systemId, + &fReaderMgr); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + else + { + expSysId.set(normalizedURI); + } + + // If they didn't create a source via the entity handler, then we + // have to create one on our own. + if (!srcToFill) + { + if (fDisableDefaultEntityResolution) + return srcToFill; + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBufBid ddSys(&fBufMgr); + XMLBuffer& resolvedSysId = ddSys.getBuffer(); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + return srcToFill; +} + +// --------------------------------------------------------------------------- +// DGXMLScanner: Private parsing methods +// --------------------------------------------------------------------------- +bool DGXMLScanner::scanAttValue( const XMLAttDef* const attDef + , const XMLCh *const attrName + , XMLBuffer& toFill) +{ + enum States + { + InWhitespace + , InContent + }; + + // Get the type and name + const XMLAttDef::AttTypes type = (attDef) + ?attDef->getType() + :XMLAttDef::CData; + + // Reset the target buffer + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr.skipIfQuote(quoteCh)) + return false; + + // We have to get the current reader because we have to ignore closing + // quotes until we hit the same reader again. + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // Get attribute def - to check to see if it's declared externally or not + bool isAttExternal = (attDef) + ?attDef->isExternal() + :false; + + // Loop until we get the attribute value. Note that we use a double + // loop here to avoid the setup/teardown overhead of the exception + // handler on every round. + XMLCh nextCh; + XMLCh secondCh = 0; + States curState = InContent; + bool firstNonWS = false; + bool gotLeadingSurrogate = false; + bool escaped; + while (true) + { + try + { + while(true) + { + nextCh = fReaderMgr.getNextChar(); + + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + // Check for our ending quote in the same entity + if (nextCh == quoteCh) + { + if (curReader == fReaderMgr.getCurrentReaderNum()) + return true; + + // Watch for spillover into a previous entity + if (curReader > fReaderMgr.getCurrentReaderNum()) + { + emitError(XMLErrs::PartialMarkupInEntity); + return false; + } + } + + // Check for an entity ref now, before we let it affect our + // whitespace normalization logic below. We ignore the empty flag + // in this one. + escaped = false; + if (nextCh == chAmpersand) + { + if (scanEntityRef(true, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // If its not escaped, then make sure its not a < character, which + // is not allowed in attribute values. + if (!escaped && (nextCh == chOpenAngle)) + emitError(XMLErrs::BracketInAttrValue, attrName); + + // If the attribute is a CDATA type we do simple replacement of + // tabs and new lines with spaces, if the character is not escaped + // by way of a char ref. + // + // Otherwise, we do the standard non-CDATA normalization of + // compressing whitespace to single spaces and getting rid of leading + // and trailing whitespace. + if (type == XMLAttDef::CData) + { + if (!escaped) + { + if ((nextCh == 0x09) || (nextCh == 0x0A) || (nextCh == 0x0D)) + { + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && isAttExternal) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName); + } + nextCh = chSpace; + } + } + } + else + { + if (curState == InWhitespace) + { + if ((escaped && nextCh != chSpace) || !fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + if (firstNonWS) + toFill.append(chSpace); + curState = InContent; + firstNonWS = true; + } + else + { + continue; + } + } + else if (curState == InContent) + { + if ((nextCh == chSpace) || + (fReaderMgr.getCurrentReader()->isWhitespace(nextCh) && !escaped)) + { + curState = InWhitespace; + + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && isAttExternal) + { + if (!firstNonWS || (nextCh != chSpace) || (fReaderMgr.lookingAtSpace())) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName); + } + } + continue; + } + firstNonWS = true; + } + } + + // Else add it to the buffer + toFill.append(nextCh); + + if (secondCh) + { + toFill.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException&) + { + // Just eat it and continue. + gotLeadingSurrogate = false; + escaped = false; + } + } + return true; +} + + +// This method scans a CDATA section. It collects the character into one +// of the temp buffers and calls the document handler, if any, with the +// characters. It assumes that the fThisElement->getCharDataOpts(); + + while (true) + { + const XMLCh nextCh = fReaderMgr.getNextChar(); + + // Watch for unexpected end of file + if (!nextCh) + { + emitError(XMLErrs::UnterminatedCDATASection); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + if (fValidate && fStandalone && (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))) + { + // This document is standalone; this ignorable CDATA whitespace is forbidden. + // XML 1.0, Section 2.9 + // And see if the current element is a 'Children' style content model + if (topElem->fThisElement->isExternal()) { + + if (charOpts == XMLElementDecl::SpacesOk) // Element Content + { + // Error - standalone should have a value of "no" as whitespace detected in an + // element type with element content whose element declaration was external + fValidator->emitError(XMLValid::NoWSForStandalone); + } + } + } + + // If this is a close square bracket it could be our closing + // sequence. + if (nextCh == chCloseSquare && fReaderMgr.skippedString(CDataClose)) + { + // make sure we were not expecting a trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + if (fValidate) { + + if (charOpts != XMLElementDecl::AllCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + } + } + + // If we have a doc handler, call it + if (fDocHandler) + { + fDocHandler->docCharacters + ( + bbCData.getRawBuffer() + , bbCData.getLen() + , true + ); + } + + // And we are done + break; + } + + // Make sure its a valid character. But if we've emitted an error + // already, don't bother with the overhead since we've already told + // them about it. + if (!emittedError) + { + // Deal with surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + emittedError = true; + } + } + gotLeadingSurrogate = false; + } + } + + // Add it to the buffer + bbCData.append(nextCh); + } +} + + +void DGXMLScanner::scanCharData(XMLBuffer& toUse) +{ + // We have to watch for the stupid ]]> sequence, which is illegal in + // character data. So this is a little state machine that handles that. + enum States + { + State_Waiting + , State_GotOne + , State_GotTwo + }; + + // Reset the buffer before we start + toUse.reset(); + + // Turn on the 'throw at end' flag of the reader manager + ThrowEOEJanitor jan(&fReaderMgr, true); + + // In order to be more efficient we have to use kind of a deeply nested + // set of blocks here. The outer block puts on a try and catches end of + // entity exceptions. The inner loop is the per-character loop. If we + // put the try inside the inner loop, it would work but would require + // the exception handling code setup/teardown code to be invoked for + // each character. + XMLCh nextCh; + XMLCh secondCh = 0; + States curState = State_Waiting; + bool escaped = false; + bool gotLeadingSurrogate = false; + bool notDone = true; + while (notDone) + { + try + { + while (true) + { + // Eat through as many plain content characters as possible without + // needing special handling. Moving most content characters here, + // in this one call, rather than running the overall loop once + // per content character, is a speed optimization. + if (curState == State_Waiting && !gotLeadingSurrogate) + { + fReaderMgr.movePlainContentChars(toUse); + } + + // Try to get another char from the source + // The code from here on down covers all contengencies, + if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh)) + { + // If we were waiting for a trailing surrogate, its an error + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + notDone = false; + break; + } + + // Watch for a reference. Note that the escapement mechanism + // is ignored in this content. + escaped = false; + if (nextCh == chAmpersand) + { + sendCharData(toUse); + + // Turn off the throwing at the end of entity during this + ThrowEOEJanitor jan(&fReaderMgr, false); + + if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + else + { + if (escaped && !fElemStack.isEmpty()) + fElemStack.setReferenceEscaped(); + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Make sure the returned char is a valid XML char + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // Keep the state machine up to date + if (!escaped) + { + if (nextCh == chCloseSquare) + { + if (curState == State_Waiting) + curState = State_GotOne; + else if (curState == State_GotOne) + curState = State_GotTwo; + } + else if (nextCh == chCloseAngle) + { + if (curState == State_GotTwo) + emitError(XMLErrs::BadSequenceInCharData); + curState = State_Waiting; + } + else + { + curState = State_Waiting; + } + } + else + { + curState = State_Waiting; + } + + // Add this char to the buffer + toUse.append(nextCh); + + if (secondCh) + { + toUse.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException& toCatch) + { + // Some entity ended, so we have to send any accumulated + // chars and send an end of entity event. + sendCharData(toUse); + gotLeadingSurrogate = false; + + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + // Check the validity constraints as per XML 1.0 Section 2.9 + if (fValidate && fStandalone) + { + // See if the text contains whitespace + // Get the raw data we need for the callback + const XMLCh* rawBuf = toUse.getRawBuffer(); + const XMLSize_t len = toUse.getLen(); + const bool isSpaces = fReaderMgr.getCurrentReader()->containsWhiteSpace(rawBuf, len); + + if (isSpaces) + { + // And see if the current element is a 'Children' style content model + const ElemStack::StackElem* topElem = fElemStack.topElement(); + + if (topElem->fThisElement->isExternal()) { + + // Get the character data opts for the current element + XMLElementDecl::CharDataOpts charOpts = topElem->fThisElement->getCharDataOpts(); + + if (charOpts == XMLElementDecl::SpacesOk) // => Element Content + { + // Error - standalone should have a value of "no" as whitespace detected in an + // element type with element content whose element declaration was external + // + fValidator->emitError(XMLValid::NoWSForStandalone); + } + } + } + } + // Send any char data that we accumulated into the buffer + sendCharData(toUse); +} + + +// This method will scan a general/character entity ref. It will either +// expand a char ref and return it directly, or push a reader for a general +// entity. +// +// The return value indicates whether the char parameters hold the value +// or whether the value was pushed as a reader, or that it failed. +// +// The escaped flag tells the caller whether the returned parameter resulted +// from a character reference, which escapes the character in some cases. It +// only makes any difference if the return value indicates the value was +// returned directly. +DGXMLScanner::EntityExpRes +DGXMLScanner::scanEntityRef( const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped) +{ + // Assume no escape + secondCh = 0; + escaped = false; + + // We have to insure that its all in one entity + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // If the next char is a pound, then its a character reference and we + // need to expand it always. + if (fReaderMgr.skippedChar(chPound)) + { + // Its a character reference, so scan it and get back the numeric + // value it represents. + if (!scanCharRef(firstCh, secondCh)) + return EntityExp_Failed; + + escaped = true; + + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + return EntityExp_Returned; + } + + // Expand it since its a normal entity ref + XMLBufBid bbName(&fBufMgr); + + int colonPosition; + bool validName = fDoNamespaces ? fReaderMgr.getQName(bbName.getBuffer(), &colonPosition) : + fReaderMgr.getName(bbName.getBuffer()); + if (!validName) + { + if (bbName.isEmpty()) + emitError(XMLErrs::ExpectedEntityRefName); + else + emitError(XMLErrs::InvalidEntityRefName, bbName.getRawBuffer()); + return EntityExp_Failed; + } + + // Next char must be a semi-colon. But if its not, just emit + // an error and try to continue. + if (!fReaderMgr.skippedChar(chSemiColon)) + emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer()); + + // Make sure we ended up on the same entity reader as the & char + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // Look up the name in the general entity pool + XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer()); + + // If it does not exist, then obviously an error + if (!decl) + { + // XML 1.0 Section 4.1 + // Well-formedness Constraint for entity not found: + // In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references, + // or a document with "standalone='yes'", for an entity reference that does not occur within the external subset + // or a parameter entity + // + // Else it's Validity Constraint + if (fStandalone || fHasNoDTD) + emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer()); + else { + if (fValidate) + fValidator->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer()); + } + + return EntityExp_Failed; + } + + // XML 1.0 Section 4.1 + // If we are a standalone document, then it has to have been declared + // in the internal subset. + if (fStandalone && !decl->getDeclaredInIntSubset()) + emitError(XMLErrs::IllegalRefInStandalone, bbName.getRawBuffer()); + + if (decl->isExternal()) + { + // If its unparsed, then its not valid here + if (decl->isUnparsed()) + { + emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer()); + return EntityExp_Failed; + } + + // If we are in an attribute value, then not valid but keep going + if (inAttVal) + emitError(XMLErrs::NoExtRefsInAttValue); + + // And now create a reader to read this entity + InputSource* srcUsed; + XMLReader* reader = fReaderMgr.createReader + ( + decl->getBaseURI() + , decl->getSystemId() + , decl->getPublicId() + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , srcUsed + , fCalculateSrcOfs + , fLowWaterMark + , fDisableDefaultEntityResolution + ); + + // Put a janitor on the source so it gets cleaned up on exit + Janitor janSrc(srcUsed); + + // If the creation failed, and its not because the source was empty, + // then emit an error and return. + if (!reader) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager); + + // Push the reader. If its a recursive expansion, then emit an error + // and return an failure. + if (!fReaderMgr.pushReader(reader, decl)) + { + emitError(XMLErrs::RecursiveEntity, decl->getName()); + return EntityExp_Failed; + } + + // here's where we need to check if there's a SecurityManager, + // how many entity references we've had + if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) { + XMLCh expLimStr[32]; + XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager); + emitError + ( + XMLErrs::EntityExpansionLimitExceeded + , expLimStr + ); + // there seems nothing better to do than reset the entity expansion counter + fEntityExpansionCount = 0; + } + + // Do a start entity reference event. + // + // For now, we supress them in att values. Later, when + // the stuff is in place to correctly allow DOM to handle them + // we'll turn this back on. + if (fDocHandler && !inAttVal) + fDocHandler->startEntityReference(*decl); + + // If it starts with the XML string, then parse a text decl + if (checkXMLDecl(true)) + scanXMLDecl(Decl_Text); + } + else + { + // If its one of the special char references, then we can return + // it as a character, and its considered escaped. + if (decl->getIsSpecialChar()) + { + firstCh = decl->getValue()[0]; + escaped = true; + return EntityExp_Returned; + } + + // Create a reader over a memory stream over the entity value + // We force it to assume UTF-16 by passing in an encoding + // string. This way it won't both trying to predecode the + // first line, looking for an XML/TextDecl. + XMLReader* valueReader = fReaderMgr.createIntEntReader + ( + decl->getName() + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , decl->getValue() + , decl->getValueLen() + , false + ); + + // Try to push the entity reader onto the reader manager stack, + // where it will become the subsequent input. If it fails, that + // means the entity is recursive, so issue an error. The reader + // will have just been discarded, but we just keep going. + if (!fReaderMgr.pushReader(valueReader, decl)) + emitError(XMLErrs::RecursiveEntity, decl->getName()); + + // here's where we need to check if there's a SecurityManager, + // how many entity references we've had + if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) { + XMLCh expLimStr[32]; + XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager); + emitError + ( + XMLErrs::EntityExpansionLimitExceeded + , expLimStr + ); + } + + // Do a start entity reference event. + // + // For now, we supress them in att values. Later, when + // the stuff is in place to correctly allow DOM to handle them + // we'll turn this back on. + if (fDocHandler && !inAttVal) + fDocHandler->startEntityReference(*decl); + + // If it starts with the XML string, then it's an error + if (checkXMLDecl(true)) { + emitError(XMLErrs::TextDeclNotLegalHere); + fReaderMgr.skipPastChar(chCloseAngle); + } + } + return EntityExp_Pushed; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/DGXMLScanner.hpp b/include/xercesc/internal/DGXMLScanner.hpp new file mode 100644 index 0000000..db0dacb --- /dev/null +++ b/include/xercesc/internal/DGXMLScanner.hpp @@ -0,0 +1,192 @@ +/* + * 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: DGXMLScanner.hpp 810580 2009-09-02 15:52:22Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DGXMLSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_DGXMLSCANNER_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DTDElementDecl; +class DTDGrammar; +class DTDValidator; + +// This is an integrated scanner class, which does DTD/XML Schema grammar +// processing. +class XMLPARSER_EXPORT DGXMLScanner : public XMLScanner +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DGXMLScanner + ( + XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DGXMLScanner + ( + XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~DGXMLScanner(); + + // ----------------------------------------------------------------------- + // XMLScanner public virtual methods + // ----------------------------------------------------------------------- + virtual const XMLCh* getName() const; + virtual NameIdPool* getEntityDeclPool(); + virtual const NameIdPool* getEntityDeclPool() const; + virtual void scanDocument + ( + const InputSource& src + ); + virtual bool scanNext(XMLPScanToken& toFill); + virtual Grammar* loadGrammar + ( + const InputSource& src + , const short grammarType + , const bool toCache = false + ); + + virtual Grammar::GrammarType getCurrentGrammarType() const; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DGXMLScanner(); + DGXMLScanner(const DGXMLScanner&); + DGXMLScanner& operator=(const DGXMLScanner&); + + // ----------------------------------------------------------------------- + // XMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual void scanCDSection(); + virtual void scanCharData(XMLBuffer& toToUse); + virtual EntityExpRes scanEntityRef + ( + const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped + ); + virtual void scanDocTypeDecl(); + virtual void scanReset(const InputSource& src); + virtual void sendCharData(XMLBuffer& toSend); + virtual InputSource* resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void commonInit(); + void cleanUp(); + + XMLSize_t buildAttList + ( + const XMLSize_t attCount + , XMLElementDecl* elemDecl + , RefVectorOf& toFill + ); + void updateNSMap + ( + const XMLCh* const attrPrefix + , const XMLCh* const attrLocalName + , const XMLCh* const attrValue + ); + void scanAttrListforNameSpaces(RefVectorOf* theAttrList, XMLSize_t attCount, XMLElementDecl* elemDecl); + + // ----------------------------------------------------------------------- + // Private scanning methods + // ----------------------------------------------------------------------- + bool scanAttValue + ( + const XMLAttDef* const attDef + , const XMLCh *const attrName + , XMLBuffer& toFill + ); + bool scanContent(); + void scanEndTag(bool& gotData); + bool scanStartTag(bool& gotData); + bool scanStartTagNS(bool& gotData); + + // ----------------------------------------------------------------------- + // Grammar preparsing methods + // ----------------------------------------------------------------------- + Grammar* loadDTDGrammar(const InputSource& src, const bool toCache = false); + + // ----------------------------------------------------------------------- + // Data members + // + // fRawAttrList + // During the initial scan of the attributes we can only do a raw + // scan for key/value pairs. So this vector is used to store them + // until they can be processed (and put into fAttrList.) + // + // fDTDValidator + // The DTD validator instance. + // + // fDTDElemNonDeclPool + // registry of "faulted-in" DTD element decls + // fElemCount + // count of the number of start tags seen so far (starts at 1). + // Used for duplicate attribute detection/processing of required/defaulted attributes + // fAttDefRegistry + // mapping from XMLAttDef instances to the count of the last + // start tag where they were utilized. + // fUndeclaredAttrRegistry + // mapping of attr QNames to detect duplicates + // + // ----------------------------------------------------------------------- + ValueVectorOf* fAttrNSList; + DTDValidator* fDTDValidator; + DTDGrammar* fDTDGrammar; + NameIdPool* fDTDElemNonDeclPool; + unsigned int fElemCount; + RefHashTableOf* fAttDefRegistry; + Hash2KeysSetOf* fUndeclaredAttrRegistry; +}; + +inline const XMLCh* DGXMLScanner::getName() const +{ + return XMLUni::fgDGXMLScanner; +} + +inline Grammar::GrammarType DGXMLScanner::getCurrentGrammarType() const +{ + return Grammar::DTDGrammarType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/ElemStack.cpp b/include/xercesc/internal/ElemStack.cpp new file mode 100644 index 0000000..1ce9a8f --- /dev/null +++ b/include/xercesc/internal/ElemStack.cpp @@ -0,0 +1,891 @@ +/* + * 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: ElemStack.cpp 830538 2009-10-28 13:41:11Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// ElemStack: Constructors and Destructor +// --------------------------------------------------------------------------- +ElemStack::ElemStack(MemoryManager* const manager) : + + fEmptyNamespaceId(0) + , fGlobalPoolId(0) + , fPrefixPool(109, manager) + , fGlobalNamespaces(0) + , fStack(0) + , fStackCapacity(32) + , fStackTop(0) + , fUnknownNamespaceId(0) + , fXMLNamespaceId(0) + , fXMLPoolId(0) + , fXMLNSNamespaceId(0) + , fXMLNSPoolId(0) + , fNamespaceMap(0) + , fMemoryManager(manager) +{ + // Do an initial allocation of the stack and zero it out + fStack = (StackElem**) fMemoryManager->allocate + ( + fStackCapacity * sizeof(StackElem*) + );//new StackElem*[fStackCapacity]; + memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); + + fNamespaceMap = new (fMemoryManager) ValueVectorOf(16, fMemoryManager); +} + +ElemStack::~ElemStack() +{ + if(fGlobalNamespaces) + { + fMemoryManager->deallocate(fGlobalNamespaces->fMap); + delete fGlobalNamespaces; + } + + // + // Start working from the bottom of the stack and clear it out as we + // go up. Once we hit an uninitialized one, we can break out. + // + for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) + { + // If this entry has been set, then lets clean it up + if (!fStack[stackInd]) + break; + + fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren; + fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap; + fMemoryManager->deallocate(fStack[stackInd]->fSchemaElemName); + delete fStack[stackInd]; + } + + // Delete the stack array itself now + fMemoryManager->deallocate(fStack);//delete [] fStack; + delete fNamespaceMap; +} + + +// --------------------------------------------------------------------------- +// ElemStack: Stack access +// --------------------------------------------------------------------------- +XMLSize_t ElemStack::addLevel() +{ + // See if we need to expand the stack + if (fStackTop == fStackCapacity) + expandStack(); + + // If this element has not been initialized yet, then initialize it + if (!fStack[fStackTop]) + { + fStack[fStackTop] = new (fMemoryManager) StackElem; + fStack[fStackTop]->fChildCapacity = 0; + fStack[fStackTop]->fChildren = 0; + fStack[fStackTop]->fMapCapacity = 0; + fStack[fStackTop]->fMap = 0; + fStack[fStackTop]->fSchemaElemName = 0; + fStack[fStackTop]->fSchemaElemNameMaxLen = 0; + } + + // Set up the new top row + fStack[fStackTop]->fThisElement = 0; + fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; + fStack[fStackTop]->fChildCount = 0; + fStack[fStackTop]->fMapCount = 0; + fStack[fStackTop]->fValidationFlag = false; + fStack[fStackTop]->fCommentOrPISeen = false; + fStack[fStackTop]->fReferenceEscaped = false; + fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; + fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; + fStack[fStackTop]->fCurrentGrammar = 0; + + // Bump the top of stack + fStackTop++; + + return fStackTop-1; +} + + +XMLSize_t ElemStack::addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum) +{ + // See if we need to expand the stack + if (fStackTop == fStackCapacity) + expandStack(); + + // If this element has not been initialized yet, then initialize it + if (!fStack[fStackTop]) + { + fStack[fStackTop] = new (fMemoryManager) StackElem; + fStack[fStackTop]->fChildCapacity = 0; + fStack[fStackTop]->fChildren = 0; + fStack[fStackTop]->fMapCapacity = 0; + fStack[fStackTop]->fMap = 0; + fStack[fStackTop]->fSchemaElemName = 0; + fStack[fStackTop]->fSchemaElemNameMaxLen = 0; + } + + // Set up the new top row + fStack[fStackTop]->fThisElement = toSet; + fStack[fStackTop]->fReaderNum = readerNum; + fStack[fStackTop]->fChildCount = 0; + fStack[fStackTop]->fMapCount = 0; + fStack[fStackTop]->fValidationFlag = false; + fStack[fStackTop]->fCommentOrPISeen = false; + fStack[fStackTop]->fReferenceEscaped = false; + fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; + fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; + fStack[fStackTop]->fCurrentGrammar = 0; + + // Bump the top of stack + fStackTop++; + + return fStackTop-1; +} + + + +const ElemStack::StackElem* ElemStack::popTop() +{ + // Watch for an underflow error + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); + + fStackTop--; + return fStack[fStackTop]; +} + + +void +ElemStack::setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum) +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + fStack[fStackTop - 1]->fThisElement = toSet; + fStack[fStackTop - 1]->fReaderNum = readerNum; +} + + +// --------------------------------------------------------------------------- +// ElemStack: Stack top access +// --------------------------------------------------------------------------- +XMLSize_t ElemStack::addChild(QName* const child, const bool toParent) +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + // + // If they want to add to the parent, then we have to have at least two + // elements on the stack. + // + if (toParent && (fStackTop < 2)) + ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed, fMemoryManager); + + // Get a convenience pointer to the stack top row + StackElem* curRow = toParent + ? fStack[fStackTop - 2] : fStack[fStackTop - 1]; + + // See if we need to expand this row's child array + if (curRow->fChildCount == curRow->fChildCapacity) + { + // Increase the capacity by a quarter and allocate a new row + const XMLSize_t newCapacity = curRow->fChildCapacity ? + (XMLSize_t)(curRow->fChildCapacity * 1.25) : + 32; + QName** newRow = (QName**) fMemoryManager->allocate + ( + newCapacity * sizeof(QName*) + );//new QName*[newCapacity]; + + // + // Copy over the old contents. We don't have to initialize the new + // part because The current child count is used to know how much of + // it is valid. + // + // Only both doing this if there is any current content, since + // this code also does the initial faulting in of the array when + // both the current capacity and child count are zero. + // + for (XMLSize_t index = 0; index < curRow->fChildCount; index++) + newRow[index] = curRow->fChildren[index]; + + // Clean up the old children and store the new info + fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren; + curRow->fChildren = newRow; + curRow->fChildCapacity = newCapacity; + } + + // Add this id to the end of the row's child id array and bump the count + curRow->fChildren[curRow->fChildCount++] = child; + + // Return the level of the index we just filled (before the bump) + return curRow->fChildCount - 1; +} + +const ElemStack::StackElem* ElemStack::topElement() const +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + return fStack[fStackTop - 1]; +} + + +// --------------------------------------------------------------------------- +// ElemStack: Prefix map methods +// --------------------------------------------------------------------------- +void ElemStack::addGlobalPrefix(const XMLCh* const prefixToAdd + , const unsigned int uriId) +{ + if (!fGlobalNamespaces) + { + fGlobalNamespaces = new (fMemoryManager) StackElem; + fGlobalNamespaces->fChildCapacity = 0; + fGlobalNamespaces->fChildren = 0; + fGlobalNamespaces->fMapCapacity = 0; + fGlobalNamespaces->fMap = 0; + fGlobalNamespaces->fMapCount = 0; + fGlobalNamespaces->fSchemaElemName = 0; + fGlobalNamespaces->fSchemaElemNameMaxLen = 0; + fGlobalNamespaces->fThisElement = 0; + fGlobalNamespaces->fReaderNum = 0xFFFFFFFF; + fGlobalNamespaces->fChildCount = 0; + fGlobalNamespaces->fValidationFlag = false; + fGlobalNamespaces->fCommentOrPISeen = false; + fGlobalNamespaces->fReferenceEscaped = false; + fGlobalNamespaces->fCurrentURI = fUnknownNamespaceId; + fGlobalNamespaces->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; + fGlobalNamespaces->fCurrentGrammar = 0; + } + + // Map the prefix to its unique id + const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); + + // + // Add a new element to the prefix map for this element. If its full, + // then expand it out. + // + if (fGlobalNamespaces->fMapCount == fGlobalNamespaces->fMapCapacity) + expandMap(fGlobalNamespaces); + + // + // And now add a new element for this prefix. Watch for the special case + // of xmlns=="", and force it to ""=[globalid] + // + fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fPrefId = prefId; + if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) + fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = fEmptyNamespaceId; + else + fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = uriId; + + // Bump the map count now + fGlobalNamespaces->fMapCount++; +} + +void ElemStack::addPrefix( const XMLCh* const prefixToAdd + , const unsigned int uriId) +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + // Get a convenience pointer to the stack top row + StackElem* curRow = fStack[fStackTop - 1]; + + // Map the prefix to its unique id + const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); + + // + // Add a new element to the prefix map for this element. If its full, + // then expand it out. + // + if (curRow->fMapCount == curRow->fMapCapacity) + expandMap(curRow); + + // + // And now add a new element for this prefix. Watch for the special case + // of xmlns=="", and force it to ""=[globalid] + // + curRow->fMap[curRow->fMapCount].fPrefId = prefId; + if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) + curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId; + else + curRow->fMap[curRow->fMapCount].fURIId = uriId; + + // Bump the map count now + curRow->fMapCount++; +} + + +unsigned int ElemStack::mapPrefixToURI( const XMLCh* const prefixToMap + , bool& unknown) const +{ + // Assume we find it + unknown = false; + + // + // Map the prefix to its unique id, from the prefix string pool. If its + // not a valid prefix, then its a failure. + // + unsigned int prefixId = (!prefixToMap || !*prefixToMap)?fGlobalPoolId : fPrefixPool.getId(prefixToMap); + if (prefixId == 0) + { + unknown = true; + return fUnknownNamespaceId; + } + // + // Check for the special prefixes 'xml' and 'xmlns' since they cannot + // be overridden. + // + else if (prefixId == fXMLPoolId) + return fXMLNamespaceId; + else if (prefixId == fXMLNSPoolId) + return fXMLNSNamespaceId; + + // + // Start at the stack top and work backwards until we come to some + // element that mapped this prefix. + // + for (XMLSize_t index = fStackTop; index > 0; index--) + { + // Get a convenience pointer to the current element + StackElem* curRow = fStack[index-1]; + + // Search the map at this level for the passed prefix + for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) + { + if (curRow->fMap[mapIndex].fPrefId == prefixId) + return curRow->fMap[mapIndex].fURIId; + } + } + // If the prefix wasn't found, try in the global namespaces + if(fGlobalNamespaces) + { + for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) + { + if (fGlobalNamespaces->fMap[mapIndex].fPrefId == prefixId) + return fGlobalNamespaces->fMap[mapIndex].fURIId; + } + } + + // + // If the prefix is an empty string, then we will return the special + // global namespace id. This can be overridden, but no one has or we + // would have not gotten here. + // + if (!*prefixToMap) + return fEmptyNamespaceId; + + // Oh well, don't have a clue so return the unknown id + unknown = true; + return fUnknownNamespaceId; +} + + +ValueVectorOf* ElemStack::getNamespaceMap() const +{ + fNamespaceMap->removeAllElements(); + + // Start at the stack top and work backwards until we come to some + // element that mapped this prefix. + for (XMLSize_t index = fStackTop; index > 0; index--) + { + // Get a convenience pointer to the current element + StackElem* curRow = fStack[index-1]; + + // If no prefixes mapped at this level, then go the next one + if (!curRow->fMapCount) + continue; + + // Search the map at this level for the passed prefix + for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) + fNamespaceMap->addElement(&(curRow->fMap[mapIndex])); + } + // Add the global namespaces + if(fGlobalNamespaces) + { + for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) + fNamespaceMap->addElement(&(fGlobalNamespaces->fMap[mapIndex])); + } + + return fNamespaceMap; +} + +// --------------------------------------------------------------------------- +// ElemStack: Miscellaneous methods +// --------------------------------------------------------------------------- +void ElemStack::reset( const unsigned int emptyId + , const unsigned int unknownId + , const unsigned int xmlId + , const unsigned int xmlNSId) +{ + if(fGlobalNamespaces) + { + fMemoryManager->deallocate(fGlobalNamespaces->fMap); + delete fGlobalNamespaces; + fGlobalNamespaces = 0; + } + + // Reset the stack top to clear the stack + fStackTop = 0; + + // if first time, put in the standard prefixes + if (fXMLPoolId == 0) { + + fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); + fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); + fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); + } + + // And store the new special URI ids + fEmptyNamespaceId = emptyId; + fUnknownNamespaceId = unknownId; + fXMLNamespaceId = xmlId; + fXMLNSNamespaceId = xmlNSId; +} + + +// --------------------------------------------------------------------------- +// ElemStack: Private helpers +// --------------------------------------------------------------------------- +void ElemStack::expandMap(StackElem* const toExpand) +{ + // For convenience get the old map size + const XMLSize_t oldCap = toExpand->fMapCapacity; + + // + // Expand the capacity by 25%, or initialize it to 16 if its currently + // empty. Then allocate a new temp buffer. + // + const XMLSize_t newCapacity = oldCap ? + (XMLSize_t )(oldCap * 1.25) : 16; + PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate + ( + newCapacity * sizeof(PrefMapElem) + );//new PrefMapElem[newCapacity]; + + // + // Copy over the old stuff. We DON'T have to zero out the new stuff + // since this is a by value map and the current map index controls what + // is relevant. + // + memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem)); + + // Delete the old map and store the new stuff + fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap; + toExpand->fMap = newMap; + toExpand->fMapCapacity = newCapacity; +} + +void ElemStack::expandStack() +{ + // Expand the capacity by 25% and allocate a new buffer + const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); + StackElem** newStack = (StackElem**) fMemoryManager->allocate + ( + newCapacity * sizeof(StackElem*) + );//new StackElem*[newCapacity]; + + // Copy over the old stuff + memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); + + // + // And zero out the new stuff. Though we use a stack top, we reuse old + // stack contents so we need to know if elements have been initially + // allocated or not as we push new stuff onto the stack. + // + memset + ( + &newStack[fStackCapacity] + , 0 + , (newCapacity - fStackCapacity) * sizeof(StackElem*) + ); + + // Delete the old array and update our members + fMemoryManager->deallocate(fStack);//delete [] fStack; + fStack = newStack; + fStackCapacity = newCapacity; +} + + + +// --------------------------------------------------------------------------- +// WFElemStack: Constructors and Destructor +// --------------------------------------------------------------------------- +WFElemStack::WFElemStack(MemoryManager* const manager) : + + fEmptyNamespaceId(0) + , fGlobalPoolId(0) + , fStackCapacity(32) + , fStackTop(0) + , fUnknownNamespaceId(0) + , fXMLNamespaceId(0) + , fXMLPoolId(0) + , fXMLNSNamespaceId(0) + , fXMLNSPoolId(0) + , fMapCapacity(0) + , fMap(0) + , fStack(0) + , fPrefixPool(109, manager) + , fMemoryManager(manager) +{ + // Do an initial allocation of the stack and zero it out + fStack = (StackElem**) fMemoryManager->allocate + ( + fStackCapacity * sizeof(StackElem*) + );//new StackElem*[fStackCapacity]; + memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); +} + +WFElemStack::~WFElemStack() +{ + // + // Start working from the bottom of the stack and clear it out as we + // go up. Once we hit an uninitialized one, we can break out. + // + for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) + { + // If this entry has been set, then lets clean it up + if (!fStack[stackInd]) + break; + + fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement; + delete fStack[stackInd]; + } + + if (fMap) + fMemoryManager->deallocate(fMap);//delete [] fMap; + + // Delete the stack array itself now + fMemoryManager->deallocate(fStack);//delete [] fStack; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Stack access +// --------------------------------------------------------------------------- +XMLSize_t WFElemStack::addLevel() +{ + // See if we need to expand the stack + if (fStackTop == fStackCapacity) + expandStack(); + + + // If this element has not been initialized yet, then initialize it + if (!fStack[fStackTop]) + { + fStack[fStackTop] = new (fMemoryManager) StackElem; + fStack[fStackTop]->fThisElement = 0; + fStack[fStackTop]->fElemMaxLength = 0; + } + + // Set up the new top row + fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; + fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; + fStack[fStackTop]->fTopPrefix = -1; + + if (fStackTop != 0) + fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; + + // Bump the top of stack + fStackTop++; + + return fStackTop-1; +} + + +XMLSize_t +WFElemStack::addLevel(const XMLCh* const toSet, + const unsigned int toSetLen, + const unsigned int readerNum) +{ + // See if we need to expand the stack + if (fStackTop == fStackCapacity) + expandStack(); + + // If this element has not been initialized yet, then initialize it + if (!fStack[fStackTop]) + { + fStack[fStackTop] = new (fMemoryManager) StackElem; + fStack[fStackTop]->fThisElement = 0; + fStack[fStackTop]->fElemMaxLength = 0; + } + + // Set up the new top row + fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; + fStack[fStackTop]->fTopPrefix = -1; + + // And store the new stuff + if (toSetLen > fStack[fStackTop]->fElemMaxLength) { + + fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement; + fStack[fStackTop]->fElemMaxLength = toSetLen; + fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate + ( + (toSetLen + 1) * sizeof(XMLCh) + );//new XMLCh[toSetLen + 1]; + } + + XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1); + fStack[fStackTop]->fReaderNum = readerNum; + + if (fStackTop != 0) + fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; + + // Bump the top of stack + fStackTop++; + + return fStackTop-1; +} + + + +const WFElemStack::StackElem* WFElemStack::popTop() +{ + // Watch for an underflow error + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); + + fStackTop--; + return fStack[fStackTop]; +} + + +void +WFElemStack::setElement(const XMLCh* const toSet, + const unsigned int toSetLen, + const unsigned int readerNum) +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) { + + fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement; + fStack[fStackTop - 1]->fElemMaxLength = toSetLen; + fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate + ( + (toSetLen + 1) * sizeof(XMLCh) + );//new XMLCh[toSetLen + 1]; + } + + XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1); + fStack[fStackTop - 1]->fReaderNum = readerNum; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Stack top access +// --------------------------------------------------------------------------- +const WFElemStack::StackElem* WFElemStack::topElement() const +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + return fStack[fStackTop - 1]; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Prefix map methods +// --------------------------------------------------------------------------- +void WFElemStack::addPrefix( const XMLCh* const prefixToAdd + , const unsigned int uriId) +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + // Get a convenience pointer to the stack top row + StackElem* curRow = fStack[fStackTop - 1]; + + // Map the prefix to its unique id + const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); + + // + // Add a new element to the prefix map for this element. If its full, + // then expand it out. + // + if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity) + expandMap(); + + // + // And now add a new element for this prefix. Watch for the special case + // of xmlns=="", and force it to ""=[globalid] + // + fMap[curRow->fTopPrefix + 1].fPrefId = prefId; + if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) + fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId; + else + fMap[curRow->fTopPrefix + 1].fURIId = uriId; + + // Bump the map count now + curRow->fTopPrefix++; +} + + +unsigned int WFElemStack::mapPrefixToURI( const XMLCh* const prefixToMap + , bool& unknown) const +{ + // Assume we find it + unknown = false; + + // + // Map the prefix to its unique id, from the prefix string pool. If its + // not a valid prefix, then its a failure. + // + unsigned int prefixId = fPrefixPool.getId(prefixToMap); + if (!prefixId) + { + unknown = true; + return fUnknownNamespaceId; + } + + // + // Check for the special prefixes 'xml' and 'xmlns' since they cannot + // be overridden. + // + if (prefixId == fXMLPoolId) + return fXMLNamespaceId; + else if (prefixId == fXMLNSPoolId) + return fXMLNSNamespaceId; + + // + // Start at the stack top and work backwards until we come to some + // element that mapped this prefix. + // + // Get a convenience pointer to the stack top row + StackElem* curRow = fStack[fStackTop - 1]; + for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--) + { + if (fMap[mapIndex].fPrefId == prefixId) + return fMap[mapIndex].fURIId; + } + + // + // If the prefix is an empty string, then we will return the special + // global namespace id. This can be overridden, but no one has or we + // would have not gotten here. + // + if (!*prefixToMap) + return fEmptyNamespaceId; + + // Oh well, don't have a clue so return the unknown id + unknown = true; + return fUnknownNamespaceId; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Miscellaneous methods +// --------------------------------------------------------------------------- +void WFElemStack::reset( const unsigned int emptyId + , const unsigned int unknownId + , const unsigned int xmlId + , const unsigned int xmlNSId) +{ + // Reset the stack top to clear the stack + fStackTop = 0; + + // if first time, put in the standard prefixes + if (fXMLPoolId == 0) { + + fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); + fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); + fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); + } + + // And store the new special URI ids + fEmptyNamespaceId = emptyId; + fUnknownNamespaceId = unknownId; + fXMLNamespaceId = xmlId; + fXMLNSNamespaceId = xmlNSId; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Private helpers +// --------------------------------------------------------------------------- +void WFElemStack::expandMap() +{ + // + // Expand the capacity by 25%, or initialize it to 16 if its currently + // empty. Then allocate a new temp buffer. + // + const XMLSize_t newCapacity = fMapCapacity ? + (XMLSize_t)(fMapCapacity * 1.25) : 16; + PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate + ( + newCapacity * sizeof(PrefMapElem) + );//new PrefMapElem[newCapacity]; + + // + // Copy over the old stuff. We DON'T have to zero out the new stuff + // since this is a by value map and the current map index controls what + // is relevant. + // + if (fMapCapacity) { + + memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem)); + fMemoryManager->deallocate(fMap);//delete [] fMap; + } + + fMap = newMap; + fMapCapacity = newCapacity; +} + +void WFElemStack::expandStack() +{ + // Expand the capacity by 25% and allocate a new buffer + const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); + StackElem** newStack = (StackElem**) fMemoryManager->allocate + ( + newCapacity * sizeof(StackElem*) + );//new StackElem*[newCapacity]; + + // Copy over the old stuff + memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); + + // + // And zero out the new stuff. Though we use a stack top, we reuse old + // stack contents so we need to know if elements have been initially + // allocated or not as we push new stuff onto the stack. + // + memset + ( + &newStack[fStackCapacity] + , 0 + , (newCapacity - fStackCapacity) * sizeof(StackElem*) + ); + + // Delete the old array and update our members + fMemoryManager->deallocate(fStack);//delete [] fStack; + fStack = newStack; + fStackCapacity = newCapacity; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/ElemStack.hpp b/include/xercesc/internal/ElemStack.hpp new file mode 100644 index 0000000..5457c72 --- /dev/null +++ b/include/xercesc/internal/ElemStack.hpp @@ -0,0 +1,592 @@ +/* + * 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: ElemStack.hpp 830538 2009-10-28 13:41:11Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ELEMSTACK_HPP) +#define XERCESC_INCLUDE_GUARD_ELEMSTACK_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLElementDecl; +class Grammar; + +struct PrefMapElem : public XMemory +{ + unsigned int fPrefId; + unsigned int fURIId; +}; + +// +// During the scan of content, we have to keep up with the nesting of +// elements (for validation and wellformedness purposes) and we have to +// have places to remember namespace (prefix to URI) mappings. +// +// We only have to keep a stack of the current path down through the tree +// that we are currently scanning, and keep track of any children of any +// elements along that path. +// +// So, this data structure is a stack, which represents the current path +// through the tree that we've worked our way down to. For each node in +// the stack, there is an array of element ids that represent the ids of +// the child elements scanned so far. Upon exit from that element, its +// array of child elements is validated. +// +// Since we have the actual XMLElementDecl in the stack nodes, when its time +// to validate, we just extract the content model from that element decl +// and validate. All the required data falls easily to hand. Note that we +// actually have some derivative of XMLElementDecl, which is specific to +// the validator used, but the abstract API is sufficient for the needs of +// the scanner. +// +// Since the namespace support also requires the storage of information on +// a nested element basis, this structure also holds the namespace info. For +// each level, the prefixes defined at that level (and the namespaces that +// they map to) are stored. +// +class XMLPARSER_EXPORT ElemStack : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Class specific data types + // + // These really should be private, but some of the compilers we have to + // support are too dumb to deal with that. + // + // PrefMapElem + // fURIId is the id of the URI from the validator's URI map. The + // fPrefId is the id of the prefix from our own prefix pool. The + // namespace stack consists of these elements. + // + // StackElem + // fThisElement is the basic element decl for the current element. + // The fRowCapacity is how large fChildIds has grown so far. + // fChildCount is how many of them are valid right now. + // + // The fMapCapacity is how large fMap has grown so far. fMapCount + // is how many of them are valid right now. + // + // Note that we store the reader number we were in when we found the + // start tag. We'll use this at the end tag to test for unbalanced + // markup in entities. + // + // MapModes + // When a prefix is mapped to a namespace id, it matters whether the + // QName being mapped is an attribute or name. Attributes are not + // affected by an sibling xmlns attributes, whereas elements are + // affected by its own xmlns attributes. + // ----------------------------------------------------------------------- + struct StackElem : public XMemory + { + XMLElementDecl* fThisElement; + XMLSize_t fReaderNum; + + XMLSize_t fChildCapacity; + XMLSize_t fChildCount; + QName** fChildren; + + PrefMapElem* fMap; + XMLSize_t fMapCapacity; + XMLSize_t fMapCount; + + bool fValidationFlag; + bool fCommentOrPISeen; + bool fReferenceEscaped; + unsigned int fCurrentScope; + Grammar* fCurrentGrammar; + unsigned int fCurrentURI; + XMLCh * fSchemaElemName; + XMLSize_t fSchemaElemNameMaxLen; + + int fPrefixColonPos; + }; + + enum MapModes + { + Mode_Attribute + , Mode_Element + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + ElemStack(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~ElemStack(); + + + // ----------------------------------------------------------------------- + // Stack access + // ----------------------------------------------------------------------- + XMLSize_t addLevel(); + XMLSize_t addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum); + const StackElem* popTop(); + + + // ----------------------------------------------------------------------- + // Stack top access + // ----------------------------------------------------------------------- + XMLSize_t addChild(QName* const child, const bool toParent); + const StackElem* topElement() const; + void setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum); + + void setValidationFlag(bool validationFlag); + bool getValidationFlag(); + + inline void setCommentOrPISeen(); + inline bool getCommentOrPISeen() const; + + inline void setReferenceEscaped(); + inline bool getReferenceEscaped() const; + + void setCurrentScope(int currentScope); + int getCurrentScope(); + + void setCurrentGrammar(Grammar* currentGrammar); + Grammar* getCurrentGrammar(); + + void setCurrentURI(unsigned int uri); + unsigned int getCurrentURI(); + + inline void setCurrentSchemaElemName(const XMLCh * const schemaElemName); + inline XMLCh *getCurrentSchemaElemName(); + + void setPrefixColonPos(int colonPos); + int getPrefixColonPos() const; + + // ----------------------------------------------------------------------- + // Prefix map methods + // ----------------------------------------------------------------------- + void addGlobalPrefix + ( + const XMLCh* const prefixToAdd + , const unsigned int uriId + ); + void addPrefix + ( + const XMLCh* const prefixToAdd + , const unsigned int uriId + ); + unsigned int mapPrefixToURI + ( + const XMLCh* const prefixToMap + , bool& unknown + ) const; + ValueVectorOf* getNamespaceMap() const; + unsigned int getPrefixId(const XMLCh* const prefix) const; + const XMLCh* getPrefixForId(unsigned int prefId) const; + + // ----------------------------------------------------------------------- + // Miscellaneous methods + // ----------------------------------------------------------------------- + bool isEmpty() const; + void reset + ( + const unsigned int emptyId + , const unsigned int unknownId + , const unsigned int xmlId + , const unsigned int xmlNSId + ); + + unsigned int getEmptyNamespaceId(); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ElemStack(const ElemStack&); + ElemStack& operator=(const ElemStack&); + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void expandMap(StackElem* const toExpand); + void expandStack(); + + + // ----------------------------------------------------------------------- + // Data members + // + // fEmptyNamespaceId + // This is the special URI id for the "" namespace, which is magic + // because of the xmlns="" operation. + // + // fGlobalPoolId + // This is a special URI id that is returned when the namespace + // prefix is "" and no one has explicitly mapped that prefix to an + // explicit URI (or when they explicitly clear any such mapping, + // which they can also do.) And also its prefix pool id, which is + // stored here for fast access. + // + // fPrefixPool + // This is the prefix pool where prefixes are hashed and given unique + // ids. These ids are used to track prefixes in the element stack. + // + // fGlobalNamespaces + // This object contains the namespace bindings that are globally valid + // + // fStack + // fStackCapacity + // fStackTop + // This the stack array. Its an array of pointers to StackElem + // structures. The capacity is the current high water mark of the + // stack. The top is the current top of stack (i.e. the part of it + // being used.) + // + // fUnknownNamespaceId + // This is the URI id for the special URI that is assigned to any + // prefix which has not been mapped. This lets us keep going after + // issuing the error. + // + // fXMLNamespaceId + // fXMLPoolId + // fXMLNSNamespaceId + // fXMLNSPoolId + // These are the URI ids for the special URIs that are assigned to + // the 'xml' and 'xmlns' namespaces. And also its prefix pool id, + // which is stored here for fast access. + // ----------------------------------------------------------------------- + unsigned int fEmptyNamespaceId; + unsigned int fGlobalPoolId; + XMLStringPool fPrefixPool; + StackElem* fGlobalNamespaces; + StackElem** fStack; + XMLSize_t fStackCapacity; + XMLSize_t fStackTop; + unsigned int fUnknownNamespaceId; + unsigned int fXMLNamespaceId; + unsigned int fXMLPoolId; + unsigned int fXMLNSNamespaceId; + unsigned int fXMLNSPoolId; + ValueVectorOf* fNamespaceMap; + MemoryManager* fMemoryManager; +}; + + +class XMLPARSER_EXPORT WFElemStack : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Class specific data types + // + // These really should be private, but some of the compilers we have to + // support are too dumb to deal with that. + // + // PrefMapElem + // fURIId is the id of the URI from the validator's URI map. The + // fPrefId is the id of the prefix from our own prefix pool. The + // namespace stack consists of these elements. + // + // StackElem + // fThisElement is the basic element decl for the current element. + // The fRowCapacity is how large fChildIds has grown so far. + // fChildCount is how many of them are valid right now. + // + // The fMapCapacity is how large fMap has grown so far. fMapCount + // is how many of them are valid right now. + // + // Note that we store the reader number we were in when we found the + // start tag. We'll use this at the end tag to test for unbalanced + // markup in entities. + // + // MapModes + // When a prefix is mapped to a namespace id, it matters whether the + // QName being mapped is an attribute or name. Attributes are not + // affected by an sibling xmlns attributes, whereas elements are + // affected by its own xmlns attributes. + // ----------------------------------------------------------------------- + struct StackElem : public XMemory + { + int fTopPrefix; + unsigned int fCurrentURI; + unsigned int fReaderNum; + unsigned int fElemMaxLength; + XMLCh* fThisElement; + }; + + enum MapModes + { + Mode_Attribute + , Mode_Element + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + WFElemStack(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~WFElemStack(); + + + // ----------------------------------------------------------------------- + // Stack access + // ----------------------------------------------------------------------- + XMLSize_t addLevel(); + XMLSize_t addLevel(const XMLCh* const toSet, const unsigned int toSetLen, + const unsigned int readerNum); + const StackElem* popTop(); + + + // ----------------------------------------------------------------------- + // Stack top access + // ----------------------------------------------------------------------- + const StackElem* topElement() const; + void setElement(const XMLCh* const toSet, const unsigned int toSetLen, + const unsigned int readerNum); + + void setCurrentURI(unsigned int uri); + unsigned int getCurrentURI(); + + // ----------------------------------------------------------------------- + // Prefix map methods + // ----------------------------------------------------------------------- + void addPrefix + ( + const XMLCh* const prefixToAdd + , const unsigned int uriId + ); + unsigned int mapPrefixToURI + ( + const XMLCh* const prefixToMap + , bool& unknown + ) const; + + + // ----------------------------------------------------------------------- + // Miscellaneous methods + // ----------------------------------------------------------------------- + bool isEmpty() const; + void reset + ( + const unsigned int emptyId + , const unsigned int unknownId + , const unsigned int xmlId + , const unsigned int xmlNSId + ); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + WFElemStack(const WFElemStack&); + WFElemStack& operator=(const WFElemStack&); + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void expandMap(); + void expandStack(); + + + // ----------------------------------------------------------------------- + // Data members + // + // fEmptyNamespaceId + // This is the special URI id for the "" namespace, which is magic + // because of the xmlns="" operation. + // + // fGlobalPoolId + // This is a special URI id that is returned when the namespace + // prefix is "" and no one has explicitly mapped that prefix to an + // explicit URI (or when they explicitly clear any such mapping, + // which they can also do.) And also its prefix pool id, which is + // stored here for fast access. + // + // fPrefixPool + // This is the prefix pool where prefixes are hashed and given unique + // ids. These ids are used to track prefixes in the element stack. + // + // fStack + // fStackCapacity + // fStackTop + // This the stack array. Its an array of pointers to StackElem + // structures. The capacity is the current high water mark of the + // stack. The top is the current top of stack (i.e. the part of it + // being used.) + // + // fUnknownNamespaceId + // This is the URI id for the special URI that is assigned to any + // prefix which has not been mapped. This lets us keep going after + // issuing the error. + // + // fXMLNamespaceId + // fXMLPoolId + // fXMLNSNamespaceId + // fXMLNSPoolId + // These are the URI ids for the special URIs that are assigned to + // the 'xml' and 'xmlns' namespaces. And also its prefix pool id, + // which is stored here for fast access. + // ----------------------------------------------------------------------- + unsigned int fEmptyNamespaceId; + unsigned int fGlobalPoolId; + XMLSize_t fStackCapacity; + XMLSize_t fStackTop; + unsigned int fUnknownNamespaceId; + unsigned int fXMLNamespaceId; + unsigned int fXMLPoolId; + unsigned int fXMLNSNamespaceId; + unsigned int fXMLNSPoolId; + XMLSize_t fMapCapacity; + PrefMapElem* fMap; + StackElem** fStack; + XMLStringPool fPrefixPool; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// ElemStack: Miscellaneous methods +// --------------------------------------------------------------------------- +inline bool ElemStack::isEmpty() const +{ + return (fStackTop == 0); +} + +inline bool ElemStack::getValidationFlag() +{ + return fStack[fStackTop-1]->fValidationFlag; +} + +inline void ElemStack::setValidationFlag(bool validationFlag) +{ + fStack[fStackTop-1]->fValidationFlag = validationFlag; +} + +inline bool ElemStack::getCommentOrPISeen() const +{ + return fStack[fStackTop-1]->fCommentOrPISeen; +} + +inline void ElemStack::setCommentOrPISeen() +{ + fStack[fStackTop-1]->fCommentOrPISeen = true; +} + +inline bool ElemStack::getReferenceEscaped() const +{ + return fStack[fStackTop-1]->fReferenceEscaped; +} + +inline void ElemStack::setReferenceEscaped() +{ + fStack[fStackTop-1]->fReferenceEscaped = true; +} + +inline void ElemStack::setCurrentSchemaElemName(const XMLCh * const schemaElemName) +{ + XMLSize_t schemaElemNameLen = XMLString::stringLen(schemaElemName); + XMLSize_t stackPos = fStackTop-1; + + if(fStack[stackPos]->fSchemaElemNameMaxLen <= schemaElemNameLen) + { + XMLCh *tempStr = fStack[stackPos]->fSchemaElemName; + fStack[stackPos]->fSchemaElemNameMaxLen = schemaElemNameLen << 1; + fStack[stackPos]->fSchemaElemName = (XMLCh *)fMemoryManager->allocate((fStack[stackPos]->fSchemaElemNameMaxLen)*sizeof(XMLCh)); + fMemoryManager->deallocate(tempStr); + } + XMLString::copyString(fStack[stackPos]->fSchemaElemName, schemaElemName); +} + +inline XMLCh *ElemStack::getCurrentSchemaElemName() +{ + return fStack[fStackTop-1]->fSchemaElemName; +} + +inline int ElemStack::getCurrentScope() +{ + return fStack[fStackTop-1]->fCurrentScope; +} + +inline void ElemStack::setCurrentScope(int currentScope) +{ + fStack[fStackTop-1]->fCurrentScope = currentScope; +} + +inline Grammar* ElemStack::getCurrentGrammar() +{ + return fStack[fStackTop-1]->fCurrentGrammar; +} + +inline void ElemStack::setCurrentGrammar(Grammar* currentGrammar) +{ + fStack[fStackTop-1]->fCurrentGrammar = currentGrammar; +} + +inline unsigned int ElemStack::getCurrentURI() +{ + return fStack[fStackTop-1]->fCurrentURI; +} + +inline void ElemStack::setCurrentURI(unsigned int uri) +{ + fStack[fStackTop-1]->fCurrentURI = uri; +} + +inline unsigned int ElemStack::getPrefixId(const XMLCh* const prefix) const +{ + return fPrefixPool.getId(prefix); +} + +inline const XMLCh* ElemStack::getPrefixForId(unsigned int prefId) const +{ + return fPrefixPool.getValueForId(prefId); +} + +inline void ElemStack::setPrefixColonPos(int colonPos) +{ + fStack[fStackTop-1]->fPrefixColonPos = colonPos; +} + +inline int ElemStack::getPrefixColonPos() const { + return fStack[fStackTop-1]->fPrefixColonPos; +} + +inline unsigned int ElemStack::getEmptyNamespaceId() { + return fEmptyNamespaceId; +} + +// --------------------------------------------------------------------------- +// WFElemStack: Miscellaneous methods +// --------------------------------------------------------------------------- +inline bool WFElemStack::isEmpty() const +{ + return (fStackTop == 0); +} + +inline unsigned int WFElemStack::getCurrentURI() +{ + return fStack[fStackTop-1]->fCurrentURI; +} + +inline void WFElemStack::setCurrentURI(unsigned int uri) +{ + fStack[fStackTop-1]->fCurrentURI = uri; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/EndOfEntityException.hpp b/include/xercesc/internal/EndOfEntityException.hpp new file mode 100644 index 0000000..7e46ac2 --- /dev/null +++ b/include/xercesc/internal/EndOfEntityException.hpp @@ -0,0 +1,116 @@ +/* + * 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: EndOfEntityException.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ENDOFENTITYEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_ENDOFENTITYEXCEPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLEntityDecl; + +// +// This class is only used internally. Its thrown by the ReaderMgr class, +// when an entity ends, and is caught in the scanner. This tells the scanner +// that an entity has ended, and allows it to do the right thing according +// to what was going on when the entity ended. +// +// Since its internal, it does not bother implementing XMLException. +// +class XMLPARSER_EXPORT EndOfEntityException +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + EndOfEntityException( XMLEntityDecl* entityThatEnded + , const XMLSize_t readerNum) : + + fEntity(entityThatEnded) + , fReaderNum(readerNum) + { + } + + EndOfEntityException(const EndOfEntityException& toCopy) : + + fEntity(toCopy.fEntity) + , fReaderNum(toCopy.fReaderNum) + { + } + + ~EndOfEntityException() + { + } + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLEntityDecl& getEntity(); + const XMLEntityDecl& getEntity() const; + XMLSize_t getReaderNum() const; + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + EndOfEntityException& operator = (const EndOfEntityException&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fEntity + // This is a reference to the entity that ended, causing this + // exception. + // + // fReaderNum + // The unique reader number of the reader that was handling this + // entity. This is used to know whether a particular entity has + // ended. + // ----------------------------------------------------------------------- + XMLEntityDecl* fEntity; + XMLSize_t fReaderNum; +}; + + +// --------------------------------------------------------------------------- +// EndOfEntityException: Getter methods +// --------------------------------------------------------------------------- +inline XMLEntityDecl& EndOfEntityException::getEntity() +{ + return *fEntity; +} + +inline const XMLEntityDecl& EndOfEntityException::getEntity() const +{ + return *fEntity; +} + +inline XMLSize_t EndOfEntityException::getReaderNum() const +{ + return fReaderNum; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/IANAEncodings.hpp b/include/xercesc/internal/IANAEncodings.hpp new file mode 100644 index 0000000..40e089a --- /dev/null +++ b/include/xercesc/internal/IANAEncodings.hpp @@ -0,0 +1,834 @@ +/* + * 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: IANAEncodings.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IANAENCODINGS_HPP) +#define XERCESC_INCLUDE_GUARD_IANAENCODINGS_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// ---------------------------------------------------------------- +// This file was generated from the IANA charset source. +// so do not edit this file directly!! +// ---------------------------------------------------------------- + +const XMLCh gEncodingArray[][46] = +{ + { 0x0041,0x004E,0x0053,0x0049,0x005F,0x0058,0x0033,0x002E,0x0034,0x002D,0x0031,0x0039,0x0036,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0036,0x00 } + , { 0x0041,0x004E,0x0053,0x0049,0x005F,0x0058,0x0033,0x002E,0x0034,0x002D,0x0031,0x0039,0x0038,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0036,0x0034,0x0036,0x002E,0x0069,0x0072,0x0076,0x003A,0x0031,0x0039,0x0039,0x0031,0x00 } + , { 0x0041,0x0053,0x0043,0x0049,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0055,0x0053,0x00 } + , { 0x0055,0x0053,0x002D,0x0041,0x0053,0x0043,0x0049,0x0049,0x00 } + , { 0x0075,0x0073,0x00 } + , { 0x0049,0x0042,0x004D,0x0033,0x0036,0x0037,0x00 } + , { 0x0063,0x0070,0x0033,0x0036,0x0037,0x00 } + , { 0x0063,0x0073,0x0041,0x0053,0x0043,0x0049,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x002D,0x0055,0x0054,0x0046,0x002D,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0030,0x0036,0x0034,0x0036,0x0055,0x0054,0x0046,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0036,0x0034,0x0036,0x002E,0x0062,0x0061,0x0073,0x0069,0x0063,0x003A,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0072,0x0065,0x0066,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x0062,0x0061,0x0073,0x0069,0x0063,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0049,0x004E,0x0056,0x0041,0x0052,0x0049,0x0041,0x004E,0x0054,0x00 } + , { 0x0063,0x0073,0x0049,0x004E,0x0056,0x0041,0x0052,0x0049,0x0041,0x004E,0x0054,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0036,0x0034,0x0036,0x002E,0x0069,0x0072,0x0076,0x003A,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0032,0x00 } + , { 0x0069,0x0072,0x0076,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0049,0x006E,0x0074,0x006C,0x0052,0x0065,0x0066,0x0056,0x0065,0x0072,0x0073,0x0069,0x006F,0x006E,0x00 } + , { 0x0042,0x0053,0x005F,0x0034,0x0037,0x0033,0x0030,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0047,0x0042,0x00 } + , { 0x0067,0x0062,0x00 } + , { 0x0075,0x006B,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0034,0x0055,0x006E,0x0069,0x0074,0x0065,0x0064,0x004B,0x0069,0x006E,0x0067,0x0064,0x006F,0x006D,0x00 } + , { 0x004E,0x0041,0x0054,0x0053,0x002D,0x0053,0x0045,0x0046,0x0049,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x002D,0x0031,0x00 } + , { 0x0063,0x0073,0x004E,0x0041,0x0054,0x0053,0x0053,0x0045,0x0046,0x0049,0x00 } + , { 0x004E,0x0041,0x0054,0x0053,0x002D,0x0053,0x0045,0x0046,0x0049,0x002D,0x0041,0x0044,0x0044,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x002D,0x0032,0x00 } + , { 0x0063,0x0073,0x004E,0x0041,0x0054,0x0053,0x0053,0x0045,0x0046,0x0049,0x0041,0x0044,0x0044,0x00 } + , { 0x004E,0x0041,0x0054,0x0053,0x002D,0x0044,0x0041,0x004E,0x004F,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x002D,0x0031,0x00 } + , { 0x0063,0x0073,0x004E,0x0041,0x0054,0x0053,0x0044,0x0041,0x004E,0x004F,0x00 } + , { 0x004E,0x0041,0x0054,0x0053,0x002D,0x0044,0x0041,0x004E,0x004F,0x002D,0x0041,0x0044,0x0044,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x002D,0x0032,0x00 } + , { 0x0063,0x0073,0x004E,0x0041,0x0054,0x0053,0x0044,0x0041,0x004E,0x004F,0x0041,0x0044,0x0044,0x00 } + , { 0x0053,0x0045,0x004E,0x005F,0x0038,0x0035,0x0030,0x0032,0x0030,0x0030,0x005F,0x0042,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0030,0x00 } + , { 0x0046,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0046,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0053,0x0045,0x00 } + , { 0x0073,0x0065,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0030,0x0053,0x0077,0x0065,0x0064,0x0069,0x0073,0x0068,0x00 } + , { 0x0053,0x0045,0x004E,0x005F,0x0038,0x0035,0x0030,0x0032,0x0030,0x0030,0x005F,0x0043,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0053,0x0045,0x0032,0x00 } + , { 0x0073,0x0065,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0031,0x0053,0x0077,0x0065,0x0064,0x0069,0x0073,0x0068,0x0046,0x006F,0x0072,0x004E,0x0061,0x006D,0x0065,0x0073,0x00 } + , { 0x004B,0x0053,0x005F,0x0043,0x005F,0x0035,0x0036,0x0030,0x0031,0x002D,0x0031,0x0039,0x0038,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0039,0x00 } + , { 0x004B,0x0053,0x005F,0x0043,0x005F,0x0035,0x0036,0x0030,0x0031,0x002D,0x0031,0x0039,0x0038,0x0039,0x00 } + , { 0x004B,0x0053,0x0043,0x005F,0x0035,0x0036,0x0030,0x0031,0x00 } + , { 0x006B,0x006F,0x0072,0x0065,0x0061,0x006E,0x00 } + , { 0x0063,0x0073,0x004B,0x0053,0x0043,0x0035,0x0036,0x0030,0x0031,0x0031,0x0039,0x0038,0x0037,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0032,0x0030,0x0032,0x0032,0x002D,0x004B,0x0052,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0030,0x0032,0x0032,0x004B,0x0052,0x00 } + , { 0x0045,0x0055,0x0043,0x002D,0x004B,0x0052,0x00 } + , { 0x0063,0x0073,0x0045,0x0055,0x0043,0x004B,0x0052,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0032,0x0030,0x0032,0x0032,0x002D,0x004A,0x0050,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0030,0x0032,0x0032,0x004A,0x0050,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0032,0x0030,0x0032,0x0032,0x002D,0x004A,0x0050,0x002D,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0030,0x0032,0x0032,0x004A,0x0050,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0032,0x0030,0x0032,0x0032,0x002D,0x0043,0x004E,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0032,0x0030,0x0032,0x0032,0x002D,0x0043,0x004E,0x002D,0x0045,0x0058,0x0054,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0030,0x002D,0x0031,0x0039,0x0036,0x0039,0x002D,0x006A,0x0070,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0030,0x002D,0x0031,0x0039,0x0036,0x0039,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0033,0x00 } + , { 0x006B,0x0061,0x0074,0x0061,0x006B,0x0061,0x006E,0x0061,0x00 } + , { 0x0078,0x0030,0x0032,0x0030,0x0031,0x002D,0x0037,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0033,0x004A,0x0049,0x0053,0x0043,0x0036,0x0032,0x0032,0x0030,0x006A,0x0070,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0030,0x002D,0x0031,0x0039,0x0036,0x0039,0x002D,0x0072,0x006F,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x00 } + , { 0x006A,0x0070,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x004A,0x0050,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0034,0x004A,0x0049,0x0053,0x0043,0x0036,0x0032,0x0032,0x0030,0x0072,0x006F,0x00 } + , { 0x0049,0x0054,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0049,0x0054,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0049,0x0074,0x0061,0x006C,0x0069,0x0061,0x006E,0x00 } + , { 0x0050,0x0054,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0050,0x0054,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0036,0x0050,0x006F,0x0072,0x0074,0x0075,0x0067,0x0075,0x0065,0x0073,0x0065,0x00 } + , { 0x0045,0x0053,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0037,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0045,0x0053,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0037,0x0053,0x0070,0x0061,0x006E,0x0069,0x0073,0x0068,0x00 } + , { 0x0067,0x0072,0x0065,0x0065,0x006B,0x0037,0x002D,0x006F,0x006C,0x0064,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0038,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0038,0x0047,0x0072,0x0065,0x0065,0x006B,0x0037,0x004F,0x006C,0x0064,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x002D,0x0067,0x0072,0x0065,0x0065,0x006B,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0039,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0039,0x004C,0x0061,0x0074,0x0069,0x006E,0x0047,0x0072,0x0065,0x0065,0x006B,0x00 } + , { 0x0044,0x0049,0x004E,0x005F,0x0036,0x0036,0x0030,0x0030,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0032,0x0031,0x00 } + , { 0x0064,0x0065,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0044,0x0045,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0031,0x0047,0x0065,0x0072,0x006D,0x0061,0x006E,0x00 } + , { 0x004E,0x0046,0x005F,0x005A,0x005F,0x0036,0x0032,0x002D,0x0030,0x0031,0x0030,0x005F,0x0028,0x0031,0x0039,0x0037,0x0033,0x0029,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0032,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0046,0x0052,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0035,0x0046,0x0072,0x0065,0x006E,0x0063,0x0068,0x00 } + , { 0x004C,0x0061,0x0074,0x0069,0x006E,0x002D,0x0067,0x0072,0x0065,0x0065,0x006B,0x002D,0x0031,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0032,0x0037,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0037,0x004C,0x0061,0x0074,0x0069,0x006E,0x0047,0x0072,0x0065,0x0065,0x006B,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0035,0x0034,0x0032,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0033,0x0037,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0035,0x0034,0x0032,0x0037,0x0043,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0036,0x002D,0x0031,0x0039,0x0037,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0034,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0034,0x0032,0x004A,0x0049,0x0053,0x0043,0x0036,0x0032,0x0032,0x0036,0x0031,0x0039,0x0037,0x0038,0x00 } + , { 0x0042,0x0053,0x005F,0x0076,0x0069,0x0065,0x0077,0x0064,0x0061,0x0074,0x0061,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0034,0x0037,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0034,0x0037,0x0042,0x0053,0x0056,0x0069,0x0065,0x0077,0x0064,0x0061,0x0074,0x0061,0x00 } + , { 0x0049,0x004E,0x0049,0x0053,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0034,0x0039,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0034,0x0039,0x0049,0x004E,0x0049,0x0053,0x00 } + , { 0x0049,0x004E,0x0049,0x0053,0x002D,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0035,0x0030,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0035,0x0030,0x0049,0x004E,0x0049,0x0053,0x0038,0x00 } + , { 0x0049,0x004E,0x0049,0x0053,0x002D,0x0063,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0035,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0035,0x0031,0x0049,0x004E,0x0049,0x0053,0x0043,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0035,0x0034,0x0032,0x0037,0x003A,0x0031,0x0039,0x0038,0x0031,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0035,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x0035,0x0034,0x0032,0x0037,0x0043,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x0031,0x0039,0x0038,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0035,0x0034,0x0032,0x0038,0x003A,0x0031,0x0039,0x0038,0x0030,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0035,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0035,0x0034,0x0032,0x0038,0x0047,0x0072,0x0065,0x0065,0x006B,0x00 } + , { 0x0047,0x0042,0x005F,0x0031,0x0039,0x0038,0x0038,0x002D,0x0038,0x0030,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0035,0x0037,0x00 } + , { 0x0063,0x006E,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0043,0x004E,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0035,0x0037,0x0047,0x0042,0x0031,0x0039,0x0038,0x0038,0x00 } + , { 0x0047,0x0042,0x005F,0x0032,0x0033,0x0031,0x0032,0x002D,0x0038,0x0030,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0035,0x0038,0x00 } + , { 0x0063,0x0068,0x0069,0x006E,0x0065,0x0073,0x0065,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0035,0x0038,0x0047,0x0042,0x0032,0x0033,0x0031,0x0032,0x0038,0x0030,0x00 } + , { 0x004E,0x0053,0x005F,0x0034,0x0035,0x0035,0x0031,0x002D,0x0031,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0036,0x0030,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x004E,0x004F,0x00 } + , { 0x006E,0x006F,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0030,0x0044,0x0061,0x006E,0x0069,0x0073,0x0068,0x004E,0x006F,0x0072,0x0077,0x0065,0x0067,0x0069,0x0061,0x006E,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0030,0x004E,0x006F,0x0072,0x0077,0x0065,0x0067,0x0069,0x0061,0x006E,0x0031,0x00 } + , { 0x004E,0x0053,0x005F,0x0034,0x0035,0x0035,0x0031,0x002D,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x004E,0x004F,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0036,0x0031,0x00 } + , { 0x006E,0x006F,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0031,0x004E,0x006F,0x0072,0x0077,0x0065,0x0067,0x0069,0x0061,0x006E,0x0032,0x00 } + , { 0x004E,0x0046,0x005F,0x005A,0x005F,0x0036,0x0032,0x002D,0x0030,0x0031,0x0030,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0036,0x0039,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0046,0x0052,0x00 } + , { 0x0066,0x0072,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0039,0x0046,0x0072,0x0065,0x006E,0x0063,0x0068,0x00 } + , { 0x0076,0x0069,0x0064,0x0065,0x006F,0x0074,0x0065,0x0078,0x002D,0x0073,0x0075,0x0070,0x0070,0x006C,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0037,0x0030,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0037,0x0030,0x0056,0x0069,0x0064,0x0065,0x006F,0x0074,0x0065,0x0078,0x0053,0x0075,0x0070,0x0070,0x0031,0x00 } + , { 0x0050,0x0054,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0050,0x0054,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0034,0x0050,0x006F,0x0072,0x0074,0x0075,0x0067,0x0075,0x0065,0x0073,0x0065,0x0032,0x00 } + , { 0x0045,0x0053,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0045,0x0053,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0035,0x0053,0x0070,0x0061,0x006E,0x0069,0x0073,0x0068,0x0032,0x00 } + , { 0x004D,0x0053,0x005A,0x005F,0x0037,0x0037,0x0039,0x0035,0x002E,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0048,0x0055,0x00 } + , { 0x0068,0x0075,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0036,0x0048,0x0075,0x006E,0x0067,0x0061,0x0072,0x0069,0x0061,0x006E,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0036,0x002D,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x0037,0x00 } + , { 0x0078,0x0030,0x0032,0x0030,0x0038,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0058,0x0030,0x0032,0x0030,0x0038,0x002D,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0037,0x004A,0x0049,0x0053,0x0058,0x0030,0x0032,0x0030,0x0038,0x00 } + , { 0x0067,0x0072,0x0065,0x0065,0x006B,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x0038,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0038,0x0047,0x0072,0x0065,0x0065,0x006B,0x0037,0x00 } + , { 0x0041,0x0053,0x004D,0x004F,0x005F,0x0034,0x0034,0x0039,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0039,0x0030,0x0033,0x0036,0x00 } + , { 0x0061,0x0072,0x0061,0x0062,0x0069,0x0063,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0038,0x0039,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0039,0x0041,0x0053,0x004D,0x004F,0x0034,0x0034,0x0039,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0030,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0030,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0039,0x002D,0x0031,0x0039,0x0038,0x0034,0x002D,0x0061,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0031,0x00 } + , { 0x006A,0x0070,0x002D,0x006F,0x0063,0x0072,0x002D,0x0061,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0031,0x004A,0x0049,0x0053,0x0043,0x0036,0x0032,0x0032,0x0039,0x0031,0x0039,0x0038,0x0034,0x0061,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0039,0x002D,0x0031,0x0039,0x0038,0x0034,0x002D,0x0062,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x004A,0x0050,0x002D,0x004F,0x0043,0x0052,0x002D,0x0042,0x00 } + , { 0x006A,0x0070,0x002D,0x006F,0x0063,0x0072,0x002D,0x0062,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0032,0x004A,0x0049,0x0053,0x0043,0x0036,0x0032,0x0039,0x0039,0x0031,0x0039,0x0038,0x0034,0x0062,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0039,0x002D,0x0031,0x0039,0x0038,0x0034,0x002D,0x0062,0x002D,0x0061,0x0064,0x0064,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0033,0x00 } + , { 0x006A,0x0070,0x002D,0x006F,0x0063,0x0072,0x002D,0x0062,0x002D,0x0061,0x0064,0x0064,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0033,0x004A,0x0049,0x0053,0x0036,0x0032,0x0032,0x0039,0x0031,0x0039,0x0038,0x0034,0x0062,0x0061,0x0064,0x0064,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0039,0x002D,0x0031,0x0039,0x0038,0x0034,0x002D,0x0068,0x0061,0x006E,0x0064,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0034,0x00 } + , { 0x006A,0x0070,0x002D,0x006F,0x0063,0x0072,0x002D,0x0068,0x0061,0x006E,0x0064,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0034,0x004A,0x0049,0x0053,0x0036,0x0032,0x0032,0x0039,0x0031,0x0039,0x0038,0x0034,0x0068,0x0061,0x006E,0x0064,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0039,0x002D,0x0031,0x0039,0x0038,0x0034,0x002D,0x0068,0x0061,0x006E,0x0064,0x002D,0x0061,0x0064,0x0064,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0035,0x00 } + , { 0x006A,0x0070,0x002D,0x006F,0x0063,0x0072,0x002D,0x0068,0x0061,0x006E,0x0064,0x002D,0x0061,0x0064,0x0064,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0035,0x004A,0x0049,0x0053,0x0036,0x0032,0x0032,0x0039,0x0031,0x0039,0x0038,0x0034,0x0068,0x0061,0x006E,0x0064,0x0061,0x0064,0x0064,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0043,0x0036,0x0032,0x0032,0x0039,0x002D,0x0031,0x0039,0x0038,0x0034,0x002D,0x006B,0x0061,0x006E,0x0061,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0036,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0036,0x004A,0x0049,0x0053,0x0043,0x0036,0x0032,0x0032,0x0039,0x0031,0x0039,0x0038,0x0034,0x006B,0x0061,0x006E,0x0061,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0032,0x0030,0x0033,0x0033,0x002D,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0038,0x00 } + , { 0x0065,0x0031,0x0033,0x0062,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0032,0x0030,0x0033,0x0033,0x00 } + , { 0x0041,0x004E,0x0053,0x0049,0x005F,0x0058,0x0033,0x002E,0x0031,0x0031,0x0030,0x002D,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0039,0x0039,0x00 } + , { 0x0043,0x0053,0x0041,0x005F,0x0054,0x0035,0x0030,0x0030,0x002D,0x0031,0x0039,0x0038,0x0033,0x00 } + , { 0x004E,0x0041,0x0050,0x004C,0x0050,0x0053,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0039,0x0039,0x004E,0x0041,0x0050,0x004C,0x0050,0x0053,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x003A,0x0031,0x0039,0x0038,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0030,0x0030,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0031,0x00 } + , { 0x006C,0x0031,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0031,0x0039,0x00 } + , { 0x0043,0x0050,0x0038,0x0031,0x0039,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0032,0x003A,0x0031,0x0039,0x0038,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0030,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0032,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0032,0x00 } + , { 0x006C,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0032,0x00 } + , { 0x0054,0x002E,0x0036,0x0031,0x002D,0x0037,0x0062,0x0069,0x0074,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0030,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0030,0x0032,0x0054,0x0036,0x0031,0x0037,0x0062,0x0069,0x0074,0x00 } + , { 0x0054,0x002E,0x0036,0x0031,0x002D,0x0038,0x0062,0x0069,0x0074,0x00 } + , { 0x0054,0x002E,0x0036,0x0031,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0030,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0030,0x0033,0x0054,0x0036,0x0031,0x0038,0x0062,0x0069,0x0074,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0033,0x003A,0x0031,0x0039,0x0038,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0030,0x0039,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0033,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0033,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0033,0x00 } + , { 0x006C,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0033,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0034,0x003A,0x0031,0x0039,0x0038,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0031,0x0030,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0034,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0034,0x00 } + , { 0x006C,0x0034,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0034,0x00 } + , { 0x0045,0x0043,0x004D,0x0041,0x002D,0x0063,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0031,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0031,0x0031,0x0045,0x0043,0x004D,0x0041,0x0043,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x0043,0x0053,0x0041,0x005F,0x005A,0x0032,0x0034,0x0033,0x002E,0x0034,0x002D,0x0031,0x0039,0x0038,0x0035,0x002D,0x0031,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0032,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0043,0x0041,0x00 } + , { 0x0063,0x0073,0x0061,0x0037,0x002D,0x0031,0x00 } + , { 0x0063,0x0061,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0032,0x0031,0x0043,0x0061,0x006E,0x0061,0x0064,0x0069,0x0061,0x006E,0x0031,0x00 } + , { 0x0043,0x0053,0x0041,0x005F,0x005A,0x0032,0x0034,0x0033,0x002E,0x0034,0x002D,0x0031,0x0039,0x0038,0x0035,0x002D,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0032,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0043,0x0041,0x0032,0x00 } + , { 0x0063,0x0073,0x0061,0x0037,0x002D,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0032,0x0032,0x0043,0x0061,0x006E,0x0061,0x0064,0x0069,0x0061,0x006E,0x0032,0x00 } + , { 0x0043,0x0053,0x0041,0x005F,0x005A,0x0032,0x0034,0x0033,0x002E,0x0034,0x002D,0x0031,0x0039,0x0038,0x0035,0x002D,0x0067,0x0072,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0032,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0032,0x0033,0x0043,0x0053,0x0041,0x005A,0x0032,0x0034,0x0033,0x0034,0x0031,0x0039,0x0038,0x0035,0x0067,0x0072,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x003A,0x0031,0x0039,0x0038,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0032,0x0037,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x00 } + , { 0x0045,0x0043,0x004D,0x0041,0x002D,0x0031,0x0031,0x0034,0x00 } + , { 0x0041,0x0053,0x004D,0x004F,0x002D,0x0037,0x0030,0x0038,0x00 } + , { 0x0061,0x0072,0x0061,0x0062,0x0069,0x0063,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0041,0x0072,0x0061,0x0062,0x0069,0x0063,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x002D,0x0045,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0038,0x0035,0x0039,0x0036,0x0045,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x002D,0x0045,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x002D,0x0049,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0038,0x0035,0x0039,0x0036,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0036,0x002D,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0037,0x003A,0x0031,0x0039,0x0038,0x0037,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0032,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0037,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0037,0x00 } + , { 0x0045,0x004C,0x004F,0x0054,0x005F,0x0039,0x0032,0x0038,0x00 } + , { 0x0045,0x0043,0x004D,0x0041,0x002D,0x0031,0x0031,0x0038,0x00 } + , { 0x0067,0x0072,0x0065,0x0065,0x006B,0x00 } + , { 0x0067,0x0072,0x0065,0x0065,0x006B,0x0038,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0047,0x0072,0x0065,0x0065,0x006B,0x00 } + , { 0x0054,0x002E,0x0031,0x0030,0x0031,0x002D,0x0047,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0032,0x0038,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0032,0x0038,0x0054,0x0031,0x0030,0x0031,0x0047,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x003A,0x0031,0x0039,0x0038,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0033,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x00 } + , { 0x0068,0x0065,0x0062,0x0072,0x0065,0x0077,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0048,0x0065,0x0062,0x0072,0x0065,0x0077,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x002D,0x0045,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0038,0x0035,0x0039,0x0038,0x0045,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x002D,0x0045,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x002D,0x0049,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0038,0x0035,0x0039,0x0038,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0038,0x002D,0x0049,0x00 } + , { 0x0043,0x0053,0x004E,0x005F,0x0033,0x0036,0x0039,0x0031,0x0030,0x0033,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0033,0x0039,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0033,0x0039,0x0043,0x0053,0x004E,0x0033,0x0036,0x0039,0x0031,0x0030,0x0033,0x00 } + , { 0x004A,0x0055,0x0053,0x005F,0x0049,0x002E,0x0042,0x0031,0x002E,0x0030,0x0030,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0059,0x0055,0x00 } + , { 0x006A,0x0073,0x00 } + , { 0x0079,0x0075,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0034,0x0031,0x004A,0x0055,0x0053,0x0049,0x0042,0x0031,0x0030,0x0030,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0036,0x0039,0x0033,0x0037,0x002D,0x0032,0x002D,0x0061,0x0064,0x0064,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0054,0x0065,0x0078,0x0074,0x0043,0x006F,0x006D,0x006D,0x00 } + , { 0x0049,0x0045,0x0043,0x005F,0x0050,0x0032,0x0037,0x002D,0x0031,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0034,0x0033,0x0049,0x0045,0x0043,0x0050,0x0032,0x0037,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0035,0x003A,0x0031,0x0039,0x0038,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0035,0x00 } + , { 0x0063,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0043,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x004A,0x0055,0x0053,0x005F,0x0049,0x002E,0x0042,0x0031,0x002E,0x0030,0x0030,0x0033,0x002D,0x0073,0x0065,0x0072,0x0062,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0036,0x00 } + , { 0x0073,0x0065,0x0072,0x0062,0x0069,0x0061,0x006E,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0034,0x0036,0x0053,0x0065,0x0072,0x0062,0x0069,0x0061,0x006E,0x00 } + , { 0x004A,0x0055,0x0053,0x005F,0x0049,0x002E,0x0042,0x0031,0x002E,0x0030,0x0030,0x0033,0x002D,0x006D,0x0061,0x0063,0x00 } + , { 0x006D,0x0061,0x0063,0x0065,0x0064,0x006F,0x006E,0x0069,0x0061,0x006E,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0037,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0034,0x0037,0x004D,0x0061,0x0063,0x0065,0x0064,0x006F,0x006E,0x0069,0x0061,0x006E,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0039,0x003A,0x0031,0x0039,0x0038,0x0039,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0034,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0039,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0039,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0035,0x00 } + , { 0x006C,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0035,0x00 } + , { 0x0067,0x0072,0x0065,0x0065,0x006B,0x002D,0x0063,0x0063,0x0069,0x0074,0x0074,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0030,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0030,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0030,0x0047,0x0072,0x0065,0x0065,0x006B,0x0043,0x0043,0x0049,0x0054,0x0054,0x00 } + , { 0x004E,0x0043,0x005F,0x004E,0x0043,0x0030,0x0030,0x002D,0x0031,0x0030,0x003A,0x0038,0x0031,0x00 } + , { 0x0063,0x0075,0x0062,0x0061,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0043,0x0055,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0031,0x0043,0x0075,0x0062,0x0061,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0036,0x0039,0x0033,0x0037,0x002D,0x0032,0x002D,0x0032,0x0035,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0039,0x0033,0x0037,0x0041,0x0064,0x0064,0x00 } + , { 0x0047,0x004F,0x0053,0x0054,0x005F,0x0031,0x0039,0x0037,0x0036,0x0038,0x002D,0x0037,0x0034,0x00 } + , { 0x0053,0x0054,0x005F,0x0053,0x0045,0x0056,0x005F,0x0033,0x0035,0x0038,0x002D,0x0038,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0033,0x0047,0x004F,0x0053,0x0054,0x0031,0x0039,0x0037,0x0036,0x0038,0x0037,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0073,0x0075,0x0070,0x0070,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0034,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0031,0x002D,0x0032,0x002D,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0038,0x0038,0x0035,0x0039,0x0053,0x0075,0x0070,0x0070,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0031,0x0030,0x0033,0x0036,0x0037,0x002D,0x0062,0x006F,0x0078,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0030,0x0033,0x0036,0x0037,0x0042,0x006F,0x0078,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0030,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0037,0x00 } + , { 0x006C,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0030,0x003A,0x0031,0x0039,0x0039,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x004C,0x0061,0x0074,0x0069,0x006E,0x0036,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0036,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x002D,0x006C,0x0061,0x0070,0x00 } + , { 0x006C,0x0061,0x0070,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0038,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0038,0x004C,0x0061,0x0070,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0058,0x0030,0x0032,0x0031,0x0032,0x002D,0x0031,0x0039,0x0039,0x0030,0x00 } + , { 0x0078,0x0030,0x0032,0x0031,0x0032,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0035,0x0039,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0031,0x0035,0x0039,0x004A,0x0049,0x0053,0x0058,0x0030,0x0032,0x0031,0x0032,0x0031,0x0039,0x0039,0x0030,0x00 } + , { 0x0044,0x0053,0x005F,0x0032,0x0030,0x0038,0x0039,0x00 } + , { 0x0044,0x0053,0x0032,0x0030,0x0038,0x0039,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x0044,0x004B,0x00 } + , { 0x0064,0x006B,0x00 } + , { 0x0063,0x0073,0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x0044,0x0061,0x006E,0x0069,0x0073,0x0068,0x00 } + , { 0x0075,0x0073,0x002D,0x0064,0x006B,0x00 } + , { 0x0063,0x0073,0x0055,0x0053,0x0044,0x004B,0x00 } + , { 0x0064,0x006B,0x002D,0x0075,0x0073,0x00 } + , { 0x0063,0x0073,0x0044,0x004B,0x0055,0x0053,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0058,0x0030,0x0032,0x0030,0x0031,0x00 } + , { 0x0058,0x0030,0x0032,0x0030,0x0031,0x00 } + , { 0x0063,0x0073,0x0048,0x0061,0x006C,0x0066,0x0057,0x0069,0x0064,0x0074,0x0068,0x004B,0x0061,0x0074,0x0061,0x006B,0x0061,0x006E,0x0061,0x00 } + , { 0x004B,0x0053,0x0043,0x0035,0x0036,0x0033,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x0036,0x0034,0x0036,0x002D,0x004B,0x0052,0x00 } + , { 0x0063,0x0073,0x004B,0x0053,0x0043,0x0035,0x0036,0x0033,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x002D,0x0055,0x0043,0x0053,0x002D,0x0032,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x002D,0x0055,0x0043,0x0053,0x002D,0x0034,0x00 } + , { 0x0063,0x0073,0x0055,0x0043,0x0053,0x0034,0x00 } + , { 0x0044,0x0045,0x0043,0x002D,0x004D,0x0043,0x0053,0x00 } + , { 0x0064,0x0065,0x0063,0x00 } + , { 0x0063,0x0073,0x0044,0x0045,0x0043,0x004D,0x0043,0x0053,0x00 } + , { 0x0068,0x0070,0x002D,0x0072,0x006F,0x006D,0x0061,0x006E,0x0038,0x00 } + , { 0x0072,0x006F,0x006D,0x0061,0x006E,0x0038,0x00 } + , { 0x0072,0x0038,0x00 } + , { 0x0063,0x0073,0x0048,0x0050,0x0052,0x006F,0x006D,0x0061,0x006E,0x0038,0x00 } + , { 0x006D,0x0061,0x0063,0x0069,0x006E,0x0074,0x006F,0x0073,0x0068,0x00 } + , { 0x006D,0x0061,0x0063,0x00 } + , { 0x0063,0x0073,0x004D,0x0061,0x0063,0x0069,0x006E,0x0074,0x006F,0x0073,0x0068,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0033,0x0037,0x00 } + , { 0x0063,0x0070,0x0030,0x0033,0x0037,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0075,0x0073,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0063,0x0061,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0077,0x0074,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x006E,0x006C,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0030,0x0033,0x0037,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0033,0x0038,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0049,0x004E,0x0054,0x00 } + , { 0x0063,0x0070,0x0030,0x0033,0x0038,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0030,0x0033,0x0038,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0037,0x0033,0x00 } + , { 0x0043,0x0050,0x0032,0x0037,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0037,0x0033,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0037,0x0034,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0042,0x0045,0x00 } + , { 0x0043,0x0050,0x0032,0x0037,0x0034,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0037,0x0034,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0037,0x0035,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0042,0x0052,0x00 } + , { 0x0063,0x0070,0x0032,0x0037,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0037,0x0035,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0037,0x0037,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0043,0x0050,0x002D,0x0044,0x004B,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0043,0x0050,0x002D,0x004E,0x004F,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0037,0x0037,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0037,0x0038,0x00 } + , { 0x0043,0x0050,0x0032,0x0037,0x0038,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0066,0x0069,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0073,0x0065,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0037,0x0038,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0038,0x0030,0x00 } + , { 0x0043,0x0050,0x0032,0x0038,0x0030,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0069,0x0074,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0038,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0038,0x0031,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x004A,0x0050,0x002D,0x0045,0x00 } + , { 0x0063,0x0070,0x0032,0x0038,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0038,0x0031,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0038,0x0034,0x00 } + , { 0x0043,0x0050,0x0032,0x0038,0x0034,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0065,0x0073,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0038,0x0034,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0038,0x0035,0x00 } + , { 0x0043,0x0050,0x0032,0x0038,0x0035,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0067,0x0062,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0038,0x0035,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0039,0x0030,0x00 } + , { 0x0063,0x0070,0x0032,0x0039,0x0030,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x004A,0x0050,0x002D,0x006B,0x0061,0x006E,0x0061,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0039,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0032,0x0039,0x0037,0x00 } + , { 0x0063,0x0070,0x0032,0x0039,0x0037,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0066,0x0072,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0032,0x0039,0x0037,0x00 } + , { 0x0049,0x0042,0x004D,0x0034,0x0032,0x0030,0x00 } + , { 0x0063,0x0070,0x0034,0x0032,0x0030,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0061,0x0072,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0034,0x0032,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0034,0x0032,0x0033,0x00 } + , { 0x0063,0x0070,0x0034,0x0032,0x0033,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0067,0x0072,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0034,0x0032,0x0033,0x00 } + , { 0x0049,0x0042,0x004D,0x0034,0x0032,0x0034,0x00 } + , { 0x0063,0x0070,0x0034,0x0032,0x0034,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0068,0x0065,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0034,0x0032,0x0034,0x00 } + , { 0x0049,0x0042,0x004D,0x0034,0x0033,0x0037,0x00 } + , { 0x0063,0x0070,0x0034,0x0033,0x0037,0x00 } + , { 0x0034,0x0033,0x0037,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0038,0x0043,0x006F,0x0064,0x0065,0x0050,0x0061,0x0067,0x0065,0x0034,0x0033,0x0037,0x00 } + , { 0x0049,0x0042,0x004D,0x0035,0x0030,0x0030,0x00 } + , { 0x0043,0x0050,0x0035,0x0030,0x0030,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0062,0x0065,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0063,0x0068,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0035,0x0030,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0037,0x0037,0x0035,0x00 } + , { 0x0063,0x0070,0x0037,0x0037,0x0035,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0037,0x0037,0x0035,0x0042,0x0061,0x006C,0x0074,0x0069,0x0063,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0035,0x0030,0x00 } + , { 0x0063,0x0070,0x0038,0x0035,0x0030,0x00 } + , { 0x0038,0x0035,0x0030,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0038,0x0035,0x0030,0x004D,0x0075,0x006C,0x0074,0x0069,0x006C,0x0069,0x006E,0x0067,0x0075,0x0061,0x006C,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0035,0x0031,0x00 } + , { 0x0063,0x0070,0x0038,0x0035,0x0031,0x00 } + , { 0x0038,0x0035,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0035,0x0031,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0035,0x0032,0x00 } + , { 0x0063,0x0070,0x0038,0x0035,0x0032,0x00 } + , { 0x0038,0x0035,0x0032,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0070,0x0038,0x0035,0x0032,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0035,0x0035,0x00 } + , { 0x0063,0x0070,0x0038,0x0035,0x0035,0x00 } + , { 0x0038,0x0035,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0035,0x0035,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0035,0x0037,0x00 } + , { 0x0063,0x0070,0x0038,0x0035,0x0037,0x00 } + , { 0x0038,0x0035,0x0037,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0035,0x0037,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0030,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0030,0x00 } + , { 0x0038,0x0036,0x0030,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0031,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0031,0x00 } + , { 0x0038,0x0036,0x0031,0x00 } + , { 0x0063,0x0070,0x002D,0x0069,0x0073,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0031,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0032,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0032,0x00 } + , { 0x0038,0x0036,0x0032,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0038,0x0036,0x0032,0x004C,0x0061,0x0074,0x0069,0x006E,0x0048,0x0065,0x0062,0x0072,0x0065,0x0077,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0033,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0033,0x00 } + , { 0x0038,0x0036,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0033,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0034,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0034,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0034,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0035,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0035,0x00 } + , { 0x0038,0x0036,0x0035,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0035,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0036,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0036,0x00 } + , { 0x0038,0x0036,0x0036,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0036,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0038,0x00 } + , { 0x0043,0x0050,0x0038,0x0036,0x0038,0x00 } + , { 0x0063,0x0070,0x002D,0x0061,0x0072,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0038,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0036,0x0039,0x00 } + , { 0x0063,0x0070,0x0038,0x0036,0x0039,0x00 } + , { 0x0038,0x0036,0x0039,0x00 } + , { 0x0063,0x0070,0x002D,0x0067,0x0072,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0036,0x0039,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0037,0x0030,0x00 } + , { 0x0043,0x0050,0x0038,0x0037,0x0030,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0072,0x006F,0x0065,0x0063,0x0065,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0079,0x0075,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0037,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0037,0x0031,0x00 } + , { 0x0043,0x0050,0x0038,0x0037,0x0031,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0069,0x0073,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0037,0x0031,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0038,0x0030,0x00 } + , { 0x0063,0x0070,0x0038,0x0038,0x0030,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0043,0x0079,0x0072,0x0069,0x006C,0x006C,0x0069,0x0063,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0038,0x0030,0x00 } + , { 0x0049,0x0042,0x004D,0x0038,0x0039,0x0031,0x00 } + , { 0x0063,0x0070,0x0038,0x0039,0x0031,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0038,0x0039,0x0031,0x00 } + , { 0x0049,0x0042,0x004D,0x0039,0x0030,0x0033,0x00 } + , { 0x0063,0x0070,0x0039,0x0030,0x0033,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0039,0x0030,0x0033,0x00 } + , { 0x0049,0x0042,0x004D,0x0039,0x0030,0x0034,0x00 } + , { 0x0063,0x0070,0x0039,0x0030,0x0034,0x00 } + , { 0x0039,0x0030,0x0034,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x0042,0x004D,0x0039,0x0030,0x0034,0x00 } + , { 0x0049,0x0042,0x004D,0x0039,0x0030,0x0035,0x00 } + , { 0x0043,0x0050,0x0039,0x0030,0x0035,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0074,0x0072,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0039,0x0030,0x0035,0x00 } + , { 0x0049,0x0042,0x004D,0x0039,0x0031,0x0038,0x00 } + , { 0x0043,0x0050,0x0039,0x0031,0x0038,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0063,0x0070,0x002D,0x0061,0x0072,0x0032,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0039,0x0031,0x0038,0x00 } + , { 0x0049,0x0042,0x004D,0x0031,0x0030,0x0032,0x0036,0x00 } + , { 0x0043,0x0050,0x0031,0x0030,0x0032,0x0036,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0031,0x0030,0x0032,0x0036,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0041,0x0054,0x002D,0x0044,0x0045,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0041,0x0054,0x0044,0x0045,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0041,0x0054,0x002D,0x0044,0x0045,0x002D,0x0041,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0041,0x0054,0x0044,0x0045,0x0041,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0043,0x0041,0x002D,0x0046,0x0052,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0043,0x0041,0x0046,0x0052,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0044,0x004B,0x002D,0x004E,0x004F,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0044,0x004B,0x004E,0x004F,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0044,0x004B,0x002D,0x004E,0x004F,0x002D,0x0041,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0044,0x004B,0x004E,0x004F,0x0041,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0046,0x0049,0x002D,0x0053,0x0045,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0046,0x0049,0x0053,0x0045,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0046,0x0049,0x002D,0x0053,0x0045,0x002D,0x0041,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0046,0x0049,0x0053,0x0045,0x0041,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0046,0x0052,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0046,0x0052,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0049,0x0054,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0049,0x0054,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0050,0x0054,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0050,0x0054,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0045,0x0053,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0045,0x0053,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0045,0x0053,0x002D,0x0041,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0045,0x0053,0x0041,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0045,0x0053,0x002D,0x0053,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0045,0x0053,0x0053,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0055,0x004B,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0055,0x004B,0x00 } + , { 0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x002D,0x0055,0x0053,0x00 } + , { 0x0063,0x0073,0x0045,0x0042,0x0043,0x0044,0x0049,0x0043,0x0055,0x0053,0x00 } + , { 0x0055,0x004E,0x004B,0x004E,0x004F,0x0057,0x004E,0x002D,0x0038,0x0042,0x0049,0x0054,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x006B,0x006E,0x006F,0x0077,0x006E,0x0038,0x0042,0x0069,0x0054,0x00 } + , { 0x004D,0x004E,0x0045,0x004D,0x004F,0x004E,0x0049,0x0043,0x00 } + , { 0x0063,0x0073,0x004D,0x006E,0x0065,0x006D,0x006F,0x006E,0x0069,0x0063,0x00 } + , { 0x004D,0x004E,0x0045,0x004D,0x00 } + , { 0x0063,0x0073,0x004D,0x006E,0x0065,0x006D,0x00 } + , { 0x0056,0x0049,0x0053,0x0043,0x0049,0x0049,0x00 } + , { 0x0063,0x0073,0x0056,0x0049,0x0053,0x0043,0x0049,0x0049,0x00 } + , { 0x0056,0x0049,0x0051,0x0052,0x00 } + , { 0x0063,0x0073,0x0056,0x0049,0x0051,0x0052,0x00 } + , { 0x004B,0x004F,0x0049,0x0038,0x002D,0x0052,0x00 } + , { 0x0063,0x0073,0x004B,0x004F,0x0049,0x0038,0x0052,0x00 } + , { 0x004B,0x004F,0x0049,0x0038,0x002D,0x0055,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0030,0x0038,0x0035,0x0038,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0030,0x0038,0x0035,0x0038,0x00 } + , { 0x0043,0x0050,0x0030,0x0030,0x0038,0x0035,0x0038,0x00 } + , { 0x0050,0x0043,0x002D,0x004D,0x0075,0x006C,0x0074,0x0069,0x006C,0x0069,0x006E,0x0067,0x0075,0x0061,0x006C,0x002D,0x0038,0x0035,0x0030,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0030,0x0039,0x0032,0x0034,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0030,0x0039,0x0032,0x0034,0x00 } + , { 0x0043,0x0050,0x0030,0x0030,0x0039,0x0032,0x0034,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x004C,0x0061,0x0074,0x0069,0x006E,0x0039,0x002D,0x002D,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0030,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0030,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0030,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0075,0x0073,0x002D,0x0033,0x0037,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0031,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0031,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0031,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0064,0x0065,0x002D,0x0032,0x0037,0x0033,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0032,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0032,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0032,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0064,0x006B,0x002D,0x0032,0x0037,0x0037,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x006E,0x006F,0x002D,0x0032,0x0037,0x0037,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0033,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0033,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0033,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0066,0x0069,0x002D,0x0032,0x0037,0x0038,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0073,0x0065,0x002D,0x0032,0x0037,0x0038,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0034,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0034,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0034,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0069,0x0074,0x002D,0x0032,0x0038,0x0030,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0035,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0035,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0035,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0065,0x0073,0x002D,0x0032,0x0038,0x0034,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0036,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0036,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0036,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0067,0x0062,0x002D,0x0032,0x0038,0x0035,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0037,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0037,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0037,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0066,0x0072,0x002D,0x0032,0x0039,0x0037,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0038,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0038,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0038,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0069,0x006E,0x0074,0x0065,0x0072,0x006E,0x0061,0x0074,0x0069,0x006F,0x006E,0x0061,0x006C,0x002D,0x0035,0x0030,0x0030,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0049,0x0042,0x004D,0x0030,0x0031,0x0031,0x0034,0x0039,0x00 } + , { 0x0043,0x0043,0x0053,0x0049,0x0044,0x0030,0x0031,0x0031,0x0034,0x0039,0x00 } + , { 0x0043,0x0050,0x0030,0x0031,0x0031,0x0034,0x0039,0x00 } + , { 0x0065,0x0062,0x0063,0x0064,0x0069,0x0063,0x002D,0x0069,0x0073,0x002D,0x0038,0x0037,0x0031,0x002B,0x0065,0x0075,0x0072,0x006F,0x00 } + , { 0x0042,0x0069,0x0067,0x0035,0x002D,0x0048,0x004B,0x0053,0x0043,0x0053,0x00 } + , { 0x0055,0x004E,0x0049,0x0043,0x004F,0x0044,0x0045,0x002D,0x0031,0x002D,0x0031,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0031,0x0031,0x00 } + , { 0x0053,0x0043,0x0053,0x0055,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0037,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0031,0x0036,0x0042,0x0045,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0031,0x0036,0x004C,0x0045,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0031,0x0036,0x00 } + , { 0x0043,0x0045,0x0053,0x0055,0x002D,0x0038,0x00 } + , { 0x0063,0x0073,0x0043,0x0045,0x0053,0x0055,0x002D,0x0038,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0033,0x0032,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0033,0x0032,0x0042,0x0045,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0033,0x0032,0x004C,0x0045,0x00 } + , { 0x0055,0x004E,0x0049,0x0043,0x004F,0x0044,0x0045,0x002D,0x0031,0x002D,0x0031,0x002D,0x0055,0x0054,0x0046,0x002D,0x0037,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0031,0x0031,0x0055,0x0054,0x0046,0x0037,0x00 } + , { 0x0055,0x0054,0x0046,0x002D,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0033,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0034,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0069,0x0072,0x002D,0x0031,0x0039,0x0039,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0034,0x003A,0x0031,0x0039,0x0039,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0034,0x00 } + , { 0x006C,0x0061,0x0074,0x0069,0x006E,0x0038,0x00 } + , { 0x0069,0x0073,0x006F,0x002D,0x0063,0x0065,0x006C,0x0074,0x0069,0x0063,0x00 } + , { 0x006C,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x005F,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x0036,0x00 } + , { 0x00 } + , { 0x0047,0x0042,0x004B,0x00 } + , { 0x0043,0x0050,0x0039,0x0033,0x0036,0x00 } + , { 0x004D,0x0053,0x0039,0x0033,0x0036,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0039,0x0033,0x0036,0x00 } + , { 0x0047,0x0042,0x0031,0x0038,0x0030,0x0033,0x0030,0x00 } + , { 0x004A,0x0049,0x0053,0x005F,0x0045,0x006E,0x0063,0x006F,0x0064,0x0069,0x006E,0x0067,0x00 } + , { 0x0063,0x0073,0x004A,0x0049,0x0053,0x0045,0x006E,0x0063,0x006F,0x0064,0x0069,0x006E,0x0067,0x00 } + , { 0x0053,0x0068,0x0069,0x0066,0x0074,0x005F,0x004A,0x0049,0x0053,0x00 } + , { 0x004D,0x0053,0x005F,0x004B,0x0061,0x006E,0x006A,0x0069,0x00 } + , { 0x0063,0x0073,0x0053,0x0068,0x0069,0x0066,0x0074,0x004A,0x0049,0x0053,0x00 } + , { 0x0045,0x0078,0x0074,0x0065,0x006E,0x0064,0x0065,0x0064,0x005F,0x0055,0x004E,0x0049,0x0058,0x005F,0x0043,0x006F,0x0064,0x0065,0x005F,0x0050,0x0061,0x0063,0x006B,0x0065,0x0064,0x005F,0x0046,0x006F,0x0072,0x006D,0x0061,0x0074,0x005F,0x0066,0x006F,0x0072,0x005F,0x004A,0x0061,0x0070,0x0061,0x006E,0x0065,0x0073,0x0065,0x00 } + , { 0x0063,0x0073,0x0045,0x0055,0x0043,0x0050,0x006B,0x0064,0x0046,0x006D,0x0074,0x004A,0x0061,0x0070,0x0061,0x006E,0x0065,0x0073,0x0065,0x00 } + , { 0x0045,0x0055,0x0043,0x002D,0x004A,0x0050,0x00 } + , { 0x0045,0x0078,0x0074,0x0065,0x006E,0x0064,0x0065,0x0064,0x005F,0x0055,0x004E,0x0049,0x0058,0x005F,0x0043,0x006F,0x0064,0x0065,0x005F,0x0046,0x0069,0x0078,0x0065,0x0064,0x005F,0x0057,0x0069,0x0064,0x0074,0x0068,0x005F,0x0066,0x006F,0x0072,0x005F,0x004A,0x0061,0x0070,0x0061,0x006E,0x0065,0x0073,0x0065,0x00 } + , { 0x0063,0x0073,0x0045,0x0055,0x0043,0x0046,0x0069,0x0078,0x0057,0x0069,0x0064,0x004A,0x0061,0x0070,0x0061,0x006E,0x0065,0x0073,0x0065,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x002D,0x0055,0x0043,0x0053,0x002D,0x0042,0x0061,0x0073,0x0069,0x0063,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0041,0x0053,0x0043,0x0049,0x0049,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x002D,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x002D,0x004C,0x0061,0x0074,0x0069,0x006E,0x0031,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x004C,0x0061,0x0074,0x0069,0x006E,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0031,0x0030,0x0036,0x0034,0x0036,0x002D,0x004A,0x002D,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x002D,0x0049,0x0042,0x004D,0x002D,0x0031,0x0032,0x0036,0x0031,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0049,0x0042,0x004D,0x0031,0x0032,0x0036,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x002D,0x0049,0x0042,0x004D,0x002D,0x0031,0x0032,0x0036,0x0038,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0049,0x0042,0x004D,0x0031,0x0032,0x0036,0x0038,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x002D,0x0049,0x0042,0x004D,0x002D,0x0031,0x0032,0x0037,0x0036,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0049,0x0042,0x004D,0x0031,0x0032,0x0037,0x0036,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x002D,0x0049,0x0042,0x004D,0x002D,0x0031,0x0032,0x0036,0x0034,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0049,0x0042,0x004D,0x0031,0x0032,0x0036,0x0034,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x002D,0x0049,0x0042,0x004D,0x002D,0x0031,0x0032,0x0036,0x0035,0x00 } + , { 0x0063,0x0073,0x0055,0x006E,0x0069,0x0063,0x006F,0x0064,0x0065,0x0049,0x0042,0x004D,0x0031,0x0032,0x0036,0x0035,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x002D,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0033,0x002E,0x0030,0x002D,0x004C,0x0061,0x0074,0x0069,0x006E,0x002D,0x0031,0x00 } + , { 0x0063,0x0073,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x0033,0x0030,0x004C,0x0061,0x0074,0x0069,0x006E,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0031,0x002D,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0033,0x002E,0x0031,0x002D,0x004C,0x0061,0x0074,0x0069,0x006E,0x002D,0x0031,0x00 } + , { 0x0063,0x0073,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x0033,0x0031,0x004C,0x0061,0x0074,0x0069,0x006E,0x0031,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0032,0x002D,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x004C,0x0061,0x0074,0x0069,0x006E,0x002D,0x0032,0x00 } + , { 0x0063,0x0073,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x0033,0x0031,0x004C,0x0061,0x0074,0x0069,0x006E,0x0032,0x00 } + , { 0x0049,0x0053,0x004F,0x002D,0x0038,0x0038,0x0035,0x0039,0x002D,0x0039,0x002D,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x004C,0x0061,0x0074,0x0069,0x006E,0x002D,0x0035,0x00 } + , { 0x0063,0x0073,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x0033,0x0031,0x004C,0x0061,0x0074,0x0069,0x006E,0x0035,0x00 } + , { 0x0041,0x0064,0x006F,0x0062,0x0065,0x002D,0x0053,0x0074,0x0061,0x006E,0x0064,0x0061,0x0072,0x0064,0x002D,0x0045,0x006E,0x0063,0x006F,0x0064,0x0069,0x006E,0x0067,0x00 } + , { 0x0063,0x0073,0x0041,0x0064,0x006F,0x0062,0x0065,0x0053,0x0074,0x0061,0x006E,0x0064,0x0061,0x0072,0x0064,0x0045,0x006E,0x0063,0x006F,0x0064,0x0069,0x006E,0x0067,0x00 } + , { 0x0056,0x0065,0x006E,0x0074,0x0075,0x0072,0x0061,0x002D,0x0055,0x0053,0x00 } + , { 0x0063,0x0073,0x0056,0x0065,0x006E,0x0074,0x0075,0x0072,0x0061,0x0055,0x0053,0x00 } + , { 0x0056,0x0065,0x006E,0x0074,0x0075,0x0072,0x0061,0x002D,0x0049,0x006E,0x0074,0x0065,0x0072,0x006E,0x0061,0x0074,0x0069,0x006F,0x006E,0x0061,0x006C,0x00 } + , { 0x0063,0x0073,0x0056,0x0065,0x006E,0x0074,0x0075,0x0072,0x0061,0x0049,0x006E,0x0074,0x0065,0x0072,0x006E,0x0061,0x0074,0x0069,0x006F,0x006E,0x0061,0x006C,0x00 } + , { 0x0050,0x0043,0x0038,0x002D,0x0044,0x0061,0x006E,0x0069,0x0073,0x0068,0x002D,0x004E,0x006F,0x0072,0x0077,0x0065,0x0067,0x0069,0x0061,0x006E,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0038,0x0044,0x0061,0x006E,0x0069,0x0073,0x0068,0x004E,0x006F,0x0072,0x0077,0x0065,0x0067,0x0069,0x0061,0x006E,0x00 } + , { 0x0050,0x0043,0x0038,0x002D,0x0054,0x0075,0x0072,0x006B,0x0069,0x0073,0x0068,0x00 } + , { 0x0063,0x0073,0x0050,0x0043,0x0038,0x0054,0x0075,0x0072,0x006B,0x0069,0x0073,0x0068,0x00 } + , { 0x0049,0x0042,0x004D,0x002D,0x0053,0x0079,0x006D,0x0062,0x006F,0x006C,0x0073,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0053,0x0079,0x006D,0x0062,0x006F,0x006C,0x0073,0x00 } + , { 0x0049,0x0042,0x004D,0x002D,0x0054,0x0068,0x0061,0x0069,0x00 } + , { 0x0063,0x0073,0x0049,0x0042,0x004D,0x0054,0x0068,0x0061,0x0069,0x00 } + , { 0x0048,0x0050,0x002D,0x004C,0x0065,0x0067,0x0061,0x006C,0x00 } + , { 0x0063,0x0073,0x0048,0x0050,0x004C,0x0065,0x0067,0x0061,0x006C,0x00 } + , { 0x0048,0x0050,0x002D,0x0050,0x0069,0x002D,0x0066,0x006F,0x006E,0x0074,0x00 } + , { 0x0063,0x0073,0x0048,0x0050,0x0050,0x0069,0x0046,0x006F,0x006E,0x0074,0x00 } + , { 0x0048,0x0050,0x002D,0x004D,0x0061,0x0074,0x0068,0x0038,0x00 } + , { 0x0063,0x0073,0x0048,0x0050,0x004D,0x0061,0x0074,0x0068,0x0038,0x00 } + , { 0x0041,0x0064,0x006F,0x0062,0x0065,0x002D,0x0053,0x0079,0x006D,0x0062,0x006F,0x006C,0x002D,0x0045,0x006E,0x0063,0x006F,0x0064,0x0069,0x006E,0x0067,0x00 } + , { 0x0063,0x0073,0x0048,0x0050,0x0050,0x0053,0x004D,0x0061,0x0074,0x0068,0x00 } + , { 0x0048,0x0050,0x002D,0x0044,0x0065,0x0073,0x006B,0x0054,0x006F,0x0070,0x00 } + , { 0x0063,0x0073,0x0048,0x0050,0x0044,0x0065,0x0073,0x006B,0x0074,0x006F,0x0070,0x00 } + , { 0x0056,0x0065,0x006E,0x0074,0x0075,0x0072,0x0061,0x002D,0x004D,0x0061,0x0074,0x0068,0x00 } + , { 0x0063,0x0073,0x0056,0x0065,0x006E,0x0074,0x0075,0x0072,0x0061,0x004D,0x0061,0x0074,0x0068,0x00 } + , { 0x004D,0x0069,0x0063,0x0072,0x006F,0x0073,0x006F,0x0066,0x0074,0x002D,0x0050,0x0075,0x0062,0x006C,0x0069,0x0073,0x0068,0x0069,0x006E,0x0067,0x00 } + , { 0x0063,0x0073,0x004D,0x0069,0x0063,0x0072,0x006F,0x0073,0x006F,0x0066,0x0074,0x0050,0x0075,0x0062,0x006C,0x0069,0x0073,0x0068,0x0069,0x006E,0x0067,0x00 } + , { 0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0033,0x0031,0x004A,0x00 } + , { 0x0063,0x0073,0x0057,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x0033,0x0031,0x004A,0x00 } + , { 0x0047,0x0042,0x0032,0x0033,0x0031,0x0032,0x00 } + , { 0x0063,0x0073,0x0047,0x0042,0x0032,0x0033,0x0031,0x0032,0x00 } + , { 0x0042,0x0069,0x0067,0x0035,0x00 } + , { 0x0063,0x0073,0x0042,0x0069,0x0067,0x0035,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0030,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0031,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0032,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0033,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0034,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0035,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0036,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0037,0x00 } + , { 0x0077,0x0069,0x006E,0x0064,0x006F,0x0077,0x0073,0x002D,0x0031,0x0032,0x0035,0x0038,0x00 } + , { 0x0054,0x0049,0x0053,0x002D,0x0036,0x0032,0x0030,0x00 } + , { 0x0048,0x005A,0x002D,0x0047,0x0042,0x002D,0x0032,0x0033,0x0031,0x0032,0x00 } + +}; +const unsigned int gEncodingArraySize = 791; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/internal/IGXMLScanner.cpp b/include/xercesc/internal/IGXMLScanner.cpp new file mode 100644 index 0000000..6bc136b --- /dev/null +++ b/include/xercesc/internal/IGXMLScanner.cpp @@ -0,0 +1,3271 @@ +/* + * 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: IGXMLScanner.cpp 1663359 2015-03-02 17:01:52Z scantor $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ReaderMgrResetType; + + +// --------------------------------------------------------------------------- +// IGXMLScanner: Constructors and Destructor +// --------------------------------------------------------------------------- +IGXMLScanner::IGXMLScanner( XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(valToAdopt, grammarResolver, manager) + , fSeeXsi(false) + , fGrammarType(Grammar::UnKnown) + , fElemStateSize(16) + , fElemState(0) + , fElemLoopState(0) + , fContent(1023, manager) + , fRawAttrList(0) + , fRawAttrColonListSize(32) + , fRawAttrColonList(0) + , fDTDValidator(0) + , fSchemaValidator(0) + , fDTDGrammar(0) + , fICHandler(0) + , fLocationPairs(0) + , fDTDElemNonDeclPool(0) + , fSchemaElemNonDeclPool(0) + , fElemCount(0) + , fAttDefRegistry(0) + , fUndeclaredAttrRegistry(0) + , fPSVIAttrList(0) + , fModel(0) + , fPSVIElement(0) + , fErrorStack(0) + , fSchemaInfoList(0) + , fCachedSchemaInfoList (0) +{ + CleanupType cleanup(this, &IGXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +IGXMLScanner::IGXMLScanner( XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errHandler + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager) + , fSeeXsi(false) + , fGrammarType(Grammar::UnKnown) + , fElemStateSize(16) + , fElemState(0) + , fElemLoopState(0) + , fContent(1023, manager) + , fRawAttrList(0) + , fRawAttrColonListSize(32) + , fRawAttrColonList(0) + , fDTDValidator(0) + , fSchemaValidator(0) + , fDTDGrammar(0) + , fICHandler(0) + , fLocationPairs(0) + , fDTDElemNonDeclPool(0) + , fSchemaElemNonDeclPool(0) + , fElemCount(0) + , fAttDefRegistry(0) + , fUndeclaredAttrRegistry(0) + , fPSVIAttrList(0) + , fModel(0) + , fPSVIElement(0) + , fErrorStack(0) + , fSchemaInfoList(0) + , fCachedSchemaInfoList (0) +{ + CleanupType cleanup(this, &IGXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +IGXMLScanner::~IGXMLScanner() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Getter methods +// --------------------------------------------------------------------------- +NameIdPool* IGXMLScanner::getEntityDeclPool() +{ + if(!fDTDGrammar) + return 0; + return fDTDGrammar->getEntityDeclPool(); +} + +const NameIdPool* IGXMLScanner::getEntityDeclPool() const +{ + if(!fDTDGrammar) + return 0; + return fDTDGrammar->getEntityDeclPool(); +} + +// --------------------------------------------------------------------------- +// IGXMLScanner: Main entry point to scan a document +// --------------------------------------------------------------------------- +void IGXMLScanner::scanDocument(const InputSource& src) +{ + // Bump up the sequence id for this parser instance. This will invalidate + // any previous progressive scan tokens. + fSequenceId++; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + // Reset the scanner and its plugged in stuff for a new run. This + // resets all the data structures, creates the initial reader and + // pushes it on the stack, and sets up the base document path. + scanReset(src); + + // If we have a document handler, then call the start document + if (fDocHandler) + fDocHandler->startDocument(); + + // Scan the prolog part, which is everything before the root element + // including the DTD subsets. + scanProlog(); + + // If we got to the end of input, then its not a valid XML file. + // Else, go on to scan the content. + if (fReaderMgr.atEOF()) + { + emitError(XMLErrs::EmptyMainEntity); + } + else + { + // Scan content, and tell it its not an external entity + if (scanContent()) + { + // Do post-parse validation if required + if (fValidate) + { + // We handle ID reference semantics at this level since + // its required by XML 1.0. + checkIDRefs(); + + // Then allow the validator to do any extra stuff it wants +// fValidator->postParseValidation(); + } + + // That went ok, so scan for any miscellaneous stuff + if (!fReaderMgr.atEOF()) + scanMiscellaneous(); + } + } + + // If we have a document handler, then call the end document + if (fDocHandler) + fDocHandler->endDocument(); + + //cargill debug: + //fGrammarResolver->getXSModel(); + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } +} + + +bool IGXMLScanner::scanNext(XMLPScanToken& token) +{ + // Make sure this token is still legal + if (!isLegalToken(token)) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager); + + // Find the next token and remember the reader id + XMLSize_t orgReader; + XMLTokens curToken; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + bool retVal = true; + + try + { + while (true) + { + // We have to handle any end of entity exceptions that happen here. + // We could be at the end of X nested entities, each of which will + // generate an end of entity exception as we try to move forward. + try + { + curToken = senseNextToken(orgReader); + break; + } + catch(const EndOfEntityException& toCatch) + { + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + if (curToken == Token_CharData) + { + scanCharData(fCDataBuf); + } + else if (curToken == Token_EOF) + { + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + retVal = false; + } + else + { + // Its some sort of markup + bool gotData = true; + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + if (fDoNamespaces) + scanStartTagNS(gotData); + else + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // If we hit the end, then do the miscellaneous part + if (!gotData) + { + // Do post-parse validation if required + if (fValidate) + { + // We handle ID reference semantics at this level since + // its required by XML 1.0. + checkIDRefs(); + + // Then allow the validator to do any extra stuff it wants +// fValidator->postParseValidation(); + } + + // That went ok, so scan for any miscellaneous stuff + scanMiscellaneous(); + + if (toCheckIdentityConstraint()) + fICHandler->endDocument(); + + if (fDocHandler) + fDocHandler->endDocument(); + } + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception so return failure + retVal = false; + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so return failure + retVal = false; + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + retVal = false; + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + // If we are not at the end, release the object that will + // reset the ReaderMgr. + if (retVal) + resetReaderMgr.release(); + + return retVal; +} + + + +// --------------------------------------------------------------------------- +// IGXMLScanner: Private helper methods. Most of these are implemented in +// IGXMLScanner2.Cpp. +// --------------------------------------------------------------------------- + +// This method handles the common initialization, to avoid having to do +// it redundantly in multiple constructors. +void IGXMLScanner::commonInit() +{ + + // Create the element state array + fElemState = (unsigned int*) fMemoryManager->allocate + ( + fElemStateSize * sizeof(unsigned int) + ); //new unsigned int[fElemStateSize]; + fElemLoopState = (unsigned int*) fMemoryManager->allocate + ( + fElemStateSize * sizeof(unsigned int) + ); //new unsigned int[fElemStateSize]; + + // And we need one for the raw attribute scan. This just stores key/ + // value string pairs (prior to any processing.) + fRawAttrList = new (fMemoryManager) RefVectorOf(32, true, fMemoryManager); + fRawAttrColonList = (int*) fMemoryManager->allocate + ( + fRawAttrColonListSize * sizeof(int) + ); + + // Create the Validator and init them + fDTDValidator = new (fMemoryManager) DTDValidator(); + initValidator(fDTDValidator); + fSchemaValidator = new (fMemoryManager) SchemaValidator(0, fMemoryManager); + initValidator(fSchemaValidator); + + // Create IdentityConstraint info + fICHandler = new (fMemoryManager) IdentityConstraintHandler(this, fMemoryManager); + + // Create schemaLocation pair info + fLocationPairs = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + // create pools for undeclared elements + fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool(29, 128, fMemoryManager); + fSchemaElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool(29, true, 128, fMemoryManager); + fAttDefRegistry = new (fMemoryManager) RefHashTableOf + ( + 131, false, fMemoryManager + ); + fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf(7, fMemoryManager); + fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager); + + fSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf(29, fMemoryManager); + fCachedSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf(29, fMemoryManager); + + // use fDTDValidator as the default validator + if (!fValidator) + fValidator = fDTDValidator; +} + +void IGXMLScanner::cleanUp() +{ + fMemoryManager->deallocate(fElemState); //delete [] fElemState; + fMemoryManager->deallocate(fElemLoopState); //delete [] fElemLoopState; + delete fRawAttrList; + fMemoryManager->deallocate(fRawAttrColonList); + delete fDTDValidator; + delete fSchemaValidator; + delete fICHandler; + delete fLocationPairs; + delete fDTDElemNonDeclPool; + delete fSchemaElemNonDeclPool; + delete fAttDefRegistry; + delete fUndeclaredAttrRegistry; + delete fPSVIAttrList; + delete fPSVIElement; + delete fErrorStack; + delete fSchemaInfoList; + delete fCachedSchemaInfoList; +} + +// --------------------------------------------------------------------------- +// IGXMLScanner: Private scanning methods +// --------------------------------------------------------------------------- + +// This method is called from scanStartTag() to handle the very raw initial +// scan of the attributes. It just fills in the passed collection with +// key/value pairs for each attribute. No processing is done on them at all. +XMLSize_t +IGXMLScanner::rawAttrScan(const XMLCh* const elemName + , RefVectorOf& toFill + , bool& isEmpty) +{ + // Keep up with how many attributes we've seen so far, and how many + // elements are available in the vector. This way we can reuse old + // elements until we run out and then expand it. + XMLSize_t attCount = 0; + XMLSize_t curVecSize = toFill.size(); + + // Assume it is not empty + isEmpty = false; + + // We loop until we either see a /> or >, handling key/value pairs util + // we get there. We place them in the passed vector, which we will expand + // as required to hold them. + while (true) + { + // Get the next character, which should be non-space + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + // + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + bool bFoundSpace; + fReaderMgr.skipPastSpaces(bFoundSpace); + if (!bFoundSpace) + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + // Ok, peek another char + nextCh = fReaderMgr.peekNextChar(); + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume it's going to be an attribute, so get a name from + // the input. + int colonPosition; + if (!fReaderMgr.getQName(fAttNameBuf, &colonPosition)) + { + if (fAttNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedAttrName); + else + emitError(XMLErrs::InvalidAttrName, fAttNameBuf.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return attCount; + } + + const XMLCh* curAttNameBuf = fAttNameBuf.getRawBuffer(); + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemName); + return attCount; + } + else + { + // Something went really wrong + return attCount; + } + } + + // Next should be the quoted attribute value. We just do a simple + // and stupid scan of this value. The only thing we do here + // is to expand entity references. + if (!basicAttrValueScan(curAttNameBuf, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemName); + return attCount; + } + else + { + // Something went really wrong + return attCount; + } + } + + // And now lets add it to the passed collection. If we have not + // filled it up yet, then we use the next element. Else we add + // a new one. + KVStringPair* curPair = 0; + if (attCount >= curVecSize) + { + curPair = new (fMemoryManager) KVStringPair + ( + curAttNameBuf + , fAttNameBuf.getLen() + , fAttValueBuf.getRawBuffer() + , fAttValueBuf.getLen() + , fMemoryManager + ); + toFill.addElement(curPair); + } + else + { + curPair = toFill.elementAt(attCount); + curPair->set + ( + curAttNameBuf, + fAttNameBuf.getLen(), + fAttValueBuf.getRawBuffer(), + fAttValueBuf.getLen() + ); + } + + if (attCount >= fRawAttrColonListSize) { + resizeRawAttrColonList(); + } + // Set the position of the colon and bump the count of attributes we've gotten + fRawAttrColonList[attCount++] = colonPosition; + + // And go to the top again for another attribute + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, elemName); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, elemName); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + return attCount; +} + + +// This method will kick off the scanning of the primary content of the +// document, i.e. the elements. +bool IGXMLScanner::scanContent() +{ + // Go into a loop until we hit the end of the root element, or we fall + // out because there is no root element. + // + // We have to do kind of a deeply nested double loop here in order to + // avoid doing the setup/teardown of the exception handler on each + // round. Doing it this way we only do it when an exception actually + // occurs. + bool gotData = true; + bool inMarkup = false; + while (gotData) + { + try + { + while (gotData) + { + // Sense what the next top level token is. According to what + // this tells us, we will call something to handle that kind + // of thing. + XMLSize_t orgReader; + const XMLTokens curToken = senseNextToken(orgReader); + + // Handle character data and end of file specially. Char data + // is not markup so we don't want to handle it in the loop + // below. + if (curToken == Token_CharData) + { + // Scan the character data and call appropriate events. Let + // him use our local character data buffer for efficiency. + scanCharData(fCDataBuf); + continue; + } + else if (curToken == Token_EOF) + { + // The element stack better be empty at this point or we + // ended prematurely before all elements were closed. + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + // Its the end of file, so clear the got data flag + gotData = false; + continue; + } + + // We are in some sort of markup now + inMarkup = true; + + // According to the token we got, call the appropriate + // scanning method. + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + if (fDoNamespaces) + scanStartTagNS(gotData); + else + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // And we are back out of markup again + inMarkup = false; + } + } + catch(const EndOfEntityException& toCatch) + { + // If we were in some markup when this happened, then its a + // partial markup error. + if (inMarkup) + emitError(XMLErrs::PartialMarkupInEntity); + + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + + inMarkup = false; + } + } + + // It went ok, so return success + return true; +} + + +void IGXMLScanner::scanEndTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the end of the root element. + gotData = true; + + // Check if the element stack is empty. If so, then this is an unbalanced + // element (i.e. more ends than starts, perhaps because of bad text + // causing one to be skipped.) + if (fElemStack.isEmpty()) + { + emitError(XMLErrs::MoreEndThanStartTags); + fReaderMgr.skipPastChar(chCloseAngle); + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager); + } + + // Pop the stack of the element we are supposed to be ending. Remember + // that we don't own this. The stack just keeps them and reuses them. + unsigned int uriId = (fDoNamespaces) + ? fElemStack.getCurrentURI() : fEmptyNamespaceId; + + // these get initialized below + const ElemStack::StackElem* topElem = 0; + const XMLCh *elemName = 0; + + // Make sure that its the end of the element that we expect + // special case for schema validation, whose element decls, + // obviously don't contain prefix information + if(fGrammarType == Grammar::SchemaGrammarType) + { + elemName = fElemStack.getCurrentSchemaElemName(); + topElem = fElemStack.topElement(); + } + else + { + topElem = fElemStack.topElement(); + elemName = topElem->fThisElement->getFullName(); + } + if (!fReaderMgr.skippedStringLong(elemName)) + { + emitError + ( + XMLErrs::ExpectedEndOfTagX + , elemName + ); + fReaderMgr.skipPastChar(chCloseAngle); + fElemStack.popTop(); + return; + } + + // Make sure we are back on the same reader as where we started + if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialTagMarkupError); + + // Skip optional whitespace + fReaderMgr.skipPastSpaces(); + + // Make sure we find the closing bracket + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError + ( + XMLErrs::UnterminatedEndTag + , topElem->fThisElement->getFullName() + ); + } + + if (fGrammarType == Grammar::SchemaGrammarType) + { + // reset error occurred + fPSVIElemContext.fErrorOccurred = fErrorStack->pop(); + if (fValidate && topElem->fThisElement->isDeclared()) + { + fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo(); + if(!fPSVIElemContext.fCurrentTypeInfo) + fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + else + fPSVIElemContext.fCurrentDV = 0; + if(fPSVIHandler) + { + fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue(); + + if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString)) + fPSVIElemContext.fNormalizedValue = 0; + } + } + else + { + fPSVIElemContext.fCurrentDV = 0; + fPSVIElemContext.fCurrentTypeInfo = 0; + fPSVIElemContext.fNormalizedValue = 0; + } + } + + // If validation is enabled, then lets pass him the list of children and + // this element and let him validate it. + DatatypeValidator* psviMemberType = 0; + if (fValidate) + { + + // + // XML1.0-3rd + // Validity Constraint: + // The declaration matches EMPTY and the element has no content (not even + // entity references, comments, PIs or white space). + // + if ( (fGrammarType == Grammar::DTDGrammarType) && + (topElem->fCommentOrPISeen) && + (((DTDElementDecl*) topElem->fThisElement)->getModelType() == DTDElementDecl::Empty)) + { + fValidator->emitError + ( + XMLValid::EmptyElemHasContent + , topElem->fThisElement->getFullName() + ); + } + + // + // XML1.0-3rd + // Validity Constraint: + // + // The declaration matches children and the sequence of child elements + // belongs to the language generated by the regular expression in the + // content model, with optional white space, comments and PIs + // (i.e. markup matching production [27] Misc) between the start-tag and + // the first child element, between child elements, or between the last + // child element and the end-tag. + // + // Note that + // a CDATA section containing only white space or + // a reference to an entity whose replacement text is character references + // expanding to white space do not match the nonterminal S, and hence + // cannot appear in these positions; however, + // a reference to an internal entity with a literal value consisting + // of character references expanding to white space does match S, + // since its replacement text is the white space resulting from expansion + // of the character references. + // + if ( (fGrammarType == Grammar::DTDGrammarType) && + (topElem->fReferenceEscaped) && + (((DTDElementDecl*) topElem->fThisElement)->getModelType() == DTDElementDecl::Children)) + { + fValidator->emitError + ( + XMLValid::ElemChildrenHasInvalidWS + , topElem->fThisElement->getFullName() + ); + } + XMLSize_t failure; + bool res = fValidator->checkContent + ( + topElem->fThisElement + , topElem->fChildren + , topElem->fChildCount + , &failure + ); + + if (!res) + { + // One of the elements is not valid for the content. NOTE that + // if no children were provided but the content model requires + // them, it comes back with a zero value. But we cannot use that + // to index the child array in this case, and have to put out a + // special message. + if (!topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::EmptyNotValidForContent + , topElem->fThisElement->getFormattedContentModel() + ); + } + else if (failure >= topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::NotEnoughElemsForCM + , topElem->fThisElement->getFormattedContentModel() + ); + } + else + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , topElem->fChildren[failure]->getRawName() + , topElem->fThisElement->getFormattedContentModel() + ); + } + } + + + if (fGrammarType == Grammar::SchemaGrammarType) { + if (((SchemaValidator*) fValidator)->getErrorOccurred()) + fPSVIElemContext.fErrorOccurred = true; + else if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union) + psviMemberType = fValidationContext->getValidatingMemberType(); + + if (fPSVIHandler) + { + fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified(); + if(fPSVIElemContext.fIsSpecified) + fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)topElem->fThisElement)->getDefaultValue(); + } + + // call matchers and de-activate context + if (toCheckIdentityConstraint()) + { + fICHandler->deactivateContext + ( + (SchemaElementDecl *) topElem->fThisElement + , fContent.getRawBuffer() + , fValidationContext + , fPSVIElemContext.fCurrentDV + ); + } + + } + } + + // QName dv needed topElem to resolve URIs on the checkContent + fElemStack.popTop(); + + // See if it was the root element, to avoid multiple calls below + const bool isRoot = fElemStack.isEmpty(); + + if (fGrammarType == Grammar::SchemaGrammarType) + { + if (fPSVIHandler) + { + endElementPSVI( + (SchemaElementDecl*)topElem->fThisElement, psviMemberType); + } + // now we can reset the datatype buffer, since the + // application has had a chance to copy the characters somewhere else + ((SchemaValidator *)fValidator)->clearDatatypeBuffer(); + } + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + if (fGrammarType == Grammar::SchemaGrammarType) { + if (topElem->fPrefixColonPos != -1) + fPrefixBuf.set(elemName, topElem->fPrefixColonPos); + else + fPrefixBuf.reset(); + } + else { + fPrefixBuf.set(topElem->fThisElement->getElementName()->getPrefix()); + } + fDocHandler->endElement + ( + *topElem->fThisElement + , uriId + , isRoot + , fPrefixBuf.getRawBuffer() + ); + } + + if (fGrammarType == Grammar::SchemaGrammarType) { + if (!isRoot) + { + // update error information + fErrorStack->push((fErrorStack->size() && fErrorStack->pop()) || fPSVIElemContext.fErrorOccurred); + + + } + } + + // If this was the root, then done with content + gotData = !isRoot; + + if (gotData) { + if (fDoNamespaces) { + // Restore the grammar + fGrammar = fElemStack.getCurrentGrammar(); + fGrammarType = fGrammar->getGrammarType(); + if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) { + if (fValidatorFromUser) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + else { + fValidator = fSchemaValidator; + } + } + else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) { + if (fValidatorFromUser) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager); + else { + fValidator = fDTDValidator; + } + } + + fValidator->setGrammar(fGrammar); + } + + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } +} + + +// This method handles the high level logic of scanning the DOCType +// declaration. This calls the DTDScanner and kicks off both the scanning of +// the internal subset and the scanning of the external subset, if any. +// +// When we get here the 'resetDocType(); + + // There must be some space after DOCTYPE + bool skippedSomething; + fReaderMgr.skipPastSpaces(skippedSomething); + if (!skippedSomething) + { + emitError(XMLErrs::ExpectedWhitespace); + + // Just skip the Doctype declaration and return + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Get a buffer for the root element + XMLBufBid bbRootName(&fBufMgr); + + // Get a name from the input, which should be the name of the root + // element of the upcoming content. + int colonPosition; + bool validName = fDoNamespaces ? fReaderMgr.getQName(bbRootName.getBuffer(), &colonPosition) : + fReaderMgr.getName(bbRootName.getBuffer()); + if (!validName) + { + if (bbRootName.isEmpty()) + emitError(XMLErrs::NoRootElemInDOCTYPE); + else + emitError(XMLErrs::InvalidRootElemInDOCTYPE, bbRootName.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Store the root element name for later check + setRootElemName(bbRootName.getRawBuffer()); + + // This element obviously is not going to exist in the element decl + // pool yet, but we need to call docTypeDecl. So force it into + // the element decl pool, marked as being there because it was in + // the DOCTYPE. Later, when its declared, the status will be updated. + // + // Only do this if we are not reusing the validator! If we are reusing, + // then look it up instead. It has to exist! + MemoryManager* const rootDeclMgr = + fUseCachedGrammar ? fMemoryManager : fGrammarPoolMemoryManager; + + DTDElementDecl* rootDecl = new (rootDeclMgr) DTDElementDecl + ( + bbRootName.getRawBuffer() + , fEmptyNamespaceId + , DTDElementDecl::Any + , rootDeclMgr + ); + + Janitor rootDeclJanitor(rootDecl); + rootDecl->setCreateReason(DTDElementDecl::AsRootElem); + rootDecl->setExternalElemDeclaration(true); + if(!fUseCachedGrammar) + { + fGrammar->putElemDecl(rootDecl); + rootDeclJanitor.release(); + } else + { + // attach this to the undeclared element pool so that it gets deleted + XMLElementDecl* elemDecl = fDTDElemNonDeclPool->getByKey(bbRootName.getRawBuffer()); + if (elemDecl) + { + rootDecl->setId(elemDecl->getId()); + } + else + { + rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl)); + rootDeclJanitor.release(); + } + } + + // Skip any spaces after the name + fReaderMgr.skipPastSpaces(); + + // And now if we are looking at a >, then we are done. It is not + // required to have an internal or external subset, though why you + // would not escapes me. + if (fReaderMgr.skippedChar(chCloseAngle)) { + + // If we have a doc type handler and advanced callbacks are enabled, + // call the doctype event. + if (fDocTypeHandler) + fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false); + return; + } + + // either internal/external subset + if (fValScheme == Val_Auto && !fValidate) + fValidate = true; + + bool hasIntSubset = false; + bool hasExtSubset = false; + XMLCh* sysId = 0; + XMLCh* pubId = 0; + + DTDScanner dtdScanner + ( + (DTDGrammar*) fGrammar + , fDocTypeHandler + , fGrammarPoolMemoryManager + , fMemoryManager + ); + dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr); + + // If the next character is '[' then we have no external subset cause + // there is no system id, just the opening character of the internal + // subset. Else, has to be an id. + // + // Just look at the next char, don't eat it. + if (fReaderMgr.peekNextChar() == chOpenSquare) + { + hasIntSubset = true; + } + else + { + // Indicate we have an external subset + hasExtSubset = true; + fHasNoDTD = false; + + // Get buffers for the ids + XMLBufBid bbPubId(&fBufMgr); + XMLBufBid bbSysId(&fBufMgr); + + // Get the external subset id + if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External)) + { + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Get copies of the ids we got + pubId = XMLString::replicate(bbPubId.getRawBuffer(), fMemoryManager); + sysId = XMLString::replicate(bbSysId.getRawBuffer(), fMemoryManager); + + // Skip spaces and check again for the opening of an internal subset + fReaderMgr.skipPastSpaces(); + + // Just look at the next char, don't eat it. + if (fReaderMgr.peekNextChar() == chOpenSquare) { + hasIntSubset = true; + } + } + + // Insure that the ids get cleaned up, if they got allocated + ArrayJanitor janSysId(sysId, fMemoryManager); + ArrayJanitor janPubId(pubId, fMemoryManager); + + // If we have a doc type handler and advanced callbacks are enabled, + // call the doctype event. + if (fDocTypeHandler) + fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset); + + // Ok, if we had an internal subset, we are just past the [ character + // and need to parse that first. + if (hasIntSubset) + { + // Eat the opening square bracket + fReaderMgr.getNextChar(); + + checkInternalDTD(hasExtSubset, sysId, pubId); + + // And try to scan the internal subset. If we fail, try to recover + // by skipping forward tot he close angle and returning. + if (!dtdScanner.scanInternalSubset()) + { + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Do a sanity check that some expanded PE did not propogate out of + // the doctype. This could happen if it was terminated early by bad + // syntax. + if (fReaderMgr.getReaderDepth() > 1) + { + emitError(XMLErrs::PEPropogated); + + // Ask the reader manager to pop back down to the main level + fReaderMgr.cleanStackBackTo(1); + } + + fReaderMgr.skipPastSpaces(); + } + + // And that should leave us at the closing > of the DOCTYPE line + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + // Do a special check for the common scenario of an extra ] char at + // the end. This is easy to recover from. + if (fReaderMgr.skippedChar(chCloseSquare) + && fReaderMgr.skippedChar(chCloseAngle)) + { + emitError(XMLErrs::ExtraCloseSquare); + } + else + { + emitError(XMLErrs::UnterminatedDOCTYPE); + fReaderMgr.skipPastChar(chCloseAngle); + } + } + + // If we had an external subset, then we need to deal with that one + // next. If we are reusing the validator, then don't scan it. + if (hasExtSubset) { + + InputSource* srcUsed=0; + Janitor janSrc(srcUsed); + // If we had an internal subset and we're using the cached grammar, it + // means that the ignoreCachedDTD is set, so we ignore the cached + // grammar + if (fUseCachedGrammar && !hasIntSubset) + { + srcUsed = resolveSystemId(sysId, pubId); + if (srcUsed) { + janSrc.reset(srcUsed); + Grammar* grammar = fGrammarResolver->getGrammar(srcUsed->getSystemId()); + + if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType) { + + fDTDGrammar = (DTDGrammar*) grammar; + fGrammar = fDTDGrammar; + fValidator->setGrammar(fGrammar); + // If we don't report at least the external subset boundaries, + // an advanced document handler cannot know when the DTD end, + // since we've already sent a doctype decl that indicates there's + // there's an external subset. + if (fDocTypeHandler) + { + fDocTypeHandler->startExtSubset(); + fDocTypeHandler->endExtSubset(); + } + + return; + } + } + } + + if (fLoadExternalDTD || fValidate) + { + // And now create a reader to read this entity + XMLReader* reader; + if (srcUsed) { + reader = fReaderMgr.createReader + ( + *srcUsed + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + } + else { + reader = fReaderMgr.createReader + ( + sysId + , pubId + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , srcUsed + , fCalculateSrcOfs + , fLowWaterMark + , fDisableDefaultEntityResolution + ); + janSrc.reset(srcUsed); + } + // If it failed then throw an exception + if (!reader) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed ? srcUsed->getSystemId() : sysId, fMemoryManager); + + if (fToCacheGrammar) { + + unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId()); + const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId); + + fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString); + ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr); + fGrammarResolver->putGrammar(fGrammar); + } + + // In order to make the processing work consistently, we have to + // make this look like an external entity. So create an entity + // decl and fill it in and push it with the reader, as happens + // with an external entity. Put a janitor on it to insure it gets + // cleaned up. The reader manager does not adopt them. + const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull }; + DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); + declDTD->setSystemId(sysId); + declDTD->setIsExternal(true); + Janitor janDecl(declDTD); + + // Mark this one as a throw at end + reader->setThrowAtEnd(true); + + // And push it onto the stack, with its pseudo name + fReaderMgr.pushReader(reader, declDTD); + + // Tell it its not in an include section + dtdScanner.scanExtSubsetDecl(false, true); + } + } +} + +bool IGXMLScanner::scanStartTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Get the QName. In this case, we are not doing namespaces, so we just + // use it as is and don't have to break it into parts. + if (!fReaderMgr.getName(fQNameBuf)) + { + emitError(XMLErrs::ExpectedElementName); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // Assume it won't be an empty tag + bool isEmpty = false; + + // Lets try to look up the element in the validator's element decl pool + // We can pass bogus values for the URI id and the base name. We know that + // this can only be called if we are doing a DTD style validator and that + // he will only look at the QName. + // + // We tell him to fault in a decl if he does not find one. + // Actually, we *don't* tell him to fault in a decl if he does not find one- NG + bool wasAdded = false; + const XMLCh *rawQName = fQNameBuf.getRawBuffer(); + XMLElementDecl* elemDecl = fGrammar->getElemDecl + ( + fEmptyNamespaceId + , 0 + , rawQName + , Grammar::TOP_LEVEL_SCOPE + ); + // look for it in the undeclared pool: + if(!elemDecl) + { + elemDecl = fDTDElemNonDeclPool->getByKey(rawQName); + } + if(!elemDecl) + { + // we're assuming this must be a DTD element. DTD's can be + // used with or without namespaces, but schemas cannot be used without + // namespaces. + wasAdded = true; + elemDecl = new (fMemoryManager) DTDElementDecl + ( + rawQName + , fEmptyNamespaceId + , DTDElementDecl::Any + , fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } + + // We do something different here according to whether we found the + // element or not. + if (wasAdded) + { + // If validating then emit an error + if (fValidate) + { + // This is to tell the reuse Validator that this element was + // faulted-in, was not an element in the validator pool originally + elemDecl->setCreateReason(XMLElementDecl::JustFaultIn); + + fValidator->emitError + ( + XMLValid::ElementNotDefined + , elemDecl->getFullName() + ); + } + } + else + { + // If its not marked declared and validating, then emit an error + if (fValidate && !elemDecl->isDeclared()) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , elemDecl->getFullName() + ); + } + } + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Expand the element stack and add the new element + fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum()); + fElemStack.setValidationFlag(fValidate); + + // Validate the element + if (fValidate) + fValidator->validateElement(elemDecl); + + // If this is the first element and we are validating, check the root + // element. + if (isRoot) + { + fRootGrammar = fGrammar; + + if (fValidate) + { + // If a DocType exists, then check if it matches the root name there. + if (fRootElemName && !XMLString::equals(fQNameBuf.getRawBuffer(), fRootElemName)) + fValidator->emitError(XMLValid::RootElemNotLikeDocType); + } + } + else + { + // If the element stack is not empty, then add this element as a + // child of the previous top element. If its empty, this is the root + // elem and is not the child of anything. + fElemStack.addChild(elemDecl->getElementName(), true); + } + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // We loop until we either see a /> or >, handling attribute/value + // pairs until we get there. + XMLSize_t attCount = 0; + XMLSize_t curAttListSize = fAttrList->size(); + wasAdded = false; + + fElemCount++; + + while (true) + { + // And get the next non-space character + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + bool bFoundSpace; + fReaderMgr.skipPastSpaces(bFoundSpace); + if (!bFoundSpace) + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + // Ok, peek another char + nextCh = fReaderMgr.peekNextChar(); + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume its going to be an attribute, so get a name from + // the input. + if (!fReaderMgr.getName(fAttNameBuf)) + { + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.skipPastChar(chCloseAngle); + return false; + } + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + return false; + } + else + { + // Something went really wrong + return false; + } + } + // See if this attribute is declared for this element. If we are + // not validating of course it will not be at first, but we will + // fault it into the pool (to avoid lots of redundant errors.) + XMLCh * namePtr = fAttNameBuf.getRawBuffer(); + XMLAttDef* attDef = ((DTDElementDecl *)elemDecl)->getAttDef(namePtr); + + // Add this attribute to the attribute list that we use to + // pass them to the handler. We reuse its existing elements + // but expand it as required. + // Note that we want to this first since this will + // make a copy of the namePtr; we can then make use of + // that copy in the hashtable lookup that checks + // for duplicates. This will mean we may have to update + // the type of the XMLAttr later. + XMLAttr* curAtt; + if (attCount >= curAttListSize) + { + curAtt = new (fMemoryManager) XMLAttr + ( + 0 + , namePtr + , XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , (attDef)?attDef->getType():XMLAttDef::CData + , true + , fMemoryManager + ); + fAttrList->addElement(curAtt); + } + else + { + curAtt = fAttrList->elementAt(attCount); + curAtt->set + ( + 0 + , namePtr + , XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , (attDef)?attDef->getType():XMLAttDef::CData + ); + curAtt->setSpecified(true); + } + // reset namePtr so it refers to newly-allocated memory + namePtr = (XMLCh *)curAtt->getName(); + + if (!attDef) + { + // If there is a validation handler, then we are validating + // so emit an error. + if (fValidate) + { + fValidator->emitError + ( + XMLValid::AttNotDefinedForElement + , fAttNameBuf.getRawBuffer() + , elemDecl->getFullName() + ); + } + if(!fUndeclaredAttrRegistry->putIfNotPresent(namePtr, 0)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr + , elemDecl->getFullName() + ); + } + } + else + { + // prepare for duplicate detection + unsigned int *curCountPtr = fAttDefRegistry->get(attDef); + if(!curCountPtr) + { + curCountPtr = getNewUIntPtr(); + *curCountPtr = fElemCount; + fAttDefRegistry->put(attDef, curCountPtr); + } + else if(*curCountPtr < fElemCount) + *curCountPtr = fElemCount; + else + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , attDef->getFullName() + , elemDecl->getFullName() + ); + } + } + + // Skip any whitespace before the value and then scan the att + // value. This will come back normalized with entity refs and + // char refs expanded. + fReaderMgr.skipPastSpaces(); + if (!scanAttValue(attDef, namePtr, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + return false; + } + else + { + // Something went really wrong + return false; + } + } + // must set the newly-minted value on the XMLAttr: + curAtt->setValue(fAttValueBuf.getRawBuffer()); + + // Now that its all stretched out, lets look at its type and + // determine if it has a valid value. It will output any needed + // errors, but we just keep going. We only need to do this if + // we are validating. + if (attDef) + { + // Let the validator pass judgement on the attribute value + if (fValidate) + { + fValidator->validateAttrValue + ( + attDef + , fAttValueBuf.getRawBuffer() + , false + , elemDecl + ); + } + } + + attCount++; + // And jump back to the top of the loop + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + if(attCount) + { + // clean up after ourselves: + // clear the map used to detect duplicate attributes + fUndeclaredAttrRegistry->removeAll(); + } + + // Ok, so lets get an enumerator for the attributes of this element + // and run through them for well formedness and validity checks. But + // make sure that we had any attributes before we do it, since the list + // would have have gotten faulted in anyway. + if (elemDecl->hasAttDefs()) + { + // N.B.: this assumes DTD validation. + XMLAttDefList& attDefList = elemDecl->getAttDefList(); + for(XMLSize_t i=0; iget(&curDef); + if (!attCountPtr || *attCountPtr < fElemCount) + { // did not occur + if (fValidate) + { + // If we are validating and its required, then an error + if (defType == XMLAttDef::Required) + { + fValidator->emitError + ( + XMLValid::RequiredAttrNotProvided + , curDef.getFullName() + ); + } + else if ((defType == XMLAttDef::Default) || + (defType == XMLAttDef::Fixed) ) + { + if (fStandalone && curDef.isExternal()) + { + // XML 1.0 Section 2.9 + // Document is standalone, so attributes must not be defaulted. + fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName()); + + } + } + } + + // Fault in the value if needed, and bump the att count + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + // Let the validator pass judgement on the attribute value + if (fValidate) + { + fValidator->validateAttrValue + ( + &curDef + , curDef.getValue() + , false + , elemDecl + ); + } + + XMLAttr* curAtt; + if (attCount >= curAttListSize) + { + curAtt = new (fMemoryManager) XMLAttr + ( + 0 + , curDef.getFullName() + , XMLUni::fgZeroLenString + , curDef.getValue() + , curDef.getType() + , false + , fMemoryManager + ); + fAttrList->addElement(curAtt); + curAttListSize++; + } + else + { + curAtt = fAttrList->elementAt(attCount); + curAtt->set + ( + 0 + , curDef.getFullName() + , XMLUni::fgZeroLenString + , curDef.getValue() + , curDef.getType() + ); + curAtt->setSpecified(false); + } + attCount++; + } + } + } + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // If validating, then insure that its legal to have no content + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent(elemDecl, 0, 0, &failure); + if (!res) + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , elemDecl->getFullName() + , elemDecl->getFormattedContentModel() + ); + } + } + + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + else { + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } + } + + // If we have a document handler, then tell it about this start tag. We + // don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send + // any prefix since its just one big name if we are not doing namespaces. + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl + , fEmptyNamespaceId + , 0 + , *fAttrList + , attCount + , isEmpty + , isRoot + ); + } + + return true; +} + + +// This method is called to scan a start tag when we are processing +// namespaces. There are two different versions of this method, one for +// namespace aware processing and one for non-namespace aware processing. +// +// This method is called after we've scanned the < of a start tag. So we +// have to get the element name, then scan the attributes, after which +// we are either going to see >, />, or attributes followed by one of those +// sequences. +bool IGXMLScanner::scanStartTagNS(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Reset element content buffer + fContent.reset(); + + // The current position is after the open bracket, so we need to read in + // in the element name. + int prefixColonPos; + if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos)) + { + if (fQNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedElementName); + else + emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer()); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // First we have to do the rawest attribute scan. We don't do any + // normalization of them at all, since we don't know yet what type they + // might be (since we need the element decl in order to do that.) + bool isEmpty; + XMLSize_t attCount = rawAttrScan + ( + fQNameBuf.getRawBuffer() + , *fRawAttrList + , isEmpty + ); + + // save the contentleafname and currentscope before addlevel, for later use + ContentLeafNameTypeVector* cv = 0; + XMLContentModel* cm = 0; + unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE; + bool laxThisOne = false; + + if (!isRoot && fGrammarType == Grammar::SchemaGrammarType) + { + // schema validator will have correct type if validating + SchemaElementDecl* tempElement = (SchemaElementDecl*) + fElemStack.topElement()->fThisElement; + SchemaElementDecl::ModelTypes modelType = tempElement->getModelType(); + ComplexTypeInfo *currType = 0; + + if (fValidate) + { + currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if (currType) + modelType = (SchemaElementDecl::ModelTypes)currType->getContentType(); + else // something must have gone wrong + modelType = SchemaElementDecl::Any; + } + else + { + currType = tempElement->getComplexTypeInfo(); + } + + if ((modelType == SchemaElementDecl::Mixed_Simple) + || (modelType == SchemaElementDecl::Mixed_Complex) + || (modelType == SchemaElementDecl::Children)) + { + cm = currType->getContentModel(); + cv = cm->getContentLeafNameTypeVector(); + currentScope = fElemStack.getCurrentScope(); + } + else if (modelType == SchemaElementDecl::Any) { + laxThisOne = true; + } + } + + // Now, since we might have to update the namespace map for this element, + // but we don't have the element decl yet, we just tell the element stack + // to expand up to get ready. + XMLSize_t elemDepth = fElemStack.addLevel(); + fElemStack.setValidationFlag(fValidate); + fElemStack.setPrefixColonPos(prefixColonPos); + + // Check if there is any external schema location specified, and if we are at root, + // go through them first before scanning those specified in the instance document + if (isRoot && fDoSchema + && (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)) { + + if (fExternalSchemaLocation) + parseSchemaLocation(fExternalSchemaLocation, true); + if (fExternalNoNamespaceSchemaLocation) + resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true); + } + + // Make an initial pass through the list and find any xmlns attributes or + // schema attributes. + if (attCount) { + scanRawAttrListforNameSpaces(attCount); + } + + // Also find any default or fixed xmlns attributes in DTD defined for + // this element. + XMLElementDecl* elemDecl = 0; + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + + if (fGrammarType == Grammar::DTDGrammarType) { + + if (!fSkipDTDValidation) { + elemDecl = fGrammar->getElemDecl( + fEmptyNamespaceId, 0, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE + ); + + if (elemDecl) { + if (elemDecl->hasAttDefs()) { + XMLAttDefList& attDefList = elemDecl->getAttDefList(); + for(XMLSize_t i=0; igetByKey(qnameRawBuf); + } + } + + // Resolve the qualified name to a URI and name so that we can look up + // the element decl for this element. We have now update the prefix to + // namespace map so we should get the correct element now. + unsigned int uriId = resolveQNameWithColon( + qnameRawBuf, fPrefixBuf, ElemStack::Mode_Element, prefixColonPos + ); + + //if schema, check if we should lax or skip the validation of this element + bool parentValidation = fValidate; + if (cv) { + QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager); + // elementDepth will be > 0, as cv is only constructed if element is not + // root. + laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1); + } + + // Look up the element now in the grammar. This will get us back a + // generic element decl object. We tell him to fault one in if he does + // not find it. + bool wasAdded = false; + const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1]; + + if (fDoSchema) { + + if (fGrammarType == Grammar::DTDGrammarType) { + if (!switchGrammar(getURIText(uriId))) { + fValidator->emitError( + XMLValid::GrammarNotFound, getURIText(uriId) + ); + } + } + + if (fGrammarType == Grammar::SchemaGrammarType) { + elemDecl = fGrammar->getElemDecl( + uriId, nameRawBuf, qnameRawBuf, currentScope + ); + + // if not found, then it may be a reference, try TOP_LEVEL_SCOPE + if (!elemDecl) { + bool checkTopLevel = (currentScope != Grammar::TOP_LEVEL_SCOPE); + const XMLCh* original_uriStr = fGrammar->getTargetNamespace(); + unsigned int orgGrammarUri = fURIStringPool->getId(original_uriStr); + + if (orgGrammarUri != uriId) { + if (switchGrammar(getURIText(uriId))) { + checkTopLevel = true; + } + else { + // the laxElementValidation routine (called above) will + // set fValidate to false for a "skipped" element + if (!laxThisOne && fValidate) { + fValidator->emitError( + XMLValid::GrammarNotFound, getURIText(uriId) + ); + } + checkTopLevel = false; + } + } + + if (checkTopLevel) { + elemDecl = fGrammar->getElemDecl( + uriId, nameRawBuf, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE + ); + } + + if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) { + + if (orgGrammarUri == uriId) { + // still not found in specified uri + // try emptyNamespace see if element should be + // un-qualified. + // Use a temp variable until we decide this is the case + if (uriId != fEmptyNamespaceId) { + XMLElementDecl* tempElemDecl = fGrammar->getElemDecl( + fEmptyNamespaceId, nameRawBuf, qnameRawBuf, currentScope + ); + + if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) { + fValidator->emitError( + XMLValid::ElementNotUnQualified, qnameRawBuf + ); + elemDecl = tempElemDecl; + } + } + } + // still Not found in specified uri + // go to original Grammar again to see if element needs + // to be fully qualified. + // Use a temp variable until we decide this is the case + else if (uriId == fEmptyNamespaceId) { + + if (switchGrammar(original_uriStr)) { + XMLElementDecl* tempElemDecl = fGrammar->getElemDecl( + orgGrammarUri, nameRawBuf, qnameRawBuf, currentScope + ); + if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) { + fValidator->emitError( + XMLValid::ElementNotQualified, qnameRawBuf + ); + elemDecl = tempElemDecl; + } + } + else if (!laxThisOne && fValidate) { + fValidator->emitError( + XMLValid::GrammarNotFound,original_uriStr + ); + } + } + } + + if (!elemDecl) { + // still not found + // switch back to original grammar first if necessary + if (orgGrammarUri != uriId) { + switchGrammar(original_uriStr); + } + + // look in the list of undeclared elements, as would have been + // done before we made grammars stateless: + elemDecl = fSchemaElemNonDeclPool->getByKey( + nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE + ); + } + } + } + } + + if (!elemDecl) { + + if (fGrammarType == Grammar::DTDGrammarType) { + elemDecl = new (fMemoryManager) DTDElementDecl( + qnameRawBuf, uriId, DTDElementDecl::Any, fMemoryManager + ); + elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl)); + } + else if (fGrammarType == Grammar::SchemaGrammarType) { + elemDecl = new (fMemoryManager) SchemaElementDecl( + fPrefixBuf.getRawBuffer(), nameRawBuf, uriId + , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId( + fSchemaElemNonDeclPool->put((void*)elemDecl->getBaseName() + , uriId, (int)Grammar::TOP_LEVEL_SCOPE, (SchemaElementDecl*)elemDecl) + ); + } else { + fValidator->emitError( + XMLValid::GrammarNotFound, getURIText(uriId) + ); + } + wasAdded = true; + } + + // this info needed for DOMTypeInfo + fPSVIElemContext.fErrorOccurred = false; + + // We do something different here according to whether we found the + // element or not. + bool bXsiTypeSet= (fValidator && fGrammarType == Grammar::SchemaGrammarType)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false; + if (wasAdded) + { + if (laxThisOne && !bXsiTypeSet) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + else if (fValidate) + { + // If validating then emit an error + + // This is to tell the reuse Validator that this element was + // faulted-in, was not an element in the grammar pool originally + elemDecl->setCreateReason(XMLElementDecl::JustFaultIn); + + // xsi:type was specified, don't complain about missing definition + if(!bXsiTypeSet) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , elemDecl->getFullName() + ); + + if(fGrammarType == Grammar::SchemaGrammarType) + { + fPSVIElemContext.fErrorOccurred = true; + } + } + } + } + else + { + // If its not marked declared and validating, then emit an error + if (!elemDecl->isDeclared()) { + if(elemDecl->getCreateReason() == XMLElementDecl::NoReason) { + if(!bXsiTypeSet && fGrammarType == Grammar::SchemaGrammarType) { + fPSVIElemContext.fErrorOccurred = true; + } + } + + if (laxThisOne) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + else if (fValidate && !bXsiTypeSet) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , elemDecl->getFullName() + ); + } + } + } + + // Now we can update the element stack to set the current element + // decl. We expanded the stack above, but couldn't store the element + // decl because we didn't know it yet. + fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum()); + fElemStack.setCurrentURI(uriId); + + if (isRoot) + { + fRootGrammar = fGrammar; + if (fGrammarType == Grammar::SchemaGrammarType && !fRootElemName) + fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager); + } + + if (fGrammarType == Grammar::SchemaGrammarType && fPSVIHandler) + { + + fPSVIElemContext.fElemDepth++; + if (elemDecl->isDeclared()) + { + fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth; + } + else + { + fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth; + + /****** + * While we report an error for historical reasons, this should + * actually result in lax assessment - NG. + if (isRoot && fValidate) + fPSVIElemContext.fErrorOccurred = true; + *****/ + } + } + + // Validate the element + if (fValidate) + { + fValidator->validateElement(elemDecl); + if (fValidator->handlesSchema()) + { + if (((SchemaValidator*) fValidator)->getErrorOccurred()) + fPSVIElemContext.fErrorOccurred = true; + } + } + + if (fGrammarType == Grammar::SchemaGrammarType) { + + // squirrel away the element's QName, so that we can do an efficient + // end-tag match + fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer()); + + ComplexTypeInfo* typeinfo = (fValidate) + ? ((SchemaValidator*)fValidator)->getCurrentTypeInfo() + : ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo(); + + if (typeinfo) { + currentScope = typeinfo->getScopeDefined(); + + // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type) + XMLCh* typeName = typeinfo->getTypeName(); + const int comma = XMLString::indexOf(typeName, chComma); + if (comma > 0) { + XMLBuffer prefixBuf(comma+1, fMemoryManager); + prefixBuf.append(typeName, comma); + const XMLCh* uriStr = prefixBuf.getRawBuffer(); + + bool errorCondition = !switchGrammar(uriStr) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + , prefixBuf.getRawBuffer() + ); + } + } + else if (comma == 0) { + bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + , XMLUni::fgZeroLenString + ); + } + } + } + fElemStack.setCurrentScope(currentScope); + + // Set element next state + if (elemDepth >= fElemStateSize) { + resizeElemState(); + } + + fElemState[elemDepth] = 0; + fElemLoopState[elemDepth] = 0; + } + + fElemStack.setCurrentGrammar(fGrammar); + + // If this is the first element and we are validating, check the root + // element. + if (isRoot) + { + if (fValidate) + { + // If a DocType exists, then check if it matches the root name there. + if (fRootElemName && !XMLString::equals(qnameRawBuf, fRootElemName)) + fValidator->emitError(XMLValid::RootElemNotLikeDocType); + } + } + else if (parentValidation) + { + // If the element stack is not empty, then add this element as a + // child of the previous top element. If its empty, this is the root + // elem and is not the child of anything. + fElemStack.addChild(elemDecl->getElementName(), true); + } + + // PSVI handling: even if it turns out there are + // no attributes, we need to reset this list... + if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType ) + fPSVIAttrList->reset(); + + // Now lets get the fAttrList filled in. This involves faulting in any + // defaulted and fixed attributes and normalizing the values of any that + // we got explicitly. + // + // We update the attCount value with the total number of attributes, but + // it goes in with the number of values we got during the raw scan of + // explictly provided attrs above. + attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList); + if(attCount) + { + // clean up after ourselves: + // clear the map used to detect duplicate attributes + fUndeclaredAttrRegistry->removeAll(); + } + + // activate identity constraints + if (fGrammar && + fGrammarType == Grammar::SchemaGrammarType && + toCheckIdentityConstraint()) + { + fICHandler->activateIdentityConstraint + ( + (SchemaElementDecl*) elemDecl + , (int) elemDepth + , uriId + , fPrefixBuf.getRawBuffer() + , *fAttrList + , attCount + , fValidationContext + ); + } + + // Since the element may have default values, call start tag now regardless if it is empty or not + // If we have a document handler, then tell it about this start tag + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl + , uriId + , fPrefixBuf.getRawBuffer() + , *fAttrList + , attCount + , false + , isRoot + ); + } + + // if we have a PSVIHandler, now's the time to call + // its handleAttributesPSVI method: + if(fPSVIHandler && fGrammarType == Grammar::SchemaGrammarType) + { + QName *eName = elemDecl->getElementName(); + fPSVIHandler->handleAttributesPSVI + ( + eName->getLocalPart() + , fURIStringPool->getValueForId(eName->getURI()) + , fPSVIAttrList + ); + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // reset current type info + DatatypeValidator* psviMemberType = 0; + if (fGrammarType == Grammar::SchemaGrammarType) + { + if (fValidate && elemDecl->isDeclared()) + { + fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo(); + if(!fPSVIElemContext.fCurrentTypeInfo) + fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + else + fPSVIElemContext.fCurrentDV = 0; + if(fPSVIHandler) + { + fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue(); + + if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString)) + fPSVIElemContext.fNormalizedValue = 0; + } + } + else + { + fPSVIElemContext.fCurrentDV = 0; + fPSVIElemContext.fCurrentTypeInfo = 0; + fPSVIElemContext.fNormalizedValue = 0; + } + } + + // If validating, then insure that its legal to have no content + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent(elemDecl, 0, 0, &failure); + if (!res) + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , elemDecl->getFullName() + , elemDecl->getFormattedContentModel() + ); + } + + if (fGrammarType == Grammar::SchemaGrammarType) { + + if (((SchemaValidator*) fValidator)->getErrorOccurred()) + { + fPSVIElemContext.fErrorOccurred = true; + } + else + { + if (fPSVIHandler) + { + fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified(); + if(fPSVIElemContext.fIsSpecified) + fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue(); + } + // note that if we're empty, won't be a current DV + if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union) + psviMemberType = fValidationContext->getValidatingMemberType(); + } + + // call matchers and de-activate context + if (toCheckIdentityConstraint()) + { + fICHandler->deactivateContext + ( + (SchemaElementDecl *) elemDecl + , fContent.getRawBuffer() + , fValidationContext + , fPSVIElemContext.fCurrentDV + ); + } + + } + } + else if (fGrammarType == Grammar::SchemaGrammarType) { + ((SchemaValidator*)fValidator)->resetNillable(); + } + + if (fGrammarType == Grammar::SchemaGrammarType) + { + if (fPSVIHandler) + { + endElementPSVI((SchemaElementDecl*)elemDecl, psviMemberType); + } + } + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + fDocHandler->endElement + ( + *elemDecl + , uriId + , isRoot + , fPrefixBuf.getRawBuffer() + ); + } + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + else + { + // Restore the grammar + fGrammar = fElemStack.getCurrentGrammar(); + fGrammarType = fGrammar->getGrammarType(); + if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) { + if (fValidatorFromUser) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + else { + fValidator = fSchemaValidator; + } + } + else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) { + if (fValidatorFromUser) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager); + else { + fValidator = fDTDValidator; + } + } + + fValidator->setGrammar(fGrammar); + + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } + } + else if (fGrammarType == Grammar::SchemaGrammarType) + { + // send a partial element psvi + if (fPSVIHandler) + { + + ComplexTypeInfo* curTypeInfo = 0; + DatatypeValidator* curDV = 0; + XSTypeDefinition* typeDef = 0; + + if (fValidate && elemDecl->isDeclared()) + { + curTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo(); + + if (curTypeInfo) + { + typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo); + } + else + { + curDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + + if (curDV) + { + typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV); + } + } + } + + fPSVIElement->reset + ( + PSVIElement::VALIDITY_NOTKNOWN + , PSVIElement::VALIDATION_NONE + , fRootElemName + , ((SchemaValidator*) fValidator)->getIsElemSpecified() + , (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0 + , typeDef + , 0 //memberType + , fModel + , ((SchemaElementDecl*)elemDecl)->getDefaultValue() + , 0 + , 0 + , 0 + ); + + + fPSVIHandler->handlePartialElementPSVI + ( + elemDecl->getBaseName() + , fURIStringPool->getValueForId(elemDecl->getURI()) + , fPSVIElement + ); + + } + + // not empty + fErrorStack->push(fPSVIElemContext.fErrorOccurred); + } + + return true; +} + + +// --------------------------------------------------------------------------- +// IGXMLScanner: Helper methos +// --------------------------------------------------------------------------- +void IGXMLScanner::resizeElemState() { + + unsigned int newSize = fElemStateSize * 2; + unsigned int* newElemState = (unsigned int*) fMemoryManager->allocate + ( + newSize * sizeof(unsigned int) + ); //new unsigned int[newSize]; + unsigned int* newElemLoopState = (unsigned int*) fMemoryManager->allocate + ( + newSize * sizeof(unsigned int) + ); //new unsigned int[newSize]; + + // Copy the existing values + unsigned int index = 0; + for (; index < fElemStateSize; index++) + { + newElemState[index] = fElemState[index]; + newElemLoopState[index] = fElemLoopState[index]; + } + + for (; index < newSize; index++) + newElemLoopState[index] = newElemState[index] = 0; + + // Delete the old array and udpate our members + fMemoryManager->deallocate(fElemState); //delete [] fElemState; + fMemoryManager->deallocate(fElemLoopState); //delete [] fElemState; + fElemState = newElemState; + fElemLoopState = newElemLoopState; + fElemStateSize = newSize; +} + +void IGXMLScanner::resizeRawAttrColonList() { + + unsigned int newSize = fRawAttrColonListSize * 2; + int* newRawAttrColonList = (int*) fMemoryManager->allocate + ( + newSize * sizeof(int) + ); //new int[newSize]; + + // Copy the existing values + unsigned int index = 0; + for (; index < fRawAttrColonListSize; index++) + newRawAttrColonList[index] = fRawAttrColonList[index]; + + // Delete the old array and udpate our members + fMemoryManager->deallocate(fRawAttrColonList); //delete [] fRawAttrColonList; + fRawAttrColonList = newRawAttrColonList; + fRawAttrColonListSize = newSize; +} + +// --------------------------------------------------------------------------- +// IGXMLScanner: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* IGXMLScanner::loadGrammar(const InputSource& src + , const short grammarType + , const bool toCache) +{ + Grammar* loadedGrammar = 0; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + fGrammarResolver->cacheGrammarFromParse(false); + // if the new grammar has to be cached, better use the already cached + // grammars, or the an exception will be thrown when caching an already + // cached grammar + fGrammarResolver->useCachedGrammarInParse(toCache); + fRootGrammar = 0; + + if (fValScheme == Val_Auto) { + fValidate = true; + } + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + fSeeXsi = false; + + if (grammarType == Grammar::SchemaGrammarType) { + loadedGrammar = loadXMLSchemaGrammar(src, toCache); + } + else if (grammarType == Grammar::DTDGrammarType) { + loadedGrammar = loadDTDGrammar(src, toCache); + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + return loadedGrammar; +} + +void IGXMLScanner::resetCachedGrammar () +{ + fCachedSchemaInfoList->removeAll (); +} + +Grammar* IGXMLScanner::loadDTDGrammar(const InputSource& src, + const bool toCache) +{ + // Reset the validators + fDTDValidator->reset(); + if (fValidatorFromUser) + fValidator->reset(); + + if (!fValidator->handlesDTD()) { + if (fValidatorFromUser && fValidate) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager); + else { + fValidator = fDTDValidator; + } + } + + fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString); + + if (fDTDGrammar) { + fDTDGrammar->reset(); + } + else { + fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager); + fGrammarResolver->putGrammar(fDTDGrammar); + } + + fGrammar = fDTDGrammar; + fGrammarType = fGrammar->getGrammarType(); + fValidator->setGrammar(fGrammar); + + // And for all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Clear out the id reference list + resetValidationContext(); + // and clear out the darned undeclared DTD element pool... + fDTDElemNonDeclPool->removeAll(); + + if (toCache) { + + unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId()); + const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId); + + fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString); + ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr); + fGrammarResolver->putGrammar(fGrammar); + } + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // In order to make the processing work consistently, we have to + // make this look like an external entity. So create an entity + // decl and fill it in and push it with the reader, as happens + // with an external entity. Put a janitor on it to insure it gets + // cleaned up. The reader manager does not adopt them. + const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull }; + DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); + declDTD->setSystemId(src.getSystemId()); + declDTD->setIsExternal(true); + Janitor janDecl(declDTD); + + // Mark this one as a throw at end + newReader->setThrowAtEnd(true); + + // And push it onto the stack, with its pseudo name + fReaderMgr.pushReader(newReader, declDTD); + + // If we have a doc type handler and advanced callbacks are enabled, + // call the doctype event. + if (fDocTypeHandler) { + + // Create a dummy root + DTDElementDecl* rootDecl = new (fGrammarPoolMemoryManager) DTDElementDecl + ( + gDTDStr + , fEmptyNamespaceId + , DTDElementDecl::Any + , fGrammarPoolMemoryManager + ); + rootDecl->setCreateReason(DTDElementDecl::AsRootElem); + rootDecl->setExternalElemDeclaration(true); + Janitor janSrc(rootDecl); + + fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true); + } + + // Create DTDScanner + DTDScanner dtdScanner + ( + (DTDGrammar*) fGrammar + , fDocTypeHandler + , fGrammarPoolMemoryManager + , fMemoryManager + ); + dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr); + + // Tell it its not in an include section + dtdScanner.scanExtSubsetDecl(false, true); + + if (fValidate) { + // validate the DTD scan so far + fValidator->preContentValidation(false, true); + } + + if (toCache) + fGrammarResolver->cacheGrammars(); + + return fDTDGrammar; +} + +// --------------------------------------------------------------------------- +// IGXMLScanner: Helper methods +// --------------------------------------------------------------------------- +void IGXMLScanner::processSchemaLocation(XMLCh* const schemaLoc) +{ + XMLCh* locStr = schemaLoc; + XMLReader* curReader = fReaderMgr.getCurrentReader(); + + fLocationPairs->removeAllElements(); + while (*locStr) + { + do { + // Do we have an escaped character ? + if (*locStr == 0xFFFF) + continue; + + if (!curReader->isWhitespace(*locStr)) + break; + + *locStr = chNull; + } while (*++locStr); + + if (*locStr) { + + fLocationPairs->addElement(locStr); + + while (*++locStr) { + // Do we have an escaped character ? + if (*locStr == 0xFFFF) + continue; + if (curReader->isWhitespace(*locStr)) + break; + } + } + } +} + +void IGXMLScanner::endElementPSVI(SchemaElementDecl* const elemDecl, + DatatypeValidator* const memberDV) +{ + PSVIElement::ASSESSMENT_TYPE validationAttempted; + PSVIElement::VALIDITY_STATE validity = PSVIElement::VALIDITY_NOTKNOWN; + + if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fFullValidationDepth) + validationAttempted = PSVIElement::VALIDATION_FULL; + else if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fNoneValidationDepth) + validationAttempted = PSVIElement::VALIDATION_NONE; + else + { + validationAttempted = PSVIElement::VALIDATION_PARTIAL; + fPSVIElemContext.fFullValidationDepth = + fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth - 1; + } + + if (fValidate && elemDecl->isDeclared()) + { + validity = (fPSVIElemContext.fErrorOccurred) + ? PSVIElement::VALIDITY_INVALID : PSVIElement::VALIDITY_VALID; + } + + XSTypeDefinition* typeDef = 0; + bool isMixed = false; + if (fPSVIElemContext.fCurrentTypeInfo) + { + typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentTypeInfo); + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes)fPSVIElemContext.fCurrentTypeInfo->getContentType(); + isMixed = (modelType == SchemaElementDecl::Mixed_Simple + || modelType == SchemaElementDecl::Mixed_Complex); + } + else if (fPSVIElemContext.fCurrentDV) + typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentDV); + + XMLCh* canonicalValue = 0; + if (fPSVIElemContext.fNormalizedValue && !isMixed && + validity == PSVIElement::VALIDITY_VALID) + { + if (memberDV) + canonicalValue = (XMLCh*) memberDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager); + else if (fPSVIElemContext.fCurrentDV) + canonicalValue = (XMLCh*) fPSVIElemContext.fCurrentDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager); + } + + fPSVIElement->reset + ( + validity + , validationAttempted + , fRootElemName + , fPSVIElemContext.fIsSpecified + , (elemDecl->isDeclared()) + ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0 + , typeDef + , (memberDV) ? (XSSimpleTypeDefinition*) fModel->getXSObject(memberDV) : 0 + , fModel + , elemDecl->getDefaultValue() + , fPSVIElemContext.fNormalizedValue + , canonicalValue + ); + + fPSVIHandler->handleElementPSVI + ( + elemDecl->getBaseName() + , fURIStringPool->getValueForId(elemDecl->getURI()) + , fPSVIElement + ); + + // decrease element depth + fPSVIElemContext.fElemDepth--; + +} + +void IGXMLScanner::resetPSVIElemContext() +{ + fPSVIElemContext.fIsSpecified = false; + fPSVIElemContext.fErrorOccurred = false; + fPSVIElemContext.fElemDepth = -1; + fPSVIElemContext.fFullValidationDepth = -1; + fPSVIElemContext.fNoneValidationDepth = -1; + fPSVIElemContext.fCurrentDV = 0; + fPSVIElemContext.fCurrentTypeInfo = 0; + fPSVIElemContext.fNormalizedValue = 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/IGXMLScanner.hpp b/include/xercesc/internal/IGXMLScanner.hpp new file mode 100644 index 0000000..5123f98 --- /dev/null +++ b/include/xercesc/internal/IGXMLScanner.hpp @@ -0,0 +1,308 @@ +/* + * 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: IGXMLScanner.hpp 882548 2009-11-20 13:44:14Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IGXMLSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_IGXMLSCANNER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DTDElementDecl; +class DTDGrammar; +class DTDValidator; +class SchemaValidator; +class IdentityConstraintHandler; +class IdentityConstraint; +class ContentLeafNameTypeVector; +class SchemaAttDef; +class XMLContentModel; +class XSModel; +class PSVIAttributeList; +class PSVIElement; + +// This is an integrated scanner class, which does DTD/XML Schema grammar +// processing. +class XMLPARSER_EXPORT IGXMLScanner : public XMLScanner +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + IGXMLScanner + ( + XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + IGXMLScanner + ( + XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~IGXMLScanner(); + + // ----------------------------------------------------------------------- + // XMLScanner public virtual methods + // ----------------------------------------------------------------------- + virtual const XMLCh* getName() const; + virtual NameIdPool* getEntityDeclPool(); + virtual const NameIdPool* getEntityDeclPool() const; + virtual void scanDocument + ( + const InputSource& src + ); + virtual bool scanNext(XMLPScanToken& toFill); + virtual Grammar* loadGrammar + ( + const InputSource& src + , const short grammarType + , const bool toCache = false + ); + + virtual void resetCachedGrammar (); + virtual Grammar::GrammarType getCurrentGrammarType() const; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IGXMLScanner(); + IGXMLScanner(const IGXMLScanner&); + IGXMLScanner& operator=(const IGXMLScanner&); + + // ----------------------------------------------------------------------- + // XMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual void scanCDSection(); + virtual void scanCharData(XMLBuffer& toToUse); + virtual EntityExpRes scanEntityRef + ( + const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped + ); + virtual void scanDocTypeDecl(); + virtual void scanReset(const InputSource& src); + virtual void sendCharData(XMLBuffer& toSend); + virtual InputSource* resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void commonInit(); + void cleanUp(); + + XMLSize_t buildAttList + ( + const RefVectorOf& providedAttrs + , const XMLSize_t attCount + , XMLElementDecl* elemDecl + , RefVectorOf& toFill + ); + bool normalizeAttValue + ( + const XMLAttDef* const attDef + , const XMLCh* const name + , const XMLCh* const value + , XMLBuffer& toFill + ); + bool normalizeAttRawValue + ( + const XMLCh* const attrName + , const XMLCh* const value + , XMLBuffer& toFill + ); + void updateNSMap + ( + const XMLCh* const attrName + , const XMLCh* const attrValue + ); + void updateNSMap + ( + const XMLCh* const attrName + , const XMLCh* const attrValue + , const int colonPosition + ); + void scanRawAttrListforNameSpaces(XMLSize_t attCount); + void parseSchemaLocation(const XMLCh* const schemaLocationStr, bool ignoreLoadSchema = false); + void resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema = false); + bool switchGrammar(const XMLCh* const newGrammarNameSpace); + bool laxElementValidation(QName* element, ContentLeafNameTypeVector* cv, + const XMLContentModel* const cm, + const XMLSize_t parentElemDepth); + bool anyAttributeValidation(SchemaAttDef* attWildCard, + unsigned int uriId, + bool& skipThisOne, + bool& laxThisOne); + void resizeElemState(); + void processSchemaLocation(XMLCh* const schemaLoc); + + void resizeRawAttrColonList(); + + // ----------------------------------------------------------------------- + // Private scanning methods + // ----------------------------------------------------------------------- + bool basicAttrValueScan + ( + const XMLCh* const attrName + , XMLBuffer& toFill + ); + XMLSize_t rawAttrScan + ( + const XMLCh* const elemName + , RefVectorOf& toFill + , bool& isEmpty + ); + bool scanAttValue + ( + const XMLAttDef* const attDef + , const XMLCh* const attrName + , XMLBuffer& toFill + ); + bool scanContent(); + void scanEndTag(bool& gotData); + bool scanStartTag(bool& gotData); + bool scanStartTagNS(bool& gotData); + + // ----------------------------------------------------------------------- + // IdentityConstraints Activation methods + // ----------------------------------------------------------------------- + inline bool toCheckIdentityConstraint() const; + + // ----------------------------------------------------------------------- + // Grammar preparsing methods + // ----------------------------------------------------------------------- + Grammar* loadXMLSchemaGrammar(const InputSource& src, const bool toCache = false); + Grammar* loadDTDGrammar(const InputSource& src, const bool toCache = false); + + // ----------------------------------------------------------------------- + // PSVI handling methods + // ----------------------------------------------------------------------- + void endElementPSVI(SchemaElementDecl* const elemDecl, + DatatypeValidator* const memberDV); + void resetPSVIElemContext(); + + // ----------------------------------------------------------------------- + // Data members + // + // fRawAttrList + // During the initial scan of the attributes we can only do a raw + // scan for key/value pairs. So this vector is used to store them + // until they can be processed (and put into fAttrList.) + // + // fDTDValidator + // The DTD validator instance. + // + // fSchemaValidator + // The Schema validator instance. + // + // fSeeXsi + // This flag indicates a schema has been seen. + // + // fElemState + // fElemLoopState + // fElemStateSize + // Stores an element next state from DFA content model - used for + // wildcard validation + // + // fDTDElemNonDeclPool + // registry of "faulted-in" DTD element decls + // fSchemaElemNonDeclPool + // registry for elements without decls in the grammar + // fElemCount + // count of the number of start tags seen so far (starts at 1). + // Used for duplicate attribute detection/processing of required/defaulted attributes + // fAttDefRegistry + // mapping from XMLAttDef instances to the count of the last + // start tag where they were utilized. + // fUndeclaredAttrRegistry + // set of attr QNames to detect duplicates + // fPSVIAttrList + // PSVI attribute list implementation that needs to be + // filled when a PSVIHandler is registered + // fSchemaInfoList + // Transient schema info list that is passed to TraverseSchema instances. + // fCachedSchemaInfoList + // Cached Schema info list that is passed to TraverseSchema instances. + // + // ----------------------------------------------------------------------- + bool fSeeXsi; + Grammar::GrammarType fGrammarType; + unsigned int fElemStateSize; + unsigned int* fElemState; + unsigned int* fElemLoopState; + XMLBuffer fContent; + RefVectorOf* fRawAttrList; + unsigned int fRawAttrColonListSize; + int* fRawAttrColonList; + DTDValidator* fDTDValidator; + SchemaValidator* fSchemaValidator; + DTDGrammar* fDTDGrammar; + IdentityConstraintHandler* fICHandler; + ValueVectorOf* fLocationPairs; + NameIdPool* fDTDElemNonDeclPool; + RefHash3KeysIdPool* fSchemaElemNonDeclPool; + unsigned int fElemCount; + RefHashTableOf*fAttDefRegistry; + Hash2KeysSetOf* fUndeclaredAttrRegistry; + PSVIAttributeList * fPSVIAttrList; + XSModel* fModel; + PSVIElement* fPSVIElement; + ValueStackOf* fErrorStack; + PSVIElemContext fPSVIElemContext; + RefHash2KeysTableOf* fSchemaInfoList; + RefHash2KeysTableOf* fCachedSchemaInfoList; +}; + +inline const XMLCh* IGXMLScanner::getName() const +{ + return XMLUni::fgIGXMLScanner; +} + +inline bool IGXMLScanner::toCheckIdentityConstraint() const +{ + return fValidate && fIdentityConstraintChecking && fICHandler; +} + +inline Grammar::GrammarType IGXMLScanner::getCurrentGrammarType() const +{ + return fGrammarType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/IGXMLScanner2.cpp b/include/xercesc/internal/IGXMLScanner2.cpp new file mode 100644 index 0000000..2eccadf --- /dev/null +++ b/include/xercesc/internal/IGXMLScanner2.cpp @@ -0,0 +1,3479 @@ +/* + * 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: IGXMLScanner2.cpp 1662894 2015-02-28 02:41:57Z scantor $ + */ + +// --------------------------------------------------------------------------- +// This file holds some of the grunt work methods of IGXMLScanner.cpp to keep +// it a little more readable. +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +inline XMLAttDefList& getAttDefList(bool isSchemaGrammar + , ComplexTypeInfo* currType + , XMLElementDecl* elemDecl); + +// --------------------------------------------------------------------------- +// IGXMLScanner: Private helper methods +// --------------------------------------------------------------------------- + +// This method is called from scanStartTagNS() to build up the list of +// XMLAttr objects that will be passed out in the start tag callout. We +// get the key/value pairs from the raw scan of explicitly provided attrs, +// which have not been normalized. And we get the element declaration from +// which we will get any defaulted or fixed attribute defs and add those +// in as well. +XMLSize_t +IGXMLScanner::buildAttList(const RefVectorOf& providedAttrs + , const XMLSize_t attCount + , XMLElementDecl* elemDecl + , RefVectorOf& toFill) +{ + // If doing DTD's, Ask the element to clear the 'provided' flag on all of the att defs + // that it owns, and to return us a boolean indicating whether it has + // any defs. If schemas are being validated, the complexType + // at the top of the SchemaValidator's stack will + // know what's best. REVISIT: don't modify grammar at all; eliminate + // this step... + ComplexTypeInfo *currType = 0; + DatatypeValidator *currDV = 0; + if(fGrammar->getGrammarType() == Grammar::SchemaGrammarType && fValidate) + { + currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if (!currType) { + currDV = ((SchemaValidator*)fValidator)->getCurrentDatatypeValidator(); + } + } + + const bool hasDefs = (currType && fValidate) + ? currType->hasAttDefs() + : elemDecl->hasAttDefs(); + + // another set of attributes; increment element counter + fElemCount++; + + // If there are no expliclitily provided attributes and there are no + // defined attributes for the element, the we don't have anything to do. + // So just return zero in this case. + if (!hasDefs && !attCount) + return 0; + + // Keep up with how many attrs we end up with total + XMLSize_t retCount = 0; + + // And get the current size of the output vector. This lets us use + // existing elements until we fill it, then start adding new ones. + const XMLSize_t curAttListSize = toFill.size(); + + // We need a buffer into which raw scanned attribute values will be + // normalized. + XMLBufBid bbNormal(&fBufMgr); + XMLBuffer& normBuf = bbNormal.getBuffer(); + + // + // Decide if to use hash table to do duplicate checking + // + bool toUseHashTable = false; + if (fGrammarType == Grammar::DTDGrammarType) + { + setAttrDupChkRegistry(attCount, toUseHashTable); + } + + XMLBufBid bbPrefix(&fBufMgr); + XMLBuffer& prefixBuf = bbPrefix.getBuffer(); + + // Loop through our explicitly provided attributes, which are in the raw + // scanned form, and build up XMLAttr objects. + XMLSize_t index; + const XMLCh* prefPtr, *suffPtr; + for (index = 0; index < attCount; index++) + { + PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID; + PSVIItem::ASSESSMENT_TYPE attrAssessed = PSVIItem::VALIDATION_FULL; + const KVStringPair* curPair = providedAttrs.elementAt(index); + + // We have to split the name into its prefix and name parts. Then + // we map the prefix to its URI. + const XMLCh* const namePtr = curPair->getKey(); + + const int colonInd = fRawAttrColonList[index]; + unsigned int uriId; + if (colonInd != -1) + { + prefixBuf.set(namePtr, colonInd); + prefPtr = prefixBuf.getRawBuffer(); + suffPtr = namePtr + colonInd + 1; + // Map the prefix to a URI id + uriId = resolvePrefix(prefPtr, ElemStack::Mode_Attribute); + } + else + { + // No colon, so we just have a name with no prefix + prefPtr = XMLUni::fgZeroLenString; + suffPtr = namePtr; + // an empty prefix is always the empty namespace, when dealing with attributes + uriId = fEmptyNamespaceId; + } + + // If the uri comes back as the xmlns or xml URI or its just a name + // and that name is 'xmlns', then we handle it specially. So set a + // boolean flag that lets us quickly below know which we are dealing + // with. + const bool isNSAttr = (uriId == fEmptyNamespaceId)? + XMLString::equals(suffPtr, XMLUni::fgXMLNSString) : + (uriId == fXMLNSNamespaceId || XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI)); + + + // If its not a special case namespace attr of some sort, then we + // do normal checking and processing. + XMLAttDef::AttTypes attType = XMLAttDef::CData; + DatatypeValidator *attrValidator = 0; + PSVIAttribute *psviAttr = 0; + bool otherXSI = false; + + if (isNSAttr && fGrammarType == Grammar::SchemaGrammarType) + { + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + else + { + bool ValueValidate = false; + bool tokenizeBuffer = false; + + if (uriId == fXMLNSNamespaceId) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI); + } + else if (XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI)) + { + if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL)) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN); + + ValueValidate = true; + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCATION)) + { + // use anyURI as the validator + // tokenize the data and use the anyURI data for each piece + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI); + //We should validate each value in the schema location however + //this lead to a performance degradation of around 4%. Since + //the first value of each pair needs to match what is in the + //schema document and the second value needs to be valid in + //order to open the document we won't validate it. Need to + //do performance analysis of the anyuri datatype. + //ValueValidate = true; + ValueValidate = false; + tokenizeBuffer = true; + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION)) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI); + //We should validate this value however + //this lead to a performance degradation of around 4%. Since + //the value needs to be valid in + //order to open the document we won't validate it. Need to + //do performance analysis of the anyuri datatype. + //ValueValidate = true; + ValueValidate = false; + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE)) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME); + + ValueValidate = true; + } + else { + otherXSI = true; + } + } + + if (!otherXSI) { + normalizeAttRawValue + ( + namePtr + , curPair->getValue() + , normBuf + ); + + if (fValidate && attrValidator && ValueValidate) + { + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(attrValidator, normBuf.getRawBuffer(), normBuf, true); + + ValidationContext* const theContext = + getValidationContext(); + + if (theContext) + { + try + { + if (tokenizeBuffer) { + XMLStringTokenizer tokenizer(normBuf.getRawBuffer(), fMemoryManager); + while (tokenizer.hasMoreTokens()) { + attrValidator->validate( + tokenizer.nextToken(), + theContext, + fMemoryManager); + } + } + else { + attrValidator->validate( + normBuf.getRawBuffer(), + theContext, + fMemoryManager); + } + } + catch (const XMLException& idve) + { + fValidator->emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); + } + } + } + + if(getPSVIHandler()) + { + psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); + XSSimpleTypeDefinition *validatingType = (attrValidator) + ? (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator) + : 0; + // no attribute declarations for these... + psviAttr->reset( + fRootElemName + , PSVIItem::VALIDITY_NOTKNOWN + , PSVIItem::VALIDATION_NONE + , validatingType + , 0 + , 0 + , false + , 0 + , attrValidator + ); + } + } + } + } + + if (!isNSAttr || fGrammarType == Grammar::DTDGrammarType || otherXSI) + { + // Some checking for attribute wild card first (for schema) + bool laxThisOne = false; + bool skipThisOne = false; + + XMLAttDef* attDefForWildCard = 0; + XMLAttDef* attDef = 0; + + if (fGrammarType == Grammar::SchemaGrammarType) { + + //retrieve the att def + SchemaAttDef* attWildCard = 0; + if (currType) { + attDef = currType->getAttDef(suffPtr, uriId); + attWildCard = currType->getAttWildCard(); + } + else if (!currDV) { // check explicitly-set wildcard + attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, uriId); + attWildCard = ((SchemaElementDecl*)elemDecl)->getAttWildCard(); + } + + // if not found or faulted in - check for a matching wildcard attribute + // if no matching wildcard attribute, check (un)qualifed cases and flag + // appropriate errors + if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn)) { + + if (attWildCard) { + //if schema, see if we should lax or skip the validation of this attribute + if (anyAttributeValidation(attWildCard, uriId, skipThisOne, laxThisOne)) { + + if(!skipThisOne) + { + SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(getURIText(uriId)); + if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType) { + RefHashTableOf* attRegistry = sGrammar->getAttributeDeclRegistry(); + if (attRegistry) { + attDefForWildCard = attRegistry->get(suffPtr); + } + } + } + } + } + else if (currType) { + // not found, see if the attDef should be qualified or not + if (uriId == fEmptyNamespaceId) { + attDef = currType->getAttDef(suffPtr + , fURIStringPool->getId(fGrammar->getTargetNamespace())); + if (fValidate + && attDef + && attDef->getCreateReason() != XMLAttDef::JustFaultIn) { + // the attribute should be qualified + fValidator->emitError + ( + XMLValid::AttributeNotQualified + , attDef->getFullName() + ); + if(fGrammarType == Grammar::SchemaGrammarType) { + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + { + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + } + } + else { + attDef = currType->getAttDef(suffPtr + , fEmptyNamespaceId); + if (fValidate + && attDef + && attDef->getCreateReason() != XMLAttDef::JustFaultIn) { + // the attribute should be qualified + fValidator->emitError + ( + XMLValid::AttributeNotUnQualified + , attDef->getFullName() + ); + if(fGrammarType == Grammar::SchemaGrammarType) { + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + { + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + } + } + } + } + } + + // Find this attribute within the parent element. We pass both + // the uriID/name and the raw QName buffer, since we don't know + // how the derived validator and its elements store attributes. + else + { + if(fGrammarType == Grammar::DTDGrammarType) + attDef = ((DTDElementDecl *)elemDecl)->getAttDef ( namePtr); + } + + // now need to prepare for duplicate detection + if(attDef) + { + unsigned int *curCountPtr = fAttDefRegistry->get(attDef); + if(!curCountPtr) + { + curCountPtr = getNewUIntPtr(); + *curCountPtr = fElemCount; + fAttDefRegistry->put(attDef, curCountPtr); + } + else if(*curCountPtr < fElemCount) + *curCountPtr = fElemCount; + else + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , attDef->getFullName() + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + } + else + { + if(fGrammarType == Grammar::DTDGrammarType) + { + if(!fUndeclaredAttrRegistry->putIfNotPresent(namePtr, 0)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr + , elemDecl->getFullName() + ); + } + } + else // schema grammar + { + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + } + } + + if(fGrammarType == Grammar::SchemaGrammarType ) + { + // if we've found either an attDef or an attDefForWildCard, + // then we're doing full validation and it may still be valid. + if(!attDef && !attDefForWildCard) + { + if(!laxThisOne && !skipThisOne) + { + fPSVIElemContext.fErrorOccurred = true; + } + if(getPSVIHandler()) + { + if(!laxThisOne && !skipThisOne) + { + attrValid = PSVIItem::VALIDITY_INVALID; + } + else if(laxThisOne) + { + attrValid = PSVIItem::VALIDITY_NOTKNOWN; + attrAssessed = PSVIItem::VALIDATION_PARTIAL; + } + else + { + attrValid = PSVIItem::VALIDITY_NOTKNOWN; + attrAssessed = PSVIItem::VALIDATION_NONE; + } + } + } + } + + bool errorCondition = fValidate && !attDefForWildCard && !attDef; + if (errorCondition && !skipThisOne && !laxThisOne) + { + // + // Its not valid for this element, so issue an error if we are + // validating. + // + XMLBufBid bbMsg(&fBufMgr); + XMLBuffer& bufMsg = bbMsg.getBuffer(); + if (uriId != fEmptyNamespaceId) { + XMLBufBid bbURI(&fBufMgr); + XMLBuffer& bufURI = bbURI.getBuffer(); + + getURIText(uriId, bufURI); + + bufMsg.append(chOpenCurly); + bufMsg.append(bufURI.getRawBuffer()); + bufMsg.append(chCloseCurly); + } + bufMsg.append(suffPtr); + fValidator->emitError + ( + XMLValid::AttNotDefinedForElement + , bufMsg.getRawBuffer() + , elemDecl->getFullName() + ); + } + + // Now normalize the raw value since we have the attribute type. We + // don't care about the return status here. If it failed, an error + // was issued, which is all we care about. + if (attDefForWildCard) { + normalizeAttValue( + attDefForWildCard, namePtr, curPair->getValue(), normBuf + ); + + // If we found an attdef for this one, then lets validate it. + const XMLCh* xsNormalized = normBuf.getRawBuffer(); + DatatypeValidator* tempDV = ((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the attribute according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf, true); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + + if (fNormalizeData && fValidate) { + normBuf.set(xsNormalized); + } + } + + if (fValidate ) { + fValidator->validateAttrValue( + attDefForWildCard, xsNormalized, false, elemDecl + ); + attrValidator = ((SchemaValidator*)fValidator)->getMostRecentAttrValidator(); + if(((SchemaValidator *)fValidator)->getErrorOccurred()) + { + fPSVIElemContext.fErrorOccurred = true; + if(getPSVIHandler()) + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + else { // no decl; default DOMTypeInfo to anySimpleType + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + + // Save the type for later use + attType = attDefForWildCard->getType(); + } + else { + normalizeAttValue( + attDef, namePtr, curPair->getValue(), normBuf + ); + + // If we found an attdef for this one, then lets validate it. + if (attDef) + { + const XMLCh* xsNormalized = normBuf.getRawBuffer(); + if (fGrammarType == Grammar::SchemaGrammarType) + { + DatatypeValidator* tempDV = ((SchemaAttDef*) attDef)->getDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the attribute according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf, true); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + if (fNormalizeData && fValidate && !skipThisOne) { + normBuf.set(xsNormalized); + } + } + } + + if (fValidate && !skipThisOne) + { + fValidator->validateAttrValue( + attDef, xsNormalized, false, elemDecl + ); + + if(fGrammarType == Grammar::SchemaGrammarType) + { + attrValidator = ((SchemaValidator*)fValidator)->getMostRecentAttrValidator(); + if(((SchemaValidator *)fValidator)->getErrorOccurred()) + { + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + } + else if(fGrammarType == Grammar::SchemaGrammarType) { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + } + else // no attDef at all; default to anySimpleType + { + if(fGrammarType == Grammar::SchemaGrammarType) { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + } + + // Save the type for later use + if (attDef) + { + attType = attDef->getType(); + } + } + + // now fill in the PSVIAttributes entry for this attribute: + if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType) + { + psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); + SchemaAttDef *actualAttDef = 0; + if(attDef) + actualAttDef = (SchemaAttDef *)attDef; + else if (attDefForWildCard) + actualAttDef = (SchemaAttDef *)attDefForWildCard; + if(actualAttDef) + { + XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef); + DatatypeValidator * attrDataType = actualAttDef->getDatatypeValidator(); + XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType); + if(attrValid != PSVIItem::VALIDITY_VALID) + { + psviAttr->reset + ( + fRootElemName + , attrValid + , attrAssessed + , validatingType + , 0 + , actualAttDef->getValue() + , false + , attrDecl + , 0 + ); + } + else + { + XSSimpleTypeDefinition *memberType = 0; + if(validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION) + memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator); + psviAttr->reset + ( + fRootElemName + , attrValid + , attrAssessed + , validatingType + , memberType + , actualAttDef->getValue() + , false + , attrDecl + , (memberType)?attrValidator:attrDataType + ); + } + } + else + { + psviAttr->reset + ( + fRootElemName + , attrValid + , attrAssessed + , 0 + , 0 + , 0 + , false + , 0 + , 0 + ); + } + } + } + + // Add this attribute to the attribute list that we use to pass them + // to the handler. We reuse its existing elements but expand it as + // required. + XMLAttr* curAttr; + + // check for duplicate namespace attributes: + // by checking for qualified names with the same local part and with prefixes + // which have been bound to namespace names that are identical. + if (fGrammarType == Grammar::DTDGrammarType) { + if (!toUseHashTable) + { + for (XMLSize_t attrIndex=0; attrIndex < retCount; attrIndex++) { + curAttr = toFill.elementAt(attrIndex); + if (uriId == curAttr->getURIId() && + XMLString::equals(suffPtr, curAttr->getName())) { + emitError + ( + + XMLErrs::AttrAlreadyUsedInSTag + , curAttr->getName() + , elemDecl->getFullName() + ); + } + } + } + else + { + if (fAttrDupChkRegistry->containsKey((void*)suffPtr, uriId)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , suffPtr + , elemDecl->getFullName() + ); + } + } + } + + if (retCount >= curAttListSize) + { + curAttr = new (fMemoryManager) XMLAttr + ( + uriId + , suffPtr + , prefPtr + , normBuf.getRawBuffer() + , attType + , true + , fMemoryManager + ); + toFill.addElement(curAttr); + } + else + { + curAttr = toFill.elementAt(retCount); + curAttr->set + ( + uriId + , suffPtr + , prefPtr + , normBuf.getRawBuffer() + , attType + ); + curAttr->setSpecified(true); + } + + if (toUseHashTable) + { + fAttrDupChkRegistry->put((void*)suffPtr, uriId, curAttr); + } + + if(psviAttr) + psviAttr->setValue(curAttr->getValue()); + + // Bump the count of attrs in the list + retCount++; + } + + // Now, if there are any attributes declared by this element, let's + // go through them and make sure that any required ones are provided, + // and fault in any fixed ones and defaulted ones that are not provided + // literally. + if (hasDefs) + { + // Check after all specified attrs are scanned + // (1) report error for REQUIRED attrs that are missing (V_TAGc) + // (2) add default attrs if missing (FIXED and NOT_FIXED) + + + XMLAttDefList &attDefList = getAttDefList(fGrammarType == Grammar::SchemaGrammarType, currType, elemDecl); + + for(XMLSize_t i=0; igetDefaultType(); + unsigned int *attCountPtr = fAttDefRegistry->get((void *)curDef); + if (!attCountPtr || *attCountPtr < fElemCount) + { // did not occur + // note that since there is no attribute information + // item present, there is no PSVI infoset to augment here *except* + // that the element is invalid + + //the attribute is not provided + if (fValidate) + { + // If we are validating and its required, then an error + if ((defType == XMLAttDef::Required) || + (defType == XMLAttDef::Required_And_Fixed) ) + + { + fValidator->emitError + ( + XMLValid::RequiredAttrNotProvided + , curDef->getFullName() + ); + if(fGrammarType == Grammar::SchemaGrammarType) + { + fPSVIElemContext.fErrorOccurred = true; + } + } + else if ((defType == XMLAttDef::Default) || + (defType == XMLAttDef::Fixed) ) + { + if (fStandalone && curDef->isExternal()) + { + // XML 1.0 Section 2.9 + // Document is standalone, so attributes must not be defaulted. + fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef->getFullName(), elemDecl->getFullName()); + if(fGrammarType == Grammar::SchemaGrammarType) + { + fPSVIElemContext.fErrorOccurred = true; + } + } + } + } + + // Fault in the value if needed, and bump the att count. + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + // Let the validator pass judgement on the attribute value + if (fValidate) + { + fValidator->validateAttrValue + ( + curDef + , curDef->getValue() + , false + , elemDecl + ); + } + + XMLAttr* curAtt; + if (retCount >= curAttListSize) + { + curAtt = new (fMemoryManager) XMLAttr(fMemoryManager); + fValidator->faultInAttr(*curAtt, *curDef); + fAttrList->addElement(curAtt); + } + else + { + curAtt = fAttrList->elementAt(retCount); + fValidator->faultInAttr(*curAtt, *curDef); + } + + if (fGrammarType == Grammar::DTDGrammarType) + { + // Map the new attribute's prefix to a URI id and store + // that in the attribute object. + curAtt->setURIId + ( + resolvePrefix(curAtt->getPrefix(), ElemStack::Mode_Attribute) + ); + } + + // Indicate it was not explicitly specified and bump count + curAtt->setSpecified(false); + retCount++; + if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType) + { + QName *attName = ((SchemaAttDef *)curDef)->getAttName(); + PSVIAttribute *defAttrToFill = fPSVIAttrList->getPSVIAttributeToFill + ( + attName->getLocalPart(), fURIStringPool->getValueForId( attName->getURI()) + ); + XSAttributeDeclaration *defAttrDecl = (XSAttributeDeclaration *)fModel->getXSObject((void *)curDef); + DatatypeValidator * attrDataType = ((SchemaAttDef *)curDef)->getDatatypeValidator(); + XSSimpleTypeDefinition *defAttrType = + (XSSimpleTypeDefinition*)fModel->getXSObject(attrDataType); + // would have occurred during validation of default value + if(((SchemaValidator *)fValidator)->getErrorOccurred()) + { + defAttrToFill->reset( + fRootElemName + , PSVIItem::VALIDITY_INVALID + , PSVIItem::VALIDATION_FULL + , defAttrType + , 0 + , curDef->getValue() + , true + , defAttrDecl + , 0 + ); + } + else + { + XSSimpleTypeDefinition *defAttrMemberType = 0; + if(defAttrType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION) + { + defAttrMemberType = (XSSimpleTypeDefinition *)fModel->getXSObject + ( + ((SchemaValidator*)fValidator)->getMostRecentAttrValidator() + ); + } + defAttrToFill->reset( + fRootElemName + , PSVIItem::VALIDITY_VALID + , PSVIItem::VALIDATION_FULL + , defAttrType + , defAttrMemberType + , curDef->getValue() + , true + , defAttrDecl + , (defAttrMemberType)?((SchemaValidator *)fValidator)->getMostRecentAttrValidator():attrDataType + ); + } + defAttrToFill->setValue(curDef->getValue()); + } + } + } + else if(attCountPtr) + { + //attribute is provided + // (schema) report error for PROHIBITED attrs that are present (V_TAGc) + if (defType == XMLAttDef::Prohibited && fValidate) + { + fValidator->emitError + ( + XMLValid::ProhibitedAttributePresent + , curDef->getFullName() + ); + if(fGrammarType == Grammar::SchemaGrammarType) + { + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + { + QName *attQName = ((SchemaAttDef *)curDef)->getAttName(); + // bad luck... + PSVIAttribute *prohibitedAttr = fPSVIAttrList->getAttributePSVIByName + ( + attQName->getLocalPart(), + fURIStringPool->getValueForId(attQName->getURI()) + ); + prohibitedAttr->updateValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + } + } + return retCount; +} + + +// This method will take a raw attribute value and normalize it according to +// the rules of the attribute type. It will put the resulting value into the +// passed buffer. +// +// This code assumes that escaped characters in the original value (via char +// refs) are prefixed by a 0xFFFF character. This is because some characters +// are legal if escaped only. And some escape chars are not subject to +// normalization rules. +bool IGXMLScanner::normalizeAttValue( const XMLAttDef* const attDef + , const XMLCh* const attName + , const XMLCh* const value + , XMLBuffer& toFill) +{ + // A simple state value for a whitespace processing state machine + enum States + { + InWhitespace + , InContent + }; + + // Get the type and name + const XMLAttDef::AttTypes type = (attDef)?attDef->getType():XMLAttDef::CData; + + // Assume its going to go fine, and empty the target buffer in preperation + bool retVal = true; + toFill.reset(); + + // Loop through the chars of the source value and normalize it according + // to the type. + XMLCh nextCh; + const XMLCh* srcPtr = value; + + if (type == XMLAttDef::CData || type > XMLAttDef::Notation) { + // Get the next character from the source. We have to watch for + // escaped characters (which are indicated by a 0xFFFF value followed + // by the char that was escaped.) + while ((nextCh = *srcPtr++)!=0) + { + switch(nextCh) + { + // Do we have an escaped character ? + case 0xFFFF: + nextCh = *srcPtr++; + break; + case 0x09: + case 0x0A: + case 0x0D: + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && attDef && attDef->isExternal()) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attName); + } + nextCh = chSpace; + break; + case chOpenAngle: + // If its not escaped, then make sure its not a < character, which is + // not allowed in attribute values. + emitError(XMLErrs::BracketInAttrValue, attName); + retVal = false; + break; + } + + // Add this char to the target buffer + toFill.append(nextCh); + } + } + else { + States curState = InContent; + bool firstNonWS = false; + // Get the next character from the source. We have to watch for + // escaped characters (which are indicated by a 0xFFFF value followed + // by the char that was escaped.) + while ((nextCh = *srcPtr)!=0) + { + // Do we have an escaped character ? + if (nextCh == 0xFFFF) + { + nextCh = *++srcPtr; + } + else if (nextCh == chOpenAngle) { + // If its not escaped, then make sure its not a < character, which is + // not allowed in attribute values. + emitError(XMLErrs::BracketInAttrValue, attName); + retVal = false; + } + + if (curState == InWhitespace) + { + if (!fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + if (firstNonWS) + toFill.append(chSpace); + curState = InContent; + firstNonWS = true; + } + else + { + srcPtr++; + continue; + } + } + else if (curState == InContent) + { + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + curState = InWhitespace; + srcPtr++; + + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && attDef && attDef->isExternal()) + { + if (!firstNonWS || (nextCh != chSpace) || (!*srcPtr) || fReaderMgr.getCurrentReader()->isWhitespace(*srcPtr)) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attName); + } + } + continue; + } + firstNonWS = true; + } + + // Add this char to the target buffer + toFill.append(nextCh); + + // And move up to the next character in the source + srcPtr++; + } + } + + return retVal; +} + +// This method will just normalize the input value as CDATA without +// any standalone checking. +bool IGXMLScanner::normalizeAttRawValue( const XMLCh* const attrName + , const XMLCh* const value + , XMLBuffer& toFill) +{ + // Assume its going to go fine, and empty the target buffer in preperation + bool retVal = true; + toFill.reset(); + + // Loop through the chars of the source value and normalize it according + // to the type. + bool escaped; + XMLCh nextCh; + const XMLCh* srcPtr = value; + while (*srcPtr) + { + // Get the next character from the source. We have to watch for + // escaped characters (which are indicated by a 0xFFFF value followed + // by the char that was escaped.) + nextCh = *srcPtr; + escaped = (nextCh == 0xFFFF); + if (escaped) + nextCh = *++srcPtr; + + // If its not escaped, then make sure its not a < character, which is + // not allowed in attribute values. + if (!escaped && (*srcPtr == chOpenAngle)) + { + emitError(XMLErrs::BracketInAttrValue, attrName); + retVal = false; + } + + if (!escaped) + { + // NOTE: Yes this is a little redundant in that a 0x20 is + // replaced with an 0x20. But its faster to do this (I think) + // than checking for 9, A, and D separately. + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + nextCh = chSpace; + } + + // Add this char to the target buffer + toFill.append(nextCh); + + // And move up to the next character in the source + srcPtr++; + } + return retVal; +} + +// This method will reset the scanner data structures, and related plugged +// in stuff, for a new scan session. We get the input source for the primary +// XML entity, create the reader for it, and push it on the stack so that +// upon successful return from here we are ready to go. +void IGXMLScanner::scanReset(const InputSource& src) +{ + // This call implicitly tells us that we are going to reuse the scanner + // if it was previously used. So tell the validator to reset itself. + // + // But, if the fUseCacheGrammar flag is set, then don't reset it. + // + // NOTE: The ReaderMgr is flushed on the way out, because that is + // required to insure that files are closed. + fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar); + fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar); + + // Clear transient schema info list. + // + fSchemaInfoList->removeAll (); + + // fModel may need updating, as fGrammarResolver could have cleaned it + if(getPSVIHandler()) + fModel = fGrammarResolver->getXSModel(); + + { + XMLDTDDescriptionImpl theDTDDescription(XMLUni::fgDTDEntityString, fMemoryManager); + fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(&theDTDDescription); + } + + if (!fDTDGrammar) { + + fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager); + fGrammarResolver->putGrammar(fDTDGrammar); + } + else + fDTDGrammar->reset(); + + fGrammar = fDTDGrammar; + fGrammarType = fGrammar->getGrammarType(); + fRootGrammar = 0; + + if (fValidatorFromUser) { + if (fValidator->handlesDTD()) + fValidator->setGrammar(fGrammar); + else if (fValidator->handlesSchema()) { + + ((SchemaValidator*) fValidator)->setErrorReporter(fErrorReporter); + ((SchemaValidator*) fValidator)->setGrammarResolver(fGrammarResolver); + ((SchemaValidator*) fValidator)->setExitOnFirstFatal(fExitOnFirstFatal); + } + } + else { + // set fValidator as fDTDValidator + fValidator = fDTDValidator; + fValidator->setGrammar(fGrammar); + } + + // Reset validation + fValidate = (fValScheme == Val_Always) ? true : false; + + // Ignore skipDTDValidation flag if no schema processing is taking place */ + fSkipDTDValidation = fSkipDTDValidation && fDoSchema; + + // And for all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Clear out the id reference list + resetValidationContext(); + + // Reset the Root Element Name + fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName; + fRootElemName = 0; + + // Reset IdentityConstraints + if (fICHandler) + fICHandler->reset(); + + // Reset the element stack, and give it the latest ids for the special + // URIs it has to know about. + fElemStack.reset + ( + fEmptyNamespaceId + , fUnknownNamespaceId + , fXMLNamespaceId + , fXMLNSNamespaceId + ); + + if (!fSchemaNamespaceId) + fSchemaNamespaceId = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI); + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + fSeeXsi = false; + + // Reset PSVI context + // note that we always need this around for DOMTypeInfo + if (!fPSVIElement) + fPSVIElement = new (fMemoryManager) PSVIElement(fMemoryManager); + + if (!fErrorStack) + { + fErrorStack = new (fMemoryManager) ValueStackOf(8, fMemoryManager); + } + else + { + fErrorStack->removeAllElements(); + } + + resetPSVIElemContext(); + + // Reset the validators + fDTDValidator->reset(); + fDTDValidator->setErrorReporter(fErrorReporter); + fSchemaValidator->reset(); + fSchemaValidator->setErrorReporter(fErrorReporter); + fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal); + fSchemaValidator->setGrammarResolver(fGrammarResolver); + if (fValidatorFromUser) + fValidator->reset(); + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , true + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // Push this read onto the reader manager + fReaderMgr.pushReader(newReader, 0); + + // and reset security-related things if necessary: + if(fSecurityManager != 0) + { + fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit(); + fEntityExpansionCount = 0; + } + fElemCount = 0; + if(fUIntPoolRowTotal >= 32) + { // 8 KB tied up with validating attributes... + fAttDefRegistry->removeAll(); + recreateUIntPool(); + } + else + { + // note that this will implicitly reset the values of the hashtables, + // though their buckets will still be tied up + resetUIntPool(); + } + fUndeclaredAttrRegistry->removeAll(); + fDTDElemNonDeclPool->removeAll(); +} + + +// This method is called between markup in content. It scans for character +// data that is sent to the document handler. It watches for any markup +// characters that would indicate that the character data has ended. It also +// handles expansion of general and character entities. +// +// sendData() is a local static helper for this method which handles some +// code that must be done in three different places here. +void IGXMLScanner::sendCharData(XMLBuffer& toSend) +{ + // If no data in the buffer, then nothing to do + if (toSend.isEmpty()) + return; + + // We do different things according to whether we are validating or + // not. If not, its always just characters; else, it depends on the + // current element's content model. + if (fValidate) + { + // Get the raw data we need for the callback + const XMLCh* rawBuf = toSend.getRawBuffer(); + XMLSize_t len = toSend.getLen(); + + // And see if the current element is a 'Children' style content model + const ElemStack::StackElem* topElem = fElemStack.topElement(); + + // Get the character data opts for the current element + XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData; + if(fGrammar->getGrammarType() == Grammar::SchemaGrammarType) + { + // And see if the current element is a 'Children' style content model + ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if(currType) + { + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType(); + if(modelType == SchemaElementDecl::Children || + modelType == SchemaElementDecl::ElementOnlyEmpty) + charOpts = XMLElementDecl::SpacesOk; + else if(modelType == SchemaElementDecl::Empty) + charOpts = XMLElementDecl::NoCharData; + } + } else // DTD grammar + charOpts = topElem->fThisElement->getCharDataOpts(); + + if (charOpts == XMLElementDecl::NoCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + //if(fGrammarType == Grammar::SchemaGrammarType) + //{ + // if (getPSVIHandler()) + // { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + // } + // } + } + else if (fReaderMgr.getCurrentReader()->isAllSpaces(rawBuf, len)) + { + // Its all spaces. So, if they can take spaces, then send it + // as ignorable whitespace. If they can handle any char data + // send it as characters. + if (charOpts == XMLElementDecl::SpacesOk) { + if (fDocHandler) + fDocHandler->ignorableWhitespace(rawBuf, len, false); + } + else if (charOpts == XMLElementDecl::AllCharData) + { + if (fGrammarType != Grammar::SchemaGrammarType) + { + if (fDocHandler) + fDocHandler->docCharacters(rawBuf, len, false); + } + else + { + XMLSize_t xsLen; + const XMLCh* xsNormalized; + SchemaValidator *schemaValidator = (SchemaValidator *)fValidator; + DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the character according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, fWSNormalizeBuf); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + xsLen = fWSNormalizeBuf.getLen(); + } + else { + xsNormalized = rawBuf; + xsLen = len ; + } + + // tell the schema validation about the character data for checkContent later + schemaValidator->setDatatypeBuffer(xsNormalized); + + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) { + fContent.append(xsNormalized, xsLen); + } + + if (fDocHandler) { + if (fNormalizeData) { + fDocHandler->docCharacters(xsNormalized, xsLen, false); + } + else { + fDocHandler->docCharacters(rawBuf, len, false); + } + } + } + } + } + else + { + // If they can take any char data, then send it. Otherwise, they + // can only handle whitespace and can't handle this stuff so + // issue an error. + if (charOpts == XMLElementDecl::AllCharData) + { + if (fGrammarType != Grammar::SchemaGrammarType) + { + if (fDocHandler) + fDocHandler->docCharacters(rawBuf, len, false); + } + else + { + XMLSize_t xsLen; + const XMLCh* xsNormalized; + SchemaValidator *schemaValidator = (SchemaValidator*)fValidator; + DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the character according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, fWSNormalizeBuf); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + xsLen = fWSNormalizeBuf.getLen(); + } + else { + xsNormalized = rawBuf; + xsLen = len; + } + + // tell the schema validation about the character data for checkContent later + schemaValidator->setDatatypeBuffer(xsNormalized); + + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) { + fContent.append(xsNormalized, xsLen); + } + + if (fDocHandler) { + if (fNormalizeData) { + fDocHandler->docCharacters(xsNormalized, xsLen, false); + } + else { + fDocHandler->docCharacters(rawBuf, len, false); + } + } + } + } + else + { + fValidator->emitError(XMLValid::NoCharDataInCM); + if(fGrammarType == Grammar::SchemaGrammarType) + { + if (getPSVIHandler()) + { + // REVISIT: + // PSVIAttribute->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + } + else + { + // call all active identity constraints + if (fGrammarType == Grammar::SchemaGrammarType) { + + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) + fContent.append(toSend.getRawBuffer(), toSend.getLen()); + } + + // Always assume its just char data if not validating + if (fDocHandler) + fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false); + } + + // Reset buffer + toSend.reset(); +} + + + +// This method is called with a key/value string pair that represents an +// xmlns="yyy" or xmlns:xxx="yyy" attribute. This method will update the +// current top of the element stack based on this data. We know that when +// we get here, that it is one of these forms, so we don't bother confirming +// it. +// +// But we have to ensure +// 1. xxx is not xmlns +// 2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa +// 3. yyy is not XMLUni::fgXMLNSURIName +// 4. if xxx is not null, then yyy cannot be an empty string. +void IGXMLScanner::updateNSMap(const XMLCh* const attrName + , const XMLCh* const attrValue) +{ + updateNSMap(attrName, attrValue, XMLString::indexOf(attrName, chColon)); +} + +void IGXMLScanner::updateNSMap(const XMLCh* const attrName + , const XMLCh* const attrValue + , const int colonOfs) +{ + // We need a buffer to normalize the attribute value into + XMLBufBid bbNormal(&fBufMgr); + XMLBuffer& normalBuf = bbNormal.getBuffer(); + + // Normalize the value into the passed buffer. In this case, we don't + // care about the return value. An error was issued for the error, which + // is all we care about here. + normalizeAttRawValue(attrName, attrValue, normalBuf); + XMLCh* namespaceURI = normalBuf.getRawBuffer(); + + // We either have the default prefix (""), or we point it into the attr + // name parameter. Note that the xmlns is not the prefix we care about + // here. To us, the 'prefix' is really the local part of the attrName + // parameter. + // + // Check 1. xxx is not xmlns + // 2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa + // 3. yyy is not XMLUni::fgXMLNSURIName + // 4. if xxx is not null, then yyy cannot be an empty string. + const XMLCh* prefPtr = XMLUni::fgZeroLenString; + if (colonOfs != -1) { + prefPtr = &attrName[colonOfs + 1]; + + if (XMLString::equals(prefPtr, XMLUni::fgXMLNSString)) + emitError(XMLErrs::NoUseOfxmlnsAsPrefix); + else if (XMLString::equals(prefPtr, XMLUni::fgXMLString)) { + if (!XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) + emitError(XMLErrs::PrefixXMLNotMatchXMLURI); + } + + if (!namespaceURI) + emitError(XMLErrs::NoEmptyStrNamespace, attrName); + else if(!*namespaceURI && fXMLVersion == XMLReader::XMLV1_0) + emitError(XMLErrs::NoEmptyStrNamespace, attrName); + } + + if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName)) + emitError(XMLErrs::NoUseOfxmlnsURI); + else if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) { + if (!XMLString::equals(prefPtr, XMLUni::fgXMLString)) + emitError(XMLErrs::XMLURINotMatchXMLPrefix); + } + + // Ok, we have to get the unique id for the attribute value, which is the + // URI that this value should be mapped to. The validator has the + // namespace string pool, so we ask him to find or add this new one. Then + // we ask the element stack to add this prefix to URI Id mapping. + fElemStack.addPrefix + ( + prefPtr + , fURIStringPool->addOrFind(namespaceURI) + ); +} + +void IGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount) +{ + // Make an initial pass through the list and find any xmlns attributes or + // schema attributes. + // When we find one, send it off to be used to update the element stack's + // namespace mappings. + for (XMLSize_t index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + + // If either the key begins with "xmlns:" or its just plain + // "xmlns", then use it to update the map. + if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6) + || XMLString::equals(rawPtr, XMLUni::fgXMLNSString)) + { + const XMLCh* valuePtr = curPair->getValue(); + + updateNSMap(rawPtr, valuePtr, fRawAttrColonList[index]); + + // if the schema URI is seen in the the valuePtr, set the boolean seeXsi + if (XMLString::equals(valuePtr, SchemaSymbols::fgURI_XSI)) { + fSeeXsi = true; + } + } + } + + // walk through the list again to deal with "xsi:...." + if (fDoSchema && fSeeXsi) + { + for (XMLSize_t index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + const XMLCh* prefPtr = XMLUni::fgZeroLenString; + int colonInd = fRawAttrColonList[index]; + + if (colonInd != -1) { + + fURIBuf.set(rawPtr, colonInd); + prefPtr = fURIBuf.getRawBuffer(); + } + + // if schema URI has been seen, scan for the schema location and uri + // and resolve the schema grammar + if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) { + + const XMLCh* valuePtr = curPair->getValue(); + const XMLCh* suffPtr = &rawPtr[colonInd + 1]; + + if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCATION)) + parseSchemaLocation(valuePtr); + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION)) + resolveSchemaGrammar(valuePtr, XMLUni::fgZeroLenString); + } + } + + // do it another time, as xsi:type and xsi:nill only work if the schema grammar has been already + // loaded (JIRA XERCESC-1937) + for (XMLSize_t index = 0; index < attCount; index++) + { + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + const XMLCh* prefPtr = XMLUni::fgZeroLenString; + int colonInd = fRawAttrColonList[index]; + + if (colonInd != -1) { + + fURIBuf.set(rawPtr, colonInd); + prefPtr = fURIBuf.getRawBuffer(); + } + + // scan for schema type + if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) { + + const XMLCh* valuePtr = curPair->getValue(); + const XMLCh* suffPtr = &rawPtr[colonInd + 1]; + + if(XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE) || + XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL)) + { + if (!fValidator || !fValidator->handlesSchema()) + { + // If we are in the DTD mode, try to switch to the Schema + // mode. For that we need to find any XML Schema grammar + // that we can switch to. Such a grammar can only come + // from the cache (if it came from the schemaLocation + // attribute, we would be in the Schema mode already). + // + XMLGrammarPool* pool = fGrammarResolver->getGrammarPool (); + RefHashTableOfEnumerator i = pool->getGrammarEnumerator (); + + while (i.hasMoreElements ()) + { + Grammar& gr (i.nextElement ()); + + if (gr.getGrammarType () == Grammar::SchemaGrammarType) + { + switchGrammar (gr.getTargetNamespace ()); + break; + } + } + } + + if( fValidator && fValidator->handlesSchema() ) + { + if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE)) + { + XMLBufBid bbXsi(&fBufMgr); + XMLBuffer& fXsiType = bbXsi.getBuffer(); + + // normalize the attribute according to schema whitespace facet + DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME); + normalizeAttRawValue(SchemaSymbols::fgXSI_TYPE, valuePtr, fXsiType); + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, fXsiType.getRawBuffer(), fXsiType, true); + if (!fXsiType.isEmpty()) { + int colonPos = -1; + unsigned int uriId = resolveQName ( + fXsiType.getRawBuffer() + , fPrefixBuf + , ElemStack::Mode_Element + , colonPos + ); + ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fXsiType.getRawBuffer() + colonPos + 1, uriId); + } + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL)) + { + // normalize the attribute according to schema whitespace facet + XMLBufBid bbXsi(&fBufMgr); + XMLBuffer& fXsiNil = bbXsi.getBuffer(); + + DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN); + normalizeAttRawValue(SchemaSymbols::fgATT_NILL, valuePtr, fXsiNil); + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, fXsiNil.getRawBuffer(), fXsiNil, true); + if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE)) + ((SchemaValidator*)fValidator)->setNillable(true); + else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE)) + ((SchemaValidator*)fValidator)->setNillable(false); + else + emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr); + } + } + } + } + } + } + +} + +void IGXMLScanner::parseSchemaLocation(const XMLCh* const schemaLocationStr, bool ignoreLoadSchema) +{ + XMLCh* locStr = XMLString::replicate(schemaLocationStr, fMemoryManager); + ArrayJanitor janLoc(locStr, fMemoryManager); + + processSchemaLocation(locStr); + XMLSize_t size = fLocationPairs->size(); + + if (size % 2 != 0 ) { + emitError(XMLErrs::BadSchemaLocation); + } else { + // We need a buffer to normalize the attribute value into + XMLBuffer normalBuf(1023, fMemoryManager); + for(XMLSize_t i=0; ielementAt(i), normalBuf); + resolveSchemaGrammar(fLocationPairs->elementAt(i+1), normalBuf.getRawBuffer(), ignoreLoadSchema); + } + } +} + +void IGXMLScanner::resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema) { + + Grammar* grammar = 0; + + { + XMLSchemaDescriptionImpl theSchemaDescription(uri, fMemoryManager); + theSchemaDescription.setLocationHints(loc); + grammar = fGrammarResolver->getGrammar(&theSchemaDescription); + } + + // If multi-import is enabled, make sure the existing grammar came + // from the import directive. Otherwise we may end up reloading + // the same schema that came from the external grammar pool. Ideally, + // we would move fSchemaInfoList to XMLGrammarPool so that it survives + // the destruction of the scanner in which case we could rely on the + // same logic we use to weed out duplicate schemas below. + // + if (!grammar || + grammar->getGrammarType() == Grammar::DTDGrammarType || + (getHandleMultipleImports() && + ((XMLSchemaDescription*)grammar->getGrammarDescription())-> + getContextType () == XMLSchemaDescription::CONTEXT_IMPORT)) + { + if (fLoadSchema || ignoreLoadSchema) + { + XSDDOMParser parser(0, fMemoryManager, 0); + + parser.setValidationScheme(XercesDOMParser::Val_Never); + parser.setDoNamespaces(true); + parser.setUserEntityHandler(fEntityHandler); + parser.setUserErrorReporter(fErrorReporter); + + //Normalize loc + XMLBufBid nnSys(&fBufMgr); + XMLBuffer& normalizedSysId = nnSys.getBuffer(); + XMLString::removeChar(loc, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the system id + XMLBufBid bbSys(&fBufMgr); + XMLBuffer& expSysId = bbSys.getBuffer(); + + // Allow the entity handler to expand the system id if they choose + // to do so. + InputSource* srcToFill = 0; + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::SchemaGrammar, + expSysId.getRawBuffer(), uri, XMLUni::fgZeroLenString, lastInfo.systemId, + &fReaderMgr); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + else + { + expSysId.set(normalizedURI); + } + + // If they didn't create a source via the entity handler, then we + // have to create one on our own. + if (!srcToFill) + { + if (fDisableDefaultEntityResolution) + return; + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBufBid ddSys(&fBufMgr); + XMLBuffer& resolvedSysId = ddSys.getBuffer(); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + // Put a janitor on the input source + Janitor janSrc(srcToFill); + + // Check if this exact schema has already been seen. + // + const XMLCh* sysId = srcToFill->getSystemId(); + unsigned int uriId = (uri && *uri) ? fURIStringPool->addOrFind(uri) : fEmptyNamespaceId; + SchemaInfo* importSchemaInfo = 0; + + if (fUseCachedGrammar) + importSchemaInfo = fCachedSchemaInfoList->get(sysId, uriId); + + if (!importSchemaInfo && !fToCacheGrammar) + importSchemaInfo = fSchemaInfoList->get(sysId, uriId); + + if (importSchemaInfo) + { + // We haven't added any new grammars so it is safe to just + // return. + // + return; + } + + // Should just issue warning if the schema is not found + bool flag = srcToFill->getIssueFatalErrorIfNotFound(); + srcToFill->setIssueFatalErrorIfNotFound(false); + + parser.parse(*srcToFill); + + // Reset the InputSource + srcToFill->setIssueFatalErrorIfNotFound(flag); + + if (parser.getSawFatal() && fExitOnFirstFatal) + emitError(XMLErrs::SchemaScanFatalError); + + DOMDocument* document = parser.getDocument(); //Our Grammar + + if (document != 0) { + + DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema + if (root != 0) + { + const XMLCh* newUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + bool newGrammar = false; + if (!XMLString::equals(newUri, uri)) { + if (fValidate || fValScheme == Val_Auto) { + fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri); + } + + grammar = fGrammarResolver->getGrammar(newUri); + newGrammar = true; + } + + if (!grammar || + grammar->getGrammarType() == Grammar::DTDGrammarType || + (getHandleMultipleImports() && + ((XMLSchemaDescription*)grammar->getGrammarDescription())-> + getContextType () == XMLSchemaDescription::CONTEXT_IMPORT)) + { + // If we switched namespace URI, recheck the schema info. + // + if (newGrammar) + { + unsigned int newUriId = (newUri && *newUri) ? fURIStringPool->addOrFind(newUri) : fEmptyNamespaceId; + + if (fUseCachedGrammar) + importSchemaInfo = fCachedSchemaInfoList->get(sysId, newUriId); + + if (!importSchemaInfo && !fToCacheGrammar) + importSchemaInfo = fSchemaInfoList->get(sysId, newUriId); + + if (importSchemaInfo) + return; + } + + // Since we have seen a grammar, set our validation flag + // at this point if the validation scheme is auto + if (fValScheme == Val_Auto && !fValidate) { + fValidate = true; + fElemStack.setValidationFlag(fValidate); + } + + // we have seen a schema, so set up the fValidator as fSchemaValidator + if (!fValidator->handlesSchema()) + { + if (fValidatorFromUser) { + // the fValidator is from user + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + } + else { + fValidator = fSchemaValidator; + } + } + + bool grammarFound = grammar && + grammar->getGrammarType() == Grammar::SchemaGrammarType; + + SchemaGrammar* schemaGrammar; + + if (grammarFound) { + schemaGrammar = (SchemaGrammar*) grammar; + } + else { + schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); + } + + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription(); + gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE); + gramDesc->setLocationHints(sysId); + + TraverseSchema traverseSchema + ( + root + , fURIStringPool + , schemaGrammar + , fGrammarResolver + , fUseCachedGrammar ? fCachedSchemaInfoList : fSchemaInfoList + , fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList + , this + , sysId + , fEntityHandler + , fErrorReporter + , fMemoryManager + , grammarFound + ); + + // Reset the now invalid schema roots in the collected + // schema info entries. + // + { + RefHash2KeysTableOfEnumerator i ( + fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList); + + while (i.hasMoreElements ()) + i.nextElement().resetRoot (); + } + + if (fGrammarType == Grammar::DTDGrammarType) { + fGrammar = schemaGrammar; + fGrammarType = Grammar::SchemaGrammarType; + fValidator->setGrammar(fGrammar); + } + + if (fValidate) { + // validate the Schema scan so far + fValidator->preContentValidation(false); + } + } + } + } + } + } + else + { + // Since we have seen a grammar, set our validation flag + // at this point if the validation scheme is auto + if (fValScheme == Val_Auto && !fValidate) { + fValidate = true; + fElemStack.setValidationFlag(fValidate); + } + + // we have seen a schema, so set up the fValidator as fSchemaValidator + if (!fValidator->handlesSchema()) + { + if (fValidatorFromUser) { + // the fValidator is from user + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + } + else { + fValidator = fSchemaValidator; + } + } + + if (fGrammarType == Grammar::DTDGrammarType) { + fGrammar = grammar; + fGrammarType = Grammar::SchemaGrammarType; + fValidator->setGrammar(fGrammar); + } + } + + // fModel may need updating: + if(getPSVIHandler()) + fModel = fGrammarResolver->getXSModel(); +} + +InputSource* IGXMLScanner::resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId) +{ + //Normalize sysId + XMLBufBid nnSys(&fBufMgr); + XMLBuffer& normalizedSysId = nnSys.getBuffer(); + XMLString::removeChar(sysId, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the system id + XMLBufBid bbSys(&fBufMgr); + XMLBuffer& expSysId = bbSys.getBuffer(); + + // Allow the entity handler to expand the system id if they choose + // to do so. + InputSource* srcToFill = 0; + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity, + expSysId.getRawBuffer(), 0, pubId, lastInfo.systemId, + &fReaderMgr); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + else + { + expSysId.set(normalizedURI); + } + + // If they didn't create a source via the entity handler, then we + // have to create one on our own. + if (!srcToFill) + { + if (fDisableDefaultEntityResolution) + return srcToFill; + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBufBid ddSys(&fBufMgr); + XMLBuffer& resolvedSysId = ddSys.getBuffer(); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + return srcToFill; +} + + +// --------------------------------------------------------------------------- +// IGXMLScanner: Private grammar preparsing methods +// --------------------------------------------------------------------------- +Grammar* IGXMLScanner::loadXMLSchemaGrammar(const InputSource& src, + const bool toCache) +{ + // Reset the validators + fSchemaValidator->reset(); + fSchemaValidator->setErrorReporter(fErrorReporter); + fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal); + fSchemaValidator->setGrammarResolver(fGrammarResolver); + + if (fValidatorFromUser) + fValidator->reset(); + + if (!fValidator->handlesSchema()) { + if (fValidatorFromUser && fValidate) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + else { + fValidator = fSchemaValidator; + } + } + + XSDDOMParser parser(0, fMemoryManager, 0); + + parser.setValidationScheme(XercesDOMParser::Val_Never); + parser.setDoNamespaces(true); + parser.setUserEntityHandler(fEntityHandler); + parser.setUserErrorReporter(fErrorReporter); + + // Should just issue warning if the schema is not found + bool flag = src.getIssueFatalErrorIfNotFound(); + ((InputSource&) src).setIssueFatalErrorIfNotFound(false); + + parser.parse(src); + + // Reset the InputSource + ((InputSource&) src).setIssueFatalErrorIfNotFound(flag); + + if (parser.getSawFatal() && fExitOnFirstFatal) + emitError(XMLErrs::SchemaScanFatalError); + + DOMDocument* document = parser.getDocument(); //Our Grammar + + if (document != 0) { + + DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema + if (root != 0) + { + const XMLCh* nsUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + Grammar* grammar = fGrammarResolver->getGrammar(nsUri); + + // Check if this exact schema has already been seen. + // + const XMLCh* sysId = src.getSystemId(); + SchemaInfo* importSchemaInfo = 0; + + if (grammar) + { + if (nsUri && *nsUri) + importSchemaInfo = fCachedSchemaInfoList->get(sysId, fURIStringPool->addOrFind(nsUri)); + else + importSchemaInfo = fCachedSchemaInfoList->get(sysId, fEmptyNamespaceId); + } + + if (!importSchemaInfo) + { + bool grammarFound = grammar && + grammar->getGrammarType() == Grammar::SchemaGrammarType && + getHandleMultipleImports(); + + SchemaGrammar* schemaGrammar; + + if (grammarFound) + schemaGrammar = (SchemaGrammar*) grammar; + else + schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); + + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription(); + gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE); + gramDesc->setLocationHints(sysId); + + TraverseSchema traverseSchema + ( + root + , fURIStringPool + , schemaGrammar + , fGrammarResolver + , fCachedSchemaInfoList + , toCache ? fCachedSchemaInfoList : fSchemaInfoList + , this + , sysId + , fEntityHandler + , fErrorReporter + , fMemoryManager + , grammarFound + ); + + grammar = schemaGrammar; + + // Reset the now invalid schema roots in the collected + // schema info entries. + // + { + RefHash2KeysTableOfEnumerator i ( + toCache ? fCachedSchemaInfoList : fSchemaInfoList); + + while (i.hasMoreElements ()) + i.nextElement().resetRoot (); + } + } + + if (fValidate) { + // validate the Schema scan so far + fValidator->setGrammar(grammar); + fValidator->preContentValidation(false); + } + + if (toCache) { + fGrammarResolver->cacheGrammars(); + } + + if(getPSVIHandler()) + fModel = fGrammarResolver->getXSModel(); + + return grammar; + } + } + + return 0; +} + + + +// --------------------------------------------------------------------------- +// IGXMLScanner: Private parsing methods +// --------------------------------------------------------------------------- + +// This method is called to do a raw scan of an attribute value. It does not +// do normalization (since we don't know their types yet.) It just scans the +// value and does entity expansion. +// +// End of entity's must be dealt with here. During DTD scan, they can come +// from external entities. During content, they can come from any entity. +// We just eat the end of entity and continue with our scan until we come +// to the closing quote. If an unterminated value causes us to go through +// subsequent entities, that will cause errors back in the calling code, +// but there's little we can do about it here. +bool IGXMLScanner::basicAttrValueScan(const XMLCh* const attrName, XMLBuffer& toFill) +{ + // Reset the target buffer + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr.skipIfQuote(quoteCh)) + return false; + + // We have to get the current reader because we have to ignore closing + // quotes until we hit the same reader again. + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // Loop until we get the attribute value. Note that we use a double + // loop here to avoid the setup/teardown overhead of the exception + // handler on every round. + while (true) + { + try + { + while(true) + { + XMLCh nextCh = fReaderMgr.getNextChar(); + + if (nextCh != quoteCh) + { + if (nextCh != chAmpersand) + { + if ((nextCh < 0xD800) || (nextCh > 0xDFFF)) + { + // Its got to at least be a valid XML character + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + if (nextCh == 0) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf); + } + } else // its a surrogate + { + // Deal with surrogate pairs + + // we expect a a leading surrogate. + if (nextCh <= 0xDBFF) + { + toFill.append(nextCh); + + // process the trailing surrogate + nextCh = fReaderMgr.getNextChar(); + + // it should be a trailing surrogate. + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + } else + { + // Its a trailing surrogate, but we are not expecting it + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + } + } else // its a chAmpersand + { + // Check for an entity ref . We ignore the empty flag in + // this one. + + bool escaped; + XMLCh firstCh; + XMLCh secondCh + ; + // If it was not returned directly, then jump back up + if (scanEntityRef(true, firstCh, secondCh, escaped) == EntityExp_Returned) + { + // If it was escaped, then put in a 0xFFFF value. This will + // be used later during validation and normalization of the + // value to know that the following character was via an + // escape char. + if (escaped) + toFill.append(0xFFFF); + + toFill.append(firstCh); + if (secondCh) + toFill.append(secondCh); + } + continue; + } + } else // its a quoteCh + { + // Check for our ending quote. It has to be in the same entity + // as where we started. Quotes in nested entities are ignored. + + if (curReader == fReaderMgr.getCurrentReaderNum()) + { + return true; + } + + // Watch for spillover into a previous entity + if (curReader > fReaderMgr.getCurrentReaderNum()) + { + emitError(XMLErrs::PartialMarkupInEntity); + return false; + } + } + + // add it to the buffer + toFill.append(nextCh); + + } + } + catch(const EndOfEntityException&) + { + // Just eat it and continue. + } + } + return true; +} + + +bool IGXMLScanner::scanAttValue( const XMLAttDef* const attDef + , const XMLCh* const attrName + , XMLBuffer& toFill) +{ + enum States + { + InWhitespace + , InContent + }; + + // Get the type and name + const XMLAttDef::AttTypes type = (attDef) + ?attDef->getType() + :XMLAttDef::CData; + + // Reset the target buffer + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr.skipIfQuote(quoteCh)) + return false; + + // We have to get the current reader because we have to ignore closing + // quotes until we hit the same reader again. + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // Get attribute def - to check to see if it's declared externally or not + bool isAttExternal = (attDef) + ?attDef->isExternal() + :false; + + // Loop until we get the attribute value. Note that we use a double + // loop here to avoid the setup/teardown overhead of the exception + // handler on every round. + XMLCh nextCh; + XMLCh secondCh = 0; + States curState = InContent; + bool firstNonWS = false; + bool gotLeadingSurrogate = false; + bool escaped; + while (true) + { + try + { + while(true) + { + nextCh = fReaderMgr.getNextChar(); + + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + // Check for our ending quote in the same entity + if (nextCh == quoteCh) + { + if (curReader == fReaderMgr.getCurrentReaderNum()) + return true; + + // Watch for spillover into a previous entity + if (curReader > fReaderMgr.getCurrentReaderNum()) + { + emitError(XMLErrs::PartialMarkupInEntity); + return false; + } + } + + // Check for an entity ref now, before we let it affect our + // whitespace normalization logic below. We ignore the empty flag + // in this one. + escaped = false; + if (nextCh == chAmpersand) + { + if (scanEntityRef(true, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // If its not escaped, then make sure its not a < character, which + // is not allowed in attribute values. + if (!escaped && (nextCh == chOpenAngle)) + emitError(XMLErrs::BracketInAttrValue, attrName); + + // If the attribute is a CDATA type we do simple replacement of + // tabs and new lines with spaces, if the character is not escaped + // by way of a char ref. + // + // Otherwise, we do the standard non-CDATA normalization of + // compressing whitespace to single spaces and getting rid of leading + // and trailing whitespace. + if (type == XMLAttDef::CData) + { + if (!escaped) + { + if ((nextCh == 0x09) || (nextCh == 0x0A) || (nextCh == 0x0D)) + { + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && isAttExternal) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName); + } + nextCh = chSpace; + } + } + } + else + { + if (curState == InWhitespace) + { + if ((escaped && nextCh != chSpace) || !fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + if (firstNonWS) + toFill.append(chSpace); + curState = InContent; + firstNonWS = true; + } + else + { + continue; + } + } + else if (curState == InContent) + { + if ((nextCh == chSpace) || + (fReaderMgr.getCurrentReader()->isWhitespace(nextCh) && !escaped)) + { + curState = InWhitespace; + + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && isAttExternal) + { + if (!firstNonWS || (nextCh != chSpace) || (fReaderMgr.lookingAtSpace())) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName); + } + } + continue; + } + firstNonWS = true; + } + } + + // Else add it to the buffer + toFill.append(nextCh); + + if (secondCh) + { + toFill.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException&) + { + // Just eat it and continue. + gotLeadingSurrogate = false; + escaped = false; + } + } + return true; +} + + +// This method scans a CDATA section. It collects the character into one +// of the temp buffers and calls the document handler, if any, with the +// characters. It assumes that the getGrammarType() == Grammar::SchemaGrammarType) + { + // And see if the current element is a 'Children' style content model + ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if(currType) + { + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType(); + if(modelType == SchemaElementDecl::Children || + modelType == SchemaElementDecl::ElementOnlyEmpty) + charOpts = XMLElementDecl::SpacesOk; + else if(modelType == SchemaElementDecl::Empty) + charOpts = XMLElementDecl::NoCharData; + } + } else // DTD grammar + charOpts = topElem->fThisElement->getCharDataOpts(); + + while (true) + { + const XMLCh nextCh = fReaderMgr.getNextChar(); + + // Watch for unexpected end of file + if (!nextCh) + { + emitError(XMLErrs::UnterminatedCDATASection); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + if (fValidate && fStandalone && (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))) + { + // This document is standalone; this ignorable CDATA whitespace is forbidden. + // XML 1.0, Section 2.9 + // And see if the current element is a 'Children' style content model + if (topElem->fThisElement->isExternal()) { + + if (charOpts == XMLElementDecl::SpacesOk) // Element Content + { + // Error - standalone should have a value of "no" as whitespace detected in an + // element type with element content whose element declaration was external + fValidator->emitError(XMLValid::NoWSForStandalone); + if(fGrammarType == Grammar::SchemaGrammarType) + { + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + } + + // If this is a close square bracket it could be our closing + // sequence. + if (nextCh == chCloseSquare && fReaderMgr.skippedString(CDataClose)) + { + // make sure we were not expecting a trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + if (fGrammarType == Grammar::SchemaGrammarType) { + + XMLSize_t xsLen = bbCData.getLen(); + const XMLCh* xsNormalized = bbCData.getRawBuffer(); + DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the character according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + xsLen = fWSNormalizeBuf.getLen(); + if (fNormalizeData && fValidate) { + bbCData.set(xsNormalized); + } + } + + if (fValidate) { + + // tell the schema validation about the character data for checkContent later + ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized); + + if (charOpts != XMLElementDecl::AllCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) { + fContent.append(xsNormalized, xsLen); + } + } + else { + if (fValidate) { + + if (charOpts != XMLElementDecl::AllCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + } + } + } + + // If we have a doc handler, call it + if (fDocHandler) + { + fDocHandler->docCharacters( + bbCData.getRawBuffer(), bbCData.getLen(), true + ); + } + + // And we are done + break; + } + + // Make sure its a valid character. But if we've emitted an error + // already, don't bother with the overhead since we've already told + // them about it. + if (!emittedError) + { + // Deal with surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + emittedError = true; + } + } + gotLeadingSurrogate = false; + } + } + + // Add it to the buffer + bbCData.append(nextCh); + } +} + + +void IGXMLScanner::scanCharData(XMLBuffer& toUse) +{ + // We have to watch for the stupid ]]> sequence, which is illegal in + // character data. So this is a little state machine that handles that. + enum States + { + State_Waiting + , State_GotOne + , State_GotTwo + }; + + // Reset the buffer before we start + toUse.reset(); + + // Turn on the 'throw at end' flag of the reader manager + ThrowEOEJanitor jan(&fReaderMgr, true); + + // In order to be more efficient we have to use kind of a deeply nested + // set of blocks here. The outer block puts on a try and catches end of + // entity exceptions. The inner loop is the per-character loop. If we + // put the try inside the inner loop, it would work but would require + // the exception handling code setup/teardown code to be invoked for + // each character. + XMLCh nextCh; + XMLCh secondCh = 0; + States curState = State_Waiting; + bool escaped = false; + bool gotLeadingSurrogate = false; + bool notDone = true; + while (notDone) + { + try + { + while (true) + { + // Eat through as many plain content characters as possible without + // needing special handling. Moving most content characters here, + // in this one call, rather than running the overall loop once + // per content character, is a speed optimization. + if (curState == State_Waiting && !gotLeadingSurrogate) + { + fReaderMgr.movePlainContentChars(toUse); + } + + // Try to get another char from the source + // The code from here on down covers all contengencies, + if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh)) + { + // If we were waiting for a trailing surrogate, its an error + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + notDone = false; + break; + } + + // Watch for a reference. Note that the escapement mechanism + // is ignored in this content. + escaped = false; + if (nextCh == chAmpersand) + { + sendCharData(toUse); + + // Turn off the throwing at the end of entity during this + ThrowEOEJanitor jan(&fReaderMgr, false); + + if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + else + { + if (escaped && !fElemStack.isEmpty()) + fElemStack.setReferenceEscaped(); + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Make sure the returned char is a valid XML char + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // Keep the state machine up to date + if (!escaped) + { + if (nextCh == chCloseSquare) + { + if (curState == State_Waiting) + curState = State_GotOne; + else if (curState == State_GotOne) + curState = State_GotTwo; + } + else if (nextCh == chCloseAngle) + { + if (curState == State_GotTwo) + emitError(XMLErrs::BadSequenceInCharData); + curState = State_Waiting; + } + else + { + curState = State_Waiting; + } + } + else + { + curState = State_Waiting; + } + + // Add this char to the buffer + toUse.append(nextCh); + + if (secondCh) + { + toUse.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException& toCatch) + { + // Some entity ended, so we have to send any accumulated + // chars and send an end of entity event. + sendCharData(toUse); + gotLeadingSurrogate = false; + + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + // Check the validity constraints as per XML 1.0 Section 2.9 + if (fValidate && fStandalone) + { + // See if the text contains whitespace + // Get the raw data we need for the callback + const XMLCh* rawBuf = toUse.getRawBuffer(); + const XMLSize_t len = toUse.getLen(); + const bool isSpaces = fReaderMgr.getCurrentReader()->containsWhiteSpace(rawBuf, len); + + if (isSpaces) + { + // And see if the current element is a 'Children' style content model + const ElemStack::StackElem* topElem = fElemStack.topElement(); + + if (topElem->fThisElement->isExternal()) { + + // Get the character data opts for the current element + XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData; + if(fGrammar->getGrammarType() == Grammar::SchemaGrammarType) + { + // And see if the current element is a 'Children' style content model + ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if(currType) + { + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType(); + if(modelType == SchemaElementDecl::Children || + modelType == SchemaElementDecl::ElementOnlyEmpty) + charOpts = XMLElementDecl::SpacesOk; + else if(modelType == SchemaElementDecl::Empty) + charOpts = XMLElementDecl::NoCharData; + } + } else // DTD grammar + charOpts = topElem->fThisElement->getCharDataOpts(); + + if (charOpts == XMLElementDecl::SpacesOk) // => Element Content + { + // Error - standalone should have a value of "no" as whitespace detected in an + // element type with element content whose element declaration was external + // + fValidator->emitError(XMLValid::NoWSForStandalone); + if(fGrammarType == Grammar::SchemaGrammarType) + { + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + } + } + // Send any char data that we accumulated into the buffer + sendCharData(toUse); +} + + +// This method will scan a general/character entity ref. It will either +// expand a char ref and return it directly, or push a reader for a general +// entity. +// +// The return value indicates whether the char parameters hold the value +// or whether the value was pushed as a reader, or that it failed. +// +// The escaped flag tells the caller whether the returned parameter resulted +// from a character reference, which escapes the character in some cases. It +// only makes any difference if the return value indicates the value was +// returned directly. +IGXMLScanner::EntityExpRes +IGXMLScanner::scanEntityRef( const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped) +{ + // Assume no escape + secondCh = 0; + escaped = false; + + // We have to insure that its all in one entity + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // If the next char is a pound, then its a character reference and we + // need to expand it always. + if (fReaderMgr.skippedChar(chPound)) + { + // Its a character reference, so scan it and get back the numeric + // value it represents. + if (!scanCharRef(firstCh, secondCh)) + return EntityExp_Failed; + + escaped = true; + + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + return EntityExp_Returned; + } + + // Expand it since its a normal entity ref + XMLBufBid bbName(&fBufMgr); + int colonPosition; + bool validName = fDoNamespaces ? fReaderMgr.getQName(bbName.getBuffer(), &colonPosition) : + fReaderMgr.getName(bbName.getBuffer()); + if (!validName) + { + if (bbName.isEmpty()) + emitError(XMLErrs::ExpectedEntityRefName); + else + emitError(XMLErrs::InvalidEntityRefName, bbName.getRawBuffer()); + return EntityExp_Failed; + } + + // Next char must be a semi-colon. But if its not, just emit + // an error and try to continue. + if (!fReaderMgr.skippedChar(chSemiColon)) + emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer()); + + // Make sure we ended up on the same entity reader as the & char + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // Look up the name in the general entity pool + XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer()); + + // If it does not exist, then obviously an error + if (!decl) + { + // XML 1.0 Section 4.1 + // Well-formedness Constraint for entity not found: + // In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references, + // or a document with "standalone='yes'", for an entity reference that does not occur within the external subset + // or a parameter entity + // + // Else it's Validity Constraint + if (fStandalone || fHasNoDTD) + emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer()); + else { + if (fValidate) + fValidator->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer()); + } + + return EntityExp_Failed; + } + + // XML 1.0 Section 4.1 + // If we are a standalone document, then it has to have been declared + // in the internal subset. + if (fStandalone && !decl->getDeclaredInIntSubset()) + emitError(XMLErrs::IllegalRefInStandalone, bbName.getRawBuffer()); + + if (decl->isExternal()) + { + // If its unparsed, then its not valid here + if (decl->isUnparsed()) + { + emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer()); + return EntityExp_Failed; + } + + // If we are in an attribute value, then not valid but keep going + if (inAttVal) + emitError(XMLErrs::NoExtRefsInAttValue); + + // And now create a reader to read this entity + InputSource* srcUsed; + XMLReader* reader = fReaderMgr.createReader + ( + decl->getBaseURI() + , decl->getSystemId() + , decl->getPublicId() + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , srcUsed + , fCalculateSrcOfs + , fLowWaterMark + , fDisableDefaultEntityResolution + ); + + // Put a janitor on the source so it gets cleaned up on exit + Janitor janSrc(srcUsed); + + // If the creation failed, and its not because the source was empty, + // then emit an error and return. + if (!reader) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager); + + // Push the reader. If its a recursive expansion, then emit an error + // and return an failure. + if (!fReaderMgr.pushReader(reader, decl)) + { + emitError(XMLErrs::RecursiveEntity, decl->getName()); + return EntityExp_Failed; + } + + // here's where we need to check if there's a SecurityManager, + // how many entity references we've had + if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) { + XMLCh expLimStr[32]; + XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager); + emitError + ( + XMLErrs::EntityExpansionLimitExceeded + , expLimStr + ); + // there seems nothing better to be done than to reset the entity expansion counter + fEntityExpansionCount = 0; + } + + // Do a start entity reference event. + // + // For now, we supress them in att values. Later, when + // the stuff is in place to correctly allow DOM to handle them + // we'll turn this back on. + if (fDocHandler && !inAttVal) + fDocHandler->startEntityReference(*decl); + + // If it starts with the XML string, then parse a text decl + if (checkXMLDecl(true)) + scanXMLDecl(Decl_Text); + } + else + { + // If its one of the special char references, then we can return + // it as a character, and its considered escaped. + if (decl->getIsSpecialChar()) + { + firstCh = decl->getValue()[0]; + escaped = true; + return EntityExp_Returned; + } + + // Create a reader over a memory stream over the entity value + // We force it to assume UTF-16 by passing in an encoding + // string. This way it won't both trying to predecode the + // first line, looking for an XML/TextDecl. + XMLReader* valueReader = fReaderMgr.createIntEntReader + ( + decl->getName() + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , decl->getValue() + , decl->getValueLen() + , false + ); + + // Try to push the entity reader onto the reader manager stack, + // where it will become the subsequent input. If it fails, that + // means the entity is recursive, so issue an error. The reader + // will have just been discarded, but we just keep going. + if (!fReaderMgr.pushReader(valueReader, decl)) + emitError(XMLErrs::RecursiveEntity, decl->getName()); + + // here's where we need to check if there's a SecurityManager, + // how many entity references we've had + if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) { + XMLCh expLimStr[32]; + XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager); + emitError + ( + XMLErrs::EntityExpansionLimitExceeded + , expLimStr + ); + } + + // Do a start entity reference event. + // + // For now, we supress them in att values. Later, when + // the stuff is in place to correctly allow DOM to handle them + // we'll turn this back on. + if (fDocHandler && !inAttVal) + fDocHandler->startEntityReference(*decl); + + // If it starts with the XML string, then it's an error + if (checkXMLDecl(true)) { + emitError(XMLErrs::TextDeclNotLegalHere); + fReaderMgr.skipPastChar(chCloseAngle); + } + } + return EntityExp_Pushed; +} + + +bool IGXMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace) +{ + Grammar* tempGrammar = fGrammarResolver->getGrammar(newGrammarNameSpace); + + if (!tempGrammar && !fSkipDTDValidation) { + // This is a case where namespaces is on with a DTD grammar. + tempGrammar = fDTDGrammar; + } + if (!tempGrammar) { + return false; + } + else { + + Grammar::GrammarType tempGrammarType = tempGrammar->getGrammarType(); + if (tempGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) { + if (fValidatorFromUser) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + else { + fValidator = fSchemaValidator; + } + } + else if (tempGrammarType == Grammar::DTDGrammarType) { + if (fSkipDTDValidation) { + return false; + } + + if (!fValidator->handlesDTD()) { + if (fValidatorFromUser) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager); + else { + fValidator = fDTDValidator; + } + } + } + + fGrammarType = tempGrammarType; + fGrammar = tempGrammar; + fValidator->setGrammar(fGrammar); + return true; + } +} + +// check if we should skip or lax the validation of the element +// if skip - no validation +// if lax - validate only if the element if found +bool IGXMLScanner::laxElementValidation(QName* element, ContentLeafNameTypeVector* cv, + const XMLContentModel* const cm, + const XMLSize_t parentElemDepth) +{ + bool skipThisOne = false; + bool laxThisOne = false; + unsigned int elementURI = element->getURI(); + unsigned int currState = fElemState[parentElemDepth]; + unsigned int currLoop = fElemLoopState[parentElemDepth]; + + if (currState == XMLContentModel::gInvalidTrans) { + return laxThisOne; + } + + SubstitutionGroupComparator comparator(fGrammarResolver, fURIStringPool); + + if (cv) { + XMLSize_t i = 0; + XMLSize_t leafCount = cv->getLeafCount(); + unsigned int nextState = 0; + + for (; i < leafCount; i++) { + + QName* fElemMap = cv->getLeafNameAt(i); + unsigned int uri = fElemMap->getURI(); + ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i); + + if (type == ContentSpecNode::Leaf) { + if (((uri == elementURI) + && XMLString::equals(fElemMap->getLocalPart(), element->getLocalPart())) + || comparator.isEquivalentTo(element, fElemMap)) { + + nextState = cm->getNextState(currState, i); + + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } else if ((type & 0x0f) == ContentSpecNode::Any) { + nextState = cm->getNextState(currState, i); + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + else if ((type & 0x0f) == ContentSpecNode::Any_Other) { + if (uri != elementURI && elementURI != fEmptyNamespaceId) { + nextState = cm->getNextState(currState, i); + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if ((type & 0x0f) == ContentSpecNode::Any_NS) { + if (uri == elementURI) { + nextState = cm->getNextState(currState, i); + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + + } // for + + if (i == leafCount) { // no match + fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans; + fElemLoopState[parentElemDepth] = 0; + return laxThisOne; + } + + unsigned int nextLoop = 0; + if(!cm->handleRepetitions(element, currState, currLoop, nextState, nextLoop, i, &comparator)) { + fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans; + fElemLoopState[parentElemDepth] = 0; + return laxThisOne; + } + + ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i); + if ((type & 0x0f) == ContentSpecNode::Any || + (type & 0x0f) == ContentSpecNode::Any_Other || + (type & 0x0f) == ContentSpecNode::Any_NS) + { + if (type == ContentSpecNode::Any_Skip || + type == ContentSpecNode::Any_NS_Skip || + type == ContentSpecNode::Any_Other_Skip) { + skipThisOne = true; + } + else if (type == ContentSpecNode::Any_Lax || + type == ContentSpecNode::Any_NS_Lax || + type == ContentSpecNode::Any_Other_Lax) { + laxThisOne = true; + } + } + fElemState[parentElemDepth] = nextState; + fElemLoopState[parentElemDepth] = nextLoop; + } // if + + if (skipThisOne) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + + return laxThisOne; +} + + +// check if there is an AnyAttribute, and if so, see if we should lax or skip +// if skip - no validation +// if lax - validate only if the attribute if found +bool IGXMLScanner::anyAttributeValidation(SchemaAttDef* attWildCard, unsigned int uriId, bool& skipThisOne, bool& laxThisOne) +{ + XMLAttDef::AttTypes wildCardType = attWildCard->getType(); + bool anyEncountered = false; + skipThisOne = false; + laxThisOne = false; + if (wildCardType == XMLAttDef::Any_Any) + anyEncountered = true; + else if (wildCardType == XMLAttDef::Any_Other) { + if (attWildCard->getAttName()->getURI() != uriId + && uriId != fEmptyNamespaceId) + anyEncountered = true; + } + else if (wildCardType == XMLAttDef::Any_List) { + ValueVectorOf* nameURIList = attWildCard->getNamespaceList(); + XMLSize_t listSize = (nameURIList) ? nameURIList->size() : 0; + + if (listSize) { + for (XMLSize_t i=0; i < listSize; i++) { + if (nameURIList->elementAt(i) == uriId) + anyEncountered = true; + } + } + } + + if (anyEncountered) { + XMLAttDef::DefAttTypes defType = attWildCard->getDefaultType(); + if (defType == XMLAttDef::ProcessContents_Skip) { + // attribute should just be bypassed, + skipThisOne = true; + } + else if (defType == XMLAttDef::ProcessContents_Lax) { + laxThisOne = true; + } + } + + return anyEncountered; +} + +inline XMLAttDefList& getAttDefList(bool isSchemaGrammar + , ComplexTypeInfo* currType + , XMLElementDecl* elemDecl) +{ + if (isSchemaGrammar && currType) + return currType->getAttDefList(); + else + return elemDecl->getAttDefList(); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/MemoryManagerImpl.cpp b/include/xercesc/internal/MemoryManagerImpl.cpp new file mode 100644 index 0000000..3bc35f7 --- /dev/null +++ b/include/xercesc/internal/MemoryManagerImpl.cpp @@ -0,0 +1,57 @@ +/* + * 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: MemoryManagerImpl.cpp 1662868 2015-02-28 00:52:04Z scantor $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MemoryManager* MemoryManagerImpl::getExceptionMemoryManager() +{ + return this; +} + +void* MemoryManagerImpl::allocate(XMLSize_t size) +{ + void* memptr; + try { + memptr = ::operator new(size); + } + catch(...) { + throw OutOfMemoryException(); + } + + if(memptr==NULL && size!=0) + throw OutOfMemoryException(); + return memptr; +} + +void MemoryManagerImpl::deallocate(void* p) +{ + if (p) + ::operator delete(p); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/MemoryManagerImpl.hpp b/include/xercesc/internal/MemoryManagerImpl.hpp new file mode 100644 index 0000000..1ee5c2c --- /dev/null +++ b/include/xercesc/internal/MemoryManagerImpl.hpp @@ -0,0 +1,106 @@ +/* + * 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: MemoryManagerImpl.hpp 673975 2008-07-04 09:23:56Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_MEMORYMANAGERIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_MEMORYMANAGERIMPL_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Configurable memory manager + * + *

This is Xerces default implementation of the memory + * manager interface, which will be instantiated and used + * in the absence of an application's memory manager. + *

+ */ + +class XMLUTIL_EXPORT MemoryManagerImpl : public MemoryManager +{ +public: + + /** @name Constructor */ + //@{ + + /** + * Default constructor + */ + MemoryManagerImpl() + { + } + //@} + + /** @name Destructor */ + //@{ + + /** + * Default destructor + */ + virtual ~MemoryManagerImpl() + { + } + //@} + + + /** + * This method is called to obtain the memory manager that should be + * used to allocate memory used in exceptions. + * + * @return A pointer to the memory manager + */ + virtual MemoryManager* getExceptionMemoryManager(); + + + /** @name The virtual methods in MemoryManager */ + //@{ + + /** + * This method allocates requested memory. + * + * @param size The requested memory size + * + * @return A pointer to the allocated memory + */ + virtual void* allocate(XMLSize_t size); + + /** + * This method deallocates memory + * + * @param p The pointer to the allocated memory to be deleted + */ + virtual void deallocate(void* p); + + //@} + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + MemoryManagerImpl(const MemoryManagerImpl&); + MemoryManagerImpl& operator=(const MemoryManagerImpl&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/ReaderMgr.cpp b/include/xercesc/internal/ReaderMgr.cpp new file mode 100644 index 0000000..d3879ce --- /dev/null +++ b/include/xercesc/internal/ReaderMgr.cpp @@ -0,0 +1,1120 @@ +/* + * 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: ReaderMgr.cpp 833045 2009-11-05 13:21:27Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// ReaderMgr: Constructors and Destructor +// --------------------------------------------------------------------------- +ReaderMgr::ReaderMgr(MemoryManager* const manager) : + + fCurEntity(0) + , fCurReader(0) + , fEntityHandler(0) + , fEntityStack(0) + , fNextReaderNum(1) + , fReaderStack(0) + , fThrowEOE(false) + , fXMLVersion(XMLReader::XMLV1_0) + , fStandardUriConformant(false) + , fMemoryManager(manager) +{ +} + +ReaderMgr::~ReaderMgr() +{ + // + // Clean up the reader and entity stacks. Note that we don't own the + // entities, so we don't delete the current entity (and the entity stack + // does not own its elements either, so deleting it will not delete the + // entities it still references!) + // + delete fCurReader; + delete fReaderStack; + delete fEntityStack; +} + + +// --------------------------------------------------------------------------- +// ReaderMgr: Getter methods +// --------------------------------------------------------------------------- +bool ReaderMgr::isEmpty() const +{ + return fReaderStack->empty(); +} + + +// --------------------------------------------------------------------------- +// ReaderMgr: Scanning APIs +// --------------------------------------------------------------------------- +XMLCh ReaderMgr::getNextChar() +{ + XMLCh chRet; + if (fCurReader->getNextChar(chRet)) + return chRet; + + // + // Didn't get anything back so this reader is hosed. So lets move to + // the next reader on the stack. If this fails, it will be because + // its the end of the original file, and we just return zero. + // + // If its the end of an entity and fThrowEOE is set, it will throw out + // of here. Otherwise, it will take us down to the next reader and + // we'll have more chars. + // + if (!popReader()) + return XMLCh(0); + + // Else try again and return the new character + fCurReader->getNextChar(chRet); + return chRet; +} + + +void ReaderMgr::getSpaces(XMLBuffer& toFill) +{ + // Reset the buffer before we start + toFill.reset(); + + // + // Get all the spaces from the current reader. If it returns true, + // it hit a non-space and we are done. Else we have to pop a reader + // and keep going. + // + while (!fCurReader->getSpaces(toFill)) + { + // We wore that one out, so lets pop a reader and try again + if (!popReader()) + break; + } +} + + +void ReaderMgr::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck) +{ + // Reset the target buffer before we start + toFill.reset(); + + // + // Ok, enter a loop where we ask the current reader to get chars until + // it meets the criteria. It returns false if it came back due to eating + // up all of its data. Else it returned because something matched, and + // we are done. + // + while (!fCurReader->getUpToCharOrWS(toFill, toCheck)) + { + // We ate that one up, lets try to pop another. If not, break out + if (!popReader()) + break; + } +} + + +XMLCh ReaderMgr::peekNextChar() +{ + XMLCh chRet; + if (fCurReader->peekNextChar(chRet)) + return chRet; + + // + // Didn't get anything back so this reader is hosed. So lets move to + // the next reader on the stack. If this fails, it will be because + // its the end of the original file, and we just return zero. + // + if (!popReader()) + return XMLCh(0); + + // Else peek again and return the character + fCurReader->peekNextChar(chRet); + return chRet; +} + + +bool ReaderMgr::skippedChar(const XMLCh toCheck) +{ + while (true) + { + // If we get it, then just return true now + if (fCurReader->skippedChar(toCheck)) + return true; + + // + // Check to see if we hit end of input on this reader. If so, then + // lets pop and try again. Else, we failed. If we cannot pop another + // then we failed. + // + if (!fCurReader->getNoMoreFlag()) + break; + + if (!popReader()) + break; + } + return false; +} + + +bool ReaderMgr::skippedSpace() +{ + while (true) + { + // If we get it, then just return true now + if (fCurReader->skippedSpace()) + return true; + + // + // Check to see if we hit end of input on this reader. If so, then + // lets pop and try again. Else, we failed. If we cannot pop another + // then we failed. + // + if (!fCurReader->getNoMoreFlag()) + break; + + if (!popReader()) + break; + } + return false; +} + + +bool ReaderMgr::skipIfQuote(XMLCh& chGotten) +{ + while (true) + { + // If we get it, then just return true now + if (fCurReader->skipIfQuote(chGotten)) + return true; + + // + // Check to see if we hit end of input on this reader. If so, then + // lets pop and try again. Else, we failed. If we cannot pop another + // then we failed. + // + if (!fCurReader->getNoMoreFlag()) + break; + + if (!popReader()) + break; + } + return false; +} + +void ReaderMgr::skipPastSpaces(bool& skippedSomething, bool inDecl /* = false */) +{ + // we rely on the fact that fCurReader->skipSpaces will NOT reset the flag to false, but only + // set it to true if a space is found + skippedSomething = false; + // + // Skip all the spaces in the current reader. If it returned because + // it hit a non-space, break out. Else we have to pop another entity + // and keep going. + // + while (!fCurReader->skipSpaces(skippedSomething, inDecl)) + { + // Try to pop another entity. If we can't then we are done + if (!popReader()) + break; + } +} + +void ReaderMgr::skipPastSpaces() +{ + // we are not using it, so we don't care to initialize it + bool tmpFlag; + // + // Skip all the spaces in the current reader. If it returned because + // it hit a non-space, break out. Else we have to pop another entity + // and keep going. + // + while (!fCurReader->skipSpaces(tmpFlag, false)) + { + // Try to pop another entity. If we can't then we are done + if (!popReader()) + break; + } +} + +void ReaderMgr::skipQuotedString(const XMLCh quoteCh) +{ + XMLCh nextCh; + // If we get an end of file char, then return + while ((nextCh = getNextChar())!=0) + { + // If we get the quote char, then break out + if (nextCh == quoteCh) + break; + } +} + + +XMLCh ReaderMgr::skipUntilIn(const XMLCh* const listToSkip) +{ + XMLCh nextCh; + // If we get an end of file char, then return + while ((nextCh = peekNextChar())!=0) + { + if (XMLString::indexOf(listToSkip, nextCh) != -1) + break; + + // Its one of ours so eat it + getNextChar(); + } + return nextCh; +} + + +XMLCh ReaderMgr::skipUntilInOrWS(const XMLCh* const listToSkip) +{ + XMLCh nextCh; + // If we get an end of file char, then return + while ((nextCh = peekNextChar())!=0) + { + if (fCurReader->isWhitespace(nextCh)) + break; + + if (XMLString::indexOf(listToSkip, nextCh) != -1) + break; + + // Its one of ours, so eat it + getNextChar(); + } + return nextCh; +} + + + +// --------------------------------------------------------------------------- +// ReaderMgr: Control methods +// --------------------------------------------------------------------------- + +// +// If the reader stack is empty, then there is only the original main XML +// entity left. If its empty, then we have no more input. +// +bool ReaderMgr::atEOF() const +{ + return fReaderStack->empty() && fCurReader->getNoMoreFlag(); +} + + +// +// This method is called in the case of errors to clean up the stack when +// entities have been incorrectly left on the stack due to syntax errors. +// It just cleans back the stack, and sends no entity events. +// +void ReaderMgr::cleanStackBackTo(const XMLSize_t readerNum) +{ + // + // Just start popping readers until we find the one with the indicated + // reader number. + // + while (true) + { + if (fCurReader->getReaderNum() == readerNum) + break; + + if (fReaderStack->empty()) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::RdrMgr_ReaderIdNotFound, fMemoryManager); + + delete fCurReader; + fCurReader = fReaderStack->pop(); + fCurEntity = fEntityStack->pop(); + } +} + + +XMLReader* ReaderMgr::createReader( const InputSource& src + , const bool + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLReader::Sources source + , const bool calcSrcOfs + , XMLSize_t lowWaterMark) +{ + // + // Ask the input source to create us an input stream. The particular + // type of input source will know what kind to create. + // + BinInputStream* newStream = src.makeStream(); + if (!newStream) + return 0; + + Janitor streamJanitor(newStream); + + // + // Create a new reader and return it. If the source has an encoding that + // it wants to force, then we call the constructor that does that. + // Otherwise, we just call the one that provides the provisional encoding + // to be possibly updated later by the encoding="" setting. + // + XMLReader* retVal = 0; + + // XMLReader ctor invokes refreshRawBuffer() which calls + // newStream->readBytes(). + // This readBytes() may throw exception, which neither + // refresRawBuffer(), nor XMLReader ctor catches. + // We need to handle this exception to avoid leak on newStream. + + try { + if (src.getEncoding()) + { + retVal = new (fMemoryManager) XMLReader + ( + src.getPublicId() + , src.getSystemId() + , newStream + , src.getEncoding() + , refFrom + , type + , source + , false + , calcSrcOfs + , lowWaterMark + , fXMLVersion + , fMemoryManager + ); + } + else + { + retVal = new (fMemoryManager) XMLReader + ( + src.getPublicId() + , src.getSystemId() + , newStream + , refFrom + , type + , source + , false + , calcSrcOfs + , lowWaterMark + , fXMLVersion + , fMemoryManager + ); + } + } + catch(const OutOfMemoryException&) + { + streamJanitor.release(); + + throw; + } + + assert(retVal); + + streamJanitor.release(); + + // Set the next available reader number on this reader + retVal->setReaderNum(fNextReaderNum++); + return retVal; +} + + +XMLReader* ReaderMgr::createReader( const XMLCh* const sysId + , const XMLCh* const pubId + , const bool xmlDecl + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLReader::Sources source + , InputSource*& srcToFill + , const bool calcSrcOfs + , XMLSize_t lowWaterMark + , const bool disableDefaultEntityResolution) +{ + //Normalize sysId + XMLBuffer normalizedSysId(1023, fMemoryManager); + if(sysId) + XMLString::removeChar(sysId, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the system id + XMLBuffer expSysId(1023, fMemoryManager); + + // + // Allow the entity handler to expand the system id if they choose + // to do so. + // + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + } + else + { + expSysId.set(normalizedURI); + } + + // Call the entity resolver interface to get an input source + srcToFill = 0; + if (fEntityHandler) + { + LastExtEntityInfo lastInfo; + getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity, + expSysId.getRawBuffer(), XMLUni::fgZeroLenString, pubId, lastInfo.systemId, + this); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + + // + // If they didn't create a source via the entity resolver, then we + // have to create one on our own. + // + if (!srcToFill) + { + if (disableDefaultEntityResolution) + return 0; + + LastExtEntityInfo lastInfo; + getLastExtEntityInfo(lastInfo); + +// Keep this #if 0 block as it was exposing a threading problem on AIX. +// Got rid of the problem by changing XMLURL to not throw malformedurl +// exceptions. +#if 0 + try + { + XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer(), fMemoryManager); + if (urlTmp.isRelative()) + { + ThrowXMLwithMemMgr + ( + MalformedURLException + , XMLExcepts::URL_NoProtocolPresent + , fMemoryManager + ); + } + else { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + catch(const MalformedURLException& e) + { + // Its not a URL, so lets assume its a local file name if non-standard uri is allowed + if (!fStandardUriConformant) + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , expSysId.getRawBuffer() + , fMemoryManager + ); + else + throw e; + } +#else + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBuffer resolvedSysId(1023, fMemoryManager); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } +#endif + } + + // Put a janitor on the input source + Janitor janSrc(srcToFill); + + // + // Now call the other version with the input source that we have, and + // return the resulting reader. + // + XMLReader* retVal = createReader + ( + *srcToFill + , xmlDecl + , refFrom + , type + , source + , calcSrcOfs + , lowWaterMark + ); + + // Either way, we can release the input source now + janSrc.orphan(); + + // If it failed for any reason, then return zero. + if (!retVal) + return 0; + + // Give this reader the next available reader number and return it + retVal->setReaderNum(fNextReaderNum++); + return retVal; +} + + +XMLReader* ReaderMgr::createReader( const XMLCh* const baseURI + , const XMLCh* const sysId + , const XMLCh* const pubId + , const bool xmlDecl + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLReader::Sources source + , InputSource*& srcToFill + , const bool calcSrcOfs + , XMLSize_t lowWaterMark + , const bool disableDefaultEntityResolution) +{ + //Normalize sysId + XMLBuffer normalizedSysId(1023, fMemoryManager); + XMLString::removeChar(sysId, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the system id + XMLBuffer expSysId(1023, fMemoryManager); + + // + // Allow the entity handler to expand the system id if they choose + // to do so. + // + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + } + else + { + expSysId.set(normalizedURI); + } + + // Call the entity resolver interface to get an input source + srcToFill = 0; + if (fEntityHandler) + { + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity, + expSysId.getRawBuffer(), XMLUni::fgZeroLenString, pubId, baseURI, + this); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + + // + // If they didn't create a source via the entity resolver, then we + // have to create one on our own. + // + if (!srcToFill) + { + if (disableDefaultEntityResolution) + return 0; + + LastExtEntityInfo lastInfo; + + const XMLCh* baseuri=baseURI; + if(!baseuri || !*baseuri) + { + getLastExtEntityInfo(lastInfo); + baseuri = lastInfo.systemId; + } + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(baseuri, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBuffer resolvedSysId(1023, fMemoryManager); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + baseuri + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + // Put a janitor on the input source + Janitor janSrc(srcToFill); + + // + // Now call the other version with the input source that we have, and + // return the resulting reader. + // + XMLReader* retVal = createReader + ( + *srcToFill + , xmlDecl + , refFrom + , type + , source + , calcSrcOfs + , lowWaterMark + ); + + // Either way, we can release the input source now + janSrc.orphan(); + + // If it failed for any reason, then return zero. + if (!retVal) + return 0; + + // Give this reader the next available reader number and return it + retVal->setReaderNum(fNextReaderNum++); + return retVal; +} + + +XMLReader* +ReaderMgr::createIntEntReader( const XMLCh* const sysId + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLCh* const dataBuf + , const XMLSize_t dataLen + , const bool copyBuf + , const bool calcSrcOfs + , XMLSize_t lowWaterMark) +{ + // + // This one is easy, we just create an input stream for the data and + // provide a few extra goodies. + // + // NOTE: We use a special encoding string that will be recognized + // as a 'do nothing' transcoder for the already internalized XMLCh + // data that makes up an internal entity. + // + BinMemInputStream* newStream = new (fMemoryManager) BinMemInputStream + ( + (const XMLByte*)dataBuf + , dataLen * sizeof(XMLCh) + , copyBuf ? BinMemInputStream::BufOpt_Copy + : BinMemInputStream::BufOpt_Reference + , fMemoryManager + ); + if (!newStream) + return 0; + + XMLReader* retVal = new (fMemoryManager) XMLReader + ( + sysId + , 0 + , newStream + , XMLRecognizer::XERCES_XMLCH + , refFrom + , type + , XMLReader::Source_Internal + , false + , calcSrcOfs + , lowWaterMark + , fXMLVersion + , fMemoryManager + ); + + // If it failed for any reason, then return zero. + if (!retVal) { + delete newStream; + return 0; + } + + // Set the reader number to the next available number + retVal->setReaderNum(fNextReaderNum++); + return retVal; +} + + +const XMLCh* ReaderMgr::getCurrentEncodingStr() const +{ + const XMLEntityDecl* theEntity; + const XMLReader* theReader = getLastExtEntity(theEntity); + + return theReader->getEncodingStr(); +} + + +const XMLEntityDecl* ReaderMgr::getCurrentEntity() const +{ + return fCurEntity; +} + + +XMLEntityDecl* ReaderMgr::getCurrentEntity() +{ + return fCurEntity; +} + + +XMLSize_t ReaderMgr::getReaderDepth() const +{ + // If the stack doesn't exist, its obviously zero + if (!fEntityStack) + return 0; + + // + // The return is the stack size, plus one if there is a current + // reader. So if there is no current reader and none on the stack, + // its zero, else its some non-zero value. + // + XMLSize_t retVal = fEntityStack->size(); + if (fCurReader) + retVal++; + return retVal; +} + +void ReaderMgr::getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const +{ + // + // If the reader stack never got created or we've not managed to open any + // main entity yet, then we can't give this information. + // + if (!fReaderStack || !fCurReader) + { + lastInfo.systemId = XMLUni::fgZeroLenString; + lastInfo.publicId = XMLUni::fgZeroLenString; + lastInfo.lineNumber = 0; + lastInfo.colNumber = 0; + return; + } + + // We have at least one entity so get the data + const XMLEntityDecl* theEntity; + const XMLReader* theReader = getLastExtEntity(theEntity); + + // Fill in the info structure with the reader we found + lastInfo.systemId = theReader->getSystemId(); + lastInfo.publicId = theReader->getPublicId(); + lastInfo.lineNumber = theReader->getLineNumber(); + lastInfo.colNumber = theReader->getColumnNumber(); +} + + +bool ReaderMgr::isScanningPERefOutOfLiteral() const +{ + // If the current reader is not for an entity, then definitely not + if (!fCurEntity) + return false; + + // + // If this is a PE entity, and its not being expanded in a literal + // then its true. + // + if ((fCurReader->getType() == XMLReader::Type_PE) + && (fCurReader->getRefFrom() == XMLReader::RefFrom_NonLiteral)) + { + return true; + } + return false; +} + + +bool ReaderMgr::pushReader( XMLReader* const reader + , XMLEntityDecl* const entity) +{ + // + // First, if an entity was passed, we have to confirm that this entity + // is not already on the entity stack. If so, then this is a recursive + // entity expansion, so we issue an error and refuse to put the reader + // on the stack. + // + // If there is no entity passed, then its not an entity being pushed, so + // nothing to do. If there is no entity stack yet, then of coures it + // cannot already be there. + // + if (entity && fEntityStack) + { + const XMLSize_t count = fEntityStack->size(); + const XMLCh* const theName = entity->getName(); + for (XMLSize_t index = 0; index < count; index++) + { + const XMLEntityDecl* curDecl = fEntityStack->elementAt(index); + if (curDecl) + { + if (XMLString::equals(theName, curDecl->getName())) + { + // Oops, already there so delete reader and return + delete reader; + return false; + } + } + } + } + + // + // Fault in the reader stack. Give it an initial capacity of 16, and + // tell it it does own its elements. + // + if (!fReaderStack) + fReaderStack = new (fMemoryManager) RefStackOf(16, true, fMemoryManager); + + // And the entity stack, which does not own its elements + if (!fEntityStack) + fEntityStack = new (fMemoryManager) RefStackOf(16, false, fMemoryManager); + + // + // Push the current reader and entity onto their respective stacks. + // Note that the the current entity can be null if the current reader + // is not for an entity. + // + if (fCurReader) + { + fReaderStack->push(fCurReader); + fEntityStack->push(fCurEntity); + } + + // + // Make the passed reader and entity the current top of stack. The + // passed entity can (and often is) null. + // + fCurReader = reader; + fCurEntity = entity; + + return true; +} + + +void ReaderMgr::reset() +{ + // Reset all of the flags + fThrowEOE = false; + + // Delete the current reader and flush the reader stack + delete fCurReader; + fCurReader = 0; + if (fReaderStack) + fReaderStack->removeAllElements(); + + // + // And do the same for the entity stack, but don't delete the current + // entity (if any) since we don't own them. + // + fCurEntity = 0; + if (fEntityStack) + fEntityStack->removeAllElements(); +} + + +// --------------------------------------------------------------------------- +// ReaderMgr: Implement the SAX Locator interface +// --------------------------------------------------------------------------- +const XMLCh* ReaderMgr::getPublicId() const +{ + if (!fReaderStack && !fCurReader) + return XMLUni::fgZeroLenString; + + const XMLEntityDecl* theEntity; + return getLastExtEntity(theEntity)->getPublicId(); +} + +const XMLCh* ReaderMgr::getSystemId() const +{ + if (!fReaderStack && !fCurReader) + return XMLUni::fgZeroLenString; + + const XMLEntityDecl* theEntity; + return getLastExtEntity(theEntity)->getSystemId(); +} + +XMLFileLoc ReaderMgr::getColumnNumber() const +{ + if (!fReaderStack && !fCurReader) + return 0; + + const XMLEntityDecl* theEntity; + return getLastExtEntity(theEntity)->getColumnNumber(); +} + +XMLFileLoc ReaderMgr::getLineNumber() const +{ + if (!fReaderStack && !fCurReader) + return 0; + + const XMLEntityDecl* theEntity; + return getLastExtEntity(theEntity)->getLineNumber(); +} + + + +// --------------------------------------------------------------------------- +// ReaderMgr: Private helper methods +// --------------------------------------------------------------------------- +const XMLReader* +ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const +{ + // + // Scan down the reader stack until we find a reader for an entity that + // is external. First check that there is anything in the stack at all, + // in which case the current reader is the main file and that's the one + // that we want. + // + const XMLReader* theReader = fCurReader; + + // + // If there is a current entity and it is not an external entity, then + // search the stack; else, keep the reader that we've got since its + // either an external entity reader or the main file reader. + // + const XMLEntityDecl* curEntity = fCurEntity; + if (curEntity && !curEntity->isExternal()) + { + XMLSize_t index = fReaderStack->size(); + if (index) + { + while (true) + { + // Move down to the previous element and get a pointer to it + index--; + curEntity = fEntityStack->elementAt(index); + + // + // If its null or its an external entity, then this reader + // is what we want, so break out with that one. + // + if (!curEntity) + { + theReader = fReaderStack->elementAt(index); + break; + } + else if (curEntity->isExternal()) + { + theReader = fReaderStack->elementAt(index); + break; + } + + // We hit the end, so leave the main file reader as the one + if (!index) + break; + } + } + } + + itsEntity = curEntity; + return theReader; +} + + +bool ReaderMgr::popReader() +{ + // + // We didn't get any more, so try to pop off a reader. If the reader + // stack is empty, then we are at the end, so return false. + // + if (fReaderStack->empty()) + return false; + + // + // Remember the current entity, before we pop off a new one. We might + // need this to throw the end of entity exception at the end. + // + XMLEntityDecl* prevEntity = fCurEntity; + const bool prevReaderThrowAtEnd = fCurReader->getThrowAtEnd(); + const XMLSize_t readerNum = fCurReader->getReaderNum(); + + // + // Delete the current reader and pop a new reader and entity off + // the stacks. + // + delete fCurReader; + fCurReader = fReaderStack->pop(); + fCurEntity = fEntityStack->pop(); + + // + // If there was a previous entity, and either the fThrowEOE flag is set + // or reader was marked as such, then throw an end of entity. + // + if (prevEntity && (fThrowEOE || prevReaderThrowAtEnd)) + throw EndOfEntityException(prevEntity, readerNum); + + while (true) + { + // + // They don't want us to throw, so lets just return with a new + // reader. Here we have to do a loop because we might have multiple + // readers on these stack that are empty (i.e. the last char in them + // was the ';' at the end of the entity ref that caused the next + // entity to be pushed. + // + // So we loop until we find a non-empty reader, or hit the main + // file entity. If we find one with some chars available, then break + // out and take that one. + // + if (fCurReader->charsLeftInBuffer()) + break; + + fCurReader->refreshCharBuffer(); + if (fCurReader->charsLeftInBuffer()) + break; + + // + // The current one is hosed. So, if the reader stack is empty we + // are dead meat and can give up now. + // + if (fReaderStack->empty()) + return false; + + // Else pop again and try it one more time + delete fCurReader; + fCurReader = fReaderStack->pop(); + fCurEntity = fEntityStack->pop(); + } + return true; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/ReaderMgr.hpp b/include/xercesc/internal/ReaderMgr.hpp new file mode 100644 index 0000000..1d8d783 --- /dev/null +++ b/include/xercesc/internal/ReaderMgr.hpp @@ -0,0 +1,447 @@ +/* + * 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: ReaderMgr.hpp 833045 2009-11-05 13:21:27Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_READERMGR_HPP) +#define XERCESC_INCLUDE_GUARD_READERMGR_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLEntityDecl; +class XMLEntityHandler; +class XMLDocumentHandler; +class XMLScanner; + + +// --------------------------------------------------------------------------- +// This class is used by the scanner. The scanner must deal with expansion +// of entities, some of which are totally different files (external parsed +// entities.) It does so by pushing readers onto a stack. The top reader is +// the one it wants to read out of, but that one must be popped when it is +// empty. To keep that logic from being all over the place, the scanner +// talks to the reader manager, which handles the stack and popping off +// used up readers. +// --------------------------------------------------------------------------- +class XMLPARSER_EXPORT ReaderMgr : public XMemory + , public Locator +{ +public : + // ----------------------------------------------------------------------- + // Class specific types + // ----------------------------------------------------------------------- + struct LastExtEntityInfo : public XMemory + { + const XMLCh* systemId; + const XMLCh* publicId; + XMLFileLoc lineNumber; + XMLFileLoc colNumber; + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + ReaderMgr(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~ReaderMgr(); + + + // ----------------------------------------------------------------------- + // Convenience scanning methods + // + // This are all convenience methods that work in terms of the core + // character spooling methods. + // ----------------------------------------------------------------------- + bool atEOF() const; + bool getName(XMLBuffer& toFill); + bool getQName(XMLBuffer& toFill, int* colonPosition); + bool getNameToken(XMLBuffer& toFill); + XMLCh getNextChar(); + bool getNextCharIfNot(const XMLCh chNotToGet, XMLCh& chGotten); + void movePlainContentChars(XMLBuffer &dest); + void getSpaces(XMLBuffer& toFill); + void getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck); + bool isEmpty() const; + bool lookingAtChar(const XMLCh toCheck); + bool lookingAtSpace(); + XMLCh peekNextChar(); + bool skipIfQuote(XMLCh& chGotten); + void skipPastChar(const XMLCh toSkip); + void skipPastSpaces(bool& skippedSomething, bool inDecl = false); + void skipPastSpaces(); + void skipToChar(const XMLCh toSkipTo); + bool skippedChar(const XMLCh toSkip); + bool skippedSpace(); + bool skippedString(const XMLCh* const toSkip); + bool skippedStringLong(const XMLCh* const toSkip); + void skipQuotedString(const XMLCh quoteCh); + XMLCh skipUntilIn(const XMLCh* const listToSkip); + XMLCh skipUntilInOrWS(const XMLCh* const listToSkip); + bool peekString(const XMLCh* const toPeek); + + + // ----------------------------------------------------------------------- + // Control methods + // ----------------------------------------------------------------------- + void cleanStackBackTo(const XMLSize_t readerNum); + XMLReader* createReader + ( + const InputSource& src + , const bool xmlDecl + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLReader::Sources source + , const bool calcSrsOfs = true + , XMLSize_t lowWaterMark = 100 + ); + XMLReader* createReader + ( + const XMLCh* const sysId + , const XMLCh* const pubId + , const bool xmlDecl + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLReader::Sources source + , InputSource*& srcToFill + , const bool calcSrcOfs = true + , XMLSize_t lowWaterMark = 100 + , const bool disableDefaultEntityResolution = false + ); + XMLReader* createReader + ( + const XMLCh* const baseURI + , const XMLCh* const sysId + , const XMLCh* const pubId + , const bool xmlDecl + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLReader::Sources source + , InputSource*& srcToFill + , const bool calcSrcOfs = true + , XMLSize_t lowWaterMark = 100 + , const bool disableDefaultEntityResolution = false + ); + XMLReader* createIntEntReader + ( + const XMLCh* const sysId + , const XMLReader::RefFrom refFrom + , const XMLReader::Types type + , const XMLCh* const dataBuf + , const XMLSize_t dataLen + , const bool copyBuf + , const bool calcSrcOfs = true + , XMLSize_t lowWaterMark = 100 + ); + bool isScanningPERefOutOfLiteral() const; + bool pushReader + ( + XMLReader* const reader + , XMLEntityDecl* const entity + ); + void reset(); + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + const XMLCh* getCurrentEncodingStr() const; + const XMLEntityDecl* getCurrentEntity() const; + XMLEntityDecl* getCurrentEntity(); + const XMLReader* getCurrentReader() const; + XMLReader* getCurrentReader(); + XMLSize_t getCurrentReaderNum() const; + XMLSize_t getReaderDepth() const; + void getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const; + XMLFilePos getSrcOffset() const; + bool getThrowEOE() const; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setEntityHandler(XMLEntityHandler* const newHandler); + void setThrowEOE(const bool newValue); + void setXMLVersion(const XMLReader::XMLVersion version); + void setStandardUriConformant(const bool newValue); + + // ----------------------------------------------------------------------- + // Implement the SAX Locator interface + // ----------------------------------------------------------------------- + virtual const XMLCh* getPublicId() const; + virtual const XMLCh* getSystemId() const; + virtual XMLFileLoc getLineNumber() const; + virtual XMLFileLoc getColumnNumber() const; + + +private : + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + const XMLReader* getLastExtEntity(const XMLEntityDecl*& itsEntity) const; + bool popReader(); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ReaderMgr(const ReaderMgr&); + ReaderMgr& operator=(const ReaderMgr&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fCurEntity + // This is the current top of stack entity. We pull it off the stack + // and store it here for efficiency. + // + // fCurReader + // This is the current top of stack reader. We pull it off the + // stack and store it here for efficiency. + // + // fEntityHandler + // This is the installed entity handler. Its installed via the + // scanner but he passes it on to us since we need it the most, in + // process of creating external entity readers. + // + // fEntityStack + // We need to keep up with which of the pushed readers are pushed + // entity values that are being spooled. This is done to avoid the + // problem of recursive definitions. This stack consists of refs to + // EntityDecl objects for the pushed entities. + // + // fNextReaderNum + // This is the reader serial number value. Each new reader that is + // created from this reader is given a successive number. This lets + // us catch things like partial markup errors and such. + // + // fReaderStack + // This is the stack of reader references. We own all the readers + // and destroy them when they are used up. + // + // fThrowEOE + // This flag controls whether we throw an exception when we hit an + // end of entity. The scanner doesn't really need to know about ends + // of entities in the int/ext subsets, so it will turn this flag off + // until it gets into the content usually. + // + // fXMLVersion + // Enum to indicate if each Reader should be created as XML 1.1 or + // XML 1.0 conformant + // + // fStandardUriConformant + // This flag controls whether we force conformant URI + // ----------------------------------------------------------------------- + XMLEntityDecl* fCurEntity; + XMLReader* fCurReader; + XMLEntityHandler* fEntityHandler; + RefStackOf* fEntityStack; + unsigned int fNextReaderNum; + RefStackOf* fReaderStack; + bool fThrowEOE; + XMLReader::XMLVersion fXMLVersion; + bool fStandardUriConformant; + MemoryManager* fMemoryManager; +}; + + + +// --------------------------------------------------------------------------- +// ReaderMgr: Inlined methods +// +// NOTE: We cannot put these in alphabetical and type order as we usually +// do because some of the compilers we have to support are too stupid to +// understand out of order inlines! +// --------------------------------------------------------------------------- +inline XMLSize_t ReaderMgr::getCurrentReaderNum() const +{ + return fCurReader->getReaderNum(); +} + +inline const XMLReader* ReaderMgr::getCurrentReader() const +{ + return fCurReader; +} + +inline XMLReader* ReaderMgr::getCurrentReader() +{ + return fCurReader; +} + +inline bool ReaderMgr::getName(XMLBuffer& toFill) +{ + toFill.reset(); + return fCurReader->getName(toFill, false); +} + +inline bool ReaderMgr::getQName(XMLBuffer& toFill, int *colonPosition) +{ + toFill.reset(); + return fCurReader->getQName(toFill, colonPosition); +} + +inline bool ReaderMgr::getNameToken(XMLBuffer& toFill) +{ + toFill.reset(); + return fCurReader->getName(toFill, true); +} + +inline bool ReaderMgr::getNextCharIfNot(const XMLCh chNotToGet, XMLCh& chGotten) +{ + return fCurReader->getNextCharIfNot(chNotToGet, chGotten); +} + +inline void ReaderMgr::movePlainContentChars(XMLBuffer &dest) +{ + fCurReader->movePlainContentChars(dest); +} + +inline bool ReaderMgr::getThrowEOE() const +{ + return fThrowEOE; +} + +inline XMLFilePos ReaderMgr::getSrcOffset() const +{ + return fCurReader? fCurReader->getSrcOffset() : 0; +} + +inline bool ReaderMgr::lookingAtChar(const XMLCh chToCheck) +{ + return (chToCheck == peekNextChar()); +} + +inline bool ReaderMgr::lookingAtSpace() +{ + XMLCh c = peekNextChar(); + return fCurReader->isWhitespace(c); +} + +inline void ReaderMgr::setThrowEOE(const bool newValue) +{ + fThrowEOE = newValue; +} + +inline void ReaderMgr::setStandardUriConformant(const bool newValue) +{ + fStandardUriConformant = newValue; +} + +inline bool ReaderMgr::skippedString(const XMLCh* const toSkip) +{ + return fCurReader->skippedString(toSkip); +} + +inline bool ReaderMgr::skippedStringLong(const XMLCh* const toSkip) +{ + return fCurReader->skippedStringLong(toSkip); +} + +inline void ReaderMgr::skipToChar(const XMLCh toSkipTo) +{ + XMLCh nextCh = 0; + do + { + // Get chars until we find the one to skip + nextCh = getNextChar(); + } + // Break out at end of input or the char to skip + while((nextCh != toSkipTo) && nextCh!=0); +} + +inline void ReaderMgr::skipPastChar(const XMLCh toSkipPast) +{ + XMLCh nextCh = 0; + do + { + // Get chars until we find the one to skip + nextCh = getNextChar(); + } + while((nextCh != toSkipPast) && nextCh!=0); +} + +inline bool ReaderMgr::peekString(const XMLCh* const toPeek) +{ + return fCurReader->peekString(toPeek); +} + +inline void ReaderMgr::setEntityHandler(XMLEntityHandler* const newHandler) +{ + fEntityHandler = newHandler; +} + +inline void ReaderMgr::setXMLVersion(const XMLReader::XMLVersion version) +{ + fXMLVersion = version; + fCurReader->setXMLVersion(version); +} + +// +// This is a simple class to temporarily change the 'throw at end of entity' +// flag of the reader manager. There are some places where we need to +// turn this on and off on a scoped basis. +// +class XMLPARSER_EXPORT ThrowEOEJanitor +{ +public : + // ----------------------------------------------------------------------- + // Constructors and destructor + // ----------------------------------------------------------------------- + ThrowEOEJanitor(ReaderMgr* mgrTarget, const bool newValue) : + + fOld(mgrTarget->getThrowEOE()) + , fMgr(mgrTarget) + { + mgrTarget->setThrowEOE(newValue); + } + + ~ThrowEOEJanitor() + { + fMgr->setThrowEOE(fOld); + }; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ThrowEOEJanitor(const ThrowEOEJanitor&); + ThrowEOEJanitor& operator=(const ThrowEOEJanitor&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fOld + // The previous value of the flag, which we replaced during ctor, + // and will replace during dtor. + // + // fMgr + // A pointer to the reader manager we are going to set/reset the + // flag on. + // ----------------------------------------------------------------------- + bool fOld; + ReaderMgr* fMgr; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/SGXMLScanner.cpp b/include/xercesc/internal/SGXMLScanner.cpp new file mode 100644 index 0000000..df31323 --- /dev/null +++ b/include/xercesc/internal/SGXMLScanner.cpp @@ -0,0 +1,4958 @@ +/* + * 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: SGXMLScanner.cpp 1002320 2010-09-28 18:51:54Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +inline XMLAttDefList& getAttDefList(ComplexTypeInfo* currType, XMLElementDecl* elemDecl); + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ReaderMgrResetType; + + +// --------------------------------------------------------------------------- +// SGXMLScanner: Constructors and Destructor +// --------------------------------------------------------------------------- +SGXMLScanner::SGXMLScanner( XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(valToAdopt, grammarResolver, manager) + , fSeeXsi(false) + , fGrammarType(Grammar::UnKnown) + , fElemStateSize(16) + , fElemState(0) + , fElemLoopState(0) + , fContent(1023, manager) + , fEntityTable(0) + , fRawAttrList(0) + , fRawAttrColonListSize(32) + , fRawAttrColonList(0) + , fSchemaGrammar(0) + , fSchemaValidator(0) + , fICHandler(0) + , fElemNonDeclPool(0) + , fElemCount(0) + , fAttDefRegistry(0) + , fUndeclaredAttrRegistry(0) + , fPSVIAttrList(0) + , fModel(0) + , fPSVIElement(0) + , fErrorStack(0) + , fSchemaInfoList(0) + , fCachedSchemaInfoList(0) +{ + CleanupType cleanup(this, &SGXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +SGXMLScanner::SGXMLScanner( XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errHandler + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager) + , fSeeXsi(false) + , fGrammarType(Grammar::UnKnown) + , fElemStateSize(16) + , fElemState(0) + , fElemLoopState(0) + , fContent(1023, manager) + , fEntityTable(0) + , fRawAttrList(0) + , fRawAttrColonListSize(32) + , fRawAttrColonList(0) + , fSchemaGrammar(0) + , fSchemaValidator(0) + , fICHandler(0) + , fElemNonDeclPool(0) + , fElemCount(0) + , fAttDefRegistry(0) + , fUndeclaredAttrRegistry(0) + , fPSVIAttrList(0) + , fModel(0) + , fPSVIElement(0) + , fErrorStack(0) + , fSchemaInfoList(0) + , fCachedSchemaInfoList(0) +{ + CleanupType cleanup(this, &SGXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +SGXMLScanner::~SGXMLScanner() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Getter methods +// --------------------------------------------------------------------------- +NameIdPool* SGXMLScanner::getEntityDeclPool() +{ + return 0; +} + +const NameIdPool* SGXMLScanner::getEntityDeclPool() const +{ + return 0; +} + +// --------------------------------------------------------------------------- +// SGXMLScanner: Main entry point to scan a document +// --------------------------------------------------------------------------- +void SGXMLScanner::scanDocument(const InputSource& src) +{ + // Bump up the sequence id for this parser instance. This will invalidate + // any previous progressive scan tokens. + fSequenceId++; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + // Reset the scanner and its plugged in stuff for a new run. This + // resets all the data structures, creates the initial reader and + // pushes it on the stack, and sets up the base document path. + scanReset(src); + + // If we have a document handler, then call the start document + if (fDocHandler) + fDocHandler->startDocument(); + + // Scan the prolog part, which is everything before the root element + // including the DTD subsets. + scanProlog(); + + // If we got to the end of input, then its not a valid XML file. + // Else, go on to scan the content. + if (fReaderMgr.atEOF()) + { + emitError(XMLErrs::EmptyMainEntity); + } + else + { + // Scan content, and tell it its not an external entity + if (scanContent()) + { + // Do post-parse validation if required + if (fValidate) + { + // We handle ID reference semantics at this level since + // its required by XML 1.0. + checkIDRefs(); + + // Then allow the validator to do any extra stuff it wants +// fValidator->postParseValidation(); + } + + // That went ok, so scan for any miscellaneous stuff + if (!fReaderMgr.atEOF()) + scanMiscellaneous(); + } + } + + // If we have a document handler, then call the end document + if (fDocHandler) + fDocHandler->endDocument(); + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } +} + + +bool SGXMLScanner::scanNext(XMLPScanToken& token) +{ + // Make sure this token is still legal + if (!isLegalToken(token)) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager); + + // Find the next token and remember the reader id + XMLSize_t orgReader; + XMLTokens curToken; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + bool retVal = true; + + try + { + while (true) + { + // We have to handle any end of entity exceptions that happen here. + // We could be at the end of X nested entities, each of which will + // generate an end of entity exception as we try to move forward. + try + { + curToken = senseNextToken(orgReader); + break; + } + catch(const EndOfEntityException& toCatch) + { + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + if (curToken == Token_CharData) + { + scanCharData(fCDataBuf); + } + else if (curToken == Token_EOF) + { + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + retVal = false; + } + else + { + // Its some sort of markup + bool gotData = true; + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // If we hit the end, then do the miscellaneous part + if (!gotData) + { + // Do post-parse validation if required + if (fValidate) + { + // We handle ID reference semantics at this level since + // its required by XML 1.0. + checkIDRefs(); + + // Then allow the validator to do any extra stuff it wants +// fValidator->postParseValidation(); + } + + // That went ok, so scan for any miscellaneous stuff + scanMiscellaneous(); + + if (toCheckIdentityConstraint()) + fICHandler->endDocument(); + + if (fDocHandler) + fDocHandler->endDocument(); + } + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so return failure + retVal = false; + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so return failure + retVal = false; + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + retVal = false; + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + // If we are not at the end, release the object that will + // reset the ReaderMgr. + if (retVal) + resetReaderMgr.release(); + + return retVal; +} + +// --------------------------------------------------------------------------- +// SGXMLScanner: Private scanning methods +// --------------------------------------------------------------------------- + +// This method is called from scanStartTag() to handle the very raw initial +// scan of the attributes. It just fills in the passed collection with +// key/value pairs for each attribute. No processing is done on them at all. +XMLSize_t +SGXMLScanner::rawAttrScan(const XMLCh* const elemName + , RefVectorOf& toFill + , bool& isEmpty) +{ + // Keep up with how many attributes we've seen so far, and how many + // elements are available in the vector. This way we can reuse old + // elements until we run out and then expand it. + XMLSize_t attCount = 0; + XMLSize_t curVecSize = toFill.size(); + + // Assume it is not empty + isEmpty = false; + + // We loop until we either see a /> or >, handling key/value pairs util + // we get there. We place them in the passed vector, which we will expand + // as required to hold them. + while (true) + { + // Get the next character, which should be non-space + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + // + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + // Ok, skip by them and get another char + fReaderMgr.getNextChar(); + fReaderMgr.skipPastSpaces(); + nextCh = fReaderMgr.peekNextChar(); + } + else + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume its going to be an attribute, so get a name from + // the input. + int colonPosition; + if (!fReaderMgr.getQName(fAttNameBuf, &colonPosition)) + { + if (fAttNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedAttrName); + else + emitError(XMLErrs::InvalidAttrName, fAttNameBuf.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return attCount; + } + + const XMLCh* curAttNameBuf = fAttNameBuf.getRawBuffer(); + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemName); + return attCount; + } + else + { + // Something went really wrong + return attCount; + } + } + + // Next should be the quoted attribute value. We just do a simple + // and stupid scan of this value. The only thing we do here + // is to expand entity references. + if (!basicAttrValueScan(curAttNameBuf, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, elemName); + return attCount; + } + else + { + // Something went really wrong + return attCount; + } + } + + // And now lets add it to the passed collection. If we have not + // filled it up yet, then we use the next element. Else we add + // a new one. + KVStringPair* curPair = 0; + if (attCount >= curVecSize) + { + curPair = new (fMemoryManager) KVStringPair + ( + curAttNameBuf + , fAttNameBuf.getLen() + , fAttValueBuf.getRawBuffer() + , fAttValueBuf.getLen() + , fMemoryManager + ); + toFill.addElement(curPair); + } + else + { + curPair = toFill.elementAt(attCount); + curPair->set + ( + curAttNameBuf + , fAttNameBuf.getLen() + , fAttValueBuf.getRawBuffer() + , fAttValueBuf.getLen() + ); + } + if (attCount >= fRawAttrColonListSize) { + resizeRawAttrColonList(); + } + fRawAttrColonList[attCount] = colonPosition; + + // And bump the count of attributes we've gotten + attCount++; + + // And go to the top again for another attribute + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, elemName); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, elemName); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + return attCount; +} + + +// This method will kick off the scanning of the primary content of the +// document, i.e. the elements. +bool SGXMLScanner::scanContent() +{ + // Go into a loop until we hit the end of the root element, or we fall + // out because there is no root element. + // + // We have to do kind of a deeply nested double loop here in order to + // avoid doing the setup/teardown of the exception handler on each + // round. Doing it this way we only do it when an exception actually + // occurs. + bool gotData = true; + bool inMarkup = false; + while (gotData) + { + try + { + while (gotData) + { + // Sense what the next top level token is. According to what + // this tells us, we will call something to handle that kind + // of thing. + XMLSize_t orgReader; + const XMLTokens curToken = senseNextToken(orgReader); + + // Handle character data and end of file specially. Char data + // is not markup so we don't want to handle it in the loop + // below. + if (curToken == Token_CharData) + { + // Scan the character data and call appropriate events. Let + // him use our local character data buffer for efficiency. + scanCharData(fCDataBuf); + continue; + } + else if (curToken == Token_EOF) + { + // The element stack better be empty at this point or we + // ended prematurely before all elements were closed. + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + // Its the end of file, so clear the got data flag + gotData = false; + continue; + } + + // We are in some sort of markup now + inMarkup = true; + + // According to the token we got, call the appropriate + // scanning method. + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // And we are back out of markup again + inMarkup = false; + } + } + catch(const EndOfEntityException& toCatch) + { + // If we were in some markup when this happened, then its a + // partial markup error. + if (inMarkup) + emitError(XMLErrs::PartialMarkupInEntity); + + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + + inMarkup = false; + } + } + + // It went ok, so return success + return true; +} + + +void SGXMLScanner::scanEndTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the end of the root element. + gotData = true; + + // Check if the element stack is empty. If so, then this is an unbalanced + // element (i.e. more ends than starts, perhaps because of bad text + // causing one to be skipped.) + if (fElemStack.isEmpty()) + { + emitError(XMLErrs::MoreEndThanStartTags); + fReaderMgr.skipPastChar(chCloseAngle); + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager); + } + + // Pop the stack of the element we are supposed to be ending. Remember + // that we don't own this. The stack just keeps them and reuses them. + unsigned int uriId = (fDoNamespaces) + ? fElemStack.getCurrentURI() : fEmptyNamespaceId; + + // Make sure that its the end of the element that we expect + const XMLCh *elemName = fElemStack.getCurrentSchemaElemName(); + const ElemStack::StackElem* topElem = fElemStack.topElement(); + if (!fReaderMgr.skippedStringLong(elemName)) + { + emitError + ( + XMLErrs::ExpectedEndOfTagX + , elemName + ); + fReaderMgr.skipPastChar(chCloseAngle); + fElemStack.popTop(); + return; + } + + fPSVIElemContext.fErrorOccurred = fErrorStack->pop(); + + // Make sure we are back on the same reader as where we started + if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialTagMarkupError); + + // Skip optional whitespace + fReaderMgr.skipPastSpaces(); + + // Make sure we find the closing bracket + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError + ( + XMLErrs::UnterminatedEndTag + , topElem->fThisElement->getFullName() + ); + } + + if (fValidate && topElem->fThisElement->isDeclared()) + { + fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo(); + if(!fPSVIElemContext.fCurrentTypeInfo) + fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + else + fPSVIElemContext.fCurrentDV = 0; + if (fPSVIHandler) + { + fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue(); + + if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString)) + fPSVIElemContext.fNormalizedValue = 0; + + } + } + else + { + fPSVIElemContext.fCurrentDV = 0; + fPSVIElemContext.fCurrentTypeInfo = 0; + fPSVIElemContext.fNormalizedValue = 0; + } + + // If validation is enabled, then lets pass him the list of children and + // this element and let him validate it. + DatatypeValidator* psviMemberType = 0; + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent + ( + topElem->fThisElement + , topElem->fChildren + , topElem->fChildCount + , &failure + ); + + if (!res) + { + // One of the elements is not valid for the content. NOTE that + // if no children were provided but the content model requires + // them, it comes back with a zero value. But we cannot use that + // to index the child array in this case, and have to put out a + // special message. + if (!topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::EmptyNotValidForContent + , topElem->fThisElement->getFormattedContentModel() + ); + } + else if (failure >= topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::NotEnoughElemsForCM + , topElem->fThisElement->getFormattedContentModel() + ); + } + else + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , topElem->fChildren[failure]->getRawName() + , topElem->fThisElement->getFormattedContentModel() + ); + } + + } + + // update PSVI info + if (((SchemaValidator*) fValidator)->getErrorOccurred()) + fPSVIElemContext.fErrorOccurred = true; + else if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union) + psviMemberType = fValidationContext->getValidatingMemberType(); + if (fPSVIHandler) + { + fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified(); + if(fPSVIElemContext.fIsSpecified) + fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)topElem->fThisElement)->getDefaultValue(); + } + + // call matchers and de-activate context + if (toCheckIdentityConstraint()) + { + fICHandler->deactivateContext + ( + (SchemaElementDecl *) topElem->fThisElement + , fContent.getRawBuffer() + , fValidationContext + , fPSVIElemContext.fCurrentDV + ); + } + + } + + // QName dv needed topElem to resolve URIs on the checkContent + fElemStack.popTop(); + + // See if it was the root element, to avoid multiple calls below + const bool isRoot = fElemStack.isEmpty(); + + if (fPSVIHandler) + { + endElementPSVI + ( + (SchemaElementDecl*)topElem->fThisElement, psviMemberType + ); + } + // now we can reset the datatype buffer, since the + // application has had a chance to copy the characters somewhere else + ((SchemaValidator *)fValidator)->clearDatatypeBuffer(); + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + if (fGrammarType == Grammar::SchemaGrammarType) { + if (topElem->fPrefixColonPos != -1) + fPrefixBuf.set(elemName, topElem->fPrefixColonPos); + else + fPrefixBuf.reset(); + } + else { + fPrefixBuf.set(topElem->fThisElement->getElementName()->getPrefix()); + } + fDocHandler->endElement + ( + *topElem->fThisElement + , uriId + , isRoot + , fPrefixBuf.getRawBuffer() + ); + } + + if (!isRoot) + { + // update error information + fErrorStack->push((fErrorStack->size() && fErrorStack->pop()) || fPSVIElemContext.fErrorOccurred); + } + + // If this was the root, then done with content + gotData = !isRoot; + + if (gotData) { + + // Restore the grammar + fGrammar = fElemStack.getCurrentGrammar(); + fGrammarType = fGrammar->getGrammarType(); + fValidator->setGrammar(fGrammar); + + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } +} + + +// This method handles the high level logic of scanning the DOCType +// declaration. This calls the DTDScanner and kicks off both the scanning of +// the internal subset and the scanning of the external subset, if any. +// +// When we get here the ', />, or attributes followed +// by one of those sequences. +bool SGXMLScanner::scanStartTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Reset element content + fContent.reset(); + + // The current position is after the open bracket, so we need to read in + // in the element name. + int prefixColonPos; + if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos)) + { + if (fQNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedElementName); + else + emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer()); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // First we have to do the rawest attribute scan. We don't do any + // normalization of them at all, since we don't know yet what type they + // might be (since we need the element decl in order to do that.) + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + bool isEmpty; + XMLSize_t attCount = rawAttrScan + ( + qnameRawBuf + , *fRawAttrList + , isEmpty + ); + + // save the contentleafname and currentscope before addlevel, for later use + ContentLeafNameTypeVector* cv = 0; + XMLContentModel* cm = 0; + unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE; + bool laxThisOne = false; + if (!isRoot) + { + // schema validator will have correct type if validating + SchemaElementDecl* tempElement = (SchemaElementDecl*) + fElemStack.topElement()->fThisElement; + SchemaElementDecl::ModelTypes modelType = tempElement->getModelType(); + ComplexTypeInfo *currType = 0; + + if (fValidate) + { + currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if (currType) + modelType = (SchemaElementDecl::ModelTypes)currType->getContentType(); + else // something must have gone wrong + modelType = SchemaElementDecl::Any; + } + else + { + currType = tempElement->getComplexTypeInfo(); + } + + if ((modelType == SchemaElementDecl::Mixed_Simple) + || (modelType == SchemaElementDecl::Mixed_Complex) + || (modelType == SchemaElementDecl::Children)) + { + cm = currType->getContentModel(); + cv = cm->getContentLeafNameTypeVector(); + currentScope = fElemStack.getCurrentScope(); + } + else if (modelType == SchemaElementDecl::Any) { + laxThisOne = true; + } + } + + // Now, since we might have to update the namespace map for this element, + // but we don't have the element decl yet, we just tell the element stack + // to expand up to get ready. + XMLSize_t elemDepth = fElemStack.addLevel(); + fElemStack.setValidationFlag(fValidate); + fElemStack.setPrefixColonPos(prefixColonPos); + + // Check if there is any external schema location specified, and if we are at root, + // go through them first before scanning those specified in the instance document + if (isRoot + && (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)) { + + if (fExternalSchemaLocation) + parseSchemaLocation(fExternalSchemaLocation, true); + if (fExternalNoNamespaceSchemaLocation) + resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true); + } + + // Make an initial pass through the list and find any xmlns attributes or + // schema attributes. + if (attCount) + scanRawAttrListforNameSpaces(attCount); + + // Resolve the qualified name to a URI and name so that we can look up + // the element decl for this element. We have now update the prefix to + // namespace map so we should get the correct element now. + unsigned int uriId = resolveQNameWithColon + ( + qnameRawBuf + , fPrefixBuf + , ElemStack::Mode_Element + , prefixColonPos + ); + + //if schema, check if we should lax or skip the validation of this element + bool parentValidation = fValidate; + if (cv) { + QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager); + // elementDepth will be > 0, as cv is only constructed if element is not + // root. + laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1); + } + + // Look up the element now in the grammar. This will get us back a + // generic element decl object. We tell him to fault one in if he does + // not find it. + XMLElementDecl* elemDecl = 0; + bool wasAdded = false; + const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1]; + const XMLCh* original_uriStr = fGrammar->getTargetNamespace(); + + if (uriId != fEmptyNamespaceId) { + + // Check in current grammar before switching if necessary + elemDecl = fGrammar->getElemDecl + ( + uriId + , nameRawBuf + , qnameRawBuf + , currentScope + ); + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope); + } + // this is initialized correctly only if there is + // no element decl. The other uses in this scope will only + // be encountered if there continues to be no element decl--which + // implies that this will have been initialized correctly. + unsigned int orgGrammarUri = uriId; + if (!elemDecl && ( orgGrammarUri = fURIStringPool->getId(original_uriStr)) != uriId) { + // not found, switch to the specified grammar + const XMLCh* uriStr = getURIText(uriId); + bool errorCondition = !switchGrammar(uriStr) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + ,uriStr + ); + } + + elemDecl = fGrammar->getElemDecl + ( + uriId + , nameRawBuf + , qnameRawBuf + , currentScope + ); + } + + if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) { + // if not found, then it may be a reference, try TOP_LEVEL_SCOPE + elemDecl = fGrammar->getElemDecl + ( + uriId + , nameRawBuf + , qnameRawBuf + , Grammar::TOP_LEVEL_SCOPE + ); + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE); + } + if(!elemDecl) { + // still not found in specified uri + // try emptyNamespace see if element should be un-qualified. + // Use a temp variable until we decide this is the case + XMLElementDecl* tempElemDecl = fGrammar->getElemDecl + ( + fEmptyNamespaceId + , nameRawBuf + , qnameRawBuf + , currentScope + ); + if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) { + fValidator->emitError + ( + XMLValid::ElementNotUnQualified + , qnameRawBuf + ); + elemDecl = tempElemDecl; + } + } + } + + if (!elemDecl) { + // still not found, fault this in and issue error later + // switch back to original grammar first (if necessary) + if(orgGrammarUri != uriId) + { + switchGrammar(original_uriStr); + } + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer() + , nameRawBuf + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId(fElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl)); + wasAdded = true; + } + } + else if (!elemDecl) + { + //the element has no prefix, + //thus it is either a non-qualified element defined in current targetNS + //or an element that is defined in the globalNS + + //try unqualifed first + elemDecl = fGrammar->getElemDecl + ( + uriId + , nameRawBuf + , qnameRawBuf + , currentScope + ); + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope); + } + // this is initialized correctly only if there is + // no element decl. The other uses in this scope will only + // be encountered if there continues to be no element decl--which + // implies that this will have been initialized correctly. + unsigned int orgGrammarUri = fEmptyNamespaceId; + if (!elemDecl && (orgGrammarUri = fURIStringPool->getId(original_uriStr)) != fEmptyNamespaceId) { + //not found, switch grammar and try globalNS + bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + , XMLUni::fgZeroLenString + ); + } + + elemDecl = fGrammar->getElemDecl + ( + uriId + , nameRawBuf + , qnameRawBuf + , currentScope + ); + } + + if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) { + // if not found, then it may be a reference, try TOP_LEVEL_SCOPE + elemDecl = fGrammar->getElemDecl + ( + uriId + , nameRawBuf + , qnameRawBuf + , Grammar::TOP_LEVEL_SCOPE + ); + if(!elemDecl) + { + // look in the list of undeclared elements, as would have been done + // before we made grammars stateless: + elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE); + } + if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) { + // still Not found in specified uri + // go to original Grammar again to see if element needs to be fully qualified. + bool errorCondition = !switchGrammar(original_uriStr) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + ,original_uriStr + ); + } + + // Use a temp variable until we decide this is the case + XMLElementDecl* tempElemDecl = fGrammar->getElemDecl + ( + orgGrammarUri + , nameRawBuf + , qnameRawBuf + , currentScope + ); + if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) { + fValidator->emitError + ( + XMLValid::ElementNotQualified + , qnameRawBuf + ); + elemDecl=tempElemDecl; + } + } + } + + if (!elemDecl) { + // still not found, fault this in and issue error later + // switch back to original grammar first (if necessary) + if(orgGrammarUri != fEmptyNamespaceId) + { + switchGrammar(original_uriStr); + } + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer() + , nameRawBuf + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + elemDecl->setId(fElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl)); + wasAdded = true; + } + } + + // this info needed for DOMTypeInfo + fPSVIElemContext.fErrorOccurred = false; + + // We do something different here according to whether we found the + // element or not. + bool bXsiTypeSet= (fValidator)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false; + if (wasAdded) + { + if (laxThisOne && !bXsiTypeSet) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + + // If validating then emit an error + if (fValidate) + { + // This is to tell the reuse Validator that this element was + // faulted-in, was not an element in the grammar pool originally + elemDecl->setCreateReason(XMLElementDecl::JustFaultIn); + + if(!bXsiTypeSet) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + } + } + else + { + // If its not marked declared and validating, then emit an error + if (!elemDecl->isDeclared()) { + if(elemDecl->getCreateReason() == XMLElementDecl::NoReason) { + if(!bXsiTypeSet) + fPSVIElemContext.fErrorOccurred = true; + } + if (laxThisOne) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + + if (fValidate && !bXsiTypeSet) + { + fValidator->emitError + ( + XMLValid::ElementNotDefined + , elemDecl->getFullName() + ); + } + } + } + + + // Now we can update the element stack to set the current element + // decl. We expanded the stack above, but couldn't store the element + // decl because we didn't know it yet. + fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum()); + fElemStack.setCurrentURI(uriId); + + if (isRoot) + { + fRootGrammar = fGrammar; + fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager); + } + + if (fPSVIHandler) + { + fPSVIElemContext.fElemDepth++; + + if (elemDecl->isDeclared()) + { + fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth; + } + else + { + fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth; + + /****** + * While we report an error for historical reasons, this should + * actually result in lax assessment - NG. + if (isRoot && fValidate) + fPSVIElemContext.fErrorOccurred = true; + ******/ + } + } + + // Validate the element + if (fValidate) + { + fValidator->validateElement(elemDecl); + if (((SchemaValidator*) fValidator)->getErrorOccurred()) + fPSVIElemContext.fErrorOccurred = true; + } + + // squirrel away the element's QName, so that we can do an efficient + // end-tag match + fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer()); + + ComplexTypeInfo* typeinfo = (fValidate) + ? ((SchemaValidator*)fValidator)->getCurrentTypeInfo() + : ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo(); + + if (typeinfo) { + currentScope = typeinfo->getScopeDefined(); + + // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type) + XMLCh* typeName = typeinfo->getTypeName(); + const int comma = XMLString::indexOf(typeName, chComma); + if (comma > 0) { + XMLBuffer prefixBuf(comma+1, fMemoryManager); + prefixBuf.append(typeName, comma); + const XMLCh* uriStr = prefixBuf.getRawBuffer(); + + bool errorCondition = !switchGrammar(uriStr) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + , prefixBuf.getRawBuffer() + ); + } + } + else if (comma == 0) { + bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate; + if (errorCondition && !laxThisOne) + { + fValidator->emitError + ( + XMLValid::GrammarNotFound + , XMLUni::fgZeroLenString + ); + } + } + } + fElemStack.setCurrentScope(currentScope); + + // Set element next state + if (elemDepth >= fElemStateSize) { + resizeElemState(); + } + + fElemState[elemDepth] = 0; + fElemLoopState[elemDepth] = 0; + fElemStack.setCurrentGrammar(fGrammar); + + // If this is the first element and we are validating, check the root + // element. + if (!isRoot && parentValidation) + { + // If the element stack is not empty, then add this element as a + // child of the previous top element. If its empty, this is the root + // elem and is not the child of anything. + fElemStack.addChild(elemDecl->getElementName(), true); + } + + // PSVI handling: must reset this, even if no attributes... + if(getPSVIHandler()) + fPSVIAttrList->reset(); + + // Now lets get the fAttrList filled in. This involves faulting in any + // defaulted and fixed attributes and normalizing the values of any that + // we got explicitly. + // + // We update the attCount value with the total number of attributes, but + // it goes in with the number of values we got during the raw scan of + // explictly provided attrs above. + attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList); + + if(attCount) + { + // clean up after ourselves: + // clear the map used to detect duplicate attributes + fUndeclaredAttrRegistry->removeAll(); + } + + // activate identity constraints + if (toCheckIdentityConstraint()) + { + fICHandler->activateIdentityConstraint + ( + (SchemaElementDecl*) elemDecl + , (int) elemDepth + , uriId + , fPrefixBuf.getRawBuffer() + , *fAttrList + , attCount + , fValidationContext + ); + + } + + // Since the element may have default values, call start tag now regardless if it is empty or not + // If we have a document handler, then tell it about this start tag + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl + , uriId + , fPrefixBuf.getRawBuffer() + , *fAttrList + , attCount + , false + , isRoot + ); + } // may be where we output something... + + // if we have a PSVIHandler, now's the time to call + // its handleAttributesPSVI method: + if(fPSVIHandler) + { + QName *eName = elemDecl->getElementName(); + fPSVIHandler->handleAttributesPSVI + ( + eName->getLocalPart() + , fURIStringPool->getValueForId(eName->getURI()) + , fPSVIAttrList + ); + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // reset current type info + DatatypeValidator* psviMemberType = 0; + if (fGrammarType == Grammar::SchemaGrammarType) + { + if (fValidate && elemDecl->isDeclared()) + { + fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo(); + if(!fPSVIElemContext.fCurrentTypeInfo) + fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + else + fPSVIElemContext.fCurrentDV = 0; + if(fPSVIHandler) + { + fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue(); + + if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString)) + fPSVIElemContext.fNormalizedValue = 0; + } + } + else + { + fPSVIElemContext.fCurrentDV = 0; + fPSVIElemContext.fCurrentTypeInfo = 0; + fPSVIElemContext.fNormalizedValue = 0; + } + } + + // If validating, then insure that its legal to have no content + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent(elemDecl, 0, 0, &failure); + if (!res) + { + // REVISIT: in the case of xsi:type, this may + // return the wrong string... + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , elemDecl->getFullName() + , elemDecl->getFormattedContentModel() + ); + } + + if (((SchemaValidator*) fValidator)->getErrorOccurred()) + fPSVIElemContext.fErrorOccurred = true; + // note that if we're empty, won't be a current DV + else + { + if (fPSVIHandler) + { + fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified(); + if(fPSVIElemContext.fIsSpecified) + fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue(); + } + if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union) + psviMemberType = fValidationContext->getValidatingMemberType(); + } + + // call matchers and de-activate context + if (toCheckIdentityConstraint()) + { + fICHandler->deactivateContext + ( + (SchemaElementDecl *) elemDecl + , fContent.getRawBuffer() + , fValidationContext + , fPSVIElemContext.fCurrentDV + ); + } + + } + else if (fGrammarType == Grammar::SchemaGrammarType) { + ((SchemaValidator*)fValidator)->resetNillable(); + } + + if (fPSVIHandler) + { + endElementPSVI + ( + (SchemaElementDecl*)elemDecl, psviMemberType + ); + } + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + fDocHandler->endElement + ( + *elemDecl + , uriId + , isRoot + , fPrefixBuf.getRawBuffer() + ); + } + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + else + { + // Restore the grammar + fGrammar = fElemStack.getCurrentGrammar(); + fGrammarType = fGrammar->getGrammarType(); + fValidator->setGrammar(fGrammar); + + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } + } + else // not empty + { + + // send a partial element psvi + if (fPSVIHandler) + { + + ComplexTypeInfo* curTypeInfo = 0; + DatatypeValidator* curDV = 0; + XSTypeDefinition* typeDef = 0; + + if (fValidate && elemDecl->isDeclared()) + { + curTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo(); + + if (curTypeInfo) + { + typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo); + } + else + { + curDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + + if (curDV) + { + typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV); + } + } + } + + fPSVIElement->reset + ( + PSVIElement::VALIDITY_NOTKNOWN + , PSVIElement::VALIDATION_NONE + , fRootElemName + , ((SchemaValidator*) fValidator)->getIsElemSpecified() + , (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0 + , typeDef + , 0 //memberType + , fModel + , ((SchemaElementDecl*)elemDecl)->getDefaultValue() + , 0 + , 0 + , 0 + ); + + + fPSVIHandler->handlePartialElementPSVI + ( + elemDecl->getBaseName() + , fURIStringPool->getValueForId(elemDecl->getURI()) + , fPSVIElement + ); + + } + + fErrorStack->push(fPSVIElemContext.fErrorOccurred); + } + + return true; +} + + +// --------------------------------------------------------------------------- +// SGXMLScanner: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* SGXMLScanner::loadGrammar(const InputSource& src + , const short grammarType + , const bool toCache) +{ + Grammar* loadedGrammar = 0; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + fGrammarResolver->cacheGrammarFromParse(false); + // if the new grammar has to be cached, better use the already cached + // grammars, or the an exception will be thrown when caching an already + // cached grammar + fGrammarResolver->useCachedGrammarInParse(toCache); + fRootGrammar = 0; + + if (fValScheme == Val_Auto) { + fValidate = true; + } + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + fSeeXsi = false; + + if (grammarType == Grammar::SchemaGrammarType) { + loadedGrammar = loadXMLSchemaGrammar(src, toCache); + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + return loadedGrammar; +} + +void SGXMLScanner::resetCachedGrammar () +{ + fCachedSchemaInfoList->removeAll (); +} + +// --------------------------------------------------------------------------- +// SGXMLScanner: Private helper methods +// --------------------------------------------------------------------------- +// This method handles the common initialization, to avoid having to do +// it redundantly in multiple constructors. +void SGXMLScanner::commonInit() +{ + // Create the element state array + fElemState = (unsigned int*) fMemoryManager->allocate + ( + fElemStateSize * sizeof(unsigned int) + ); //new unsigned int[fElemStateSize]; + fElemLoopState = (unsigned int*) fMemoryManager->allocate + ( + fElemStateSize * sizeof(unsigned int) + ); //new unsigned int[fElemStateSize]; + + // And we need one for the raw attribute scan. This just stores key/ + // value string pairs (prior to any processing.) + fRawAttrList = new (fMemoryManager) RefVectorOf(32, true, fMemoryManager); + fRawAttrColonList = (int*) fMemoryManager->allocate + ( + fRawAttrColonListSize * sizeof(int) + ); + + // Create the Validator and init them + fSchemaValidator = new (fMemoryManager) SchemaValidator(0, fMemoryManager); + initValidator(fSchemaValidator); + + // Create IdentityConstraint info + fICHandler = new (fMemoryManager) IdentityConstraintHandler(this, fMemoryManager); + + // Add the default entity entries for the character refs that must always + // be present. + fEntityTable = new (fMemoryManager) ValueHashTableOf(11, fMemoryManager); + fEntityTable->put((void*) XMLUni::fgAmp, chAmpersand); + fEntityTable->put((void*) XMLUni::fgLT, chOpenAngle); + fEntityTable->put((void*) XMLUni::fgGT, chCloseAngle); + fEntityTable->put((void*) XMLUni::fgQuot, chDoubleQuote); + fEntityTable->put((void*) XMLUni::fgApos, chSingleQuote); + fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool(29, true, 128, fMemoryManager); + fAttDefRegistry = new (fMemoryManager) RefHashTableOf + ( + 131, false, fMemoryManager + ); + fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf(7, fMemoryManager); + fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager); + + fSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf(29, fMemoryManager); + fCachedSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf(29, fMemoryManager); + + if (fValidator) + { + if (!fValidator->handlesSchema()) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager); + } + else + { + fValidator = fSchemaValidator; + } +} + +void SGXMLScanner::cleanUp() +{ + fMemoryManager->deallocate(fElemState); //delete [] fElemState; + fMemoryManager->deallocate(fElemLoopState); //delete [] fElemLoopState; + delete fSchemaGrammar; + delete fEntityTable; + delete fRawAttrList; + fMemoryManager->deallocate(fRawAttrColonList); + delete fSchemaValidator; + delete fICHandler; + delete fElemNonDeclPool; + delete fAttDefRegistry; + delete fUndeclaredAttrRegistry; + delete fPSVIAttrList; + if (fPSVIElement) + delete fPSVIElement; + + if (fErrorStack) + delete fErrorStack; + + delete fSchemaInfoList; + delete fCachedSchemaInfoList; +} + +void SGXMLScanner::resizeElemState() { + + unsigned int newSize = fElemStateSize * 2; + unsigned int* newElemState = (unsigned int*) fMemoryManager->allocate + ( + newSize * sizeof(unsigned int) + ); //new unsigned int[newSize]; + unsigned int* newElemLoopState = (unsigned int*) fMemoryManager->allocate + ( + newSize * sizeof(unsigned int) + ); //new unsigned int[newSize]; + + // Copy the existing values + unsigned int index = 0; + for (; index < fElemStateSize; index++) + { + newElemState[index] = fElemState[index]; + newElemLoopState[index] = fElemLoopState[index]; + } + + for (; index < newSize; index++) + newElemLoopState[index] = newElemState[index] = 0; + + // Delete the old array and udpate our members + fMemoryManager->deallocate(fElemState); //delete [] fElemState; + fMemoryManager->deallocate(fElemLoopState); //delete [] fElemLoopState; + fElemState = newElemState; + fElemLoopState = newElemLoopState; + fElemStateSize = newSize; +} + +void SGXMLScanner::resizeRawAttrColonList() { + + unsigned int newSize = fRawAttrColonListSize * 2; + int* newRawAttrColonList = (int*) fMemoryManager->allocate + ( + newSize * sizeof(int) + ); //new int[newSize]; + + // Copy the existing values + unsigned int index = 0; + for (; index < fRawAttrColonListSize; index++) + newRawAttrColonList[index] = fRawAttrColonList[index]; + + // Delete the old array and udpate our members + fMemoryManager->deallocate(fRawAttrColonList); //delete [] fRawAttrColonList; + fRawAttrColonList = newRawAttrColonList; + fRawAttrColonListSize = newSize; +} + +// This method is called from scanStartTag() to build up the list of +// XMLAttr objects that will be passed out in the start tag callout. We +// get the key/value pairs from the raw scan of explicitly provided attrs, +// which have not been normalized. And we get the element declaration from +// which we will get any defaulted or fixed attribute defs and add those +// in as well. +XMLSize_t +SGXMLScanner::buildAttList(const RefVectorOf& providedAttrs + , const XMLSize_t attCount + , XMLElementDecl* elemDecl + , RefVectorOf& toFill) +{ + // Ask the element to clear the 'provided' flag on all of the att defs + // that it owns, and to return us a boolean indicating whether it has + // any defs. + DatatypeValidator *currDV = 0; + ComplexTypeInfo *currType = 0; + + if (fValidate) + { + currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if (!currType) { + currDV = ((SchemaValidator*)fValidator)->getCurrentDatatypeValidator(); + } + } + + const bool hasDefs = (currType && fValidate) + ? currType->hasAttDefs() + : elemDecl->hasAttDefs(); + + fElemCount++; + + // If there are no expliclitily provided attributes and there are no + // defined attributes for the element, the we don't have anything to do. + // So just return zero in this case. + if (!hasDefs && !attCount) + return 0; + + // Keep up with how many attrs we end up with total + XMLSize_t retCount = 0; + + // And get the current size of the output vector. This lets us use + // existing elements until we fill it, then start adding new ones. + const XMLSize_t curAttListSize = toFill.size(); + + // We need a buffer into which raw scanned attribute values will be + // normalized. + XMLBufBid bbNormal(&fBufMgr); + XMLBuffer& normBuf = bbNormal.getBuffer(); + + XMLBufBid bbPrefix(&fBufMgr); + XMLBuffer& prefixBuf = bbPrefix.getBuffer(); + + // Loop through our explicitly provided attributes, which are in the raw + // scanned form, and build up XMLAttr objects. + XMLSize_t index; + const XMLCh* prefPtr, *suffPtr; + for (index = 0; index < attCount; index++) + { + PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID; + PSVIItem::ASSESSMENT_TYPE attrAssessed = PSVIItem::VALIDATION_FULL; + const KVStringPair* curPair = providedAttrs.elementAt(index); + + // We have to split the name into its prefix and name parts. Then + // we map the prefix to its URI. + const XMLCh* const namePtr = curPair->getKey(); + + const int colonInd = fRawAttrColonList[index]; + unsigned int uriId; + if (colonInd != -1) + { + prefixBuf.set(namePtr, colonInd); + prefPtr = prefixBuf.getRawBuffer(); + suffPtr = namePtr + colonInd + 1; + // Map the prefix to a URI id + uriId = resolvePrefix(prefPtr, ElemStack::Mode_Attribute); + } + else + { + // No colon, so we just have a name with no prefix + prefPtr = XMLUni::fgZeroLenString; + suffPtr = namePtr; + // an empty prefix is always the empty namespace, when dealing with attributes + uriId = fEmptyNamespaceId; + } + + // If the uri comes back as the xmlns or xml URI or its just a name + // and that name is 'xmlns', then we handle it specially. So set a + // boolean flag that lets us quickly below know which we are dealing + // with. + const bool isNSAttr = (uriId == fEmptyNamespaceId)? + XMLString::equals(suffPtr, XMLUni::fgXMLNSString) : + (uriId == fXMLNSNamespaceId || XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI)); + + // If its not a special case namespace attr of some sort, then we + // do normal checking and processing. + XMLAttDef::AttTypes attType = XMLAttDef::CData; + DatatypeValidator *attrValidator = 0; + PSVIAttribute *psviAttr = 0; + bool otherXSI = false; + + if (isNSAttr) + { + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + else + { + bool ValueValidate = false; + bool tokenizeBuffer = false; + + if (uriId == fXMLNSNamespaceId) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI); + } + else if (XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI)) + { + if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL)) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN); + + ValueValidate = true; + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCATION)) + { + // use anyURI as the validator + // tokenize the data and use the anyURI data for each piece + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI); + //We should validate each value in the schema location however + //this lead to a performance degradation of around 4%. Since + //the first value of each pair needs to match what is in the + //schema document and the second value needs to be valid in + //order to open the document we won't validate it. Need to + //do performance analysis of the anyuri datatype. + //ValueValidate = true; + ValueValidate = false; + tokenizeBuffer = true; + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION)) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI); + //We should validate this value however + //this lead to a performance degradation of around 4%. Since + //the value needs to be valid in + //order to open the document we won't validate it. Need to + //do performance analysis of the anyuri datatype. + //ValueValidate = true; + ValueValidate = false; + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE)) + { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME); + + ValueValidate = true; + } + else { + otherXSI = true; + } + } + + if (!otherXSI) { + normalizeAttRawValue + ( + namePtr + , curPair->getValue() + , normBuf + ); + + if (fValidate && attrValidator && ValueValidate) + { + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(attrValidator, normBuf.getRawBuffer(), normBuf, true); + + ValidationContext* const theContext = + getValidationContext(); + + if (theContext) + { + try + { + if (tokenizeBuffer) { + XMLStringTokenizer tokenizer(normBuf.getRawBuffer(), fMemoryManager); + while (tokenizer.hasMoreTokens()) { + attrValidator->validate( + tokenizer.nextToken(), + theContext, + fMemoryManager); + } + } + else { + attrValidator->validate( + normBuf.getRawBuffer(), + theContext, + fMemoryManager); + } + } + catch (const XMLException& idve) + { + fValidator->emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); + } + } + } + + if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType) + { + psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); + XSSimpleTypeDefinition *validatingType = (attrValidator) + ? (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator) + : 0; + // no attribute declarations for these... + psviAttr->reset( + fRootElemName + , PSVIItem::VALIDITY_NOTKNOWN + , PSVIItem::VALIDATION_NONE + , validatingType + , 0 + , 0 + , false + , 0 + , attrValidator + ); + } + } + } + } + + if (!isNSAttr || otherXSI) + { + // Some checking for attribute wild card first (for schema) + bool laxThisOne = false; + bool skipThisOne = false; + + XMLAttDef* attDefForWildCard = 0; + XMLAttDef* attDef = 0; + + if (fGrammarType == Grammar::SchemaGrammarType) { + + //retrieve the att def + SchemaAttDef* attWildCard = 0; + if (currType) { + attDef = currType->getAttDef(suffPtr, uriId); + attWildCard = currType->getAttWildCard(); + } + else if (!currDV) { // check explicitly-set wildcard + attWildCard = ((SchemaElementDecl*)elemDecl)->getAttWildCard(); + } + + // if not found or faulted in - check for a matching wildcard attribute + // if no matching wildcard attribute, check (un)qualifed cases and flag + // appropriate errors + if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn)) { + + if (attWildCard) { + //if schema, see if we should lax or skip the validation of this attribute + if (anyAttributeValidation(attWildCard, uriId, skipThisOne, laxThisOne)) { + + if(!skipThisOne) + { + SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(getURIText(uriId)); + if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType) { + RefHashTableOf* attRegistry = sGrammar->getAttributeDeclRegistry(); + if (attRegistry) { + attDefForWildCard = attRegistry->get(suffPtr); + } + } + } + } + } + else if (currType) { + // not found, see if the attDef should be qualified or not + if (uriId == fEmptyNamespaceId) { + attDef = currType->getAttDef(suffPtr, fURIStringPool->getId(fGrammar->getTargetNamespace())); + if (fValidate + && attDef + && attDef->getCreateReason() != XMLAttDef::JustFaultIn) { + // the attribute should be qualified + fValidator->emitError + ( + XMLValid::AttributeNotQualified + , attDef->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + { + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + } + else { + attDef = currType->getAttDef(suffPtr, fEmptyNamespaceId); + if (fValidate + && attDef + && attDef->getCreateReason() != XMLAttDef::JustFaultIn) { + // the attribute should be qualified + fValidator->emitError + ( + XMLValid::AttributeNotUnQualified + , attDef->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + { + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + } + } + } + } + + // now need to prepare for duplicate detection + if(attDef) + { + unsigned int *curCountPtr = fAttDefRegistry->get(attDef); + if(!curCountPtr) + { + curCountPtr = getNewUIntPtr(); + *curCountPtr = fElemCount; + fAttDefRegistry->put(attDef, curCountPtr); + } + else if(*curCountPtr < fElemCount) + *curCountPtr = fElemCount; + else + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , attDef->getFullName() + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + } + else + { + if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr + , elemDecl->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + } + + // if we've found either an attDef or an attDefForWildCard, + // then we're doing full validation and it may still be valid. + if(!attDef && !attDefForWildCard) + { + if(!laxThisOne && !skipThisOne) + { + fPSVIElemContext.fErrorOccurred = true; + } + if(getPSVIHandler()) + { + if(!laxThisOne && !skipThisOne) + { + attrValid = PSVIItem::VALIDITY_INVALID; + } + else if(laxThisOne) + { + attrValid = PSVIItem::VALIDITY_NOTKNOWN; + attrAssessed = PSVIItem::VALIDATION_PARTIAL; + } + else + { + attrValid = PSVIItem::VALIDITY_NOTKNOWN; + attrAssessed = PSVIItem::VALIDATION_NONE; + } + } + } + + bool errorCondition = fValidate && !attDefForWildCard && !attDef; + if (errorCondition && !skipThisOne && !laxThisOne) + { + // + // Its not valid for this element, so issue an error if we are + // validating. + // + XMLBufBid bbMsg(&fBufMgr); + XMLBuffer& bufMsg = bbMsg.getBuffer(); + if (uriId != fEmptyNamespaceId) { + XMLBufBid bbURI(&fBufMgr); + XMLBuffer& bufURI = bbURI.getBuffer(); + + getURIText(uriId, bufURI); + + bufMsg.append(chOpenCurly); + bufMsg.append(bufURI.getRawBuffer()); + bufMsg.append(chCloseCurly); + } + bufMsg.append(suffPtr); + fValidator->emitError + ( + XMLValid::AttNotDefinedForElement + , bufMsg.getRawBuffer() + , elemDecl->getFullName() + ); + } + + // Now normalize the raw value since we have the attribute type. We + // don't care about the return status here. If it failed, an error + // was issued, which is all we care about. + if (attDefForWildCard) { + normalizeAttValue( + attDefForWildCard, namePtr, curPair->getValue(), normBuf + ); + + // If we found an attdef for this one, then lets validate it. + const XMLCh* xsNormalized = normBuf.getRawBuffer(); + DatatypeValidator* tempDV = ((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the attribute according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf, true); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + if (fNormalizeData && fValidate) { + normBuf.set(xsNormalized); + } + } + + if (fValidate ) { + fValidator->validateAttrValue( + attDefForWildCard, xsNormalized, false, elemDecl + ); + attrValidator = ((SchemaValidator *)fValidator)->getMostRecentAttrValidator(); + if(((SchemaValidator *)fValidator)->getErrorOccurred()) + { + fPSVIElemContext.fErrorOccurred = true; + if(getPSVIHandler()) + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + else { // no decl; default DOMTypeInfo to anySimpleType + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + + // Save the type for later use + attType = attDefForWildCard->getType(); + } + else { + normalizeAttValue( + attDef, namePtr, curPair->getValue(), normBuf + ); + + // If we found an attdef for this one, then lets validate it. + if (attDef) + { + const XMLCh* xsNormalized = normBuf.getRawBuffer(); + if (fGrammarType == Grammar::SchemaGrammarType) + { + DatatypeValidator* tempDV = ((SchemaAttDef*) attDef)->getDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the attribute according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf, true); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + if (fNormalizeData && fValidate && !skipThisOne) { + normBuf.set(xsNormalized); + } + } + } + + if (fValidate && !skipThisOne) + { + fValidator->validateAttrValue( + attDef, xsNormalized, false, elemDecl + ); + attrValidator = ((SchemaValidator *)fValidator)->getMostRecentAttrValidator(); + if(((SchemaValidator *)fValidator)->getErrorOccurred()) + { + fPSVIElemContext.fErrorOccurred = true; + if(getPSVIHandler()) + attrValid = PSVIItem::VALIDITY_INVALID; + } + } + else { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + } + else { + attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + + // Save the type for later use + if (attDef) + { + attType = attDef->getType(); + } + } + + // now fill in the PSVIAttributes entry for this attribute: + if(getPSVIHandler()) + { + psviAttr = fPSVIAttrList->getPSVIAttributeToFill(suffPtr, fURIStringPool->getValueForId(uriId)); + SchemaAttDef *actualAttDef = 0; + if(attDef) + actualAttDef = (SchemaAttDef *)attDef; + else if (attDefForWildCard) + actualAttDef = (SchemaAttDef *)attDefForWildCard; + if(actualAttDef) + { + XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef); + DatatypeValidator * attrDataType = actualAttDef->getDatatypeValidator(); + XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType); + if(attrValid != PSVIItem::VALIDITY_VALID) + { + psviAttr->reset + ( + fRootElemName + , attrValid + , attrAssessed + , validatingType + , 0 + , actualAttDef->getValue() + , false + , attrDecl + , 0 + ); + } + else + { + XSSimpleTypeDefinition *memberType = 0; + if(validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION) + memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator); + psviAttr->reset + ( + fRootElemName + , attrValid + , attrAssessed + , validatingType + , memberType + , actualAttDef->getValue() + , false + , attrDecl + , (memberType)?attrValidator:attrDataType + ); + } + } + else + { + psviAttr->reset + ( + fRootElemName + , attrValid + , attrAssessed + , 0 + , 0 + , 0 + , false + , 0 + , 0 + ); + } + } + } + + // Add this attribute to the attribute list that we use to pass them + // to the handler. We reuse its existing elements but expand it as + // required. + XMLAttr* curAttr; + if (retCount >= curAttListSize) + { + curAttr = new (fMemoryManager) XMLAttr + ( + uriId + , suffPtr + , prefPtr + , normBuf.getRawBuffer() + , attType + , true + , fMemoryManager + ); + toFill.addElement(curAttr); + } + else + { + curAttr = toFill.elementAt(retCount); + curAttr->set + ( + uriId + , suffPtr + , prefPtr + , normBuf.getRawBuffer() + , attType + ); + curAttr->setSpecified(true); + } + if(psviAttr) + psviAttr->setValue(curAttr->getValue()); + + // Bump the count of attrs in the list + retCount++; + } + + // Now, if there are any attributes declared by this element, let's + // go through them and make sure that any required ones are provided, + // and fault in any fixed ones and defaulted ones that are not provided + // literally. + if (hasDefs) + { + // Check after all specified attrs are scanned + // (1) report error for REQUIRED attrs that are missing (V_TAGc) + // (2) add default attrs if missing (FIXED and NOT_FIXED) + + XMLAttDefList& attDefList = getAttDefList(currType, elemDecl); + + for(XMLSize_t i=0; igetDefaultType(); + + unsigned int *attCountPtr = fAttDefRegistry->get(curDef); + if (!attCountPtr || *attCountPtr < fElemCount) + { // did not occur + // note that since there is no attribute information + // item present, there is no PSVI infoset to augment here *except* + // that the element is invalid + + //the attribute is not provided + if (fValidate) + { + // If we are validating and its required, then an error + if ((defType == XMLAttDef::Required) || + (defType == XMLAttDef::Required_And_Fixed) ) + + { + fValidator->emitError + ( + XMLValid::RequiredAttrNotProvided + , curDef->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + } + else if ((defType == XMLAttDef::Default) || + (defType == XMLAttDef::Fixed) ) + { + if (fStandalone && curDef->isExternal()) + { + // XML 1.0 Section 2.9 + // Document is standalone, so attributes must not be defaulted. + fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef->getFullName(), elemDecl->getFullName()); + } + } + } + + // Fault in the value if needed, and bump the att count. + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + // Let the validator pass judgement on the attribute value + if (fValidate) + { + fValidator->validateAttrValue + ( + curDef + , curDef->getValue() + , false + , elemDecl + ); + } + + XMLAttr* curAtt; + if (retCount >= curAttListSize) + { + curAtt = new (fMemoryManager) XMLAttr(fMemoryManager); + fValidator->faultInAttr(*curAtt, *curDef); + fAttrList->addElement(curAtt); + } + else + { + curAtt = fAttrList->elementAt(retCount); + fValidator->faultInAttr(*curAtt, *curDef); + } + + // Indicate it was not explicitly specified and bump count + curAtt->setSpecified(false); + retCount++; + if(getPSVIHandler()) + { + QName *attName = ((SchemaAttDef *)curDef)->getAttName(); + PSVIAttribute *defAttrToFill = fPSVIAttrList->getPSVIAttributeToFill + ( + attName->getLocalPart(), fURIStringPool->getValueForId( attName->getURI()) + ); + XSAttributeDeclaration *defAttrDecl = (XSAttributeDeclaration *)fModel->getXSObject((void *)curDef); + DatatypeValidator * attrDataType = ((SchemaAttDef *)curDef)->getDatatypeValidator(); + XSSimpleTypeDefinition *defAttrType = + (XSSimpleTypeDefinition*)fModel->getXSObject(attrDataType); + // would have occurred during validation of default value + if(((SchemaValidator *)fValidator)->getErrorOccurred()) + { + defAttrToFill->reset( + fRootElemName + , PSVIItem::VALIDITY_INVALID + , PSVIItem::VALIDATION_FULL + , defAttrType + , 0 + , curDef->getValue() + , true + , defAttrDecl + , 0 + ); + } + else + { + XSSimpleTypeDefinition *defAttrMemberType = 0; + if(defAttrType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION) + { + defAttrMemberType = (XSSimpleTypeDefinition *)fModel->getXSObject + ( + ((SchemaValidator*)fValidator)->getMostRecentAttrValidator() + ); + } + defAttrToFill->reset + ( + fRootElemName + , PSVIItem::VALIDITY_VALID + , PSVIItem::VALIDATION_FULL + , defAttrType + , defAttrMemberType + , curDef->getValue() + , true + , defAttrDecl + , (defAttrMemberType)?((SchemaValidator *)fValidator)->getMostRecentAttrValidator():attrDataType + ); + } + defAttrToFill->setValue(curDef->getValue()); + } + } + } + else if (attCountPtr) + { + //attribute is provided + // (schema) report error for PROHIBITED attrs that are present (V_TAGc) + if (defType == XMLAttDef::Prohibited && fValidate) + { + fValidator->emitError + ( + XMLValid::ProhibitedAttributePresent + , curDef->getFullName() + ); + fPSVIElemContext.fErrorOccurred = true; + if (getPSVIHandler()) + { + QName *attQName = ((SchemaAttDef *)curDef)->getAttName(); + // bad luck... + PSVIAttribute *prohibitedAttr = fPSVIAttrList->getAttributePSVIByName + ( + attQName->getLocalPart(), + fURIStringPool->getValueForId(attQName->getURI()) + ); + prohibitedAttr->updateValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + } + + return retCount; +} + + +// This method will take a raw attribute value and normalize it according to +// the rules of the attribute type. It will put the resulting value into the +// passed buffer. +// +// This code assumes that escaped characters in the original value (via char +// refs) are prefixed by a 0xFFFF character. This is because some characters +// are legal if escaped only. And some escape chars are not subject to +// normalization rules. +bool SGXMLScanner::normalizeAttValue( const XMLAttDef* const attDef + , const XMLCh* const attName + , const XMLCh* const value + , XMLBuffer& toFill) +{ + // A simple state value for a whitespace processing state machine + enum States + { + InWhitespace + , InContent + }; + + // Get the type and name + const XMLAttDef::AttTypes type = (attDef) + ?attDef->getType() + :XMLAttDef::CData; + + // Assume its going to go fine, and empty the target buffer in preperation + bool retVal = true; + toFill.reset(); + + // Get attribute def - to check to see if it's declared externally or not + bool isAttExternal = (attDef) + ?attDef->isExternal() + :false; + + // Loop through the chars of the source value and normalize it according + // to the type. + States curState = InContent; + bool firstNonWS = false; + XMLCh nextCh; + const XMLCh* srcPtr = value; + + if (type == XMLAttDef::CData || type > XMLAttDef::Notation) { + while (*srcPtr) { + // Get the next character from the source. We have to watch for + // escaped characters (which are indicated by a 0xFFFF value followed + // by the char that was escaped.) + nextCh = *srcPtr; + + // Do we have an escaped character ? + if (nextCh == 0xFFFF) + { + nextCh = *++srcPtr; + } + else if ( (nextCh <= 0x0D) && (nextCh == 0x09 || nextCh == 0x0A || nextCh == 0x0D) ) { + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && isAttExternal) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attName); + } + nextCh = chSpace; + } + else if (nextCh == chOpenAngle) { + // If its not escaped, then make sure its not a < character, which is + // not allowed in attribute values. + emitError(XMLErrs::BracketInAttrValue, attName); + retVal = false; + } + + // Add this char to the target buffer + toFill.append(nextCh); + + // And move up to the next character in the source + srcPtr++; + } + } + else { + while (*srcPtr) + { + // Get the next character from the source. We have to watch for + // escaped characters (which are indicated by a 0xFFFF value followed + // by the char that was escaped.) + nextCh = *srcPtr; + + // Do we have an escaped character ? + if (nextCh == 0xFFFF) + { + nextCh = *++srcPtr; + } + else if (nextCh == chOpenAngle) { + // If its not escaped, then make sure its not a < character, which is + // not allowed in attribute values. + emitError(XMLErrs::BracketInAttrValue, attName); + retVal = false; + } + + if (curState == InWhitespace) + { + if (!fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + if (firstNonWS) + toFill.append(chSpace); + curState = InContent; + firstNonWS = true; + } + else + { + srcPtr++; + continue; + } + } + else if (curState == InContent) + { + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + curState = InWhitespace; + srcPtr++; + + // Check Validity Constraint for Standalone document declaration + // XML 1.0, Section 2.9 + if (fStandalone && fValidate && isAttExternal) + { + if (!firstNonWS || (nextCh != chSpace) || (!*srcPtr) || fReaderMgr.getCurrentReader()->isWhitespace(*srcPtr)) + { + // Can't have a standalone document declaration of "yes" if attribute + // values are subject to normalisation + fValidator->emitError(XMLValid::NoAttNormForStandalone, attName); + } + } + continue; + } + firstNonWS = true; + } + + // Add this char to the target buffer + toFill.append(nextCh); + + // And move up to the next character in the source + srcPtr++; + } + } + + return retVal; +} + +// This method will just normalize the input value as CDATA without +// any standalone checking. +bool SGXMLScanner::normalizeAttRawValue( const XMLCh* const attrName + , const XMLCh* const value + , XMLBuffer& toFill) +{ + // Assume its going to go fine, and empty the target buffer in preperation + bool retVal = true; + toFill.reset(); + + // Loop through the chars of the source value and normalize it according + // to the type. + bool escaped; + XMLCh nextCh; + const XMLCh* srcPtr = value; + while (*srcPtr) + { + // Get the next character from the source. We have to watch for + // escaped characters (which are indicated by a 0xFFFF value followed + // by the char that was escaped.) + nextCh = *srcPtr; + escaped = (nextCh == 0xFFFF); + if (escaped) + nextCh = *++srcPtr; + + // If its not escaped, then make sure its not a < character, which is + // not allowed in attribute values. + if (!escaped && (*srcPtr == chOpenAngle)) + { + emitError(XMLErrs::BracketInAttrValue, attrName); + retVal = false; + } + + if (!escaped) + { + // NOTE: Yes this is a little redundant in that a 0x20 is + // replaced with an 0x20. But its faster to do this (I think) + // than checking for 9, A, and D separately. + if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + nextCh = chSpace; + } + + // Add this char to the target buffer + toFill.append(nextCh); + + // And move up to the next character in the source + srcPtr++; + } + return retVal; +} + +// This method will reset the scanner data structures, and related plugged +// in stuff, for a new scan session. We get the input source for the primary +// XML entity, create the reader for it, and push it on the stack so that +// upon successful return from here we are ready to go. +void SGXMLScanner::scanReset(const InputSource& src) +{ + + // This call implicitly tells us that we are going to reuse the scanner + // if it was previously used. So tell the validator to reset itself. + // + // But, if the fUseCacheGrammar flag is set, then don't reset it. + // + // NOTE: The ReaderMgr is flushed on the way out, because that is + // required to insure that files are closed. + fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar); + fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar); + + // Clear transient schema info list. + // + fSchemaInfoList->removeAll (); + + // fModel may need updating, as fGrammarResolver could have cleaned it + if(fModel && getPSVIHandler()) + fModel = fGrammarResolver->getXSModel(); + + // Create dummy schema grammar + if (!fSchemaGrammar) { + fSchemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); + } + + fGrammar = fSchemaGrammar; + fGrammarType = Grammar::DTDGrammarType; + fRootGrammar = 0; + + fValidator->setGrammar(fGrammar); + if (fValidatorFromUser) { + + ((SchemaValidator*) fValidator)->setErrorReporter(fErrorReporter); + ((SchemaValidator*) fValidator)->setGrammarResolver(fGrammarResolver); + ((SchemaValidator*) fValidator)->setExitOnFirstFatal(fExitOnFirstFatal); + } + + // Reset validation + fValidate = (fValScheme == Val_Always) ? true : false; + + // And for all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Clear out the id reference list + resetValidationContext(); + + // Reset the Root Element Name + fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName; + fRootElemName = 0; + + // Reset IdentityConstraints + if (fICHandler) + fICHandler->reset(); + + // Reset the element stack, and give it the latest ids for the special + // URIs it has to know about. + fElemStack.reset + ( + fEmptyNamespaceId + , fUnknownNamespaceId + , fXMLNamespaceId + , fXMLNSNamespaceId + ); + + if (!fSchemaNamespaceId) + fSchemaNamespaceId = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI); + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + fSeeXsi = false; + fDoNamespaces = true; + fDoSchema = true; + + // Reset PSVI context + // Note that we always need this around for DOMTypeInfo + if (!fPSVIElement) + fPSVIElement = new (fMemoryManager) PSVIElement(fMemoryManager); + + if (!fErrorStack) + { + fErrorStack = new (fMemoryManager) ValueStackOf(8, fMemoryManager); + } + else + { + fErrorStack->removeAllElements(); + } + + resetPSVIElemContext(); + + // Reset the validators + fSchemaValidator->reset(); + fSchemaValidator->setErrorReporter(fErrorReporter); + fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal); + fSchemaValidator->setGrammarResolver(fGrammarResolver); + if (fValidatorFromUser) + fValidator->reset(); + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , true + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // Push this read onto the reader manager + fReaderMgr.pushReader(newReader, 0); + + // and reset security-related things if necessary: + if(fSecurityManager != 0) + { + fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit(); + fEntityExpansionCount = 0; + } + fElemCount = 0; + if(fUIntPoolRowTotal >= 32) + { // 8 KB tied up with validating attributes... + fAttDefRegistry->removeAll(); + recreateUIntPool(); + } + else + { + // note that this will implicitly reset the values of the hashtables, + // though their buckets will still be tied up + resetUIntPool(); + } + fUndeclaredAttrRegistry->removeAll(); +} + + +// This method is called between markup in content. It scans for character +// data that is sent to the document handler. It watches for any markup +// characters that would indicate that the character data has ended. It also +// handles expansion of general and character entities. +// +// sendData() is a local static helper for this method which handles some +// code that must be done in three different places here. +void SGXMLScanner::sendCharData(XMLBuffer& toSend) +{ + // If no data in the buffer, then nothing to do + if (toSend.isEmpty()) + return; + + // We do different things according to whether we are validating or + // not. If not, its always just characters; else, it depends on the + // current element's content model. + if (fValidate) + { + // Get the raw data we need for the callback + const XMLCh* rawBuf = toSend.getRawBuffer(); + const XMLSize_t len = toSend.getLen(); + + // Get the character data opts for the current element + XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData; + // And see if the current element is a 'Children' style content model + ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if(currType) + { + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType(); + if(modelType == SchemaElementDecl::Children || + modelType == SchemaElementDecl::ElementOnlyEmpty) + charOpts = XMLElementDecl::SpacesOk; + else if(modelType == SchemaElementDecl::Empty) + charOpts = XMLElementDecl::NoCharData; + } + + // should not be necessary once PSVI method on element decls + // are removed + if (charOpts == XMLElementDecl::NoCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + else if (fReaderMgr.getCurrentReader()->isAllSpaces(rawBuf, len)) + { + // Its all spaces. So, if they can take spaces, then send it + // as ignorable whitespace. If they can handle any char data + // send it as characters. + if (charOpts == XMLElementDecl::SpacesOk) { + if (fDocHandler) + fDocHandler->ignorableWhitespace(rawBuf, len, false); + } + else if (charOpts == XMLElementDecl::AllCharData) + { + XMLSize_t xsLen; + const XMLCh* xsNormalized; + DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the character according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, fWSNormalizeBuf); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + xsLen = fWSNormalizeBuf.getLen(); + } + else { + xsNormalized = rawBuf; + xsLen = len; + } + + // tell the schema validation about the character data for checkContent later + ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized); + + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) { + fContent.append(xsNormalized, xsLen); + } + + if (fDocHandler) { + if (fNormalizeData) { + fDocHandler->docCharacters(xsNormalized, xsLen, false); + } + else { + fDocHandler->docCharacters(rawBuf, len, false); + } + } + } + } + else + { + // If they can take any char data, then send it. Otherwise, they + // can only handle whitespace and can't handle this stuff so + // issue an error. + if (charOpts == XMLElementDecl::AllCharData) + { + XMLSize_t xsLen; + const XMLCh *xsNormalized; + DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, fWSNormalizeBuf); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + xsLen = fWSNormalizeBuf.getLen(); + } + else { + xsNormalized = rawBuf; + xsLen = len; + } + + // tell the schema validation about the character data for checkContent later + ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized); + + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) { + fContent.append(xsNormalized, xsLen); + } + + if (fDocHandler) { + if (fNormalizeData) { + fDocHandler->docCharacters(xsNormalized, xsLen, false); + } + else { + fDocHandler->docCharacters(rawBuf, len, false); + } + } + } + else + { + fValidator->emitError(XMLValid::NoCharDataInCM); + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + else + { + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) + fContent.append(toSend.getRawBuffer(), toSend.getLen()); + + // Always assume its just char data if not validating + if (fDocHandler) + fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false); + } + + // Reset buffer + toSend.reset(); +} + + + +// This method is called with a key/value string pair that represents an +// xmlns="yyy" or xmlns:xxx="yyy" attribute. This method will update the +// current top of the element stack based on this data. We know that when +// we get here, that it is one of these forms, so we don't bother confirming +// it. +// +// But we have to ensure +// 1. xxx is not xmlns +// 2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa +// 3. yyy is not XMLUni::fgXMLNSURIName +// 4. if xxx is not null, then yyy cannot be an empty string. +void SGXMLScanner::updateNSMap(const XMLCh* const attrName + , const XMLCh* const attrValue) +{ + updateNSMap(attrName, attrValue, XMLString::indexOf(attrName, chColon)); +} + +void SGXMLScanner::updateNSMap(const XMLCh* const attrName + , const XMLCh* const attrValue + , const int colonOfs) +{ + // We need a buffer to normalize the attribute value into + XMLBufBid bbNormal(&fBufMgr); + XMLBuffer& normalBuf = bbNormal.getBuffer(); + + // Normalize the value into the passed buffer. In this case, we don't + // care about the return value. An error was issued for the error, which + // is all we care about here. + normalizeAttRawValue(attrName, attrValue, normalBuf); + XMLCh* namespaceURI = normalBuf.getRawBuffer(); + + // We either have the default prefix (""), or we point it into the attr + // name parameter. Note that the xmlns is not the prefix we care about + // here. To us, the 'prefix' is really the local part of the attrName + // parameter. + // + // Check 1. xxx is not xmlns + // 2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa + // 3. yyy is not XMLUni::fgXMLNSURIName + // 4. if xxx is not null, then yyy cannot be an empty string. + const XMLCh* prefPtr = XMLUni::fgZeroLenString; + if (colonOfs != -1) { + prefPtr = &attrName[colonOfs + 1]; + + if (XMLString::equals(prefPtr, XMLUni::fgXMLNSString)) + emitError(XMLErrs::NoUseOfxmlnsAsPrefix); + else if (XMLString::equals(prefPtr, XMLUni::fgXMLString)) { + if (!XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) + emitError(XMLErrs::PrefixXMLNotMatchXMLURI); + } + + if (!namespaceURI) + emitError(XMLErrs::NoEmptyStrNamespace, attrName); + else if(!*namespaceURI && fXMLVersion == XMLReader::XMLV1_0) + emitError(XMLErrs::NoEmptyStrNamespace, attrName); + } + + if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName)) + emitError(XMLErrs::NoUseOfxmlnsURI); + else if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) { + if (!XMLString::equals(prefPtr, XMLUni::fgXMLString)) + emitError(XMLErrs::XMLURINotMatchXMLPrefix); + } + + // Ok, we have to get the unique id for the attribute value, which is the + // URI that this value should be mapped to. The validator has the + // namespace string pool, so we ask him to find or add this new one. Then + // we ask the element stack to add this prefix to URI Id mapping. + fElemStack.addPrefix + ( + prefPtr + , fURIStringPool->addOrFind(namespaceURI) + ); +} + +void SGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount) +{ + // Make an initial pass through the list and find any xmlns attributes or + // schema attributes. + // When we find one, send it off to be used to update the element stack's + // namespace mappings. + for (XMLSize_t index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + + // If either the key begins with "xmlns:" or its just plain + // "xmlns", then use it to update the map. + if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6) + || XMLString::equals(rawPtr, XMLUni::fgXMLNSString)) + { + const XMLCh* valuePtr = curPair->getValue(); + + updateNSMap(rawPtr, valuePtr, fRawAttrColonList[index]); + + // if the schema URI is seen in the the valuePtr, set the boolean seeXsi + if (XMLString::equals(valuePtr, SchemaSymbols::fgURI_XSI)) { + fSeeXsi = true; + } + } + } + + // walk through the list again to deal with "xsi:...." + if (fSeeXsi) + { + for (XMLSize_t index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + const XMLCh* prefPtr; + + int colonInd = fRawAttrColonList[index]; + + if (colonInd != -1) { + fURIBuf.set(rawPtr, colonInd); + prefPtr = fURIBuf.getRawBuffer(); + } + else { + prefPtr = XMLUni::fgZeroLenString; + } + + // if schema URI has been seen, scan for the schema location and uri + // and resolve the schema grammar + if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) { + + const XMLCh* valuePtr = curPair->getValue(); + const XMLCh* suffPtr = &rawPtr[colonInd + 1]; + + if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCATION)) + parseSchemaLocation(valuePtr); + else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION)) + resolveSchemaGrammar(valuePtr, XMLUni::fgZeroLenString); + } + } + + // do it another time, as xsi:type and xsi:nill only work if the schema grammar has been already + // loaded (JIRA XERCESC-1937) + if (fValidator && fValidator->handlesSchema()) + { + for (XMLSize_t index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + const XMLCh* prefPtr; + + int colonInd = fRawAttrColonList[index]; + + if (colonInd != -1) { + fURIBuf.set(rawPtr, colonInd); + prefPtr = fURIBuf.getRawBuffer(); + } + else { + prefPtr = XMLUni::fgZeroLenString; + } + + // scan for schema type + if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) { + + const XMLCh* valuePtr = curPair->getValue(); + const XMLCh* suffPtr = &rawPtr[colonInd + 1]; + + if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE)) + { + XMLBufBid bbXsi(&fBufMgr); + XMLBuffer& fXsiType = bbXsi.getBuffer(); + + // normalize the attribute according to schema whitespace facet + DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME); + normalizeAttRawValue(SchemaSymbols::fgXSI_TYPE, valuePtr, fXsiType); + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, fXsiType.getRawBuffer(), fXsiType, true); + if (!fXsiType.isEmpty()) { + int colonPos = -1; + unsigned int uriId = resolveQName ( + fXsiType.getRawBuffer() + , fPrefixBuf + , ElemStack::Mode_Element + , colonPos + ); + ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fXsiType.getRawBuffer() + colonPos + 1, uriId); + } + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL)) + { + // normalize the attribute according to schema whitespace facet + XMLBufBid bbXsi(&fBufMgr); + XMLBuffer& fXsiNil = bbXsi.getBuffer(); + + DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN); + normalizeAttRawValue(SchemaSymbols::fgATT_NILL, valuePtr, fXsiNil); + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, fXsiNil.getRawBuffer(), fXsiNil, true); + if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE)) + ((SchemaValidator*)fValidator)->setNillable(true); + else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE)) + ((SchemaValidator*)fValidator)->setNillable(false); + else + emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr); + } + } + } + } + } +} + +void SGXMLScanner::parseSchemaLocation(const XMLCh* const schemaLocationStr, bool ignoreLoadSchema) +{ + BaseRefVectorOf* schemaLocation = XMLString::tokenizeString(schemaLocationStr, fMemoryManager); + Janitor > janLoc(schemaLocation); + + XMLSize_t size = schemaLocation->size(); + if (size % 2 != 0 ) { + emitError(XMLErrs::BadSchemaLocation); + } else { + // We need a buffer to normalize the attribute value into + XMLBuffer normalBuf(1023, fMemoryManager); + for(XMLSize_t i=0; ielementAt(i), normalBuf); + resolveSchemaGrammar(schemaLocation->elementAt(i+1), normalBuf.getRawBuffer(), ignoreLoadSchema); + } + } +} + +void SGXMLScanner::resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema) { + + Grammar* grammar = 0; + + { + XMLSchemaDescriptionImpl theSchemaDescription(uri, fMemoryManager); + theSchemaDescription.setLocationHints(loc); + grammar = fGrammarResolver->getGrammar(&theSchemaDescription); + } + + // If multi-import is enabled, make sure the existing grammar came + // from the import directive. Otherwise we may end up reloading + // the same schema that came from the external grammar pool. Ideally, + // we would move fSchemaInfoList to XMLGrammarPool so that it survives + // the destruction of the scanner in which case we could rely on the + // same logic we use to weed out duplicate schemas below. + // + if (!grammar || grammar->getGrammarType() == Grammar::DTDGrammarType || + (getHandleMultipleImports() && + ((XMLSchemaDescription*)grammar->getGrammarDescription())-> + getContextType () == XMLSchemaDescription::CONTEXT_IMPORT)) + { + if (fLoadSchema || ignoreLoadSchema) + { + XSDDOMParser parser(0, fMemoryManager, 0); + + parser.setValidationScheme(XercesDOMParser::Val_Never); + parser.setDoNamespaces(true); + parser.setUserEntityHandler(fEntityHandler); + parser.setUserErrorReporter(fErrorReporter); + + //Normalize sysId + XMLBufBid nnSys(&fBufMgr); + XMLBuffer& normalizedSysId = nnSys.getBuffer(); + XMLString::removeChar(loc, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the system id + XMLBufBid bbSys(&fBufMgr); + XMLBuffer& expSysId = bbSys.getBuffer(); + + // Allow the entity handler to expand the system id if they choose + // to do so. + InputSource* srcToFill = 0; + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::SchemaGrammar, + expSysId.getRawBuffer(), uri, XMLUni::fgZeroLenString, lastInfo.systemId, + &fReaderMgr); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + else + { + expSysId.set(normalizedURI); + } + + // If they didn't create a source via the entity handler, then we + // have to create one on our own. + if (!srcToFill) + { + if (fDisableDefaultEntityResolution) + return; + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBufBid ddSys(&fBufMgr); + XMLBuffer& resolvedSysId = ddSys.getBuffer(); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + // Put a janitor on the input source + Janitor janSrc(srcToFill); + + // Check if this exact schema has already been seen. + // + const XMLCh* sysId = srcToFill->getSystemId(); + unsigned int uriId = (uri && *uri) ? fURIStringPool->addOrFind(uri) : fEmptyNamespaceId; + SchemaInfo* importSchemaInfo = 0; + + if (fUseCachedGrammar) + importSchemaInfo = fCachedSchemaInfoList->get(sysId, uriId); + + if (!importSchemaInfo && !fToCacheGrammar) + importSchemaInfo = fSchemaInfoList->get(sysId, uriId); + + if (importSchemaInfo) + { + // We haven't added any new grammars so it is safe to just + // return. + // + return; + } + + // Should just issue warning if the schema is not found + bool flag = srcToFill->getIssueFatalErrorIfNotFound(); + srcToFill->setIssueFatalErrorIfNotFound(false); + + parser.parse(*srcToFill); + + // Reset the InputSource + srcToFill->setIssueFatalErrorIfNotFound(flag); + + if (parser.getSawFatal() && fExitOnFirstFatal) + emitError(XMLErrs::SchemaScanFatalError); + + DOMDocument* document = parser.getDocument(); //Our Grammar + + if (document != 0) { + + DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema + if (root != 0) + { + const XMLCh* newUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + bool newGrammar = false; + if (!XMLString::equals(newUri, uri)) { + if (fValidate || fValScheme == Val_Auto) { + fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri); + } + + grammar = fGrammarResolver->getGrammar(newUri); + newGrammar = true; + } + + if (!grammar || + grammar->getGrammarType() == Grammar::DTDGrammarType || + (getHandleMultipleImports() && + ((XMLSchemaDescription*) grammar->getGrammarDescription())-> + getContextType () == XMLSchemaDescription::CONTEXT_IMPORT)) + { + // If we switched namespace URI, recheck the schema info. + // + if (newGrammar) + { + unsigned int newUriId = (newUri && *newUri) ? fURIStringPool->addOrFind(newUri) : fEmptyNamespaceId; + + if (fUseCachedGrammar) + importSchemaInfo = fCachedSchemaInfoList->get(sysId, newUriId); + + if (!importSchemaInfo && !fToCacheGrammar) + importSchemaInfo = fSchemaInfoList->get(sysId, newUriId); + + if (importSchemaInfo) + return; + } + + // Since we have seen a grammar, set our validation flag + // at this point if the validation scheme is auto + if (fValScheme == Val_Auto && !fValidate) { + fValidate = true; + fElemStack.setValidationFlag(fValidate); + } + + bool grammarFound = grammar && + grammar->getGrammarType() == Grammar::SchemaGrammarType; + + SchemaGrammar* schemaGrammar; + + if (grammarFound) { + schemaGrammar = (SchemaGrammar*) grammar; + } + else { + schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); + } + + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription(); + + gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE); + gramDesc->setLocationHints(sysId); + + TraverseSchema traverseSchema + ( + root + , fURIStringPool + , schemaGrammar + , fGrammarResolver + , fUseCachedGrammar ? fCachedSchemaInfoList : fSchemaInfoList + , fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList + , this + , sysId + , fEntityHandler + , fErrorReporter + , fMemoryManager + , grammarFound + ); + + // Reset the now invalid schema roots in the collected + // schema info entries. + // + { + RefHash2KeysTableOfEnumerator i ( + fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList); + + while (i.hasMoreElements ()) + i.nextElement().resetRoot (); + } + + if (fGrammarType == Grammar::DTDGrammarType) { + fGrammar = schemaGrammar; + fGrammarType = Grammar::SchemaGrammarType; + fValidator->setGrammar(fGrammar); + } + + if (fValidate) { + // validate the Schema scan so far + fValidator->preContentValidation(false); + } + } + } + } + } + } + else + { + // Since we have seen a grammar, set our validation flag + // at this point if the validation scheme is auto + if (fValScheme == Val_Auto && !fValidate) { + fValidate = true; + fElemStack.setValidationFlag(fValidate); + } + + // we have seen a schema, so set up the fValidator as fSchemaValidator + if (fGrammarType == Grammar::DTDGrammarType) { + fGrammar = grammar; + fGrammarType = Grammar::SchemaGrammarType; + fValidator->setGrammar(fGrammar); + } + } + // update fModel; rely on the grammar resolver to do this + // efficiently + if(getPSVIHandler()) + fModel = fGrammarResolver->getXSModel(); +} + +InputSource* SGXMLScanner::resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId) +{ + //Normalize sysId + XMLBufBid nnSys(&fBufMgr); + XMLBuffer& normalizedSysId = nnSys.getBuffer(); + XMLString::removeChar(sysId, 0xFFFF, normalizedSysId); + const XMLCh* normalizedURI = normalizedSysId.getRawBuffer(); + + // Create a buffer for expanding the system id + XMLBufBid bbSys(&fBufMgr); + XMLBuffer& expSysId = bbSys.getBuffer(); + + // Allow the entity handler to expand the system id if they choose + // to do so. + InputSource* srcToFill = 0; + if (fEntityHandler) + { + if (!fEntityHandler->expandSystemId(normalizedURI, expSysId)) + expSysId.set(normalizedURI); + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity, + expSysId.getRawBuffer(), 0, pubId, lastInfo.systemId, + &fReaderMgr); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + else + { + expSysId.set(normalizedURI); + } + + // If they didn't create a source via the entity handler, then we + // have to create one on our own. + if (!srcToFill) + { + if (fDisableDefaultEntityResolution) + return 0; + + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || + (urlTmp.isRelative())) + { + if (!fStandardUriConformant) + { + XMLBufBid ddSys(&fBufMgr); + XMLBuffer& resolvedSysId = ddSys.getBuffer(); + XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( + lastInfo.systemId + , resolvedSysId.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fStandardUriConformant && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + return srcToFill; +} + + +// --------------------------------------------------------------------------- +// SGXMLScanner: Private grammar preparsing methods +// --------------------------------------------------------------------------- +Grammar* SGXMLScanner::loadXMLSchemaGrammar(const InputSource& src, + const bool toCache) +{ + // Reset the validators + fSchemaValidator->reset(); + fSchemaValidator->setErrorReporter(fErrorReporter); + fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal); + fSchemaValidator->setGrammarResolver(fGrammarResolver); + + if (fValidatorFromUser) + fValidator->reset(); + + XSDDOMParser parser(0, fMemoryManager, 0); + + parser.setValidationScheme(XercesDOMParser::Val_Never); + parser.setDoNamespaces(true); + parser.setUserEntityHandler(fEntityHandler); + parser.setUserErrorReporter(fErrorReporter); + + // Should just issue warning if the schema is not found + bool flag = src.getIssueFatalErrorIfNotFound(); + ((InputSource&) src).setIssueFatalErrorIfNotFound(false); + + parser.parse(src); + + // Reset the InputSource + ((InputSource&) src).setIssueFatalErrorIfNotFound(flag); + + if (parser.getSawFatal() && fExitOnFirstFatal) + emitError(XMLErrs::SchemaScanFatalError); + + DOMDocument* document = parser.getDocument(); //Our Grammar + + if (document != 0) { + + DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema + if (root != 0) + { + const XMLCh* nsUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + Grammar* grammar = fGrammarResolver->getGrammar(nsUri); + + // Check if this exact schema has already been seen. + // + const XMLCh* sysId = src.getSystemId(); + SchemaInfo* importSchemaInfo = 0; + + if (grammar) + { + if (nsUri && *nsUri) + importSchemaInfo = fCachedSchemaInfoList->get(sysId, fURIStringPool->addOrFind(nsUri)); + else + importSchemaInfo = fCachedSchemaInfoList->get(sysId, fEmptyNamespaceId); + } + + if (!importSchemaInfo) + { + bool grammarFound = grammar && + grammar->getGrammarType() == Grammar::SchemaGrammarType && + getHandleMultipleImports(); + + SchemaGrammar* schemaGrammar; + + if (grammarFound) + schemaGrammar = (SchemaGrammar*) grammar; + else + schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); + + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription(); + gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE); + gramDesc->setLocationHints(sysId); + + TraverseSchema traverseSchema + ( + root + , fURIStringPool + , schemaGrammar + , fGrammarResolver + , fCachedSchemaInfoList + , toCache ? fCachedSchemaInfoList : fSchemaInfoList + , this + , sysId + , fEntityHandler + , fErrorReporter + , fMemoryManager + , grammarFound + ); + + grammar = schemaGrammar; + + // Reset the now invalid schema roots in the collected + // schema info entries. + // + { + RefHash2KeysTableOfEnumerator i ( + toCache ? fCachedSchemaInfoList : fSchemaInfoList); + + while (i.hasMoreElements ()) + i.nextElement().resetRoot (); + } + } + + if (fValidate) { + // validate the Schema scan so far + fValidator->setGrammar(grammar); + fValidator->preContentValidation(false); + } + + if (toCache) { + fGrammarResolver->cacheGrammars(); + } + + if(getPSVIHandler()) + fModel = fGrammarResolver->getXSModel(); + + return grammar; + } + } + + return 0; +} + + + +// --------------------------------------------------------------------------- +// SGXMLScanner: Private parsing methods +// --------------------------------------------------------------------------- + +// This method is called to do a raw scan of an attribute value. It does not +// do normalization (since we don't know their types yet.) It just scans the +// value and does entity expansion. +// +// End of entity's must be dealt with here. During DTD scan, they can come +// from external entities. During content, they can come from any entity. +// We just eat the end of entity and continue with our scan until we come +// to the closing quote. If an unterminated value causes us to go through +// subsequent entities, that will cause errors back in the calling code, +// but there's little we can do about it here. +bool SGXMLScanner::basicAttrValueScan(const XMLCh* const attrName, XMLBuffer& toFill) +{ + // Reset the target buffer + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr.skipIfQuote(quoteCh)) + return false; + + // We have to get the current reader because we have to ignore closing + // quotes until we hit the same reader again. + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // Loop until we get the attribute value. Note that we use a double + // loop here to avoid the setup/teardown overhead of the exception + // handler on every round. + while (true) + { + try + { + while(true) + { + XMLCh nextCh = fReaderMgr.getNextChar(); + + if (nextCh != quoteCh) + { + if (nextCh != chAmpersand) + { + if ((nextCh < 0xD800) || (nextCh > 0xDFFF)) + { + // Its got to at least be a valid XML character + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + if (nextCh == 0) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf); + } + } else // its a surrogate + { + // Deal with surrogate pairs + + // we expect a a leading surrogate. + if (nextCh <= 0xDBFF) + { + toFill.append(nextCh); + + // process the trailing surrogate + nextCh = fReaderMgr.getNextChar(); + + // it should be a trailing surrogate. + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + } else + { + // Its a trailing surrogate, but we are not expecting it + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + } + } else // its a chAmpersand + { + // Check for an entity ref . We ignore the empty flag in + // this one. + + bool escaped; + XMLCh firstCh; + XMLCh secondCh + ; + // If it was not returned directly, then jump back up + if (scanEntityRef(true, firstCh, secondCh, escaped) == EntityExp_Returned) + { + // If it was escaped, then put in a 0xFFFF value. This will + // be used later during validation and normalization of the + // value to know that the following character was via an + // escape char. + if (escaped) + toFill.append(0xFFFF); + + toFill.append(firstCh); + if (secondCh) + toFill.append(secondCh); + } + continue; + } + } else // its a quoteCh + { + // Check for our ending quote. It has to be in the same entity + // as where we started. Quotes in nested entities are ignored. + + if (curReader == fReaderMgr.getCurrentReaderNum()) + { + return true; + } + + // Watch for spillover into a previous entity + if (curReader > fReaderMgr.getCurrentReaderNum()) + { + emitError(XMLErrs::PartialMarkupInEntity); + return false; + } + } + + // add it to the buffer + toFill.append(nextCh); + + } + } + catch(const EndOfEntityException&) + { + // Just eat it and continue. + } + } + return true; +} + + +// This method scans a CDATA section. It collects the character into one +// of the temp buffers and calls the document handler, if any, with the +// characters. It assumes that the getCurrentTypeInfo(); + if(currType) + { + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType(); + if(modelType == SchemaElementDecl::Children || + modelType == SchemaElementDecl::ElementOnlyEmpty) + charOpts = XMLElementDecl::SpacesOk; + else if(modelType == SchemaElementDecl::Empty) + charOpts = XMLElementDecl::NoCharData; + } + + // should not be necessary when PSVI on element decl removed + const ElemStack::StackElem* topElem = fElemStack.topElement(); + + while (true) + { + const XMLCh nextCh = fReaderMgr.getNextChar(); + + // Watch for unexpected end of file + if (!nextCh) + { + emitError(XMLErrs::UnterminatedCDATASection); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + if (fValidate && fStandalone && (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))) + { + // This document is standalone; this ignorable CDATA whitespace is forbidden. + // XML 1.0, Section 2.9 + // And see if the current element is a 'Children' style content model + if (topElem->fThisElement->isExternal()) { + + if (charOpts == XMLElementDecl::SpacesOk) // Element Content + { + // Error - standalone should have a value of "no" as whitespace detected in an + // element type with element content whose element declaration was external + fValidator->emitError(XMLValid::NoWSForStandalone); + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + + // If this is a close square bracket it could be our closing + // sequence. + if (nextCh == chCloseSquare && fReaderMgr.skippedString(CDataClose)) + { + // make sure we were not expecting a trailing surrogate. + if (gotLeadingSurrogate) { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + + XMLSize_t xsLen = bbCData.getLen(); + const XMLCh* xsNormalized = bbCData.getRawBuffer(); + if (fValidate) { + + DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator(); + if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE) + { + // normalize the character according to schema whitespace facet + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf); + xsNormalized = fWSNormalizeBuf.getRawBuffer(); + xsLen = fWSNormalizeBuf.getLen(); + } + + // tell the schema validation about the character data for checkContent later + ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized); + + if (charOpts != XMLElementDecl::AllCharData) + { + // They definitely cannot handle any type of char data + fValidator->emitError(XMLValid::NoCharDataInCM); + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + + // call all active identity constraints + if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) { + fContent.append(xsNormalized, xsLen); + } + + // If we have a doc handler, call it + if (fDocHandler) + { + if (fNormalizeData) { + fDocHandler->docCharacters(xsNormalized, xsLen, true); + } + else { + fDocHandler->docCharacters( + bbCData.getRawBuffer(), bbCData.getLen(), true + ); + } + } + + // And we are done + break; + } + + // Make sure its a valid character. But if we've emitted an error + // already, don't bother with the overhead since we've already told + // them about it. + if (!emittedError) + { + // Deal with surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + emittedError = true; + } + } + gotLeadingSurrogate = false; + } + } + + // Add it to the buffer + bbCData.append(nextCh); + } +} + + +void SGXMLScanner::scanCharData(XMLBuffer& toUse) +{ + // We have to watch for the stupid ]]> sequence, which is illegal in + // character data. So this is a little state machine that handles that. + enum States + { + State_Waiting + , State_GotOne + , State_GotTwo + }; + + // Reset the buffer before we start + toUse.reset(); + + // Turn on the 'throw at end' flag of the reader manager + ThrowEOEJanitor jan(&fReaderMgr, true); + + // In order to be more efficient we have to use kind of a deeply nested + // set of blocks here. The outer block puts on a try and catches end of + // entity exceptions. The inner loop is the per-character loop. If we + // put the try inside the inner loop, it would work but would require + // the exception handling code setup/teardown code to be invoked for + // each character. + XMLCh nextCh; + XMLCh secondCh = 0; + States curState = State_Waiting; + bool escaped = false; + bool gotLeadingSurrogate = false; + bool notDone = true; + while (notDone) + { + try + { + while (true) + { + // Eat through as many plain content characters as possible without + // needing special handling. Moving most content characters here, + // in this one call, rather than running the overall loop once + // per content character, is a speed optimization. + if (curState == State_Waiting && !gotLeadingSurrogate) + { + fReaderMgr.movePlainContentChars(toUse); + } + + // Try to get another char from the source + // The code from here on down covers all contengencies, + if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh)) + { + // If we were waiting for a trailing surrogate, its an error + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + notDone = false; + break; + } + + // Watch for a reference. Note that the escapement mechanism + // is ignored in this content. + escaped = false; + if (nextCh == chAmpersand) + { + sendCharData(toUse); + + // Turn off the throwing at the end of entity during this + ThrowEOEJanitor jan(&fReaderMgr, false); + + if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Make sure the returned char is a valid XML char + if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // Keep the state machine up to date + if (!escaped) + { + if (nextCh == chCloseSquare) + { + if (curState == State_Waiting) + curState = State_GotOne; + else if (curState == State_GotOne) + curState = State_GotTwo; + } + else if (nextCh == chCloseAngle) + { + if (curState == State_GotTwo) + emitError(XMLErrs::BadSequenceInCharData); + curState = State_Waiting; + } + else + { + curState = State_Waiting; + } + } + else + { + curState = State_Waiting; + } + + // Add this char to the buffer + toUse.append(nextCh); + + if (secondCh) + { + toUse.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException& toCatch) + { + // Some entity ended, so we have to send any accumulated + // chars and send an end of entity event. + sendCharData(toUse); + gotLeadingSurrogate = false; + + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + // Check the validity constraints as per XML 1.0 Section 2.9 + if (fValidate && fStandalone) + { + // See if the text contains whitespace + // Get the raw data we need for the callback + const XMLCh* rawBuf = toUse.getRawBuffer(); + const XMLSize_t len = toUse.getLen(); + const bool isSpaces = fReaderMgr.getCurrentReader()->containsWhiteSpace(rawBuf, len); + + if (isSpaces) + { + // And see if the current element is a 'Children' style content model + const ElemStack::StackElem* topElem = fElemStack.topElement(); + + if (topElem->fThisElement->isExternal()) { + + // Get the character data opts for the current element + XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData; + // And see if the current element is a 'Children' style content model + ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if(currType) + { + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType(); + if(modelType == SchemaElementDecl::Children || + modelType == SchemaElementDecl::ElementOnlyEmpty) + charOpts = XMLElementDecl::SpacesOk; + } + + if (charOpts == XMLElementDecl::SpacesOk) // => Element Content + { + // Error - standalone should have a value of "no" as whitespace detected in an + // element type with element content whose element declaration was external + // + fValidator->emitError(XMLValid::NoWSForStandalone); + if (getPSVIHandler()) + { + // REVISIT: + // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID); + } + } + } + } + } + // Send any char data that we accumulated into the buffer + sendCharData(toUse); +} + + +// This method will scan a general/character entity ref. It will either +// expand a char ref and return it directly, or push a reader for a general +// entity. +// +// The return value indicates whether the char parameters hold the value +// or whether the value was pushed as a reader, or that it failed. +// +// The escaped flag tells the caller whether the returned parameter resulted +// from a character reference, which escapes the character in some cases. It +// only makes any difference if the return value indicates the value was +// returned directly. +SGXMLScanner::EntityExpRes +SGXMLScanner::scanEntityRef( const bool + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped) +{ + // Assume no escape + secondCh = 0; + escaped = false; + + // We have to insure that its all in one entity + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // If the next char is a pound, then its a character reference and we + // need to expand it always. + if (fReaderMgr.skippedChar(chPound)) + { + // Its a character reference, so scan it and get back the numeric + // value it represents. + if (!scanCharRef(firstCh, secondCh)) + return EntityExp_Failed; + + escaped = true; + + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + return EntityExp_Returned; + } + + // Expand it since its a normal entity ref + XMLBufBid bbName(&fBufMgr); + int colonPosition; + if (!fReaderMgr.getQName(bbName.getBuffer(), &colonPosition)) + { + if (bbName.isEmpty()) + emitError(XMLErrs::ExpectedEntityRefName); + else + emitError(XMLErrs::InvalidEntityRefName, bbName.getRawBuffer()); + return EntityExp_Failed; + } + + // Next char must be a semi-colon. But if its not, just emit + // an error and try to continue. + if (!fReaderMgr.skippedChar(chSemiColon)) + emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer()); + + // Make sure we ended up on the same entity reader as the & char + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // Look up the name in the general entity pool + // If it does not exist, then obviously an error + if (!fEntityTable->containsKey(bbName.getRawBuffer())) + { + // XML 1.0 Section 4.1 + // Well-formedness Constraint for entity not found: + // In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references, + // or a document with "standalone='yes'", for an entity reference that does not occur within the external subset + // or a parameter entity + if (fStandalone || fHasNoDTD) + emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer()); + + return EntityExp_Failed; + } + + // here's where we need to check if there's a SecurityManager, + // how many entity references we've had + if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) { + XMLCh expLimStr[32]; + XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager); + emitError + ( + XMLErrs::EntityExpansionLimitExceeded + , expLimStr + ); + // there seems nothing better to be done than to reset the entity expansion limit + fEntityExpansionCount = 0; + } + + firstCh = fEntityTable->get(bbName.getRawBuffer()); + escaped = true; + return EntityExp_Returned; +} + + +bool SGXMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace) +{ + Grammar* tempGrammar = fGrammarResolver->getGrammar(newGrammarNameSpace); + + if (!tempGrammar) { + tempGrammar = fSchemaGrammar; + } + + if (!tempGrammar) + return false; + else { + fGrammar = tempGrammar; + fGrammarType = fGrammar->getGrammarType(); + if (fGrammarType == Grammar::DTDGrammarType) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager); + } + + fValidator->setGrammar(fGrammar); + return true; + } +} + +// check if we should skip or lax the validation of the element +// if skip - no validation +// if lax - validate only if the element if found +bool SGXMLScanner::laxElementValidation(QName* element, ContentLeafNameTypeVector* cv, + const XMLContentModel* const cm, + const XMLSize_t parentElemDepth) +{ + bool skipThisOne = false; + bool laxThisOne = false; + unsigned int elementURI = element->getURI(); + unsigned int currState = fElemState[parentElemDepth]; + unsigned int currLoop = fElemLoopState[parentElemDepth]; + + if (currState == XMLContentModel::gInvalidTrans) { + return laxThisOne; + } + + SubstitutionGroupComparator comparator(fGrammarResolver, fURIStringPool); + + if (cv) { + XMLSize_t i = 0; + XMLSize_t leafCount = cv->getLeafCount(); + unsigned int nextState = 0; + + for (; i < leafCount; i++) { + + QName* fElemMap = cv->getLeafNameAt(i); + unsigned int uri = fElemMap->getURI(); + ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i); + + if (type == ContentSpecNode::Leaf) { + if (((uri == elementURI) + && XMLString::equals(fElemMap->getLocalPart(), element->getLocalPart())) + || comparator.isEquivalentTo(element, fElemMap)) { + + nextState = cm->getNextState(currState, i); + + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } else if ((type & 0x0f) == ContentSpecNode::Any) { + nextState = cm->getNextState(currState, i); + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + else if ((type & 0x0f) == ContentSpecNode::Any_Other) { + if (uri != elementURI && elementURI != fEmptyNamespaceId) { + nextState = cm->getNextState(currState, i); + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if ((type & 0x0f) == ContentSpecNode::Any_NS) { + if (uri == elementURI) { + nextState = cm->getNextState(currState, i); + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + + } // for + + if (i == leafCount) { // no match + fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans; + fElemLoopState[parentElemDepth] = 0; + return laxThisOne; + } + + ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i); + if ((type & 0x0f) == ContentSpecNode::Any || + (type & 0x0f) == ContentSpecNode::Any_Other || + (type & 0x0f) == ContentSpecNode::Any_NS) + { + if (type == ContentSpecNode::Any_Skip || + type == ContentSpecNode::Any_NS_Skip || + type == ContentSpecNode::Any_Other_Skip) { + skipThisOne = true; + } + else if (type == ContentSpecNode::Any_Lax || + type == ContentSpecNode::Any_NS_Lax || + type == ContentSpecNode::Any_Other_Lax) { + laxThisOne = true; + } + } + fElemState[parentElemDepth] = nextState; + fElemLoopState[parentElemDepth] = currLoop; + } // if + + if (skipThisOne) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + + return laxThisOne; +} + + +// check if there is an AnyAttribute, and if so, see if we should lax or skip +// if skip - no validation +// if lax - validate only if the attribute if found +bool SGXMLScanner::anyAttributeValidation(SchemaAttDef* attWildCard, unsigned int uriId, bool& skipThisOne, bool& laxThisOne) +{ + XMLAttDef::AttTypes wildCardType = attWildCard->getType(); + bool anyEncountered = false; + skipThisOne = false; + laxThisOne = false; + if (wildCardType == XMLAttDef::Any_Any) + anyEncountered = true; + else if (wildCardType == XMLAttDef::Any_Other) { + if (attWildCard->getAttName()->getURI() != uriId + && uriId != fEmptyNamespaceId) + anyEncountered = true; + } + else if (wildCardType == XMLAttDef::Any_List) { + ValueVectorOf* nameURIList = attWildCard->getNamespaceList(); + XMLSize_t listSize = (nameURIList) ? nameURIList->size() : 0; + + if (listSize) { + for (XMLSize_t i=0; i < listSize; i++) { + if (nameURIList->elementAt(i) == uriId) + anyEncountered = true; + } + } + } + + if (anyEncountered) { + XMLAttDef::DefAttTypes defType = attWildCard->getDefaultType(); + if (defType == XMLAttDef::ProcessContents_Skip) { + // attribute should just be bypassed, + skipThisOne = true; + if (getPSVIHandler()) + { + // REVISIT: + // PSVIAttribute->setValidationAttempted(PSVIItem::VALIDATION_NONE); + } + } + else if (defType == XMLAttDef::ProcessContents_Lax) { + laxThisOne = true; + } + } + + return anyEncountered; +} + +inline XMLAttDefList& getAttDefList(ComplexTypeInfo* currType, XMLElementDecl* elemDecl) +{ + if (currType) + return currType->getAttDefList(); + else + return elemDecl->getAttDefList(); +} + +void SGXMLScanner::endElementPSVI(SchemaElementDecl* const elemDecl, + DatatypeValidator* const memberDV) +{ + PSVIElement::ASSESSMENT_TYPE validationAttempted; + PSVIElement::VALIDITY_STATE validity = PSVIElement::VALIDITY_NOTKNOWN; + + if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fFullValidationDepth) + validationAttempted = PSVIElement::VALIDATION_FULL; + else if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fNoneValidationDepth) + validationAttempted = PSVIElement::VALIDATION_NONE; + else + { + validationAttempted = PSVIElement::VALIDATION_PARTIAL; + fPSVIElemContext.fFullValidationDepth = + fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth - 1; + } + + if (fValidate && elemDecl->isDeclared()) + { + validity = (fPSVIElemContext.fErrorOccurred) + ? PSVIElement::VALIDITY_INVALID : PSVIElement::VALIDITY_VALID; + } + + XSTypeDefinition* typeDef = 0; + bool isMixed = false; + if (fPSVIElemContext.fCurrentTypeInfo) + { + typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentTypeInfo); + SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes)fPSVIElemContext.fCurrentTypeInfo->getContentType(); + isMixed = (modelType == SchemaElementDecl::Mixed_Simple + || modelType == SchemaElementDecl::Mixed_Complex); + } + else if (fPSVIElemContext.fCurrentDV) + typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentDV); + + XMLCh* canonicalValue = 0; + if (fPSVIElemContext.fNormalizedValue && !isMixed && + validity == PSVIElement::VALIDITY_VALID) + { + if (memberDV) + canonicalValue = (XMLCh*) memberDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager); + else if (fPSVIElemContext.fCurrentDV) + canonicalValue = (XMLCh*) fPSVIElemContext.fCurrentDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager); + } + + fPSVIElement->reset + ( + validity + , validationAttempted + , fRootElemName + , fPSVIElemContext.fIsSpecified + , (elemDecl->isDeclared()) + ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0 + , typeDef + , (memberDV) ? (XSSimpleTypeDefinition*) fModel->getXSObject(memberDV) : 0 + , fModel + , elemDecl->getDefaultValue() + , fPSVIElemContext.fNormalizedValue + , canonicalValue + ); + + fPSVIHandler->handleElementPSVI + ( + elemDecl->getBaseName() + , fURIStringPool->getValueForId(elemDecl->getURI()) + , fPSVIElement + ); + + // decrease element depth + fPSVIElemContext.fElemDepth--; + +} + +void SGXMLScanner::resetPSVIElemContext() +{ + fPSVIElemContext.fIsSpecified = false; + fPSVIElemContext.fErrorOccurred = false; + fPSVIElemContext.fElemDepth = -1; + fPSVIElemContext.fFullValidationDepth = -1; + fPSVIElemContext.fNoneValidationDepth = -1; + fPSVIElemContext.fCurrentDV = 0; + fPSVIElemContext.fCurrentTypeInfo = 0; + fPSVIElemContext.fNormalizedValue = 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/SGXMLScanner.hpp b/include/xercesc/internal/SGXMLScanner.hpp new file mode 100644 index 0000000..4f334c6 --- /dev/null +++ b/include/xercesc/internal/SGXMLScanner.hpp @@ -0,0 +1,307 @@ +/* + * 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: SGXMLScanner.hpp 882548 2009-11-20 13:44:14Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SGXMLSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_SGXMLSCANNER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +class SchemaGrammar; +class SchemaValidator; +class IdentityConstraintHandler; +class IdentityConstraint; +class ContentLeafNameTypeVector; +class SchemaAttDef; +class XMLContentModel; +class XSModel; +class PSVIAttributeList; +class PSVIElement; + +// This is a scanner class, which process XML Schema grammar. +class XMLPARSER_EXPORT SGXMLScanner : public XMLScanner +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + SGXMLScanner + ( + XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + SGXMLScanner + ( + XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~SGXMLScanner(); + + // ----------------------------------------------------------------------- + // XMLScanner public virtual methods + // ----------------------------------------------------------------------- + virtual const XMLCh* getName() const; + virtual NameIdPool* getEntityDeclPool(); + virtual const NameIdPool* getEntityDeclPool() const; + virtual void scanDocument + ( + const InputSource& src + ); + virtual bool scanNext(XMLPScanToken& toFill); + virtual Grammar* loadGrammar + ( + const InputSource& src + , const short grammarType + , const bool toCache = false + ); + + virtual void resetCachedGrammar (); + virtual Grammar::GrammarType getCurrentGrammarType() const; + +protected: + // ----------------------------------------------------------------------- + // XMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual void scanReset(const InputSource& src); + + // ----------------------------------------------------------------------- + // SGXMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual bool scanStartTag(bool& gotData); + virtual void scanEndTag(bool& gotData); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + XMLSize_t buildAttList + ( + const RefVectorOf& providedAttrs + , const XMLSize_t attCount + , XMLElementDecl* elemDecl + , RefVectorOf& toFill + ); + bool laxElementValidation(QName* element, ContentLeafNameTypeVector* cv, + const XMLContentModel* const cm, + const XMLSize_t parentElemDepth); + XMLSize_t rawAttrScan + ( + const XMLCh* const elemName + , RefVectorOf& toFill + , bool& isEmpty + ); + void updateNSMap + ( + const XMLCh* const attrName + , const XMLCh* const attrValue + ); + void resizeElemState(); + + void updateNSMap + ( + const XMLCh* const attrName + , const XMLCh* const attrValue + , const int colonPosition + ); + void resizeRawAttrColonList(); + // ----------------------------------------------------------------------- + // Data members + // + // fRawAttrList + // During the initial scan of the attributes we can only do a raw + // scan for key/value pairs. So this vector is used to store them + // until they can be processed (and put into fAttrList.) + // + // fSchemaValidator + // The Schema validator instance. + // + // fSeeXsi + // This flag indicates a schema has been seen. + // + // fElemState + // fElemLoopState + // fElemStateSize + // Stores an element next state from DFA content model - used for + // wildcard validation + // + // fElemNonDeclPool + // registry for elements without decls in the grammar + // fElemCount + // count of the number of start tags seen so far (starts at 1). + // Used for duplicate attribute detection/processing of required/defaulted attributes + // fAttDefRegistry + // mapping from XMLAttDef instances to the count of the last + // start tag where they were utilized. + // fUndeclaredAttrRegistry + // set of namespaceId/localName pairs to detect duplicates + // fPSVIAttrList + // PSVI attribute list implementation that needs to be + // filled when a PSVIHandler is registered + // fSchemaInfoList + // Transient schema info list that is passed to TraverseSchema instances. + // fCachedSchemaInfoList + // Cached Schema info list that is passed to TraverseSchema instances. + // + // ----------------------------------------------------------------------- + bool fSeeXsi; + Grammar::GrammarType fGrammarType; + unsigned int fElemStateSize; + unsigned int* fElemState; + unsigned int* fElemLoopState; + XMLBuffer fContent; + ValueHashTableOf* fEntityTable; + RefVectorOf* fRawAttrList; + unsigned int fRawAttrColonListSize; + int* fRawAttrColonList; + SchemaGrammar* fSchemaGrammar; + SchemaValidator* fSchemaValidator; + IdentityConstraintHandler* fICHandler; + RefHash3KeysIdPool* fElemNonDeclPool; + unsigned int fElemCount; + RefHashTableOf*fAttDefRegistry; + Hash2KeysSetOf* fUndeclaredAttrRegistry; + PSVIAttributeList * fPSVIAttrList; + XSModel* fModel; + PSVIElement* fPSVIElement; + ValueStackOf* fErrorStack; + PSVIElemContext fPSVIElemContext; + RefHash2KeysTableOf* fSchemaInfoList; + RefHash2KeysTableOf* fCachedSchemaInfoList; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SGXMLScanner(); + SGXMLScanner(const SGXMLScanner&); + SGXMLScanner& operator=(const SGXMLScanner&); + + // ----------------------------------------------------------------------- + // XMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual void scanCDSection(); + virtual void scanCharData(XMLBuffer& toToUse); + virtual EntityExpRes scanEntityRef + ( + const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped + ); + virtual void scanDocTypeDecl(); + virtual void sendCharData(XMLBuffer& toSend); + virtual InputSource* resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void commonInit(); + void cleanUp(); + + bool normalizeAttValue + ( + const XMLAttDef* const attDef + , const XMLCh* const attrName + , const XMLCh* const value + , XMLBuffer& toFill + ); + bool normalizeAttRawValue + ( + const XMLCh* const attrName + , const XMLCh* const value + , XMLBuffer& toFill + ); + void scanRawAttrListforNameSpaces(XMLSize_t attCount); + void parseSchemaLocation(const XMLCh* const schemaLocationStr, bool ignoreLoadSchema = false); + void resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema = false); + bool switchGrammar(const XMLCh* const newGrammarNameSpace); + bool anyAttributeValidation(SchemaAttDef* attWildCard, + unsigned int uriId, + bool& skipThisOne, + bool& laxThisOne); + + // ----------------------------------------------------------------------- + // Private scanning methods + // ----------------------------------------------------------------------- + bool basicAttrValueScan + ( + const XMLCh* const attrName + , XMLBuffer& toFill + ); + bool scanAttValue + ( + const XMLAttDef* const attDef + , XMLBuffer& toFill + ); + bool scanContent(); + + // ----------------------------------------------------------------------- + // IdentityConstraints Activation methods + // ----------------------------------------------------------------------- + inline bool toCheckIdentityConstraint() const; + + // ----------------------------------------------------------------------- + // Grammar preparsing methods + // ----------------------------------------------------------------------- + Grammar* loadXMLSchemaGrammar(const InputSource& src, const bool toCache = false); + + // ----------------------------------------------------------------------- + // PSVI handling methods + // ----------------------------------------------------------------------- + void endElementPSVI(SchemaElementDecl* const elemDecl, + DatatypeValidator* const memberDV); + void resetPSVIElemContext(); +}; + +inline const XMLCh* SGXMLScanner::getName() const +{ + return XMLUni::fgSGXMLScanner; +} + +inline bool SGXMLScanner::toCheckIdentityConstraint() const +{ + return fValidate && fIdentityConstraintChecking && fICHandler; +} + +inline Grammar::GrammarType SGXMLScanner::getCurrentGrammarType() const +{ + return fGrammarType; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/ValidationContextImpl.cpp b/include/xercesc/internal/ValidationContextImpl.cpp new file mode 100644 index 0000000..4de4c3c --- /dev/null +++ b/include/xercesc/internal/ValidationContextImpl.cpp @@ -0,0 +1,217 @@ +/* + * 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: ValidationContextImpl.cpp 903149 2010-01-26 09:58:40Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructor and Destructor +// --------------------------------------------------------------------------- + +ValidationContextImpl::~ValidationContextImpl() +{ + if (fIdRefList) + delete fIdRefList; +} + +ValidationContextImpl::ValidationContextImpl(MemoryManager* const manager) +:ValidationContext(manager) +,fIdRefList(0) +,fEntityDeclPool(0) +,fToCheckIdRefList(true) +,fValidatingMemberType(0) +,fElemStack(0) +,fScanner(0) +,fNamespaceScope(0) +{ + fIdRefList = new (fMemoryManager) RefHashTableOf(109, fMemoryManager); +} + +/** + * IdRefList + * + */ +RefHashTableOf* ValidationContextImpl::getIdRefList() const +{ + return fIdRefList; +} + +void ValidationContextImpl::setIdRefList(RefHashTableOf* const newIdRefList) +{ + if (fIdRefList) + delete fIdRefList; + + fIdRefList = newIdRefList; +} + +void ValidationContextImpl::clearIdRefList() +{ + if (fIdRefList) + fIdRefList->removeAll(); + +} + +void ValidationContextImpl::addId(const XMLCh * const content) +{ + if (!fIdRefList || !fToCheckIdRefList) + return; + + XMLRefInfo* idEntry = fIdRefList->get(content); + + if (idEntry) + { + if (idEntry->getDeclared()) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_ID_Not_Unique + , content + , fMemoryManager); + } + } + else + { + idEntry = new (fMemoryManager) XMLRefInfo(content, false, false, fMemoryManager); + fIdRefList->put((void*)idEntry->getRefName(), idEntry); + } + + // + // Mark it declared + // + idEntry->setDeclared(true); + +} + +void ValidationContextImpl::addIdRef(const XMLCh * const content) +{ + if (!fIdRefList || !fToCheckIdRefList) + return; + + XMLRefInfo* idEntry = fIdRefList->get(content); + + if (!idEntry) + { + idEntry = new (fMemoryManager) XMLRefInfo(content, false, false, fMemoryManager); + fIdRefList->put((void*)idEntry->getRefName(), idEntry); + } + + // + // Mark it used + // + idEntry->setUsed(true); + +} + +void ValidationContextImpl::toCheckIdRefList(bool toCheck) +{ + fToCheckIdRefList = toCheck; +} + +/** + * EntityDeclPool + * + */ +const NameIdPool* ValidationContextImpl::getEntityDeclPool() const +{ + return fEntityDeclPool; +} + +const NameIdPool* ValidationContextImpl::setEntityDeclPool(const NameIdPool* const newEntityDeclPool) +{ + // we don't own it so we return the existing one for the owner to delete + const NameIdPool* tempPool = fEntityDeclPool; + fEntityDeclPool = newEntityDeclPool; + return tempPool; + +} + +void ValidationContextImpl::checkEntity(const XMLCh * const content) const +{ + + if (fEntityDeclPool) + { + const DTDEntityDecl* decl = fEntityDeclPool->getByKey(content); + + if (!decl || !decl->isUnparsed()) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_ENTITY_Invalid + , content + , fMemoryManager); + } + + } + else + { + ThrowXMLwithMemMgr1 + ( + InvalidDatatypeValueException + , XMLExcepts::VALUE_ENTITY_Invalid + , content + , fMemoryManager + ); + } + +} + +/* QName + */ +bool ValidationContextImpl::isPrefixUnknown(XMLCh* prefix) { + bool unknown = false; + if (XMLString::equals(prefix, XMLUni::fgXMLNSString)) { + return true; + } + else if (!XMLString::equals(prefix, XMLUni::fgXMLString)) { + if(fElemStack && !fElemStack->isEmpty()) + fElemStack->mapPrefixToURI(prefix, unknown); + else if(fNamespaceScope) + unknown = (fNamespaceScope->getNamespaceForPrefix(prefix)==fNamespaceScope->getEmptyNamespaceId()); + } + return unknown; +} + +const XMLCh* ValidationContextImpl::getURIForPrefix(XMLCh* prefix) { + bool unknown = false; + unsigned int uriId = 0; + if(fElemStack) + uriId = fElemStack->mapPrefixToURI(prefix, unknown); + else if(fNamespaceScope) + { + uriId = fNamespaceScope->getNamespaceForPrefix(prefix); + unknown = uriId == fNamespaceScope->getEmptyNamespaceId(); + } + if (!unknown) + return fScanner->getURIText(uriId); + + return XMLUni::fgZeroLenString; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/ValidationContextImpl.hpp b/include/xercesc/internal/ValidationContextImpl.hpp new file mode 100644 index 0000000..5bb82c0 --- /dev/null +++ b/include/xercesc/internal/ValidationContextImpl.hpp @@ -0,0 +1,173 @@ +/* + * 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: ValidationContextImpl.hpp 729944 2008-12-29 17:03:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_VALIDATION_CONTEXTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_VALIDATION_CONTEXTIMPL_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN +class ElemStack; +class NamespaceScope; + +class XMLPARSER_EXPORT ValidationContextImpl : public ValidationContext +{ +public : + // ----------------------------------------------------------------------- + /** @name Virtual destructor for derived classes */ + // ----------------------------------------------------------------------- + //@{ + + /** + * virtual destructor + * + */ + virtual ~ValidationContextImpl(); + + ValidationContextImpl(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + + //@} + + // ----------------------------------------------------------------------- + /** @name The ValidationContextImpl Interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * IDRefList + * + */ + virtual RefHashTableOf* getIdRefList() const; + + virtual void setIdRefList(RefHashTableOf* const); + + virtual void clearIdRefList(); + + virtual void addId(const XMLCh * const ); + + virtual void addIdRef(const XMLCh * const ); + + virtual void toCheckIdRefList(bool); + + /** + * EntityDeclPool + * + */ + virtual const NameIdPool* getEntityDeclPool() const; + + virtual const NameIdPool* setEntityDeclPool(const NameIdPool* const); + + virtual void checkEntity(const XMLCh * const ) const; + + + /** + * Union datatype handling + * + */ + + virtual DatatypeValidator * getValidatingMemberType() const; + virtual void setValidatingMemberType(DatatypeValidator * validatingMemberType) ; + + /** + * QName datatype handling + * Create default implementations for source code compatibility + */ + virtual bool isPrefixUnknown(XMLCh* prefix); + virtual void setElemStack(ElemStack* elemStack); + virtual const XMLCh* getURIForPrefix(XMLCh* prefix); + virtual void setScanner(XMLScanner* scanner); + virtual void setNamespaceScope(NamespaceScope* nsStack); + + + //@} + +private: + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + ValidationContextImpl(const ValidationContextImpl& ); + ValidationContextImpl& operator=(const ValidationContextImpl& ); + //@} + + // ----------------------------------------------------------------------- + // Data members + // + // fIDRefList: owned/adopted + // This is a list of XMLRefInfo objects. This member lets us do all + // needed ID-IDREF balancing checks. + // + // fEntityDeclPool: referenced only + // This is a pool of EntityDecl objects, which contains all of the + // general entities that are declared in the DTD subsets, plus the + // default entities (such as > < ...) defined by the XML Standard. + // + // fToAddToList + // fValidatingMemberType + // The member type in a union that actually + // validated some text. Note that the validationContext does not + // own this object, and the value of getValidatingMemberType + // will not be accurate unless the type of the most recently-validated + // element/attribute is in fact a union datatype. + // fElemStack + // Need access to elemstack to look up URI's that are inscope (while validating an XML). + // fNamespaceScope + // Need access to namespace scope to look up URI's that are inscope (while loading a schema). + // ----------------------------------------------------------------------- + + RefHashTableOf* fIdRefList; + const NameIdPool* fEntityDeclPool; + bool fToCheckIdRefList; + DatatypeValidator * fValidatingMemberType; + ElemStack* fElemStack; + XMLScanner* fScanner; + NamespaceScope* fNamespaceScope; + +}; + + + +inline DatatypeValidator * ValidationContextImpl::getValidatingMemberType() const +{ + return fValidatingMemberType; +} + +inline void ValidationContextImpl::setValidatingMemberType(DatatypeValidator * validatingMemberType) +{ + fValidatingMemberType = validatingMemberType; +} + +inline void ValidationContextImpl::setElemStack(ElemStack* elemStack) { + fElemStack = elemStack; +} + +inline void ValidationContextImpl::setScanner(XMLScanner* scanner) { + fScanner = scanner; +} + +inline void ValidationContextImpl::setNamespaceScope(NamespaceScope* nsStack) { + fNamespaceScope = nsStack; +} + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/internal/VecAttrListImpl.cpp b/include/xercesc/internal/VecAttrListImpl.cpp new file mode 100644 index 0000000..7f2ce70 --- /dev/null +++ b/include/xercesc/internal/VecAttrListImpl.cpp @@ -0,0 +1,159 @@ +/* + * 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: VecAttrListImpl.cpp 672273 2008-06-27 13:57:00Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +VecAttrListImpl::VecAttrListImpl() : + + fAdopt(false) + , fCount(0) + , fVector(0) +{ +} + +VecAttrListImpl::~VecAttrListImpl() +{ + // + // Note that some compilers can't deal with the fact that the pointer + // is to a const object, so we have to cast off the const'ness here! + // + if (fAdopt) + delete (RefVectorOf*)fVector; +} + + +// --------------------------------------------------------------------------- +// Implementation of the attribute list interface +// --------------------------------------------------------------------------- +XMLSize_t VecAttrListImpl::getLength() const +{ + return fCount; +} + +const XMLCh* VecAttrListImpl::getName(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return fVector->elementAt(index)->getQName(); +} + +const XMLCh* VecAttrListImpl::getType(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return XMLAttDef::getAttTypeString(fVector->elementAt(index)->getType(), fVector->getMemoryManager()); +} + +const XMLCh* VecAttrListImpl::getValue(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return fVector->elementAt(index)->getValue(); +} + +const XMLCh* VecAttrListImpl::getType(const XMLCh* const name) const +{ + // + // Search the vector for the attribute with the given name and return + // its type. + // + for (XMLSize_t index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + if (XMLString::equals(curElem->getQName(), name)) + return XMLAttDef::getAttTypeString(curElem->getType(), fVector->getMemoryManager()); + } + return 0; +} + +const XMLCh* VecAttrListImpl::getValue(const XMLCh* const name) const +{ + // + // Search the vector for the attribute with the given name and return + // its type. + // + for (XMLSize_t index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + if (XMLString::equals(curElem->getQName(), name)) + return curElem->getValue(); + } + return 0; +} + +const XMLCh* VecAttrListImpl::getValue(const char* const name) const +{ + // Temporarily transcode the name for lookup + XMLCh* wideName = XMLString::transcode(name, XMLPlatformUtils::fgMemoryManager); + ArrayJanitor janName(wideName, XMLPlatformUtils::fgMemoryManager); + + // + // Search the vector for the attribute with the given name and return + // its type. + // + for (XMLSize_t index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + if (XMLString::equals(curElem->getQName(), wideName)) + return curElem->getValue(); + } + return 0; +} + + + +// --------------------------------------------------------------------------- +// Setter methods +// --------------------------------------------------------------------------- +void VecAttrListImpl::setVector(const RefVectorOf* const srcVec + , const XMLSize_t count + , const bool adopt) +{ + // + // Delete the previous vector (if any) if we are adopting. Note that some + // compilers can't deal with the fact that the pointer is to a const + // object, so we have to cast off the const'ness here! + // + if (fAdopt) + delete (RefVectorOf*)fVector; + + fAdopt = adopt; + fCount = count; + fVector = srcVec; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/VecAttrListImpl.hpp b/include/xercesc/internal/VecAttrListImpl.hpp new file mode 100644 index 0000000..22ae2d5 --- /dev/null +++ b/include/xercesc/internal/VecAttrListImpl.hpp @@ -0,0 +1,96 @@ +/* + * 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: VecAttrListImpl.hpp 672273 2008-06-27 13:57:00Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_VECATTRLISTIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_VECATTRLISTIMPL_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT VecAttrListImpl : public XMemory, public AttributeList +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + VecAttrListImpl(); + ~VecAttrListImpl(); + + + // ----------------------------------------------------------------------- + // Implementation of the attribute list interface + // ----------------------------------------------------------------------- + virtual XMLSize_t getLength() const; + virtual const XMLCh* getName(const XMLSize_t index) const; + virtual const XMLCh* getType(const XMLSize_t index) const; + virtual const XMLCh* getValue(const XMLSize_t index) const; + virtual const XMLCh* getType(const XMLCh* const name) const; + virtual const XMLCh* getValue(const XMLCh* const name) const; + virtual const XMLCh* getValue(const char* const name) const; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setVector + ( + const RefVectorOf* const srcVec + , const XMLSize_t count + , const bool adopt = false + ); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + VecAttrListImpl(const VecAttrListImpl&); + VecAttrListImpl& operator=(const VecAttrListImpl&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fAdopt + // Indicates whether the passed vector is to be adopted or not. If + // so, we destroy it when we are destroyed (and when a new vector is + // set!) + // + // fCount + // The count of elements in the vector that should be considered + // valid. This is an optimization to allow vector elements to be + // reused over and over but a different count of them be valid for + // each use. + // + // fVector + // The vector that provides the backing for the list. + // ----------------------------------------------------------------------- + bool fAdopt; + XMLSize_t fCount; + const RefVectorOf* fVector; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/VecAttributesImpl.cpp b/include/xercesc/internal/VecAttributesImpl.cpp new file mode 100644 index 0000000..f475cad --- /dev/null +++ b/include/xercesc/internal/VecAttributesImpl.cpp @@ -0,0 +1,249 @@ +/* + * 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: VecAttributesImpl.cpp 672311 2008-06-27 16:05:01Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +VecAttributesImpl::VecAttributesImpl() : + + fAdopt(false) + , fCount(0) + , fVector(0) + , fScanner(0) +{ +} + +VecAttributesImpl::~VecAttributesImpl() +{ + // + // Note that some compilers can't deal with the fact that the pointer + // is to a const object, so we have to cast off the const'ness here! + // + if (fAdopt) + delete (RefVectorOf*)fVector; +} + + +// --------------------------------------------------------------------------- +// Implementation of the attribute list interface +// --------------------------------------------------------------------------- +XMLSize_t VecAttributesImpl::getLength() const +{ + return fCount; +} + +const XMLCh* VecAttributesImpl::getURI(const XMLSize_t index) const +{ + // since this func really needs to be const, like the rest, not sure how we + // make it const and re-use the fURIBuffer member variable. we're currently + // creating a buffer each time you need a URI. there has to be a better + // way to do this... + + //XMLBuffer tempBuf; + if (index >= fCount) { + + + return 0; + } + //fValidator->getURIText(fVector->elementAt(index)->getURIId(), tempBuf) ; + //return tempBuf.getRawBuffer() ; + return fScanner->getURIText(fVector->elementAt(index)->getURIId()); +} + +const XMLCh* VecAttributesImpl::getLocalName(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return fVector->elementAt(index)->getName(); +} + +const XMLCh* VecAttributesImpl::getQName(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return fVector->elementAt(index)->getQName(); +} + +const XMLCh* VecAttributesImpl::getType(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return XMLAttDef::getAttTypeString(fVector->elementAt(index)->getType(), fVector->getMemoryManager()); +} + +const XMLCh* VecAttributesImpl::getValue(const XMLSize_t index) const +{ + if (index >= fCount) { + return 0; + } + return fVector->elementAt(index)->getValue(); +} + +bool VecAttributesImpl::getIndex(const XMLCh* const uri, + const XMLCh* const localPart, + XMLSize_t& index) const +{ + // + // Search the vector for the attribute with the given name and return + // its type. + // + XMLBuffer uriBuffer(1023, fVector->getMemoryManager()) ; + for (index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + fScanner->getURIText(curElem->getURIId(), uriBuffer) ; + + if ( (XMLString::equals(curElem->getName(), localPart)) && + (XMLString::equals(uriBuffer.getRawBuffer(), uri)) ) + return true; + } + return false; +} + +int VecAttributesImpl::getIndex(const XMLCh* const uri, const XMLCh* const localPart ) const +{ + // + // Search the vector for the attribute with the given name and return + // its type. + // + XMLBuffer uriBuffer(1023, fVector->getMemoryManager()) ; + for (XMLSize_t index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + fScanner->getURIText(curElem->getURIId(), uriBuffer) ; + + if ( (XMLString::equals(curElem->getName(), localPart)) && + (XMLString::equals(uriBuffer.getRawBuffer(), uri)) ) + return (int)index ; + } + return -1; +} + +bool VecAttributesImpl::getIndex(const XMLCh* const qName, + XMLSize_t& index) const +{ + // + // Search the vector for the attribute with the given name and return + // its type. + // + for (index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + if (XMLString::equals(curElem->getQName(), qName)) + return true; + } + return false; +} + +int VecAttributesImpl::getIndex(const XMLCh* const qName ) const +{ + // + // Search the vector for the attribute with the given name and return + // its type. + // + for (XMLSize_t index = 0; index < fCount; index++) + { + const XMLAttr* curElem = fVector->elementAt(index); + + if (XMLString::equals(curElem->getQName(), qName)) + return (int)index ; + } + return -1; +} + +const XMLCh* VecAttributesImpl::getType(const XMLCh* const uri, const XMLCh* const localPart ) const +{ + XMLSize_t i; + + if (getIndex(uri, localPart, i)) + return getType(i); + else + return 0; +} + +const XMLCh* VecAttributesImpl::getType(const XMLCh* const qName) const +{ + XMLSize_t i; + + if (getIndex(qName, i)) + return getType(i); + else + return 0; +} + +const XMLCh* VecAttributesImpl::getValue(const XMLCh* const uri, const XMLCh* const localPart ) const +{ + XMLSize_t i; + + if (getIndex(uri, localPart, i)) + return getValue(i); + else + return 0; +} + +const XMLCh* VecAttributesImpl::getValue(const XMLCh* const qName) const +{ + XMLSize_t i; + + if (getIndex(qName, i)) + return getValue(i); + else + return 0; +} + +// --------------------------------------------------------------------------- +// Setter methods +// --------------------------------------------------------------------------- +void VecAttributesImpl::setVector(const RefVectorOf* const srcVec + , const XMLSize_t count + , const XMLScanner * const scanner + , const bool adopt) +{ + // + // Delete the previous vector (if any) if we are adopting. Note that some + // compilers can't deal with the fact that the pointer is to a const + // object, so we have to cast off the const'ness here! + // + if (fAdopt) + delete (RefVectorOf*)fVector; + + fAdopt = adopt; + fCount = count; + fVector = srcVec; + fScanner = scanner ; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/VecAttributesImpl.hpp b/include/xercesc/internal/VecAttributesImpl.hpp new file mode 100644 index 0000000..a7b1c1f --- /dev/null +++ b/include/xercesc/internal/VecAttributesImpl.hpp @@ -0,0 +1,117 @@ +/* + * 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: VecAttributesImpl.hpp 672311 2008-06-27 16:05:01Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_VECATTRIBUTESIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_VECATTRIBUTESIMPL_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT VecAttributesImpl : public Attributes +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + VecAttributesImpl(); + ~VecAttributesImpl(); + + + // ----------------------------------------------------------------------- + // Implementation of the attributes interface + // ----------------------------------------------------------------------- + virtual XMLSize_t getLength() const ; + + virtual const XMLCh* getURI(const XMLSize_t index) const; + virtual const XMLCh* getLocalName(const XMLSize_t index) const ; + virtual const XMLCh* getQName(const XMLSize_t index) const ; + virtual const XMLCh* getType(const XMLSize_t index) const ; + virtual const XMLCh* getValue(const XMLSize_t index) const ; + + virtual bool getIndex(const XMLCh* const uri, const XMLCh* const localPart, XMLSize_t& index) const; + virtual int getIndex(const XMLCh* const uri, const XMLCh* const localPart ) const ; + virtual bool getIndex(const XMLCh* const qName, XMLSize_t& index) const; + virtual int getIndex(const XMLCh* const qName ) const ; + + virtual const XMLCh* getType(const XMLCh* const uri, const XMLCh* const localPart ) const ; + virtual const XMLCh* getType(const XMLCh* const qName) const ; + + virtual const XMLCh* getValue(const XMLCh* const qName) const; + virtual const XMLCh* getValue(const XMLCh* const uri, const XMLCh* const localPart ) const ; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setVector + ( + const RefVectorOf* const srcVec + , const XMLSize_t count + , const XMLScanner * const scanner + , const bool adopt = false + ); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + VecAttributesImpl(const VecAttributesImpl&); + VecAttributesImpl& operator=(const VecAttributesImpl&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fAdopt + // Indicates whether the passed vector is to be adopted or not. If + // so, we destroy it when we are destroyed (and when a new vector is + // set!) + // + // fCount + // The count of elements in the vector that should be considered + // valid. This is an optimization to allow vector elements to be + // reused over and over but a different count of them be valid for + // each use. + // + // fVector + // The vector that provides the backing for the list. + // + // fScanner + // This is a pointer to the in use Scanner, so that we can resolve + // namespace URIs from UriIds + // + // fURIBuffer + // A temporary buffer which is re-used when getting namespace URI's + // ----------------------------------------------------------------------- + bool fAdopt; + XMLSize_t fCount; + const RefVectorOf* fVector; + const XMLScanner * fScanner ; +}; + +XERCES_CPP_NAMESPACE_END + +#endif // ! VECATTRIBUTESIMPL_HPP diff --git a/include/xercesc/internal/WFXMLScanner.cpp b/include/xercesc/internal/WFXMLScanner.cpp new file mode 100644 index 0000000..587f6aa --- /dev/null +++ b/include/xercesc/internal/WFXMLScanner.cpp @@ -0,0 +1,2055 @@ +/* + * 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: WFXMLScanner.cpp 833045 2009-11-05 13:21:27Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// WFXMLScanner: Constructors and Destructor +// --------------------------------------------------------------------------- + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ReaderMgrResetType; + + +WFXMLScanner::WFXMLScanner( XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(valToAdopt, grammarResolver, manager) + , fElementIndex(0) + , fElements(0) + , fEntityTable(0) + , fAttrNameHashList(0) + , fAttrNSList(0) + , fElementLookup(0) +{ + CleanupType cleanup(this, &WFXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +WFXMLScanner::WFXMLScanner( XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errHandler + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) : + + XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager) + , fElementIndex(0) + , fElements(0) + , fEntityTable(0) + , fAttrNameHashList(0) + , fAttrNSList(0) + , fElementLookup(0) +{ + CleanupType cleanup(this, &WFXMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +WFXMLScanner::~WFXMLScanner() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Getter methods +// --------------------------------------------------------------------------- +NameIdPool* WFXMLScanner::getEntityDeclPool() +{ + return 0; +} + +const NameIdPool* WFXMLScanner::getEntityDeclPool() const +{ + return 0; +} + +// --------------------------------------------------------------------------- +// WFXMLScanner: Main entry point to scan a document +// --------------------------------------------------------------------------- +void WFXMLScanner::scanDocument(const InputSource& src) +{ + // Bump up the sequence id for this parser instance. This will invalidate + // any previous progressive scan tokens. + fSequenceId++; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + // Reset the scanner and its plugged in stuff for a new run. This + // resets all the data structures, creates the initial reader and + // pushes it on the stack, and sets up the base document path. + scanReset(src); + + // If we have a document handler, then call the start document + if (fDocHandler) + fDocHandler->startDocument(); + + // Scan the prolog part, which is everything before the root element + // including the DTD subsets. + scanProlog(); + + // If we got to the end of input, then its not a valid XML file. + // Else, go on to scan the content. + if (fReaderMgr.atEOF()) + { + emitError(XMLErrs::EmptyMainEntity); + } + else + { + // Scan content, and tell it its not an external entity + if (scanContent()) + { + // That went ok, so scan for any miscellaneous stuff + if (!fReaderMgr.atEOF()) + scanMiscellaneous(); + } + } + + // If we have a document handler, then call the end document + if (fDocHandler) + fDocHandler->endDocument(); + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so fall through + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so fall through + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } +} + + +bool WFXMLScanner::scanNext(XMLPScanToken& token) +{ + // Make sure this token is still legal + if (!isLegalToken(token)) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager); + + // Find the next token and remember the reader id + XMLSize_t orgReader; + XMLTokens curToken; + bool retVal = true; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + try + { + while (true) + { + // We have to handle any end of entity exceptions that happen here. + // We could be at the end of X nested entities, each of which will + // generate an end of entity exception as we try to move forward. + try + { + curToken = senseNextToken(orgReader); + break; + } + catch(const EndOfEntityException& toCatch) + { + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + if (curToken == Token_CharData) + { + scanCharData(fCDataBuf); + } + else if (curToken == Token_EOF) + { + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + retVal = false; + } + else + { + // Its some sort of markup + bool gotData = true; + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + if (fDoNamespaces) + scanStartTagNS(gotData); + else + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // If we hit the end, then do the miscellaneous part + if (!gotData) + { + // That went ok, so scan for any miscellaneous stuff + scanMiscellaneous(); + + if (fDocHandler) + fDocHandler->endDocument(); + } + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception, so return failure + retVal = false; + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, so return failure + retVal = false; + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + // Return failure + retVal = false; + } + catch(const OutOfMemoryException&) + { + throw; + } + + // If we are not at the end, release the object that will + // reset the ReaderMgr. + if (retVal) + resetReaderMgr.release(); + + return retVal; +} + + + +// --------------------------------------------------------------------------- +// WFXMLScanner: Private helper methods. +// --------------------------------------------------------------------------- + +// This method handles the common initialization, to avoid having to do +// it redundantly in multiple constructors. +void WFXMLScanner::commonInit() +{ + fEntityTable = new (fMemoryManager) ValueHashTableOf(11, fMemoryManager); + fAttrNameHashList = new (fMemoryManager)ValueVectorOf(16, fMemoryManager); + fAttrNSList = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + fElements = new (fMemoryManager) RefVectorOf(32, true, fMemoryManager); + fElementLookup = new (fMemoryManager) RefHashTableOf(109, false, fMemoryManager); + + // Add the default entity entries for the character refs that must always + // be present. + fEntityTable->put((void*) XMLUni::fgAmp, chAmpersand); + fEntityTable->put((void*) XMLUni::fgLT, chOpenAngle); + fEntityTable->put((void*) XMLUni::fgGT, chCloseAngle); + fEntityTable->put((void*) XMLUni::fgQuot, chDoubleQuote); + fEntityTable->put((void*) XMLUni::fgApos, chSingleQuote); +} + +void WFXMLScanner::cleanUp() +{ + delete fEntityTable; + delete fAttrNameHashList; + delete fAttrNSList; + delete fElementLookup; + delete fElements; +} + +// This method will reset the scanner data structures, and related plugged +// in stuff, for a new scan session. We get the input source for the primary +// XML entity, create the reader for it, and push it on the stack so that +// upon successful return from here we are ready to go. +void WFXMLScanner::scanReset(const InputSource& src) +{ + // For all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Reset the element stack, and give it the latest ids for the special + // URIs it has to know about. + fElemStack.reset + ( + fEmptyNamespaceId + , fUnknownNamespaceId + , fXMLNamespaceId + , fXMLNSNamespaceId + ); + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + fElementIndex = 0; + + // Reset elements lookup table + fElementLookup->removeAll(); + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , true + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // Push this read onto the reader manager + fReaderMgr.pushReader(newReader, 0); + + // and reset security-related things if necessary: + if(fSecurityManager != 0) + { + fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit(); + fEntityExpansionCount = 0; + } +} + +// This method is called between markup in content. It scans for character +// data that is sent to the document handler. It watches for any markup +// characters that would indicate that the character data has ended. It also +// handles expansion of general and character entities. +// +// sendData() is a local static helper for this method which handles some +// code that must be done in three different places here. +void WFXMLScanner::sendCharData(XMLBuffer& toSend) +{ + // If no data in the buffer, then nothing to do + if (toSend.isEmpty()) + return; + + // Always assume its just char data if not validating + if (fDocHandler) + fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false); + + // Reset buffer + toSend.reset(); +} + +// --------------------------------------------------------------------------- +// WFXMLScanner: Private scanning methods +// --------------------------------------------------------------------------- + +// This method will kick off the scanning of the primary content of the +// document, i.e. the elements. +bool WFXMLScanner::scanContent() +{ + // Go into a loop until we hit the end of the root element, or we fall + // out because there is no root element. + // + // We have to do kind of a deeply nested double loop here in order to + // avoid doing the setup/teardown of the exception handler on each + // round. Doing it this way we only do it when an exception actually + // occurs. + bool gotData = true; + bool inMarkup = false; + while (gotData) + { + try + { + while (gotData) + { + // Sense what the next top level token is. According to what + // this tells us, we will call something to handle that kind + // of thing. + XMLSize_t orgReader; + const XMLTokens curToken = senseNextToken(orgReader); + + // Handle character data and end of file specially. Char data + // is not markup so we don't want to handle it in the loop + // below. + if (curToken == Token_CharData) + { + // Scan the character data and call appropriate events. Let + // him use our local character data buffer for efficiency. + scanCharData(fCDataBuf); + continue; + } + else if (curToken == Token_EOF) + { + // The element stack better be empty at this point or we + // ended prematurely before all elements were closed. + if (!fElemStack.isEmpty()) + { + const ElemStack::StackElem* topElem = fElemStack.popTop(); + emitError + ( + XMLErrs::EndedWithTagsOnStack + , topElem->fThisElement->getFullName() + ); + } + + // Its the end of file, so clear the got data flag + gotData = false; + continue; + } + + // We are in some sort of markup now + inMarkup = true; + + // According to the token we got, call the appropriate + // scanning method. + switch(curToken) + { + case Token_CData : + // Make sure we are within content + if (fElemStack.isEmpty()) + emitError(XMLErrs::CDATAOutsideOfContent); + scanCDSection(); + break; + + case Token_Comment : + scanComment(); + break; + + case Token_EndTag : + scanEndTag(gotData); + break; + + case Token_PI : + scanPI(); + break; + + case Token_StartTag : + if (fDoNamespaces) + scanStartTagNS(gotData); + else + scanStartTag(gotData); + break; + + default : + fReaderMgr.skipToChar(chOpenAngle); + break; + } + + if (orgReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // And we are back out of markup again + inMarkup = false; + } + } + catch(const EndOfEntityException& toCatch) + { + // If we were in some markup when this happened, then its a + // partial markup error. + if (inMarkup) + emitError(XMLErrs::PartialMarkupInEntity); + + // Send an end of entity reference event + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + + inMarkup = false; + } + } + + // It went ok, so return success + return true; +} + + +void WFXMLScanner::scanEndTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the end of the root element. + gotData = true; + + // Check if the element stack is empty. If so, then this is an unbalanced + // element (i.e. more ends than starts, perhaps because of bad text + // causing one to be skipped.) + if (fElemStack.isEmpty()) + { + emitError(XMLErrs::MoreEndThanStartTags); + fReaderMgr.skipPastChar(chCloseAngle); + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager); + } + + // Pop the stack of the element we are supposed to be ending. Remember + // that we don't own this. The stack just keeps them and reuses them. + unsigned int uriId = (fDoNamespaces) + ? fElemStack.getCurrentURI() : fEmptyNamespaceId; + const ElemStack::StackElem* topElem = fElemStack.popTop(); + + // See if it was the root element, to avoid multiple calls below + const bool isRoot = fElemStack.isEmpty(); + + // Make sure that its the end of the element that we expect + if (!fReaderMgr.skippedStringLong(topElem->fThisElement->getFullName())) + { + emitError + ( + XMLErrs::ExpectedEndOfTagX + , topElem->fThisElement->getFullName() + ); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // Make sure we are back on the same reader as where we started + if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialTagMarkupError); + + // Skip optional whitespace + fReaderMgr.skipPastSpaces(); + + // Make sure we find the closing bracket + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError + ( + XMLErrs::UnterminatedEndTag + , topElem->fThisElement->getFullName() + ); + } + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + fDocHandler->endElement + ( + *topElem->fThisElement + , uriId + , isRoot + , topElem->fThisElement->getElementName()->getPrefix() + ); + } + + // If this was the root, then done with content + gotData = !isRoot; +} + +void WFXMLScanner::scanDocTypeDecl() +{ + // Just skips over it + // REVISIT: Should we issue a warning + static const XMLCh doctypeIE[] = + { + chOpenSquare, chCloseAngle, chNull + }; + XMLCh nextCh = fReaderMgr.skipUntilIn(doctypeIE); + + if (nextCh == chOpenSquare) + fReaderMgr.skipPastChar(chCloseSquare); + + fReaderMgr.skipPastChar(chCloseAngle); +} + +bool WFXMLScanner::scanStartTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Get the QName. In this case, we are not doing namespaces, so we just + // use it as is and don't have to break it into parts. + if (!fReaderMgr.getName(fQNameBuf)) + { + emitError(XMLErrs::ExpectedElementName); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // Assume it won't be an empty tag + bool isEmpty = false; + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Lets try to look up the element + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + XMLElementDecl* elemDecl = fElementLookup->get(qnameRawBuf); + + if (!elemDecl) { + + if (fElementIndex < fElements->size()) { + elemDecl = fElements->elementAt(fElementIndex); + } + else { + elemDecl = new (fGrammarPoolMemoryManager) DTDElementDecl + ( + fGrammarPoolMemoryManager + ); + fElements->addElement(elemDecl); + } + + elemDecl->setElementName(XMLUni::fgZeroLenString, qnameRawBuf, fEmptyNamespaceId); + fElementLookup->put((void*)elemDecl->getFullName(), elemDecl); + fElementIndex++; + } + + // Expand the element stack and add the new element + fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum()); + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // We loop until we either see a /> or >, handling attribute/value + // pairs until we get there. + XMLSize_t attCount = 0; + XMLSize_t curAttListSize = fAttrList->size(); + while (true) + { + // And get the next non-space character + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + bool bFoundSpace; + fReaderMgr.skipPastSpaces(bFoundSpace); + if (!bFoundSpace) + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + // Ok, peek another char + nextCh = fReaderMgr.peekNextChar(); + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume its going to be an attribute, so get a name from + // the input. + if (!fReaderMgr.getName(fAttNameBuf)) + { + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.skipPastChar(chCloseAngle); + return false; + } + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // See if this attribute is declared more than one for this element. + const XMLCh* attNameRawBuf = fAttNameBuf.getRawBuffer(); + XMLSize_t attNameHash = XMLString::hash(attNameRawBuf, 109); + + if (attCount) { + + for (XMLSize_t k=0; k < attCount; k++) { + + if (fAttrNameHashList->elementAt(k) == attNameHash) { + if ( + XMLString::equals + ( + fAttrList->elementAt(k)->getName() + , attNameRawBuf + ) + ) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , attNameRawBuf + , qnameRawBuf + ); + break; + } + } + } + } + + // Skip any whitespace before the value and then scan the att + // value. This will come back normalized with entity refs and + // char refs expanded. + fReaderMgr.skipPastSpaces(); + if (!scanAttValue(attNameRawBuf, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // Add this attribute to the attribute list that we use to + // pass them to the handler. We reuse its existing elements + // but expand it as required. + XMLAttr* curAtt; + if (attCount >= curAttListSize) + { + curAtt = new (fMemoryManager) XMLAttr + ( + 0 + , attNameRawBuf + , XMLUni::fgZeroLenString + , fAttValueBuf.getRawBuffer() + , XMLAttDef::CData + , true + , fMemoryManager + ); + fAttrList->addElement(curAtt); + fAttrNameHashList->addElement(attNameHash); + } + else + { + curAtt = fAttrList->elementAt(attCount); + curAtt->set + ( + 0 + , attNameRawBuf + , XMLUni::fgZeroLenString + , fAttValueBuf.getRawBuffer() + ); + curAtt->setSpecified(true); + fAttrNameHashList->setElementAt(attNameHash, attCount); + } + attCount++; + + // And jump back to the top of the loop + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + } + + // If we have a document handler, then tell it about this start tag. We + // don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send + // any prefix since its just one big name if we are not doing namespaces. + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl + , fEmptyNamespaceId + , 0 + , *fAttrList + , attCount + , isEmpty + , isRoot + ); + } + + return true; +} + + +// This method is called to scan a start tag when we are processing +// namespaces. There are two different versions of this method, one for +// namespace aware processing an done for non-namespace aware processing. +// +// This method is called after we've scanned the < of a start tag. So we +// have to get the element name, then scan the attributes, after which +// we are either going to see >, />, or attributes followed by one of those +// sequences. +bool WFXMLScanner::scanStartTagNS(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // The current position is after the open bracket, so we need to read in + // in the element name. + int colonPosition; + if (!fReaderMgr.getQName(fQNameBuf, &colonPosition)) + { + if (fQNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedElementName); + else + emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer()); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Assume it won't be an empty tag + bool isEmpty = false; + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // Lets try to look up the element + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + XMLElementDecl* elemDecl = fElementLookup->get(qnameRawBuf); + + if (!elemDecl) { + if (!XMLString::compareNString(qnameRawBuf, XMLUni::fgXMLNSColonString, 6)) + emitError(XMLErrs::NoXMLNSAsElementPrefix, qnameRawBuf); + + if (fElementIndex < fElements->size()) { + elemDecl = fElements->elementAt(fElementIndex); + } + else { + elemDecl = new (fGrammarPoolMemoryManager) DTDElementDecl + ( + fGrammarPoolMemoryManager + ); + fElements->addElement(elemDecl); + } + + elemDecl->setElementName(qnameRawBuf, fEmptyNamespaceId); + fElementLookup->put((void*)elemDecl->getFullName(), elemDecl); + fElementIndex++; + } + + // Expand the element stack and add the new element + fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum()); + + // reset NS attribute list + fAttrNSList->removeAllElements(); + + // We loop until we either see a /> or >, handling attribute/value + // pairs until we get there. + XMLSize_t attCount = 0; + XMLSize_t curAttListSize = fAttrList->size(); + while (true) + { + // And get the next non-space character + XMLCh nextCh = fReaderMgr.peekNextChar(); + + // If the next character is not a slash or closed angle bracket, + // then it must be whitespace, since whitespace is required + // between the end of the last attribute and the name of the next + // one. + if (attCount) + { + if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) + { + bool bFoundSpace; + fReaderMgr.skipPastSpaces(bFoundSpace); + if (!bFoundSpace) + { + // Emit the error but keep on going + emitError(XMLErrs::ExpectedWhitespace); + } + // Ok, peek another char + nextCh = fReaderMgr.peekNextChar(); + } + } + + // Ok, here we first check for any of the special case characters. + // If its not one, then we do the normal case processing, which + // assumes that we've hit an attribute value, Otherwise, we do all + // the special case checks. + if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) + { + // Assume its going to be an attribute, so get a name from + // the input. + int colonPosition; + if (!fReaderMgr.getQName(fAttNameBuf, &colonPosition)) + { + if (fAttNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedAttrName); + else + emitError(XMLErrs::InvalidAttrName, fAttNameBuf.getRawBuffer()); + fReaderMgr.skipPastChar(chCloseAngle); + return false; + } + + // And next must be an equal sign + if (!scanEq()) + { + static const XMLCh tmpList[] = + { + chSingleQuote, chDoubleQuote, chCloseAngle + , chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedEqSign); + + // Try to sync back up by skipping forward until we either + // hit something meaningful. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) + { + // Jump back to top for normal processing of these + continue; + } + else if ((chFound == chSingleQuote) + || (chFound == chDoubleQuote) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through assuming that the value is to follow + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // See if this attribute is declared more than one for this element. + const XMLCh* attNameRawBuf = fAttNameBuf.getRawBuffer(); + XMLSize_t attNameHash = XMLString::hash(attNameRawBuf, 109); + if (attCount) { + + for (XMLSize_t k=0; k < attCount; k++) { + + if (fAttrNameHashList->elementAt(k) == attNameHash) { + if (XMLString::equals( + fAttrList->elementAt(k)->getQName() + , attNameRawBuf)) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , attNameRawBuf + , qnameRawBuf + ); + break; + } + } + } + } + + // Skip any whitespace before the value and then scan the att + // value. This will come back normalized with entity refs and + // char refs expanded. + fReaderMgr.skipPastSpaces(); + if (!scanAttValue(attNameRawBuf, fAttValueBuf)) + { + static const XMLCh tmpList[] = + { + chCloseAngle, chOpenAngle, chForwardSlash, chNull + }; + + emitError(XMLErrs::ExpectedAttrValue); + + // It failed, so lets try to get synced back up. We skip + // forward until we find some whitespace or one of the + // chars in our list. + const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); + + if ((chFound == chCloseAngle) + || (chFound == chForwardSlash) + || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) + { + // Just fall through and process this attribute, though + // the value will be "". + } + else if (chFound == chOpenAngle) + { + // Assume a malformed tag and that new one is starting + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + return false; + } + else + { + // Something went really wrong + return false; + } + } + + // Add this attribute to the attribute list that we use to + // pass them to the handler. We reuse its existing elements + // but expand it as required. + const XMLCh* attValueRawBuf = fAttValueBuf.getRawBuffer(); + XMLAttr* curAtt = 0; + if (attCount >= curAttListSize) + { + curAtt = new (fMemoryManager) XMLAttr + ( + fEmptyNamespaceId + , attNameRawBuf + , attValueRawBuf + , XMLAttDef::CData + , true + , fMemoryManager + ); + fAttrList->addElement(curAtt); + fAttrNameHashList->addElement(attNameHash); + } + else + { + curAtt = fAttrList->elementAt(attCount); + curAtt->set + ( + fEmptyNamespaceId + , attNameRawBuf + , attValueRawBuf + ); + curAtt->setSpecified(true); + fAttrNameHashList->setElementAt(attNameHash, attCount); + } + + // Map prefix to namespace + const XMLCh* attPrefix = curAtt->getPrefix(); + const XMLCh* attLocalName = curAtt->getName(); + const XMLCh* namespaceURI = fAttValueBuf.getRawBuffer(); + + if (attPrefix && *attPrefix) { + if (XMLString::equals(attPrefix, XMLUni::fgXMLString)) { + curAtt->setURIId(fXMLNamespaceId); + } + else if (XMLString::equals(attPrefix, XMLUni::fgXMLNSString)) { + + if (XMLString::equals(attLocalName, XMLUni::fgXMLNSString)) + emitError(XMLErrs::NoUseOfxmlnsAsPrefix); + else if (XMLString::equals(attLocalName, XMLUni::fgXMLString)) { + if (!XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) + emitError(XMLErrs::PrefixXMLNotMatchXMLURI); + } + + if (!namespaceURI) + emitError(XMLErrs::NoEmptyStrNamespace, attNameRawBuf); + else if(!*namespaceURI && fXMLVersion == XMLReader::XMLV1_0) + emitError(XMLErrs::NoEmptyStrNamespace, attNameRawBuf); + + fElemStack.addPrefix + ( + attLocalName + , fURIStringPool->addOrFind(namespaceURI) + ); + curAtt->setURIId(fXMLNSNamespaceId); + } + else { + fAttrNSList->addElement(curAtt); + } + } + else { + if (XMLString::equals(XMLUni::fgXMLNSString, attLocalName)) { + + if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName)) + emitError(XMLErrs::NoUseOfxmlnsURI); + else if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) + emitError(XMLErrs::XMLURINotMatchXMLPrefix); + + fElemStack.addPrefix + ( + XMLUni::fgZeroLenString + , fURIStringPool->addOrFind(namespaceURI) + ); + } + } + + // increment attribute count + attCount++; + + // And jump back to the top of the loop + continue; + } + + // It was some special case character so do all of the checks and + // deal with it. + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chForwardSlash) + { + fReaderMgr.getNextChar(); + isEmpty = true; + if (!fReaderMgr.skippedChar(chCloseAngle)) + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + break; + } + else if (nextCh == chCloseAngle) + { + fReaderMgr.getNextChar(); + break; + } + else if (nextCh == chOpenAngle) + { + // Check for this one specially, since its going to be common + // and it is kind of auto-recovering since we've already hit the + // next open bracket, which is what we would have seeked to (and + // skipped this whole tag.) + emitError(XMLErrs::UnterminatedStartTag, qnameRawBuf); + break; + } + else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) + { + // Check for this one specially, which is probably a missing + // attribute name, e.g. ="value". Just issue expected name + // error and eat the quoted string, then jump back to the + // top again. + emitError(XMLErrs::ExpectedAttrName); + fReaderMgr.getNextChar(); + fReaderMgr.skipQuotedString(nextCh); + fReaderMgr.skipPastSpaces(); + continue; + } + } + + // Handle provided attributes that we did not map their prefixes + for (unsigned int i=0; i < fAttrNSList->size(); i++) { + + XMLAttr* providedAttr = fAttrNSList->elementAt(i); + + providedAttr->setURIId + ( + resolvePrefix + ( + providedAttr->getPrefix(), + ElemStack::Mode_Attribute + ) + ); + } + + if(attCount) { + + // + // Decide if to use hash table to do duplicate checking + // + bool toUseHashTable = false; + setAttrDupChkRegistry(attCount, toUseHashTable); + + // check for duplicate namespace attributes: + // by checking for qualified names with the same local part and with prefixes + // which have been bound to namespace names that are identical. + XMLAttr* loopAttr; + XMLAttr* curAtt; + for (unsigned int attrIndex=0; attrIndex < attCount-1; attrIndex++) { + loopAttr = fAttrList->elementAt(attrIndex); + + if (!toUseHashTable) + { + for (unsigned int curAttrIndex = attrIndex+1; curAttrIndex < attCount; curAttrIndex++) { + curAtt = fAttrList->elementAt(curAttrIndex); + if (curAtt->getURIId() == loopAttr->getURIId() && + XMLString::equals(curAtt->getName(), loopAttr->getName())) { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , curAtt->getName() + , elemDecl->getFullName() + ); + } + } + } + else + { + if (fAttrDupChkRegistry->containsKey((void*)loopAttr->getName(), loopAttr->getURIId())) + { + emitError + ( + XMLErrs::AttrAlreadyUsedInSTag + , loopAttr->getName() + , elemDecl->getFullName() + ); + } + + fAttrDupChkRegistry->put((void*)loopAttr->getName(), loopAttr->getURIId(), loopAttr); + } + } + } + + // Resolve the qualified name to a URI. + unsigned int uriId = resolvePrefix + ( + elemDecl->getElementName()->getPrefix() + , ElemStack::Mode_Element + ); + + // Now we can update the element stack + fElemStack.setCurrentURI(uriId); + + // Tell the document handler about this start tag + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl + , uriId + , elemDecl->getElementName()->getPrefix() + , *fAttrList + , attCount + , isEmpty + , isRoot + ); + } + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // If the elem stack is empty, then it was an empty root + if (isRoot) + gotData = false; + } + + return true; +} + +// --------------------------------------------------------------------------- +// XMLScanner: Private parsing methods +// --------------------------------------------------------------------------- +bool WFXMLScanner::scanAttValue(const XMLCh* const attrName + , XMLBuffer& toFill) +{ + // Reset the target buffer + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr.skipIfQuote(quoteCh)) + return false; + + // We have to get the current reader because we have to ignore closing + // quotes until we hit the same reader again. + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // Loop until we get the attribute value. Note that we use a double + // loop here to avoid the setup/teardown overhead of the exception + // handler on every round. + XMLCh nextCh; + XMLCh secondCh = 0; + bool gotLeadingSurrogate = false; + bool escaped; + while (true) + { + try + { + while(true) + { + nextCh = fReaderMgr.getNextChar(); + + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + // Check for our ending quote in the same entity + if (nextCh == quoteCh) + { + if (curReader == fReaderMgr.getCurrentReaderNum()) + return true; + + // Watch for spillover into a previous entity + if (curReader > fReaderMgr.getCurrentReaderNum()) + { + emitError(XMLErrs::PartialMarkupInEntity); + return false; + } + } + + // Check for an entity ref now, before we let it affect our + // whitespace normalization logic below. We ignore the empty flag + // in this one. + escaped = false; + if (nextCh == chAmpersand) + { + if (scanEntityRef(true, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // If its not escaped, then make sure its not a < character, which + // is not allowed in attribute values. + if (!escaped) { + if (nextCh == chOpenAngle) + emitError(XMLErrs::BracketInAttrValue, attrName); + else if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + nextCh = chSpace; + } + + // Else add it to the buffer + toFill.append(nextCh); + + if (secondCh) + { + toFill.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException&) + { + // Just eat it and continue. + gotLeadingSurrogate = false; + escaped = false; + } + } + return true; +} + + +// This method scans a CDATA section. It collects the character into one +// of the temp buffers and calls the document handler, if any, with the +// characters. It assumes that the docCharacters + ( + bbCData.getRawBuffer() + , bbCData.getLen() + , true + ); + } + + // And we are done + break; + } + + // Make sure its a valid character. But if we've emitted an error + // already, don't bother with the overhead since we've already told + // them about it. + if (!emittedError) + { + // Deal with surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + emittedError = true; + } + } + gotLeadingSurrogate = false; + } + } + + // Add it to the buffer + bbCData.append(nextCh); + } +} + + +void WFXMLScanner::scanCharData(XMLBuffer& toUse) +{ + // We have to watch for the stupid ]]> sequence, which is illegal in + // character data. So this is a little state machine that handles that. + enum States + { + State_Waiting + , State_GotOne + , State_GotTwo + }; + + // Reset the buffer before we start + toUse.reset(); + + // Turn on the 'throw at end' flag of the reader manager + ThrowEOEJanitor jan(&fReaderMgr, true); + + // In order to be more efficient we have to use kind of a deeply nested + // set of blocks here. The outer block puts on a try and catches end of + // entity exceptions. The inner loop is the per-character loop. If we + // put the try inside the inner loop, it would work but would require + // the exception handling code setup/teardown code to be invoked for + // each character. + XMLCh nextCh; + XMLCh secondCh = 0; + States curState = State_Waiting; + bool escaped = false; + bool gotLeadingSurrogate = false; + bool notDone = true; + while (notDone) + { + try + { + while (true) + { + // Eat through as many plain content characters as possible without + // needing special handling. Moving most content characters here, + // in this one call, rather than running the overall loop once + // per content character, is a speed optimization. + if (curState == State_Waiting && !gotLeadingSurrogate) + { + fReaderMgr.movePlainContentChars(toUse); + } + + // Try to get another char from the source + // The code from here on down covers all contengencies, + if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh)) + { + // If we were waiting for a trailing surrogate, its an error + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + + notDone = false; + break; + } + + // Watch for a reference. Note that the escapement mechanism + // is ignored in this content. + escaped = false; + if (nextCh == chAmpersand) + { + sendCharData(toUse); + + // Turn off the throwing at the end of entity during this + ThrowEOEJanitor jan(&fReaderMgr, false); + + if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned) + { + gotLeadingSurrogate = false; + continue; + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Deal with surrogate pairs + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) { + emitError(XMLErrs::Expected2ndSurrogateChar); + } + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + + // Keep the state machine up to date + if (!escaped) + { + if (nextCh == chCloseSquare) + { + if (curState == State_Waiting) + curState = State_GotOne; + else if (curState == State_GotOne) + curState = State_GotTwo; + } + else if (nextCh == chCloseAngle) + { + if (curState == State_GotTwo) + emitError(XMLErrs::BadSequenceInCharData); + curState = State_Waiting; + } + else + { + curState = State_Waiting; + } + } + else + { + curState = State_Waiting; + } + + // Add this char to the buffer + toUse.append(nextCh); + + if (secondCh) + { + toUse.append(secondCh); + secondCh=0; + } + } + } + catch(const EndOfEntityException& toCatch) + { + // Some entity ended, so we have to send any accumulated + // chars and send an end of entity event. + sendCharData(toUse); + gotLeadingSurrogate = false; + + if (fDocHandler) + fDocHandler->endEntityReference(toCatch.getEntity()); + } + } + + // Send any char data that we accumulated into the buffer + sendCharData(toUse); +} + +InputSource* WFXMLScanner::resolveSystemId(const XMLCh* const /*sysId*/ + ,const XMLCh* const /*pubId*/) +{ + return 0; +} + +// This method will scan a general/character entity ref. It will either +// expand a char ref and return it directly, or push a reader for a general +// entity. +// +// The return value indicates whether the char parameters hold the value +// or whether the value was pushed as a reader, or that it failed. +// +// The escaped flag tells the caller whether the returned parameter resulted +// from a character reference, which escapes the character in some cases. It +// only makes any difference if the return value indicates the value was +// returned directly. +XMLScanner::EntityExpRes +WFXMLScanner::scanEntityRef(const bool + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped) +{ + // Assume no escape + secondCh = 0; + escaped = false; + + // We have to insure that its all in one entity + const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum(); + + // If the next char is a pound, then its a character reference and we + // need to expand it always. + if (fReaderMgr.skippedChar(chPound)) + { + // Its a character reference, so scan it and get back the numeric + // value it represents. + if (!scanCharRef(firstCh, secondCh)) + return EntityExp_Failed; + + escaped = true; + + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + return EntityExp_Returned; + } + + // Expand it since its a normal entity ref + XMLBufBid bbName(&fBufMgr); + if (!fReaderMgr.getName(bbName.getBuffer())) + { + emitError(XMLErrs::ExpectedEntityRefName); + return EntityExp_Failed; + } + + // Next char must be a semi-colon. But if its not, just emit + // an error and try to continue. + if (!fReaderMgr.skippedChar(chSemiColon)) + emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer()); + + // Make sure we ended up on the same entity reader as the & char + if (curReader != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialMarkupInEntity); + + // Look up the name in the general entity pool + // If it does not exist, then obviously an error + if (!fEntityTable->containsKey(bbName.getRawBuffer())) + { + // XML 1.0 Section 4.1 + // Well-formedness Constraint for entity not found: + // In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references, + // or a document with "standalone='yes'", for an entity reference that does not occur within the external subset + // or a parameter entity + if (fStandalone || fHasNoDTD) + emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer()); + + return EntityExp_Failed; + } + + // here's where we need to check if there's a SecurityManager, + // how many entity references we've had + if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) { + XMLCh expLimStr[32]; + XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager); + emitError + ( + XMLErrs::EntityExpansionLimitExceeded + , expLimStr + ); + // there seems nothing better to be done than to reset the entity expansion counter + fEntityExpansionCount = 0; + } + + firstCh = fEntityTable->get(bbName.getRawBuffer()); + escaped = true; + return EntityExp_Returned; +} + +// --------------------------------------------------------------------------- +// WFXMLScanner: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* WFXMLScanner::loadGrammar(const InputSource& + , const short + , const bool) +{ + // REVISIT: emit a warning or throw an exception + return 0; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/WFXMLScanner.hpp b/include/xercesc/internal/WFXMLScanner.hpp new file mode 100644 index 0000000..960858d --- /dev/null +++ b/include/xercesc/internal/WFXMLScanner.hpp @@ -0,0 +1,153 @@ +/* + * 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: WFXMLScanner.hpp 810580 2009-09-02 15:52:22Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_WFXMLSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_WFXMLSCANNER_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// This is a a non-validating scanner. No DOCTYPE or XML Schema processing +// will take place. +class XMLPARSER_EXPORT WFXMLScanner : public XMLScanner +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + WFXMLScanner + ( + XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + WFXMLScanner + ( + XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~WFXMLScanner(); + + // ----------------------------------------------------------------------- + // XMLScanner public virtual methods + // ----------------------------------------------------------------------- + virtual const XMLCh* getName() const; + virtual NameIdPool* getEntityDeclPool(); + virtual const NameIdPool* getEntityDeclPool() const; + virtual void scanDocument + ( + const InputSource& src + ); + virtual bool scanNext(XMLPScanToken& toFill); + virtual Grammar* loadGrammar + ( + const InputSource& src + , const short grammarType + , const bool toCache = false + ); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + WFXMLScanner(); + WFXMLScanner(const WFXMLScanner&); + WFXMLScanner& operator=(const WFXMLScanner&); + + // ----------------------------------------------------------------------- + // XMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual void scanCDSection(); + virtual void scanCharData(XMLBuffer& toToUse); + virtual EntityExpRes scanEntityRef + ( + const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped + ); + virtual void scanDocTypeDecl(); + virtual void scanReset(const InputSource& src); + virtual void sendCharData(XMLBuffer& toSend); + virtual InputSource* resolveSystemId(const XMLCh* const sysId + ,const XMLCh* const pubId); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void commonInit(); + void cleanUp(); + + // ----------------------------------------------------------------------- + // Private scanning methods + // ----------------------------------------------------------------------- + bool scanAttValue + ( + const XMLCh* const attrName + , XMLBuffer& toFill + ); + bool scanContent(); + void scanEndTag(bool& gotData); + bool scanStartTag(bool& gotData); + bool scanStartTagNS(bool& gotData); + + // ----------------------------------------------------------------------- + // Data members + // + // fEntityTable + // This the table that contains the default entity entries. + // + // fAttrNameHashList + // This contains the hash value for attribute names. It's used when + // checking for duplicate attributes. + // + // fAttrNSList + // This contains XMLAttr objects that we need to map their prefixes + // to URIs when namespace is enabled. + // + // ----------------------------------------------------------------------- + unsigned int fElementIndex; + RefVectorOf* fElements; + ValueHashTableOf* fEntityTable; + ValueVectorOf* fAttrNameHashList; + ValueVectorOf* fAttrNSList; + RefHashTableOf* fElementLookup; +}; + +inline const XMLCh* WFXMLScanner::getName() const +{ + return XMLUni::fgWFXMLScanner; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XMLInternalErrorHandler.hpp b/include/xercesc/internal/XMLInternalErrorHandler.hpp new file mode 100644 index 0000000..7d3239d --- /dev/null +++ b/include/xercesc/internal/XMLInternalErrorHandler.hpp @@ -0,0 +1,139 @@ +/* + * 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: XMLInternalErrorHandler.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLINTERNALERRORHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLINTERNALERRORHANDLER_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLInternalErrorHandler : public ErrorHandler +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + XMLInternalErrorHandler(ErrorHandler* userHandler = 0) : + fSawWarning(false), + fSawError(false), + fSawFatal(false), + fUserErrorHandler(userHandler) + { + } + + ~XMLInternalErrorHandler() + { + } + + // ----------------------------------------------------------------------- + // Implementation of the error handler interface + // ----------------------------------------------------------------------- + void warning(const SAXParseException& toCatch); + void error(const SAXParseException& toCatch); + void fatalError(const SAXParseException& toCatch); + void resetErrors(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getSawWarning() const; + bool getSawError() const; + bool getSawFatal() const; + + // ----------------------------------------------------------------------- + // Private data members + // + // fSawWarning + // This is set if we get any warning, and is queryable via a getter + // method. + // + // fSawError + // This is set if we get any errors, and is queryable via a getter + // method. + // + // fSawFatal + // This is set if we get any fatal, and is queryable via a getter + // method. + // + // fUserErrorHandler + // This is the error handler from user + // ----------------------------------------------------------------------- + bool fSawWarning; + bool fSawError; + bool fSawFatal; + ErrorHandler* fUserErrorHandler; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLInternalErrorHandler(const XMLInternalErrorHandler&); + XMLInternalErrorHandler& operator=(const XMLInternalErrorHandler&); +}; + +inline bool XMLInternalErrorHandler::getSawWarning() const +{ + return fSawWarning; +} + +inline bool XMLInternalErrorHandler::getSawError() const +{ + return fSawError; +} + +inline bool XMLInternalErrorHandler::getSawFatal() const +{ + return fSawFatal; +} + +inline void XMLInternalErrorHandler::warning(const SAXParseException& toCatch) +{ + fSawWarning = true; + if (fUserErrorHandler) + fUserErrorHandler->warning(toCatch); +} + +inline void XMLInternalErrorHandler::error(const SAXParseException& toCatch) +{ + fSawError = true; + if (fUserErrorHandler) + fUserErrorHandler->error(toCatch); +} + +inline void XMLInternalErrorHandler::fatalError(const SAXParseException& toCatch) +{ + fSawFatal = true; + if (fUserErrorHandler) + fUserErrorHandler->fatalError(toCatch); +} + +inline void XMLInternalErrorHandler::resetErrors() +{ + fSawWarning = false; + fSawError = false; + fSawFatal = false; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XMLReader.cpp b/include/xercesc/internal/XMLReader.cpp new file mode 100644 index 0000000..e49d0a8 --- /dev/null +++ b/include/xercesc/internal/XMLReader.cpp @@ -0,0 +1,1927 @@ +/* + * 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: XMLReader.cpp 1663380 2015-03-02 18:07:34Z scantor $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLReader: Query Methods +// --------------------------------------------------------------------------- +// Checks whether all of the chars in the passed buffer are whitespace or +// not. Breaks out on the first non-whitespace. +// +bool XMLReader::isAllSpaces(const XMLCh* const toCheck + , const XMLSize_t count) const +{ + const XMLCh* curCh = toCheck; + const XMLCh* endPtr = toCheck + count; + while (curCh < endPtr) + { + if (!(fgCharCharsTable[*curCh++] & gWhitespaceCharMask)) + return false; + } + return true; +} + + +// +// Checks whether at least one of the chars in the passed buffer are whitespace or +// not. +// +bool XMLReader::containsWhiteSpace(const XMLCh* const toCheck + , const XMLSize_t count) const +{ + const XMLCh* curCh = toCheck; + const XMLCh* endPtr = toCheck + count; + while (curCh < endPtr) + { + if (fgCharCharsTable[*curCh++] & gWhitespaceCharMask) + return true; + } + return false; +} + +// +// This one is not called terribly often, so call the XMLChar utility +// +bool XMLReader::isPublicIdChar(const XMLCh toCheck) const +{ + if (fXMLVersion == XMLV1_1) + return XMLChar1_1::isPublicIdChar(toCheck); + else + return XMLChar1_0::isPublicIdChar(toCheck); +} + +// --------------------------------------------------------------------------- +// XMLReader: Constructors and Destructor +// --------------------------------------------------------------------------- +XMLReader::XMLReader(const XMLCh* const pubId + , const XMLCh* const sysId + , BinInputStream* const streamToAdopt + , const RefFrom from + , const Types type + , const Sources source + , const bool throwAtEnd + , const bool calculateSrcOfs + , XMLSize_t lowWaterMark + , const XMLVersion version + , MemoryManager* const manager) : + fCharIndex(0) + , fCharsAvail(0) + , fCurCol(1) + , fCurLine(1) + , fEncodingStr(0) + , fForcedEncoding(false) + , fNoMore(false) + , fPublicId(XMLString::replicate(pubId, manager)) + , fRawBufIndex(0) + , fRawBytesAvail(0) + , fLowWaterMark (lowWaterMark) + , fReaderNum(0xFFFFFFFF) + , fRefFrom(from) + , fSentTrailingSpace(false) + , fSource(source) + , fSrcOfsBase(0) + , fSrcOfsSupported(false) + , fCalculateSrcOfs(calculateSrcOfs) + , fSystemId(XMLString::replicate(sysId, manager)) + , fStream(streamToAdopt) + , fSwapped(false) + , fThrowAtEnd(throwAtEnd) + , fTranscoder(0) + , fType(type) + , fMemoryManager(manager) +{ + setXMLVersion(version); + + // Do an initial load of raw bytes + refreshRawBuffer(); + + // Ask the transcoding service if it supports src offset info + fSrcOfsSupported = XMLPlatformUtils::fgTransService->supportsSrcOfs(); + + // + // Use the recognizer class to get a basic sense of what family of + // encodings this file is in. We'll start off with a reader of that + // type, and update it later if needed when we read the XMLDecl line. + // + fEncoding = XMLRecognizer::basicEncodingProbe(fRawByteBuf, fRawBytesAvail); + + #if defined(XERCES_DEBUG) + if ((fEncoding < XMLRecognizer::Encodings_Min) + || (fEncoding > XMLRecognizer::Encodings_Max)) + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Reader_BadAutoEncoding, fMemoryManager); + } + #endif + + fEncodingStr = XMLString::replicate(XMLRecognizer::nameForEncoding(fEncoding, fMemoryManager), fMemoryManager); + + // Check whether the fSwapped flag should be set or not + checkForSwapped(); + + // + // This will check to see if the first line is an XMLDecl and, if + // so, decode that first line manually one character at a time. This + // leaves enough characters in the buffer that the high level code + // can get through the Decl and call us back with the real encoding. + // + doInitDecode(); + + // + // NOTE: We won't create a transcoder until we either get a call to + // setEncoding() or we get a call to refreshCharBuffer() and no + // transcoder has been set yet. + // +} + + +XMLReader::XMLReader(const XMLCh* const pubId + , const XMLCh* const sysId + , BinInputStream* const streamToAdopt + , const XMLCh* const encodingStr + , const RefFrom from + , const Types type + , const Sources source + , const bool throwAtEnd + , const bool calculateSrcOfs + , XMLSize_t lowWaterMark + , const XMLVersion version + , MemoryManager* const manager) : + fCharIndex(0) + , fCharsAvail(0) + , fCurCol(1) + , fCurLine(1) + , fEncoding(XMLRecognizer::UTF_8) + , fEncodingStr(0) + , fForcedEncoding(true) + , fNoMore(false) + , fPublicId(XMLString::replicate(pubId, manager)) + , fRawBufIndex(0) + , fRawBytesAvail(0) + , fLowWaterMark (lowWaterMark) + , fReaderNum(0xFFFFFFFF) + , fRefFrom(from) + , fSentTrailingSpace(false) + , fSource(source) + , fSrcOfsBase(0) + , fSrcOfsSupported(false) + , fCalculateSrcOfs(calculateSrcOfs) + , fSystemId(XMLString::replicate(sysId, manager)) + , fStream(streamToAdopt) + , fSwapped(false) + , fThrowAtEnd(throwAtEnd) + , fTranscoder(0) + , fType(type) + , fMemoryManager(manager) +{ + setXMLVersion(version); + + // Do an initial load of raw bytes + refreshRawBuffer(); + + // Copy the encoding string to our member + fEncodingStr = XMLString::replicate(encodingStr, fMemoryManager); + XMLString::upperCaseASCII(fEncodingStr); + + // Ask the transcoding service if it supports src offset info + fSrcOfsSupported = XMLPlatformUtils::fgTransService->supportsSrcOfs(); + + // + // Map the passed encoding name to one of our enums. If it does not + // match one of the intrinsic encodings, it will come back 'other', + // which tells us to create a transcoder based reader. + // + fEncoding = XMLRecognizer::encodingForName(fEncodingStr); + + // test the presence of the BOM and remove it from the source + switch(fEncoding) + { + case XMLRecognizer::UCS_4B : + case XMLRecognizer::UCS_4L : + { + if (fRawBytesAvail > 4 && + (((fRawByteBuf[0] == 0x00) && (fRawByteBuf[1] == 0x00) && (fRawByteBuf[2] == 0xFE) && (fRawByteBuf[3] == 0xFF)) || + ((fRawByteBuf[0] == 0xFF) && (fRawByteBuf[1] == 0xFE) && (fRawByteBuf[2] == 0x00) && (fRawByteBuf[3] == 0x00))) ) + { + fRawBufIndex += 4; + } + break; + } + case XMLRecognizer::UTF_8 : + { + // Look at the raw buffer as short chars + const char* asChars = (const char*)fRawByteBuf; + + if (fRawBytesAvail > XMLRecognizer::fgUTF8BOMLen && + XMLString::compareNString( asChars + , XMLRecognizer::fgUTF8BOM + , XMLRecognizer::fgUTF8BOMLen) == 0) + { + fRawBufIndex += XMLRecognizer::fgUTF8BOMLen; + } + break; + } + case XMLRecognizer::UTF_16B : + case XMLRecognizer::UTF_16L : + { + if (fRawBytesAvail < 2) + break; + + const UTF16Ch* asUTF16 = (const UTF16Ch*)&fRawByteBuf[fRawBufIndex]; + if ((*asUTF16 == chUnicodeMarker) || (*asUTF16 == chSwappedUnicodeMarker)) + { + fRawBufIndex += sizeof(UTF16Ch); + } + break; + } + case XMLRecognizer::EBCDIC: + case XMLRecognizer::US_ASCII: + case XMLRecognizer::XERCES_XMLCH: + case XMLRecognizer::OtherEncoding: + case XMLRecognizer::Encodings_Count: + { + // silence warning about enumeration not being used + break; + } + } + + // Check whether the fSwapped flag should be set or not + checkForSwapped(); + + // + // Create a transcoder for the encoding. Since the encoding has been + // forced, this will be the one we will use, period. + // + XMLTransService::Codes failReason; + if (fEncoding == XMLRecognizer::OtherEncoding) + { + // + // fEncodingStr not pre-recognized, use it + // directly for transcoder + // + fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fEncodingStr + , failReason + , kCharBufSize + , fMemoryManager + ); + } + else + { + // + // Use the recognized fEncoding to create the transcoder + // + fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fEncoding + , failReason + , kCharBufSize + , fMemoryManager + ); + + } + + if (!fTranscoder) + { + // We are about to throw which means the d-tor won't be called. + // Clean up some memory. + // + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); + ArrayJanitor jan (fEncodingStr, fMemoryManager); + + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , fEncodingStr + , fMemoryManager + ); + } + + // + // Note that, unlike above, we do not do an initial decode of the + // first line. We take the caller's word that the encoding is correct + // and just assume that the first bulk decode (kicked off by the first + // get of a character) will work. + // + // So we do here the slipping in of the leading space if required. + // + if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral)) + { + // This represents no data from the source + fCharSizeBuf[fCharsAvail] = 0; + fCharOfsBuf[fCharsAvail] = 0; + fCharBuf[fCharsAvail++] = chSpace; + } +} + + +XMLReader::XMLReader(const XMLCh* const pubId + , const XMLCh* const sysId + , BinInputStream* const streamToAdopt + , XMLRecognizer::Encodings encodingEnum + , const RefFrom from + , const Types type + , const Sources source + , const bool throwAtEnd + , const bool calculateSrcOfs + , XMLSize_t lowWaterMark + , const XMLVersion version + , MemoryManager* const manager) : + fCharIndex(0) + , fCharsAvail(0) + , fCurCol(1) + , fCurLine(1) + , fEncoding(XMLRecognizer::UTF_8) + , fEncodingStr(0) + , fForcedEncoding(true) + , fNoMore(false) + , fPublicId(XMLString::replicate(pubId, manager)) + , fRawBufIndex(0) + , fRawBytesAvail(0) + , fLowWaterMark (lowWaterMark) + , fReaderNum(0xFFFFFFFF) + , fRefFrom(from) + , fSentTrailingSpace(false) + , fSource(source) + , fSrcOfsBase(0) + , fSrcOfsSupported(false) + , fCalculateSrcOfs(calculateSrcOfs) + , fSystemId(XMLString::replicate(sysId, manager)) + , fStream(streamToAdopt) + , fSwapped(false) + , fThrowAtEnd(throwAtEnd) + , fTranscoder(0) + , fType(type) + , fMemoryManager(manager) +{ + setXMLVersion(version); + + // Do an initial load of raw bytes + refreshRawBuffer(); + + // Ask the transcoding service if it supports src offset info + fSrcOfsSupported = XMLPlatformUtils::fgTransService->supportsSrcOfs(); + + // + // Use the passed encoding code + // + fEncoding = encodingEnum; + fEncodingStr = XMLString::replicate(XMLRecognizer::nameForEncoding(fEncoding, fMemoryManager), fMemoryManager); + + // Check whether the fSwapped flag should be set or not + checkForSwapped(); + + // + // Create a transcoder for the encoding. Since the encoding has been + // forced, this will be the one we will use, period. + // + XMLTransService::Codes failReason; + fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fEncoding + , failReason + , kCharBufSize + , fMemoryManager + ); + + if (!fTranscoder) + { + // We are about to throw which means the d-tor won't be called. + // Clean up some memory. + // + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); + ArrayJanitor jan (fEncodingStr, fMemoryManager); + + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , fEncodingStr + , fMemoryManager + ); + } + + // + // Note that, unlike above, we do not do an initial decode of the + // first line. We take the caller's word that the encoding is correct + // and just assume that the first bulk decode (kicked off by the first + // get of a character) will work. + // + // So we do here the slipping in of the leading space if required. + // + if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral)) + { + // This represents no data from the source + fCharSizeBuf[fCharsAvail] = 0; + fCharOfsBuf[fCharsAvail] = 0; + fCharBuf[fCharsAvail++] = chSpace; + } +} + + +XMLReader::~XMLReader() +{ + fMemoryManager->deallocate(fEncodingStr); + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); + delete fStream; + delete fTranscoder; +} + + +// --------------------------------------------------------------------------- +// XMLReader: Character buffer management methods +// --------------------------------------------------------------------------- +XMLFilePos XMLReader::getSrcOffset() const +{ + if (!fSrcOfsSupported || !fCalculateSrcOfs) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Reader_SrcOfsNotSupported, fMemoryManager); + + // + // Take the current source offset and add in the sizes that we've + // eaten from the source so far. + // + if( fCharIndex == 0 ) { + return fSrcOfsBase; + } + + if( fCharIndex < fCharsAvail ) { + + return (fSrcOfsBase + fCharOfsBuf[fCharIndex]); + } + + return (fSrcOfsBase + fCharOfsBuf[fCharIndex-1] + fCharSizeBuf[fCharIndex-1]); +} + + +bool XMLReader::refreshCharBuffer() +{ + // If the no more flag is set, then don't bother doing anything. + if (fNoMore) + return false; + + XMLSize_t startInd; + + // See if we have any existing chars. + const XMLSize_t spareChars = fCharsAvail - fCharIndex; + + // If we are full, then don't do anything. + if (spareChars == kCharBufSize) + return true; + + // + // If no transcoder has been created yet, then we never saw the + // any encoding="" string and the encoding was not forced, so lets + // create one now. We know that it won't change now. + // + // However, note that if we autosensed EBCDIC, then we have to + // consider it an error if we never got an encoding since we don't + // know what variant of EBCDIC it is. + // + if (!fTranscoder) + { + if (fEncoding == XMLRecognizer::EBCDIC) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Reader_EncodingStrRequired, fMemoryManager); + + // Ask the transcoding service to make use a transcoder + XMLTransService::Codes failReason; + fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fEncodingStr + , failReason + , kCharBufSize + , fMemoryManager + ); + + if (!fTranscoder) + { + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Trans_CantCreateCvtrFor + , fEncodingStr + , fMemoryManager + ); + } + } + + // + // Add the number of source bytes eaten so far to the base src + // offset member. + // + if (fCalculateSrcOfs) { + for (startInd = 0; startInd < fCharIndex; startInd++) + fSrcOfsBase += fCharSizeBuf[startInd]; + } + + // + // If there are spare chars, then move then down to the bottom. We + // have to move the char sizes down also. + // + startInd = 0; + if (spareChars) + { + for (XMLSize_t index = fCharIndex; index < fCharsAvail; index++) + { + fCharBuf[startInd] = fCharBuf[index]; + fCharSizeBuf[startInd] = fCharSizeBuf[index]; + startInd++; + } + } + + // + // And then get more chars, starting after any spare chars that were + // left over from the last time. + // + fCharsAvail = xcodeMoreChars + ( + &fCharBuf[startInd] + , &fCharSizeBuf[startInd] + , kCharBufSize - spareChars + ); + + // Add back in the spare chars + fCharsAvail += spareChars; + + // Reset the buffer index to zero, so we start from the 0th char again + fCharIndex = 0; + + // + // If no chars available, then we have to check for one last thing. If + // this is reader for a PE and its not being expanded inside a literal, + // then unget a trailing space. We use a boolean to avoid triggering + // this more than once. + // + if (!fCharsAvail + && (fType == Type_PE) + && (fRefFrom == RefFrom_NonLiteral) + && !fSentTrailingSpace) + { + fCharBuf[0] = chSpace; + fCharsAvail = 1; + fSentTrailingSpace = true; + } + + // + // If we get here with no more chars, then set the fNoMore flag which + // lets us optimize and know without checking that no more chars are + // available. + // + if (!fCharsAvail) + fNoMore = true; + + // Calculate fCharOfsBuf using the elements from fCharBufSize + if (fCalculateSrcOfs) + { + unsigned int last = 0; + fCharOfsBuf[0] = 0; + for (XMLSize_t index = 1; index < fCharsAvail; ++index) { + fCharOfsBuf[index] = last+fCharSizeBuf[index-1]; + last = fCharOfsBuf[index]; + // code was: + // fCharOfsBuf[index] = fCharOfsBuf[index-1]+fCharSizeBuf[index-1]; + // but on Solaris 64 bit with sun studio 11 this didn't work as + // every value of fCharOfsBuf[] was 1. + } + } + + return (fCharsAvail != 0); +} + + + +// --------------------------------------------------------------------------- +// XMLReader: Scanning methods +// --------------------------------------------------------------------------- +bool XMLReader::getName(XMLBuffer& toFill, const bool token) +{ + // Ok, first lets see if we have chars in the buffer. If not, then lets + // reload. + if (fCharIndex == fCharsAvail) + { + if (!refreshCharBuffer()) + return false; + } + + XMLSize_t charIndex_start = fCharIndex; + + // Lets check the first char for being a first name char. If not, then + // what's the point in living mannnn? Just give up now. We only do this + // if its a name and not a name token that they want. + if (!token) + { + if (fXMLVersion == XMLV1_1 && ((fCharBuf[fCharIndex] >= 0xD800) && (fCharBuf[fCharIndex] <= 0xDB7F))) { + // make sure one more char is in the buffer, the transcoder + // should put only a complete surrogate pair into the buffer + assert(fCharIndex+1 < fCharsAvail); + if ((fCharBuf[fCharIndex+1] < 0xDC00) || (fCharBuf[fCharIndex+1] > 0xDFFF)) + return false; + + // Looks ok, so lets eat it + fCharIndex += 2; + } + else { + if (!isFirstNameChar(fCharBuf[fCharIndex])) + return false; + + // Looks ok, so lets eat it + fCharIndex ++; + } + + } + + // And now we loop until we run out of data in this reader or we hit + // a non-name char. + while (true) + { + if (fXMLVersion == XMLV1_1) + { + while (fCharIndex < fCharsAvail) + { + // Check the current char and take it if its a name char. Else + // break out. + if ( (fCharBuf[fCharIndex] >= 0xD800) && (fCharBuf[fCharIndex] <= 0xDB7F) ) + { + // make sure one more char is in the buffer, the transcoder + // should put only a complete surrogate pair into the buffer + assert(fCharIndex+1 < fCharsAvail); + if ( (fCharBuf[fCharIndex+1] < 0xDC00) || + (fCharBuf[fCharIndex+1] > 0xDFFF) ) + break; + fCharIndex += 2; + + } + else + { + if (!isNameChar(fCharBuf[fCharIndex])) + break; + fCharIndex++; + } + } + } + else // XMLV1_0 + { + while (fCharIndex < fCharsAvail) + { + if (!isNameChar(fCharBuf[fCharIndex])) + break; + fCharIndex++; + } + } + + // we have to copy the accepted character(s), and update column + if (fCharIndex != charIndex_start) + { + fCurCol += (XMLFileLoc)(fCharIndex - charIndex_start); + toFill.append(&fCharBuf[charIndex_start], fCharIndex - charIndex_start); + } + + // something is wrong if there is still something in the buffer + // or if we don't get no more, then break out. + if ((fCharIndex < fCharsAvail) || + !refreshCharBuffer()) + break; + + charIndex_start = fCharIndex; + } + + return !toFill.isEmpty(); +} + +bool XMLReader::getNCName(XMLBuffer& toFill) +{ + if (fCharIndex == fCharsAvail && !refreshCharBuffer()) + return false; + + XMLSize_t charIndex_start = fCharIndex, count; + // Lets check the first char for being a first name char. If not, then + // what's the point in living mannnn? Just give up now. We only do this + // if its a name and not a name token that they want. + if (fXMLVersion == XMLV1_1 + && ((fCharBuf[fCharIndex] >= 0xD800) && (fCharBuf[fCharIndex] <= 0xDB7F))) { + // make sure one more char is in the buffer, the transcoder + // should put only a complete surrogate pair into the buffer + assert(fCharIndex+1 < fCharsAvail); + if ((fCharBuf[fCharIndex+1] < 0xDC00) || (fCharBuf[fCharIndex+1] > 0xDFFF)) + return false; + + // Looks ok, so lets eat it + fCharIndex += 2; + } + else { + if (!isFirstNCNameChar(fCharBuf[fCharIndex])) { + return false; + } + + // Looks ok, so lets eat it + fCharIndex++; + } + + do + { + if (fCharIndex == fCharsAvail) + { + // we have to copy the accepted character(s), and update the column number, + // before getting new data and losing the value of fCharIndex + if((count = fCharIndex - charIndex_start)!=0) + { + fCurCol += (XMLFileLoc)count; + toFill.append(&fCharBuf[charIndex_start], count); + } + if(!refreshCharBuffer()) + return true; + charIndex_start = fCharIndex; + } + + // Check the current char and take it if it's a name char + if (fXMLVersion == XMLV1_1) + { + while(fCharIndex < fCharsAvail) + { + if(isNCNameChar(fCharBuf[fCharIndex])) fCharIndex++; + else if((fCharBuf[fCharIndex] >= 0xD800) && (fCharBuf[fCharIndex] <= 0xDB7F) && ((fCharBuf[fCharIndex+1] < 0xDC00) || (fCharBuf[fCharIndex+1] > 0xDFFF))) fCharIndex+=2; + else break; + } + } + else + while(fCharIndex < fCharsAvail && isNCNameChar(fCharBuf[fCharIndex])) fCharIndex++; + // if we didn't consume the entire buffer, we are done + } while(fCharIndex == fCharsAvail); + + // we have to copy the accepted character(s), and update column + if((count = fCharIndex - charIndex_start)!=0) + { + fCurCol += (XMLFileLoc)count; + toFill.append(&fCharBuf[charIndex_start], count); + } + return true; +} + +bool XMLReader::getQName(XMLBuffer& toFill, int* colonPosition) +{ + // We are only looking for two iterations (i.e. 'NCNAME':'NCNAME'). + // We will stop when we finished scanning for a QName (i.e. either a second + // colon or an invalid char). + if(!getNCName(toFill)) + { + *colonPosition = -1; + return false; + } + if (fCharIndex == fCharsAvail && !refreshCharBuffer()) + { + *colonPosition = -1; + return true; + } + if (fCharBuf[fCharIndex] != chColon) + { + *colonPosition = -1; + return true; + } + + *colonPosition = (int)toFill.getLen(); + toFill.append(chColon); + fCharIndex++; + fCurCol++; + return getNCName(toFill); +} + +bool XMLReader::getSpaces(XMLBuffer& toFill) +{ + // + // We just loop until we either hit a non-space or the end of this + // entity. We return true if we returned because of a non-space and + // false if because of end of entity. + // + // NOTE: We have to maintain line/col info here and we have to do + // whitespace normalization if we are not already internalized. + // + while (true) + { + // Loop through the current chars in the buffer + while (fCharIndex < fCharsAvail) + { + // Get the current char out of the buffer + XMLCh curCh = fCharBuf[fCharIndex]; + + // + // See if its a white space char. If so, then process it. Else + // we've hit a non-space and need to return. + // + if (isWhitespace(curCh)) + { + // Eat this char + fCharIndex++; + + // + // 'curCh' is a whitespace(x20|x9|xD|xA), so we only can have + // end-of-line combinations with a leading chCR(xD) or chLF(xA) + // + // 100000 x20 + // 001001 x9 + // 001010 chLF + // 001101 chCR + // ----------- + // 000110 == (chCR|chLF) & ~(0x9|0x20) + // + // if the result of thelogical-& operation is + // true : 'curCh' must be xA or xD + // false : 'curCh' must be x20 or x9 + // + if ( ( curCh & (chCR|chLF) & ~(0x9|0x20) ) == 0 ) + { + fCurCol++; + } else + { + handleEOL(curCh, false); + } + + // Ok we can add this guy to our buffer + toFill.append(curCh); + } + else + { + // Return true to indicate we broke out due to a whitespace + return true; + } + } + + // + // We've eaten up the current buffer, so lets try to reload it. If + // we don't get anything new, then break out. If we do, then we go + // back to the top to keep getting spaces. + // + if (!refreshCharBuffer()) + break; + } + return false; +} + + +bool XMLReader::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck) +{ + while (true) + { + // Loop through the current chars in the buffer + while (fCharIndex < fCharsAvail) + { + // Get the current char out of the buffer + XMLCh curCh = fCharBuf[fCharIndex]; + + // + // See if its not a white space or our target char, then process + // it. Else, we need to return. + // + if (!isWhitespace(curCh) && (curCh != toCheck)) + { + // Eat this char + fCharIndex++; + + // + // 'curCh' is not a whitespace(x20|x9|xD|xA), so we only can + // have end-of-line combinations with a leading chNEL(x85) or + // chLineSeparator(x2028) + // + // 0010000000101000 chLineSeparator + // 0000000010000101 chNEL + // --------------------- + // 1101111101010010 == ~(chNEL|chLineSeparator) + // + // if the result of the logical-& operation is + // true : 'curCh' can not be chNEL or chLineSeparator + // false : 'curCh' can be chNEL or chLineSeparator + // + if ( curCh & (XMLCh) ~(chNEL|chLineSeparator) ) + { + fCurCol++; + } else + { + handleEOL(curCh, false); + } + + // Add it to our buffer + toFill.append(curCh); + } + else + { + return true; + } + } + + // + // We've eaten up the current buffer, so lets try to reload it. If + // we don't get anything new, then break out. If we do, then we go + // back to the top to keep getting spaces. + // + if (!refreshCharBuffer()) + break; + } + + // We never hit any non-space and ate up the whole reader + return false; + +} + +bool XMLReader::skipIfQuote(XMLCh& chGotten) +{ + if (fCharIndex == fCharsAvail && !refreshCharBuffer()) + return false; + + chGotten = fCharBuf[fCharIndex]; + if ((chGotten == chDoubleQuote) || (chGotten == chSingleQuote)) + { + fCharIndex++; + fCurCol++; + return true; + } + return false; +} + + +bool XMLReader::skipSpaces(bool& skippedSomething, bool inDecl) +{ + // DO NOT set the skippedSomething to 'false', but change it to be 'true' only + + // We enter a loop where we skip over spaces until we hit the end of + // this reader or a non-space value. The return indicates whether we + // hit the non-space (true) or the end (false). + do + { + // Loop through the current chars in the buffer + while (fCharIndex < fCharsAvail) + { + // See if its a white space char. If so, then process it. Else + // we've hit a non-space and need to return. + if (isWhitespace(fCharBuf[fCharIndex])) + { + // Get the current char out of the buffer and eat it + XMLCh curCh = fCharBuf[fCharIndex++]; + skippedSomething = true; + // + // 'curCh' is a whitespace(x20|x9|xD|xA), so we only can have + // end-of-line combinations with a leading chCR(xD) or chLF(xA) + // + // 100000 x20 + // 001001 x9 + // 001010 chLF + // 001101 chCR + // ----------- + // 000110 == (chCR|chLF) & ~(0x9|0x20) + // + // if the result of the logical-& operation is + // true : 'curCh' must be xA or xD + // false : 'curCh' must be x20 or x9 + // + if ( ( curCh & (chCR|chLF) & ~(0x9|0x20) ) == 0 ) + { + fCurCol++; + } else + { + handleEOL(curCh, inDecl); + } + } + else + return true; + } + + // We've eaten up the current buffer, so lets try to reload it. If + // we don't get anything new, then break out. If we do, then we go + // back to the top to keep getting spaces. + } while(refreshCharBuffer()); + + // We never hit any non-space and ate up the whole reader + return false; +} + +bool XMLReader::skippedChar(const XMLCh toSkip) +{ + // + // If the buffer is empty, then try to reload it. If we still get + // nothing, then return false. + // + if (fCharIndex == fCharsAvail) + { + if (!refreshCharBuffer()) + return false; + } + + // + // See if the current char is the one we want. If so, then we need + // to eat it and return true. + // + if (fCharBuf[fCharIndex] == toSkip) + { + fCharIndex++; + fCurCol++; + return true; + } + return false; +} + + +bool XMLReader::skippedSpace() +{ + // + // If the buffer is empty, then try to reload it. If we still get + // nothing, then return false. + // + if (fCharIndex == fCharsAvail) + { + if (!refreshCharBuffer()) + return false; + } + + // + // See if the current char is a whitespace. If so, then we need to eat + // it and return true. + // + const XMLCh curCh = fCharBuf[fCharIndex]; + if (isWhitespace(curCh)) + { + // Eat the character + fCharIndex++; + + // + // 'curCh' is a whitespace(x20|x9|xD|xA), so we only can have + // end-of-line combinations with a leading chCR(xD) or chLF(xA) + // + // 100000 x20 + // 001001 x9 + // 001010 chLF + // 001101 chCR + // ----------- + // 000110 == (chCR|chLF) & ~(0x9|0x20) + // + // if the result of the logical-& operation is + // true : 'curCh' must be xA or xD + // false : 'curCh' must be x20 or x9 + // + if ( ( curCh & (chCR|chLF) & ~(0x9|0x20) ) == 0 ) + { + fCurCol++; + } else + { + handleEOL((XMLCh&)curCh, false); + } + + return true; + } + return false; +} + +bool XMLReader::skippedString(const XMLCh* const toSkip) +{ + // This function works on strings that are smaller than kCharBufSize. + // This function guarantees that in case the comparison is unsuccessful + // the fCharIndex will point to the original data. + // + + // Get the length of the string to skip. + // + const XMLSize_t srcLen = XMLString::stringLen(toSkip); + XMLSize_t charsLeft = charsLeftInBuffer(); + + // See if the current reader has enough chars to test against this + // string. If not, then ask it to reload its buffer. If that does not + // get us enough, then it cannot match. + // + // NOTE: This works because strings never have to cross a reader! And + // a string to skip will never have a new line in it, so we will never + // miss adjusting the current line. + // + while (charsLeft < srcLen) + { + if (!refreshCharBuffer()) + return false; + + XMLSize_t tmp = charsLeftInBuffer(); + if (tmp == charsLeft) // if the refreshCharBuf() did not add anything new + return false; // give up and return. + + charsLeft = tmp; + } + + // Ok, now we now that the current reader has enough chars in its + // buffer and that its index is back at zero. So we can do a quick and + // dirty comparison straight to its buffer with no requirement to unget + // if it fails. + // + if (memcmp(&fCharBuf[fCharIndex], toSkip, srcLen * sizeof(XMLCh))) + return false; + + // Add the source length to the current column to get it back right. + // + fCurCol += (XMLFileLoc)srcLen; + + // And get the character buffer index back right by just adding the + // source len to it. + // + fCharIndex += srcLen; + + return true; +} + +bool XMLReader::skippedStringLong(const XMLCh* toSkip) +{ + // This function works on strings that are potentially longer than + // kCharBufSize (e.g., end tag). This function does not guarantee + // that in case the comparison is unsuccessful the fCharIndex will + // point to the original data. + // + + XMLSize_t srcLen = XMLString::stringLen(toSkip); + XMLSize_t charsLeft = charsLeftInBuffer(); + + while (srcLen != 0) + { + // Fill up the buffer with as much data as possible. + // + while (charsLeft < srcLen && charsLeft != kCharBufSize) + { + if (!refreshCharBuffer()) + return false; + + XMLSize_t tmp = charsLeftInBuffer(); + if (tmp == charsLeft) // if the refreshCharBuf() did not add anything + return false; // new give up and return. + + charsLeft = tmp; + } + + XMLSize_t n = charsLeft < srcLen ? charsLeft : srcLen; + + if (memcmp(&fCharBuf[fCharIndex], toSkip, n * sizeof(XMLCh))) + return false; + + toSkip += n; + srcLen -= n; + + fCharIndex += n; + fCurCol += (XMLFileLoc)n; + charsLeft -= n; + } + + return true; +} + +// +// This is just to peek if the next coming buffer +// matches the string toPeek. +// Similar to skippedString, but just the fCharIndex and fCurCol are not updated +// +bool XMLReader::peekString(const XMLCh* const toPeek) +{ + // Get the length of the string to skip + const XMLSize_t srcLen = XMLString::stringLen(toPeek); + + // + // See if the current reader has enough chars to test against this + // string. If not, then ask it to reload its buffer. If that does not + // get us enough, then it cannot match. + // + // NOTE: This works because strings never have to cross a reader! And + // a string to skip will never have a new line in it, so we will never + // miss adjusting the current line. + // + XMLSize_t charsLeft = charsLeftInBuffer(); + while (charsLeft < srcLen) + { + refreshCharBuffer(); + XMLSize_t t = charsLeftInBuffer(); + if (t == charsLeft) // if the refreshCharBuf() did not add anything new + return false; // give up and return. + charsLeft = t; + } + + + + + // + // Ok, now we now that the current reader has enough chars in its + // buffer and that its index is back at zero. So we can do a quick and + // dirty comparison straight to its buffer with no requirement to unget + // if it fails. + // + if (memcmp(&fCharBuf[fCharIndex], toPeek, srcLen*sizeof(XMLCh))) + return false; + + return true; +} + + +// --------------------------------------------------------------------------- +// XMLReader: Setter methods (most are inlined) +// --------------------------------------------------------------------------- +bool XMLReader::setEncoding(const XMLCh* const newEncoding) +{ + // + // If the encoding was forced, then we ignore the new value and just + // return with success. If it was forced, then we are to use that + // encoding without question. Note that, if we are forced, we created + // a transcoder up front so there is no need to do one here in that + // case. + // + if (fForcedEncoding) + return true; + + // + // upperCase the newEncoding first for better performance + // + XMLCh* inputEncoding = XMLString::replicate(newEncoding, fMemoryManager); + XMLString::upperCaseASCII(inputEncoding); + + XMLRecognizer::Encodings newBaseEncoding; + // + // Check for non-endian specific UTF-16 or UCS-4. If so, and if we + // are already in one of the endian versions of those encodings, + // then just keep it and go on. Otherwise, its not valid. + // + if (XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString) + || XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString2) + || XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString3) + || XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString4) + || XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString5) + || XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString6) + || XMLString::equals(inputEncoding, XMLUni::fgUTF16EncodingString7)) + { + fMemoryManager->deallocate(inputEncoding); + + if ((fEncoding != XMLRecognizer::UTF_16L) + && (fEncoding != XMLRecognizer::UTF_16B)) + { + return false; + } + + // Override with the original endian specific encoding + newBaseEncoding = fEncoding; + + if (fEncoding == XMLRecognizer::UTF_16L) { + fMemoryManager->deallocate(fEncodingStr); + fEncodingStr = 0; + fEncodingStr = XMLString::replicate(XMLUni::fgUTF16LEncodingString, fMemoryManager); + } + else { + fMemoryManager->deallocate(fEncodingStr); + fEncodingStr = 0; + fEncodingStr = XMLString::replicate(XMLUni::fgUTF16BEncodingString, fMemoryManager); + } + } + else if (XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString) + || XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString2) + || XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString3) + || XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString4) + || XMLString::equals(inputEncoding, XMLUni::fgUCS4EncodingString5)) + { + fMemoryManager->deallocate(inputEncoding); + + if ((fEncoding != XMLRecognizer::UCS_4L) + && (fEncoding != XMLRecognizer::UCS_4B)) + { + return false; + } + + // Override with the original endian specific encoding + newBaseEncoding = fEncoding; + + if (fEncoding == XMLRecognizer::UCS_4L) { + + fMemoryManager->deallocate(fEncodingStr); + fEncodingStr = 0; + fEncodingStr = XMLString::replicate(XMLUni::fgUCS4LEncodingString, fMemoryManager); + } + else { + + fMemoryManager->deallocate(fEncodingStr); + fEncodingStr = 0; + fEncodingStr = XMLString::replicate(XMLUni::fgUCS4BEncodingString, fMemoryManager); + } + } + else + { + // + // Try to map the string to one of our standard encodings. If its not + // one of them, then it has to be one of the non-intrinsic encodings, + // in which case we have to delete our intrinsic encoder and create a + // new one. + // + newBaseEncoding = XMLRecognizer::encodingForName(inputEncoding); + + // + // If it does not come back as one of the auto-sensed encodings, then we + // have to possibly replace it and at least check a few things. + // + if (newBaseEncoding == XMLRecognizer::OtherEncoding) + { + // + // We already know it's none of those non-endian special cases, + // so just replicate the new name and use it directly to create the transcoder + // + fMemoryManager->deallocate(fEncodingStr); + fEncodingStr = inputEncoding; + + XMLTransService::Codes failReason; + fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + fEncodingStr + , failReason + , kCharBufSize + , fMemoryManager + ); + } + else + { + // Store the new encoding string since it is just an intrinsic + fMemoryManager->deallocate(fEncodingStr); + fEncodingStr = inputEncoding; + } + } + + if (!fTranscoder) { + // + // Now we can create a transcoder using the recognized fEncoding. We + // might get back a transcoder for an intrinsically supported encoding, + // or we might get one from the underlying transcoding service. + // + XMLTransService::Codes failReason; + fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor + ( + newBaseEncoding + , failReason + , kCharBufSize + , fMemoryManager + ); + + if (!fTranscoder) + ThrowXMLwithMemMgr1(TranscodingException, XMLExcepts::Trans_CantCreateCvtrFor, fEncodingStr, fMemoryManager); + } + + // Update the base encoding member with the new base encoding found + fEncoding = newBaseEncoding; + + // Looks ok to us + return true; +} + + +// --------------------------------------------------------------------------- +// XMLReader: Private helper methods +// --------------------------------------------------------------------------- + +// +// This is called when the encoding flag is set and just sets the fSwapped +// flag appropriately. +// +void XMLReader::checkForSwapped() +{ + // Assume not swapped + fSwapped = false; + + if (XMLPlatformUtils::fgXMLChBigEndian) + { + if ((fEncoding == XMLRecognizer::UTF_16L) + || (fEncoding == XMLRecognizer::UCS_4L)) + { + fSwapped = true; + } + } + else + { + if ((fEncoding == XMLRecognizer::UTF_16B) + || (fEncoding == XMLRecognizer::UCS_4B)) + { + fSwapped = true; + } + } +} + + +// +// This is called from the constructor when the encoding is not forced. +// We assume that the encoding has been auto-sensed at this point and that +// fSwapped is set correctly. +// +// In the case of UCS-4 and EBCDIC, we don't have to check for a decl. +// The fact that we got here, means that there is one, because that's the +// only way we can autosense those. +// +void XMLReader::doInitDecode() +{ + switch(fEncoding) + { + case XMLRecognizer::UCS_4B : + case XMLRecognizer::UCS_4L : + { + // Remove bom if any + if (((fRawByteBuf[0] == 0x00) && (fRawByteBuf[1] == 0x00) && (fRawByteBuf[2] == 0xFE) && (fRawByteBuf[3] == 0xFF)) || + ((fRawByteBuf[0] == 0xFF) && (fRawByteBuf[1] == 0xFE) && (fRawByteBuf[2] == 0x00) && (fRawByteBuf[3] == 0x00)) ) + { + for (XMLSize_t i = 0; i < fRawBytesAvail; i++) + fRawByteBuf[i] = fRawByteBuf[i+4]; + + fRawBytesAvail -=4; + } + + // Look at the raw buffer as UCS4 chars + const UCS4Ch* asUCS = (const UCS4Ch*)fRawByteBuf; + + while (fRawBufIndex < fRawBytesAvail) + { + // Security fix: make sure there are at least sizeof(UCS4Ch) bytes to consume. + if (fRawBufIndex + sizeof(UCS4Ch) > fRawBytesAvail) { + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Reader_CouldNotDecodeFirstLine + , fSystemId + , fMemoryManager + ); + } + + // Get out the current 4 byte value and inc our raw buf index + UCS4Ch curVal = *asUCS++; + fRawBufIndex += sizeof(UCS4Ch); + + // Swap if that is required for this machine + if (fSwapped) + curVal = BitOps::swapBytes(curVal); + + // Make sure its at least semi legal. If not, undo and throw + if (curVal > 0xFFFF) + { + fCharsAvail = 0; + fRawBufIndex = 0; + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fEncodingStr); + ArrayJanitor janValue(fSystemId, fMemoryManager); + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Reader_CouldNotDecodeFirstLine + , fSystemId + , fMemoryManager + ); + } + + // Convert the value to an XML char and store it + fCharSizeBuf[fCharsAvail] = 4; + fCharBuf[fCharsAvail++] = XMLCh(curVal); + + // Break out on the > character + if (curVal == chCloseAngle) + break; + } + break; + } + + case XMLRecognizer::UTF_8 : + { + // If there's a utf-8 BOM (0xEF 0xBB 0xBF), skip past it. + // Don't move to char buf - no one wants to see it. + // Note: this causes any encoding= declaration to override + // the BOM's attempt to say that the encoding is utf-8. + + // Look at the raw buffer as short chars + const char* asChars = (const char*)fRawByteBuf; + + if (fRawBytesAvail > XMLRecognizer::fgUTF8BOMLen && + XMLString::compareNString( asChars + , XMLRecognizer::fgUTF8BOM + , XMLRecognizer::fgUTF8BOMLen) == 0) + { + fRawBufIndex += XMLRecognizer::fgUTF8BOMLen; + asChars += XMLRecognizer::fgUTF8BOMLen; + } + + // + // First check that there are enough bytes to even see the + // decl indentifier. If not, get out now with no action since + // there is no decl. + // + if (fRawBytesAvail < XMLRecognizer::fgASCIIPreLen) + break; + + // Check for the opening sequence. If not, then no decl + if (XMLString::compareNString( asChars + , XMLRecognizer::fgASCIIPre + , XMLRecognizer::fgASCIIPreLen)) + { + break; + } + + while (fRawBufIndex < fRawBytesAvail) + { + const char curCh = *asChars++; + fRawBufIndex++; + + // Looks ok, so store it + fCharSizeBuf[fCharsAvail] = 1; + fCharBuf[fCharsAvail++] = XMLCh(curCh); + + // Break out on a > character + if (curCh == chCloseAngle) + break; + + // + // A char greater than 0x7F is not allowed in this case. If + // so, undo and throw. + // + if (curCh & 0x80) + { + fCharsAvail = 0; + fRawBufIndex = 0; + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fEncodingStr); + ArrayJanitor janValue(fSystemId, fMemoryManager); + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Reader_CouldNotDecodeFirstLine + , fSystemId + , fMemoryManager + ); + } + } + break; + } + + case XMLRecognizer::UTF_16B : + case XMLRecognizer::UTF_16L : + { + // + // If there is a decl here, we just truncate back the characters + // as we go. No surrogate creation would be allowed here in legal + // XML, so we consider it a transoding error if we find one. + // + if (fRawBytesAvail < 2) + break; + + XMLSize_t postBOMIndex = 0; + const UTF16Ch* asUTF16 = (const UTF16Ch*)&fRawByteBuf[fRawBufIndex]; + if ((*asUTF16 == chUnicodeMarker) || (*asUTF16 == chSwappedUnicodeMarker)) + { + fRawBufIndex += sizeof(UTF16Ch); + asUTF16++; + postBOMIndex = fRawBufIndex; + } + + // First check that there are enough raw bytes for there to even + // be a decl indentifier. If not, then nothing to do. + // + if (fRawBytesAvail - fRawBufIndex < XMLRecognizer::fgUTF16PreLen) + { + fRawBufIndex = postBOMIndex; + break; + } + + // + // See we get a match on the prefix. If not, then reset and + // break out. + // + if (fEncoding == XMLRecognizer::UTF_16B) + { + if (memcmp(asUTF16, XMLRecognizer::fgUTF16BPre, XMLRecognizer::fgUTF16PreLen)) + { + fRawBufIndex = postBOMIndex; + break; + } + } + else + { + if (memcmp(asUTF16, XMLRecognizer::fgUTF16LPre, XMLRecognizer::fgUTF16PreLen)) + { + fRawBufIndex = postBOMIndex; + break; + } + } + + while (fRawBufIndex < fRawBytesAvail) + { + // Security fix: make sure there are at least sizeof(UTF16Ch) bytes to consume. + if (fRawBufIndex + sizeof(UTF16Ch) > fRawBytesAvail) { + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Reader_CouldNotDecodeFirstLine + , fSystemId + , fMemoryManager + ); + } + + // Get out the current 2 byte value + UTF16Ch curVal = *asUTF16++; + fRawBufIndex += sizeof(UTF16Ch); + + // Swap if that is required for this machine + if (fSwapped) + curVal = BitOps::swapBytes(curVal); + + // + // Store it and bump the target index, implicitly converting + // if UTF16Ch and XMLCh are not the same size. + // + fCharSizeBuf[fCharsAvail] = 2; + fCharBuf[fCharsAvail++] = curVal; + + // Break out on a > char + if (curVal == chCloseAngle) + break; + } + break; + } + + case XMLRecognizer::EBCDIC : + { + // + // We use special support in the intrinsic EBCDIC-US transcoder + // to go through one char at a time. + // + const XMLByte* srcPtr = fRawByteBuf; + while (1) + { + // Transcode one char from the source + const XMLCh chCur = XMLEBCDICTranscoder::xlatThisOne(*srcPtr++); + fRawBufIndex++; + + // + // And put it into the character buffer. This stuff has to + // look like it was normally transcoded. + // + fCharSizeBuf[fCharsAvail] = 1; + fCharBuf[fCharsAvail++] = chCur; + + // If its a > char, then break out + if (chCur == chCloseAngle) + break; + + // Watch for using up all input and get out + if (fRawBufIndex == fRawBytesAvail) + break; + } + break; + } + + default : + // It should never be anything else here + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fEncodingStr); + fMemoryManager->deallocate(fSystemId); + ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Reader_BadAutoEncoding, fMemoryManager); + break; + } + + // + // Ok, by the time we get here, if its a legal XML file we have eaten + // the XML/TextDecl. So, if we are a PE and are being referenced from + // outside a literal, then we need to throw in an arbitrary space that + // is required by XML. + // + if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral)) + fCharBuf[fCharsAvail++] = chSpace; + + // Calculate fCharOfsBuf buffer using the elements from fCharBufSize + if (fCalculateSrcOfs) + { + fCharOfsBuf[0] = 0; + for (XMLSize_t index = 1; index < fCharsAvail; ++index) { + fCharOfsBuf[index] = fCharOfsBuf[index-1]+fCharSizeBuf[index-1]; + } + } +} + + +// +// This method is called internally when we run out of bytes in the raw +// buffer. We just read as many bytes as we can into the raw buffer again +// and store the number of bytes we got. +// +void XMLReader::refreshRawBuffer() +{ + // Security fix: make sure we don't underflow on the subtraction. + if (fRawBufIndex > fRawBytesAvail) { + ThrowXMLwithMemMgr1 + ( + RuntimeException + , XMLExcepts::Str_StartIndexPastEnd + , fSystemId + , fMemoryManager + ); + } + + // + // If there are any bytes left, move them down to the start. There + // should only ever be (max bytes per char - 1) at the most. + // + const XMLSize_t bytesLeft = fRawBytesAvail - fRawBufIndex; + + // Move the existing ones down + for (XMLSize_t index = 0; index < bytesLeft; index++) + fRawByteBuf[index] = fRawByteBuf[fRawBufIndex + index]; + + // + // And then read into the buffer past the existing bytes. Add back in + // that many to the bytes read, and subtract that many from the bytes + // requested. + // + fRawBytesAvail = fStream->readBytes + ( + &fRawByteBuf[bytesLeft], kRawBufSize - bytesLeft + ) + bytesLeft; + + // + // We need to reset the buffer index back to the start in all cases, + // since any trailing data was copied down to the start. + // + fRawBufIndex = 0; +} + + +// +// This method is called internally when we run out of characters in the +// trancoded character buffer. We transcode up to another maxChars chars +// from the +// +XMLSize_t +XMLReader::xcodeMoreChars( XMLCh* const bufToFill + , unsigned char* const charSizes + , const XMLSize_t maxChars) +{ + XMLSize_t charsDone = 0; + XMLSize_t bytesEaten = 0; + bool needMode = false; + + while (!bytesEaten) + { + // If our raw buffer is low, then lets load up another batch of + // raw bytes now. + // + XMLSize_t bytesLeft = fRawBytesAvail - fRawBufIndex; + if (needMode || bytesLeft == 0 || bytesLeft < fLowWaterMark) + { + refreshRawBuffer(); + + // If there are no characters or if we need more but didn't get + // any, return zero now. + // + if (fRawBytesAvail == 0 || + (needMode && (bytesLeft == fRawBytesAvail - fRawBufIndex))) + return 0; + } + + // Ask the transcoder to internalize another batch of chars. It is + // possible that there is data in the raw buffer but the transcoder + // is unable to produce anything because transcoding of multi-byte + // encodings may have left a few bytes representing a partial + // character in the buffer that can't be used until the next chunk + // (and the rest of the character) is read. In this case set the + // needMore flag and try again. + // + + charsDone = fTranscoder->transcodeFrom + ( + &fRawByteBuf[fRawBufIndex] + , fRawBytesAvail - fRawBufIndex + , bufToFill + , maxChars + , bytesEaten + , charSizes + ); + + if (bytesEaten == 0) + needMode = true; + else + fRawBufIndex += bytesEaten; + } + + return charsDone; +} + +/*** + * + * XML1.1 + * + * 2.11 End-of-Line Handling + * + * XML parsed entities are often stored in computer files which, for editing + * convenience, are organized into lines. These lines are typically separated + * by some combination of the characters CARRIAGE RETURN (#xD) and LINE FEED (#xA). + * + * To simplify the tasks of applications, the XML processor MUST behave as if + * it normalized all line breaks in external parsed entities (including the document + * entity) on input, before parsing, by translating all of the following to a single + * #xA character: + * + * 1. the two-character sequence #xD #xA + * 2. the two-character sequence #xD #x85 + * 3. the single character #x85 + * 4. the single character #x2028 + * 5. any #xD character that is not immediately followed by #xA or #x85. + * + * + ***/ +void XMLReader::handleEOL(XMLCh& curCh, bool inDecl) +{ + // 1. the two-character sequence #xD #xA + // 2. the two-character sequence #xD #x85 + // 5. any #xD character that is not immediately followed by #xA or #x85. + switch(curCh) + { + case chCR: + fCurCol = 1; + fCurLine++; + + // + // If not already internalized, then convert it to an + // LF and eat any following LF. + // + if (fSource == Source_External) + { + if ((fCharIndex < fCharsAvail) || refreshCharBuffer()) + { + if ( fCharBuf[fCharIndex] == chLF || + ((fCharBuf[fCharIndex] == chNEL) && fNEL) ) + { + fCharIndex++; + } + } + curCh = chLF; + } + break; + + case chLF: + fCurCol = 1; + fCurLine++; + break; + + // 3. the single character #x85 + // 4. the single character #x2028 + case chNEL: + case chLineSeparator: + if (inDecl && fXMLVersion == XMLV1_1) + { + + /*** + * XML1.1 + * + * 2.11 End-of-Line Handling + * ... + * The characters #x85 and #x2028 cannot be reliably recognized and translated + * until an entity's encoding declaration (if present) has been read. + * Therefore, it is a fatal error to use them within the XML declaration or + * text declaration. + * + ***/ + ThrowXMLwithMemMgr1 + ( + TranscodingException + , XMLExcepts::Reader_NelLsepinDecl + , fSystemId + , fMemoryManager + ); + } + + if (fNEL && fSource == Source_External) + { + fCurCol = 1; + fCurLine++; + curCh = chLF; + } + break; + default: + fCurCol++; + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XMLReader.hpp b/include/xercesc/internal/XMLReader.hpp new file mode 100644 index 0000000..c49124e --- /dev/null +++ b/include/xercesc/internal/XMLReader.hpp @@ -0,0 +1,790 @@ +/* + * 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: XMLReader.hpp 833045 2009-11-05 13:21:27Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLREADER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLREADER_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class InputSource; +class BinInputStream; +class ReaderMgr; +class XMLScanner; +class XMLTranscoder; + + +// --------------------------------------------------------------------------- +// Instances of this class are used to manage the content of entities. The +// scanner maintains a stack of these, one for each entity (this means entity +// in the sense of any parsed file or internal entity) currently being +// scanned. This class, given a binary input stream will handle reading in +// the data and decoding it from its external decoding into the internal +// Unicode format. Once internallized, this class provides the access +// methods to read in the data in various ways, maintains line and column +// information, and provides high performance character attribute checking +// methods. +// +// This is NOT to be derived from. +// +// --------------------------------------------------------------------------- +class XMLPARSER_EXPORT XMLReader : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Public types + // ----------------------------------------------------------------------- + enum Types + { + Type_PE + , Type_General + }; + + enum Sources + { + Source_Internal + , Source_External + }; + + enum RefFrom + { + RefFrom_Literal + , RefFrom_NonLiteral + }; + + enum XMLVersion + { + XMLV1_0 + , XMLV1_1 + , XMLV_Unknown + }; + + + // ----------------------------------------------------------------------- + // Public, query methods + // ----------------------------------------------------------------------- + bool isAllSpaces + ( + const XMLCh* const toCheck + , const XMLSize_t count + ) const; + + bool containsWhiteSpace + ( + const XMLCh* const toCheck + , const XMLSize_t count + ) const; + + + bool isXMLLetter(const XMLCh toCheck) const; + bool isFirstNameChar(const XMLCh toCheck) const; + bool isNameChar(const XMLCh toCheck) const; + bool isPlainContentChar(const XMLCh toCheck) const; + bool isSpecialStartTagChar(const XMLCh toCheck) const; + bool isXMLChar(const XMLCh toCheck) const; + bool isWhitespace(const XMLCh toCheck) const; + bool isControlChar(const XMLCh toCheck) const; + bool isPublicIdChar(const XMLCh toCheck) const; + bool isFirstNCNameChar(const XMLCh toCheck) const; + bool isNCNameChar(const XMLCh toCheck) const; + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + XMLReader + ( + const XMLCh* const pubId + , const XMLCh* const sysId + , BinInputStream* const streamToAdopt + , const RefFrom from + , const Types type + , const Sources source + , const bool throwAtEnd = false + , const bool calculateSrcOfs = true + , XMLSize_t lowWaterMark = 100 + , const XMLVersion xmlVersion = XMLV1_0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XMLReader + ( + const XMLCh* const pubId + , const XMLCh* const sysId + , BinInputStream* const streamToAdopt + , const XMLCh* const encodingStr + , const RefFrom from + , const Types type + , const Sources source + , const bool throwAtEnd = false + , const bool calculateSrcOfs = true + , XMLSize_t lowWaterMark = 100 + , const XMLVersion xmlVersion = XMLV1_0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + XMLReader + ( + const XMLCh* const pubId + , const XMLCh* const sysId + , BinInputStream* const streamToAdopt + , XMLRecognizer::Encodings encodingEnum + , const RefFrom from + , const Types type + , const Sources source + , const bool throwAtEnd = false + , const bool calculateSrcOfs = true + , XMLSize_t lowWaterMark = 100 + , const XMLVersion xmlVersion = XMLV1_0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + ~XMLReader(); + + + // ----------------------------------------------------------------------- + // Character buffer management methods + // ----------------------------------------------------------------------- + XMLSize_t charsLeftInBuffer() const; + bool refreshCharBuffer(); + + + // ----------------------------------------------------------------------- + // Scanning methods + // ----------------------------------------------------------------------- + bool getName(XMLBuffer& toFill, const bool token); + bool getQName(XMLBuffer& toFill, int* colonPosition); + bool getNCName(XMLBuffer& toFill); + bool getNextChar(XMLCh& chGotten); + bool getNextCharIfNot(const XMLCh chNotToGet, XMLCh& chGotten); + void movePlainContentChars(XMLBuffer &dest); + bool getSpaces(XMLBuffer& toFill); + bool getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck); + bool peekNextChar(XMLCh& chGotten); + bool skipIfQuote(XMLCh& chGotten); + bool skipSpaces(bool& skippedSomething, bool inDecl = false); + bool skippedChar(const XMLCh toSkip); + bool skippedSpace(); + bool skippedString(const XMLCh* const toSkip); + bool skippedStringLong(const XMLCh* toSkip); + bool peekString(const XMLCh* const toPeek); + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLFileLoc getColumnNumber() const; + const XMLCh* getEncodingStr() const; + XMLFileLoc getLineNumber() const; + bool getNoMoreFlag() const; + const XMLCh* getPublicId() const; + XMLSize_t getReaderNum() const; + RefFrom getRefFrom() const; + Sources getSource() const; + XMLFilePos getSrcOffset() const; + const XMLCh* getSystemId() const; + bool getThrowAtEnd() const; + Types getType() const; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + bool setEncoding + ( + const XMLCh* const newEncoding + ); + void setReaderNum(const XMLSize_t newNum); + void setThrowAtEnd(const bool newValue); + void setXMLVersion(const XMLVersion version); + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLReader(const XMLReader&); + XMLReader& operator=(const XMLReader&); + + // --------------------------------------------------------------------------- + // Class Constants + // + // kCharBufSize + // The size of the character spool buffer that we use. Its not terribly + // large because its just getting filled with data from a raw byte + // buffer as we go along. We don't want to decode all the text at + // once before we find out that there is an error. + // + // NOTE: This is a size in characters, not bytes. + // + // kRawBufSize + // The size of the raw buffer from which raw bytes are spooled out + // as we transcode chunks of data. As it is emptied, it is filled back + // in again from the source stream. + // --------------------------------------------------------------------------- + enum Constants + { + kCharBufSize = 16 * 1024 + , kRawBufSize = 48 * 1024 + }; + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void checkForSwapped(); + + void doInitCharSizeChecks(); + + void doInitDecode(); + + XMLByte getNextRawByte + ( + const bool eoiOk + ); + + void refreshRawBuffer(); + + void setTranscoder + ( + const XMLCh* const newEncoding + ); + + XMLSize_t xcodeMoreChars + ( + XMLCh* const bufToFill + , unsigned char* const charSizes + , const XMLSize_t maxChars + ); + + void handleEOL + ( + XMLCh& curCh + , bool inDecl = false + ); + + // ----------------------------------------------------------------------- + // Data members + // + // fCharIndex + // The index into the character buffer. When this hits fCharsAvail + // then its time to refill. + // + // fCharBuf + // A buffer that the reader manager fills up with transcoded + // characters a small amount at a time. + // + // fCharsAvail + // The characters currently available in the character buffer. + // + // fCharSizeBuf + // This buffer is an array that contains the number of source chars + // eaten to create each char in the fCharBuf buffer. So the entry + // fCharSizeBuf[x] is the number of source chars that were eaten + // to make the internalized char fCharBuf[x]. This only contains + // useful data if fSrcOfsSupported is true. + // + // fCharOfsBuf + // This buffer is an array that contains the offset in the + // fRawByteBuf buffer of each char in the fCharBuf buffer. It + // only contains useful data if fSrcOfsSupported is true. + // + // fCurCol + // fCurLine + // The current line and column that we are in within this reader's + // text. + // + // fEncoding + // This is the rough encoding setting. This enum is set during + // construction and just tells us the rough family of encoding that + // we are doing. + // + // fEncodingStr + // This is the name of the encoding we are using. It will be + // provisionally set during construction, from the auto-sensed + // encoding. But it might be overridden when the XMLDecl is finally + // seen by the scanner. It can also be forced to a particular + // encoding, in which case fForcedEncoding is set. + // + // fForcedEncoding + // If the encoding if forced then this is set and all other + // information will be ignored. This encoding will be taken as + // gospel. This is done by calling an alternate constructor. + // + // fNoMore + // This is set when the source text is exhausted. It lets us know + // quickly that no more text is available. + // + // fRawBufIndex + // The current index into the raw byte buffer. When its equal to + // fRawBytesAvail then we need to read another buffer. + // + // fRawByteBuf + // This is the raw byte buffer that is used to spool out bytes + // from into the fCharBuf buffer, as we transcode in blocks. + // + // fRawBytesAvail + // The number of bytes currently available in the raw buffer. This + // helps deal with the last buffer's worth, which will usually not + // be a full one. + // + // fLowWaterMark + // The low water mark for the raw byte buffer. + // + // + // fReaderNum + // Each reader from a particular reader manager (which means from a + // particular document) is given a unique number. The reader manager + // sets these numbers. They are used to catch things like partial + // markup errors. + // + // fRefFrom + // This flag is provided in the ctor, and tells us if we represent + // some entity being expanded inside a literal. Sometimes things + // happen differently inside and outside literals. + // + // fPublicId + // fSystemId + // These are the system and public ids of the source that this + // reader is reading. + // + // fSentTrailingSpace + // If we are a PE entity being read and we not referenced from a + // literal, then a leading and trailing space must be faked into the + // data. This lets us know we've done the trailing space already (so + // we don't just keep doing it again and again.) + // + // fSource + // Indicates whether the content this reader is spooling as already + // been internalized. This will prevent multiple processing of + // whitespace when an already internalized entity is being spooled + // out. + // + // fSpareChar + // Some encodings can create two chars in an atomic way, e.g. + // surrogate pairs. We might not be able to store both, so we store + // it here until the next buffer transcoding operation. + // + // fSrcOfsBase + // This is the base offset within the source of this entity. Values + // in the curent fCharSizeBuf array are relative to this value. + // + // fSrcOfsSupported + // This flag is set to indicate whether source byte offset info + // is supported. For intrinsic encodings, its always set since we + // can always support it. For transcoder based encodings, we ask + // the transcoder if it supports it or not. + // + // fStream + // This is the input stream that provides the data for the reader. + // Its always treated as a raw byte stream. The derived class will + // ask for buffers of text from it and will handle making some + // sense of it. + // + // fSwapped + // If the encoding is one of the ones we do intrinsically, and its + // in a different byte order from our native order, then this is + // set to remind us to byte swap it during transcoding. + // + // fThrowAtEnd + // Indicates whether the reader manager should throw an end of entity + // exception at the end of this reader instance. This is usually + // set for top level external entity references. It overrides the + // reader manager's global flag that controls throwing at the end + // of entities. Defaults to false. + // + // fTranscoder + // If the encoding is not one that we handle intrinsically, then + // we use an an external transcoder to do it. This class is an + // abstraction that allows us to use pluggable external transcoding + // services (via XMLTransService in util.) + // + // fType + // Indicates whether this reader represents a PE or not. If this + // flag is true and the fInLiteral flag is false, then we will put + // out an extra space at the end. + // + // fgCharCharsTable; + // Pointer to XMLChar table, depends on XML version + // + // fNEL + // Boolean indicates if NEL and LSEP should be recognized as NEL + // + // fXMLVersion + // Enum to indicate if this Reader is conforming to XML 1.0 or XML 1.1 + // ----------------------------------------------------------------------- + XMLSize_t fCharIndex; + XMLCh fCharBuf[kCharBufSize]; + XMLSize_t fCharsAvail; + unsigned char fCharSizeBuf[kCharBufSize]; + unsigned int fCharOfsBuf[kCharBufSize]; + XMLFileLoc fCurCol; + XMLFileLoc fCurLine; + XMLRecognizer::Encodings fEncoding; + XMLCh* fEncodingStr; + bool fForcedEncoding; + bool fNoMore; + XMLCh* fPublicId; + XMLSize_t fRawBufIndex; + XMLByte fRawByteBuf[kRawBufSize]; + XMLSize_t fRawBytesAvail; + XMLSize_t fLowWaterMark; + XMLSize_t fReaderNum; + RefFrom fRefFrom; + bool fSentTrailingSpace; + Sources fSource; + XMLFilePos fSrcOfsBase; + bool fSrcOfsSupported; + bool fCalculateSrcOfs; + XMLCh* fSystemId; + BinInputStream* fStream; + bool fSwapped; + bool fThrowAtEnd; + XMLTranscoder* fTranscoder; + Types fType; + XMLByte* fgCharCharsTable; + bool fNEL; + XMLVersion fXMLVersion; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// XMLReader: Public, query methods +// --------------------------------------------------------------------------- +inline bool XMLReader::isNameChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gNameCharMask) != 0); +} + +inline bool XMLReader::isNCNameChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gNCNameCharMask) != 0); +} + +inline bool XMLReader::isPlainContentChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gPlainContentCharMask) != 0); +} + + +inline bool XMLReader::isFirstNameChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gFirstNameCharMask) != 0); +} + +inline bool XMLReader::isFirstNCNameChar(const XMLCh toCheck) const +{ + return (((fgCharCharsTable[toCheck] & gFirstNameCharMask) != 0) + && (toCheck != chColon)); +} + +inline bool XMLReader::isSpecialStartTagChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gSpecialStartTagCharMask) != 0); +} + +inline bool XMLReader::isXMLChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gXMLCharMask) != 0); +} + +inline bool XMLReader::isXMLLetter(const XMLCh toCheck) const +{ + return (((fgCharCharsTable[toCheck] & gFirstNameCharMask) != 0) + && (toCheck != chColon) && (toCheck != chUnderscore)); +} + +inline bool XMLReader::isWhitespace(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gWhitespaceCharMask) != 0); +} + +inline bool XMLReader::isControlChar(const XMLCh toCheck) const +{ + return ((fgCharCharsTable[toCheck] & gControlCharMask) != 0); +} + +// --------------------------------------------------------------------------- +// XMLReader: Buffer management methods +// --------------------------------------------------------------------------- +inline XMLSize_t XMLReader::charsLeftInBuffer() const +{ + return fCharsAvail - fCharIndex; +} + + +// --------------------------------------------------------------------------- +// XMLReader: Getter methods +// --------------------------------------------------------------------------- +inline XMLFileLoc XMLReader::getColumnNumber() const +{ + return fCurCol; +} + +inline const XMLCh* XMLReader::getEncodingStr() const +{ + return fEncodingStr; +} + +inline XMLFileLoc XMLReader::getLineNumber() const +{ + return fCurLine; +} + +inline bool XMLReader::getNoMoreFlag() const +{ + return fNoMore; +} + +inline const XMLCh* XMLReader::getPublicId() const +{ + return fPublicId; +} + +inline XMLSize_t XMLReader::getReaderNum() const +{ + return fReaderNum; +} + +inline XMLReader::RefFrom XMLReader::getRefFrom() const +{ + return fRefFrom; +} + +inline XMLReader::Sources XMLReader::getSource() const +{ + return fSource; +} + +inline const XMLCh* XMLReader::getSystemId() const +{ + return fSystemId; +} + +inline bool XMLReader::getThrowAtEnd() const +{ + return fThrowAtEnd; +} + +inline XMLReader::Types XMLReader::getType() const +{ + return fType; +} + +// --------------------------------------------------------------------------- +// XMLReader: Setter methods +// --------------------------------------------------------------------------- +inline void XMLReader::setReaderNum(const XMLSize_t newNum) +{ + fReaderNum = newNum; +} + +inline void XMLReader::setThrowAtEnd(const bool newValue) +{ + fThrowAtEnd = newValue; +} + +inline void XMLReader::setXMLVersion(const XMLVersion version) +{ + fXMLVersion = version; + if (version == XMLV1_1) { + fNEL = true; + fgCharCharsTable = XMLChar1_1::fgCharCharsTable1_1; + } + else { + fNEL = XMLChar1_0::enableNEL; + fgCharCharsTable = XMLChar1_0::fgCharCharsTable1_0; + } + +} + + + +// --------------------------------------------------------------------------- +// +// XMLReader: movePlainContentChars() +// +// Move as many plain (no special handling of any sort required) content +// characters as possible from this reader to the supplied destination buffer. +// +// This is THE hottest performance spot in the parser. +// +// --------------------------------------------------------------------------- +inline void XMLReader::movePlainContentChars(XMLBuffer &dest) +{ + const XMLSize_t chunkSize = fCharsAvail - fCharIndex; + const XMLCh* cursor = &fCharBuf[fCharIndex]; + XMLSize_t count=0; + for(;count= fCharsAvail) + { + // If fNoMore is set, then we have nothing else to give + if (fNoMore) + return false; + + // Try to refresh + if (!refreshCharBuffer()) + return false; + } + + // Check the next char + if (fCharBuf[fCharIndex] == chNotToGet) + return false; + + // Its not the one we want to skip so bump the index + chGotten = fCharBuf[fCharIndex++]; + + // Handle end of line normalization and line/col member maintenance. + // + // we can have end-of-line combinations with a leading + // chCR(xD), chLF(xA), chNEL(x85), or chLineSeparator(x2028) + // + // 0000000000001101 chCR + // 0000000000001010 chLF + // 0000000010000101 chNEL + // 0010000000101000 chLineSeparator + // ----------------------- + // 1101111101010000 == ~(chCR|chLF|chNEL|chLineSeparator) + // + // if the result of the logical-& operation is + // true : 'curCh' can not be chCR, chLF, chNEL or chLineSeparator + // false : 'curCh' can be chCR, chLF, chNEL or chLineSeparator + // + if ( chGotten & (XMLCh) ~(chCR|chLF|chNEL|chLineSeparator) ) + { + fCurCol++; + } else + { + handleEOL(chGotten, false); + } + + return true; +} + +// --------------------------------------------------------------------------- +// XMLReader: getNextChar() method inlined for speed +// --------------------------------------------------------------------------- +inline bool XMLReader::getNextChar(XMLCh& chGotten) +{ + // + // See if there is at least a char in the buffer. Else, do the buffer + // reload logic. + // + if (fCharIndex >= fCharsAvail) + { + // If fNoMore is set, then we have nothing else to give + if (fNoMore) + return false; + + // Try to refresh + if (!refreshCharBuffer()) + return false; + } + + chGotten = fCharBuf[fCharIndex++]; + + // Handle end of line normalization and line/col member maintenance. + // + // we can have end-of-line combinations with a leading + // chCR(xD), chLF(xA), chNEL(x85), or chLineSeparator(x2028) + // + // 0000000000001101 chCR + // 0000000000001010 chLF + // 0000000010000101 chNEL + // 0010000000101000 chLineSeparator + // ----------------------- + // 1101111101010000 == ~(chCR|chLF|chNEL|chLineSeparator) + // + // if the result of the logical-& operation is + // true : 'curCh' can not be chCR, chLF, chNEL or chLineSeparator + // false : 'curCh' can be chCR, chLF, chNEL or chLineSeparator + // + if ( chGotten & (XMLCh) ~(chCR|chLF|chNEL|chLineSeparator) ) + { + fCurCol++; + } else + { + handleEOL(chGotten, false); + } + + return true; +} + + +// --------------------------------------------------------------------------- +// XMLReader: peekNextChar() method inlined for speed +// --------------------------------------------------------------------------- +inline bool XMLReader::peekNextChar(XMLCh& chGotten) +{ + // + // If there is something still in the buffer, get it. Else do the reload + // scenario. + // + if (fCharIndex >= fCharsAvail) + { + // Try to refresh the buffer + if (!refreshCharBuffer()) + { + chGotten = chNull; + return false; + } + } + + chGotten = fCharBuf[fCharIndex]; + + // + // Even though we are only peeking, we have to act the same as the + // normal char get method in regards to newline normalization, though + // its not as complicated as the actual character getting method's. + // + if ((chGotten == chCR || (fNEL && (chGotten == chNEL || chGotten == chLineSeparator))) + && (fSource == Source_External)) + chGotten = chLF; + + return true; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XMLScanner.cpp b/include/xercesc/internal/XMLScanner.cpp new file mode 100644 index 0000000..a02cea8 --- /dev/null +++ b/include/xercesc/internal/XMLScanner.cpp @@ -0,0 +1,2398 @@ +/* + * 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: XMLScanner.cpp 882548 2009-11-20 13:44:14Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local static data +// --------------------------------------------------------------------------- +static XMLUInt32 gScannerId = 0; +static XMLMutex* sScannerMutex = 0; +static XMLMsgLoader* gMsgLoader = 0; + +void XMLInitializer::initializeXMLScanner() +{ + gMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain); + + if (!gMsgLoader) + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); + + sScannerMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager); +} + +void XMLInitializer::terminateXMLScanner() +{ + delete gMsgLoader; + gMsgLoader = 0; + + delete sScannerMutex; + sScannerMutex = 0; +} + +// +// +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ReaderMgrResetType; + + +// --------------------------------------------------------------------------- +// XMLScanner: Constructors and Destructor +// --------------------------------------------------------------------------- +XMLScanner::XMLScanner(XMLValidator* const valToAdopt, + GrammarResolver* const grammarResolver, + MemoryManager* const manager) + : fBufferSize(1024 * 1024) + , fLowWaterMark (100) + , fStandardUriConformant(false) + , fCalculateSrcOfs(false) + , fDoNamespaces(false) + , fExitOnFirstFatal(true) + , fValidationConstraintFatal(false) + , fInException(false) + , fStandalone(false) + , fHasNoDTD(true) + , fValidate(false) + , fValidatorFromUser(false) + , fDoSchema(false) + , fSchemaFullChecking(false) + , fIdentityConstraintChecking(true) + , fToCacheGrammar(false) + , fUseCachedGrammar(false) + , fLoadExternalDTD(true) + , fLoadSchema(true) + , fNormalizeData(true) + , fGenerateSyntheticAnnotations(false) + , fValidateAnnotations(false) + , fIgnoreCachedDTD(false) + , fIgnoreAnnotations(false) + , fDisableDefaultEntityResolution(false) + , fSkipDTDValidation(false) + , fHandleMultipleImports(false) + , fErrorCount(0) + , fEntityExpansionLimit(0) + , fEntityExpansionCount(0) + , fEmptyNamespaceId(0) + , fUnknownNamespaceId(0) + , fXMLNamespaceId(0) + , fXMLNSNamespaceId(0) + , fSchemaNamespaceId(0) + , fUIntPool(0) + , fUIntPoolRow(0) + , fUIntPoolCol(0) + , fUIntPoolRowTotal(2) + , fScannerId(0) + , fSequenceId(0) + , fAttrList(0) + , fAttrDupChkRegistry(0) + , fDocHandler(0) + , fDocTypeHandler(0) + , fEntityHandler(0) + , fErrorReporter(0) + , fErrorHandler(0) + , fPSVIHandler(0) + , fValidationContext(0) + , fEntityDeclPoolRetrieved(false) + , fReaderMgr(manager) + , fValidator(valToAdopt) + , fValScheme(Val_Never) + , fGrammarResolver(grammarResolver) + , fGrammarPoolMemoryManager(grammarResolver->getGrammarPoolMemoryManager()) + , fGrammar(0) + , fRootGrammar(0) + , fURIStringPool(0) + , fRootElemName(0) + , fExternalSchemaLocation(0) + , fExternalNoNamespaceSchemaLocation(0) + , fSecurityManager(0) + , fXMLVersion(XMLReader::XMLV1_0) + , fMemoryManager(manager) + , fBufMgr(manager) + , fAttNameBuf(1023, manager) + , fAttValueBuf(1023, manager) + , fCDataBuf(1023, manager) + , fQNameBuf(1023, manager) + , fPrefixBuf(1023, manager) + , fURIBuf(1023, manager) + , fWSNormalizeBuf(1023, manager) + , fElemStack(manager) +{ + CleanupType cleanup(this, &XMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XMLScanner::XMLScanner( XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errHandler + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) + + : fBufferSize(1024 * 1024) + , fLowWaterMark (100) + , fStandardUriConformant(false) + , fCalculateSrcOfs(false) + , fDoNamespaces(false) + , fExitOnFirstFatal(true) + , fValidationConstraintFatal(false) + , fInException(false) + , fStandalone(false) + , fHasNoDTD(true) + , fValidate(false) + , fValidatorFromUser(false) + , fDoSchema(false) + , fSchemaFullChecking(false) + , fIdentityConstraintChecking(true) + , fToCacheGrammar(false) + , fUseCachedGrammar(false) + , fLoadExternalDTD(true) + , fLoadSchema(true) + , fNormalizeData(true) + , fGenerateSyntheticAnnotations(false) + , fValidateAnnotations(false) + , fIgnoreCachedDTD(false) + , fIgnoreAnnotations(false) + , fDisableDefaultEntityResolution(false) + , fSkipDTDValidation(false) + , fHandleMultipleImports(false) + , fErrorCount(0) + , fEntityExpansionLimit(0) + , fEntityExpansionCount(0) + , fEmptyNamespaceId(0) + , fUnknownNamespaceId(0) + , fXMLNamespaceId(0) + , fXMLNSNamespaceId(0) + , fSchemaNamespaceId(0) + , fUIntPool(0) + , fUIntPoolRow(0) + , fUIntPoolCol(0) + , fUIntPoolRowTotal(2) + , fScannerId(0) + , fSequenceId(0) + , fAttrList(0) + , fAttrDupChkRegistry(0) + , fDocHandler(docHandler) + , fDocTypeHandler(docTypeHandler) + , fEntityHandler(entityHandler) + , fErrorReporter(errHandler) + , fErrorHandler(0) + , fPSVIHandler(0) + , fValidationContext(0) + , fEntityDeclPoolRetrieved(false) + , fReaderMgr(manager) + , fValidator(valToAdopt) + , fValScheme(Val_Never) + , fGrammarResolver(grammarResolver) + , fGrammarPoolMemoryManager(grammarResolver->getGrammarPoolMemoryManager()) + , fGrammar(0) + , fRootGrammar(0) + , fURIStringPool(0) + , fRootElemName(0) + , fExternalSchemaLocation(0) + , fExternalNoNamespaceSchemaLocation(0) + , fSecurityManager(0) + , fXMLVersion(XMLReader::XMLV1_0) + , fMemoryManager(manager) + , fBufMgr(manager) + , fAttNameBuf(1023, manager) + , fAttValueBuf(1023, manager) + , fCDataBuf(1023, manager) + , fQNameBuf(1023, manager) + , fPrefixBuf(1023, manager) + , fURIBuf(1023, manager) + , fWSNormalizeBuf(1023, manager) + , fElemStack(manager) +{ + CleanupType cleanup(this, &XMLScanner::cleanUp); + + try + { + commonInit(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XMLScanner::~XMLScanner() +{ + cleanUp(); +} + +void XMLScanner::resetCachedGrammar () +{ +} + +void XMLScanner::setValidator(XMLValidator* const valToAdopt) +{ + if (fValidatorFromUser) + delete fValidator; + fValidator = valToAdopt; + fValidatorFromUser = true; + initValidator(fValidator); +} + + + +// --------------------------------------------------------------------------- +// XMLScanner: Main entry point to scan a document +// --------------------------------------------------------------------------- +void XMLScanner::scanDocument( const XMLCh* const systemId) +{ + // First we try to parse it as a URL. If that fails, we assume its + // a file and try it that way. + InputSource* srcToUse = 0; + try + { + // Create a temporary URL. Since this is the primary document, + // it has to be fully qualified. If not, then assume we are just + // mistaking a file for a URL. + XMLURL tmpURL(fMemoryManager); + + if (XMLURL::parse(systemId, tmpURL)) { + + if (tmpURL.isRelative()) { + if (!fStandardUriConformant) + srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager); + else { + // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr + // emit the error directly + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return; + } + } + else + { + if (fStandardUriConformant && tmpURL.hasInvalidChar()) { + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return; + } + srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager); + } + } + else { + + if (!fStandardUriConformant) + srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager); + else { + // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr + // emit the error directly + // lazy bypass ... since all MalformedURLException are fatal, no need to check the type + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return; + } + } + } + catch(const XMLException& excToCatch) + { + // For any other XMLException, + // emit the error and catch any user exception thrown from here. + fInException = true; + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + return; + } + + Janitor janSrc(srcToUse); + scanDocument(*srcToUse); +} + +void XMLScanner::scanDocument( const char* const systemId) +{ + // We just delegate this to the XMLCh version after transcoding + XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager); + ArrayJanitor janBuf(tmpBuf, fMemoryManager); + scanDocument(tmpBuf); +} + + +// This method begins a progressive parse. It scans through the prolog and +// returns a token to be used on subsequent scanNext() calls. If the return +// value is true, then the token is legal and ready for further use. If it +// returns false, then the scan of the prolog failed and the token is not +// going to work on subsequent scanNext() calls. +bool XMLScanner::scanFirst( const XMLCh* const systemId + , XMLPScanToken& toFill) +{ + // First we try to parse it as a URL. If that fails, we assume its + // a file and try it that way. + InputSource* srcToUse = 0; + try + { + // Create a temporary URL. Since this is the primary document, + // it has to be fully qualified. If not, then assume we are just + // mistaking a file for a URL. + XMLURL tmpURL(fMemoryManager); + if (XMLURL::parse(systemId, tmpURL)) { + if (tmpURL.isRelative()) { + if (!fStandardUriConformant) + srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager); + else { + // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr + // emit the error directly + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return false; + } + } + else + { + if (fStandardUriConformant && tmpURL.hasInvalidChar()) { + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return false; + } + srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager); + } + } + else { + if (!fStandardUriConformant) + srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager); + else { + // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr + // emit the error directly + // lazy bypass ... since all MalformedURLException are fatal, no need to check the type + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return false; + } + } + } + catch(const XMLException& excToCatch) + { + // For any other XMLException, + // emit the error and catch any user exception thrown from here. + fInException = true; + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + return false; + } + + Janitor janSrc(srcToUse); + return scanFirst(*srcToUse, toFill); +} + +bool XMLScanner::scanFirst( const char* const systemId + , XMLPScanToken& toFill) +{ + // We just delegate this to the XMLCh version after transcoding + XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager); + ArrayJanitor janBuf(tmpBuf, fMemoryManager); + return scanFirst(tmpBuf, toFill); +} + +bool XMLScanner::scanFirst( const InputSource& src + , XMLPScanToken& toFill) +{ + // Bump up the sequence id for this new scan cycle. This will invalidate + // any previous tokens we've returned. + fSequenceId++; + + ReaderMgrResetType resetReaderMgr(&fReaderMgr, &ReaderMgr::reset); + + // Reset the scanner and its plugged in stuff for a new run. This + // resets all the data structures, creates the initial reader and + // pushes it on the stack, and sets up the base document path + scanReset(src); + + // If we have a document handler, then call the start document + if (fDocHandler) + fDocHandler->startDocument(); + + try + { + // Scan the prolog part, which is everything before the root element + // including the DTD subsets. This is all that is done on the scan + // first. + scanProlog(); + + // If we got to the end of input, then its not a valid XML file. + // Else, go on to scan the content. + if (fReaderMgr.atEOF()) + { + emitError(XMLErrs::EmptyMainEntity); + } + } + // NOTE: + // + // In all of the error processing below, the emitError() call MUST come + // before the flush of the reader mgr, or it will fail because it tries + // to find out the position in the XML source of the error. + catch(const XMLErrs::Codes) + { + // This is a 'first failure' exception so return failure + return false; + } + catch(const XMLValid::Codes) + { + // This is a 'first fatal error' type exit, return failure + return false; + } + catch(const XMLException& excToCatch) + { + // Emit the error and catch any user exception thrown from here. Make + // sure in all cases we flush the reader manager. + fInException = true; + try + { + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + return false; + } + catch(const OutOfMemoryException&) + { + // This is a special case for out-of-memory + // conditions, because resetting the ReaderMgr + // can be problematic. + resetReaderMgr.release(); + + throw; + } + + // Fill in the caller's token to make it legal and return success + toFill.set(fScannerId, fSequenceId); + + // Release the object that will reset the ReaderMgr, since there's + // more to scan. + resetReaderMgr.release(); + + return true; +} + + +void XMLScanner::scanReset(XMLPScanToken& token) +{ + // Make sure this token is still legal + if (!isLegalToken(token)) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager); + + // Reset the reader manager + fReaderMgr.reset(); + + // And invalidate any tokens by bumping our sequence number + fSequenceId++; + + // Reset our error count + fErrorCount = 0; +} + +void XMLScanner::setParseSettings(XMLScanner* const refScanner) +{ + setDocHandler(refScanner->getDocHandler()); + setDocTypeHandler(refScanner->getDocTypeHandler()); + setErrorHandler(refScanner->getErrorHandler()); + setErrorReporter(refScanner->getErrorReporter()); + setEntityHandler(refScanner->getEntityHandler()); + setDoNamespaces(refScanner->getDoNamespaces()); + setDoSchema(refScanner->getDoSchema()); + setCalculateSrcOfs(refScanner->getCalculateSrcOfs()); + setStandardUriConformant(refScanner->getStandardUriConformant()); + setExitOnFirstFatal(refScanner->getExitOnFirstFatal()); + setValidationConstraintFatal(refScanner->getValidationConstraintFatal()); + setIdentityConstraintChecking(refScanner->getIdentityConstraintChecking()); + setValidationSchemaFullChecking(refScanner->getValidationSchemaFullChecking()); + cacheGrammarFromParse(refScanner->isCachingGrammarFromParse()); + useCachedGrammarInParse(refScanner->isUsingCachedGrammarInParse()); + setLoadExternalDTD(refScanner->getLoadExternalDTD()); + setLoadSchema(refScanner->getLoadSchema()); + setNormalizeData(refScanner->getNormalizeData()); + setExternalSchemaLocation(refScanner->getExternalSchemaLocation()); + setExternalNoNamespaceSchemaLocation(refScanner->getExternalNoNamespaceSchemaLocation()); + setValidationScheme(refScanner->getValidationScheme()); + setSecurityManager(refScanner->getSecurityManager()); + setPSVIHandler(refScanner->getPSVIHandler()); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Private helper methods. +// --------------------------------------------------------------------------- + +// This method handles the common initialization, to avoid having to do +// it redundantly in multiple constructors. +void XMLScanner::commonInit() +{ + // We have to do a little init that involves statics, so we have to + // use the mutex to protect it. + { + XMLMutexLock lockInit(sScannerMutex); + + // And assign ourselves the next available scanner id + fScannerId = ++gScannerId; + } + + // Create the attribute list, which is used to store attribute values + // during start tag processing. Give it a reasonable initial size that + // will serve for most folks, though it will grow as required. + fAttrList = new (fMemoryManager) RefVectorOf(32, true, fMemoryManager); + + // Create the id ref list. This is used to enforce XML 1.0 ID ref + // semantics, i.e. all id refs must refer to elements that exist + fValidationContext = new (fMemoryManager) ValidationContextImpl(fMemoryManager); + fValidationContext->setElemStack(&fElemStack); + fValidationContext->setScanner(this); + + // Create the GrammarResolver + //fGrammarResolver = new GrammarResolver(); + + // create initial, 64-element, fUIntPool + fUIntPool = (unsigned int **)fMemoryManager->allocate(sizeof(unsigned int *) *fUIntPoolRowTotal); + memset(fUIntPool, 0, sizeof(unsigned int *) * fUIntPoolRowTotal); + fUIntPool[0] = (unsigned int *)fMemoryManager->allocate(sizeof(unsigned int) << 6); + memset(fUIntPool[0], 0, sizeof(unsigned int) << 6); + + // Register self as handler for XMLBufferFull events on the CDATA buffer + fCDataBuf.setFullHandler(this, fBufferSize); + + if (fValidator) { + fValidatorFromUser = true; + initValidator(fValidator); + } +} + +void XMLScanner::cleanUp() +{ + delete fAttrList; + delete fAttrDupChkRegistry; + delete fValidationContext; + fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName; + fMemoryManager->deallocate(fExternalSchemaLocation);//delete [] fExternalSchemaLocation; + fMemoryManager->deallocate(fExternalNoNamespaceSchemaLocation);//delete [] fExternalNoNamespaceSchemaLocation; + // delete fUIntPool + if (fUIntPool) + { + for (unsigned int i=0; i<=fUIntPoolRow; i++) + { + fMemoryManager->deallocate(fUIntPool[i]); + } + fMemoryManager->deallocate(fUIntPool); + } +} + +void XMLScanner::initValidator(XMLValidator* theValidator) { + + // Tell the validator about the stuff it needs to know in order to + // do its work. + theValidator->setScannerInfo(this, &fReaderMgr, &fBufMgr); + theValidator->setErrorReporter(fErrorReporter); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Error emitting methods +// --------------------------------------------------------------------------- + +// These methods are called whenever the scanner wants to emit an error. +// It handles getting the message loaded, doing token replacement, etc... +// and then calling the error handler, if its installed. +bool XMLScanner::emitErrorWillThrowException(const XMLErrs::Codes toEmit) +{ + if (XMLErrs::isFatal(toEmit) && fExitOnFirstFatal && !fInException) + return true; + return false; +} + +void XMLScanner::emitError(const XMLErrs::Codes toEmit) +{ + // Bump the error count if it is not a warning + if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + incrementErrorCount(); + + if (fErrorReporter) + { + // Load the message into a local for display + const XMLSize_t msgSize = 1023; + XMLCh errText[msgSize + 1]; + + if (!gMsgLoader->loadMsg(toEmit, errText, msgSize)) + { + // Probably should load a default msg here + } + + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + toEmit + , XMLUni::fgXMLErrDomain + , XMLErrs::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (emitErrorWillThrowException(toEmit)) + throw toEmit; +} + +void XMLScanner::emitError( const XMLErrs::Codes toEmit + , const XMLCh* const text1 + , const XMLCh* const text2 + , const XMLCh* const text3 + , const XMLCh* const text4) +{ + // Bump the error count if it is not a warning + if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + incrementErrorCount(); + + if (fErrorReporter) + { + // Load the message into alocal and replace any tokens found in + // the text. + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager)) + { + // Should probably load a default message here + } + + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + toEmit + , XMLUni::fgXMLErrDomain + , XMLErrs::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (emitErrorWillThrowException(toEmit)) + throw toEmit; +} + +void XMLScanner::emitError( const XMLErrs::Codes toEmit + , const char* const text1 + , const char* const text2 + , const char* const text3 + , const char* const text4) +{ + // Bump the error count if it is not a warning + if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + incrementErrorCount(); + + if (fErrorReporter) + { + // Load the message into alocal and replace any tokens found in + // the text. + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager)) + { + // Should probably load a default message here + } + + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + toEmit + , XMLUni::fgXMLErrDomain + , XMLErrs::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (emitErrorWillThrowException(toEmit)) + throw toEmit; +} + +void XMLScanner::emitError( const XMLErrs::Codes toEmit + , const XMLExcepts::Codes originalExceptCode + , const XMLCh* const text1 + , const XMLCh* const text2 + , const XMLCh* const text3 + , const XMLCh* const text4) +{ + // Bump the error count if it is not a warning + if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) + incrementErrorCount(); + + if (fErrorReporter) + { + // Load the message into alocal and replace any tokens found in + // the text. + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + + if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager)) + { + // Should probably load a default message here + } + + // Create a LastExtEntityInfo structure and get the reader manager + // to fill it in for us. This will give us the information about + // the last reader on the stack that was an external entity of some + // sort (i.e. it will ignore internal entities. + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + fErrorReporter->error + ( + originalExceptCode + , XMLUni::fgExceptDomain //fgXMLErrDomain + , XMLErrs::errorType(toEmit) + , errText + , lastInfo.systemId + , lastInfo.publicId + , lastInfo.lineNumber + , lastInfo.colNumber + ); + } + + // Bail out if its fatal an we are to give up on the first fatal error + if (emitErrorWillThrowException(toEmit)) + throw toEmit; +} + +// --------------------------------------------------------------------------- +// XMLScanner: Getter methods +// --------------------------------------------------------------------------- + +// This method allows the caller to query the current location of the scanner. +// It will return the sys/public ids of the current entity, and the line/col +// position within it. +// +// NOTE: This API returns the location with the last external file. So if its +// currently scanning an entity, the position returned will be the end of +// the entity reference in the file that had the reference. +// +/*bool +XMLScanner::getLastExtLocation( XMLCh* const sysIdToFill + , const unsigned int maxSysIdChars + , XMLCh* const pubIdToFill + , const unsigned int maxPubIdChars + , XMLSSize_t& lineToFill + , XMLSSize_t& colToFill) const +{ + // Create a local info object and get it filled in by the reader manager + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + + // Fill in the line and column number + lineToFill = lastInfo.lineNumber; + colToFill = lastInfo.colNumber; + + // And copy over as much of the ids as will fit + sysIdToFill[0] = 0; + if (lastInfo.systemId) + { + if (XMLString::stringLen(lastInfo.systemId) > maxSysIdChars) + return false; + XMLString::copyString(sysIdToFill, lastInfo.systemId); + } + + pubIdToFill[0] = 0; + if (lastInfo.publicId) + { + if (XMLString::stringLen(lastInfo.publicId) > maxPubIdChars) + return false; + XMLString::copyString(pubIdToFill, lastInfo.publicId); + } + return true; +}*/ + + +// --------------------------------------------------------------------------- +// XMLScanner: Private scanning methods +// --------------------------------------------------------------------------- + +// This method is called after the end of the root element, to handle +// any miscellaneous stuff hanging around. +void XMLScanner::scanMiscellaneous() +{ + // Get a buffer for this work + XMLBufBid bbCData(&fBufMgr); + + while (true) + { + try + { + const XMLCh nextCh = fReaderMgr.peekNextChar(); + + // Watch for end of file and break out + if (!nextCh) + break; + + if (nextCh == chOpenAngle) + { + if (checkXMLDecl(true)) + { + // Can't have an XML decl here + emitError(XMLErrs::NotValidAfterContent); + fReaderMgr.skipPastChar(chCloseAngle); + } + else if (fReaderMgr.skippedString(XMLUni::fgPIString)) + { + scanPI(); + } + else if (fReaderMgr.skippedString(XMLUni::fgCommentString)) + { + scanComment(); + } + else + { + // This can't be possible, so just give up + emitError(XMLErrs::ExpectedCommentOrPI); + fReaderMgr.skipPastChar(chCloseAngle); + } + } + else if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + // If we have a doc handler, then gather up the spaces and + // call back. Otherwise, just skip over whitespace. + if (fDocHandler) + { + fReaderMgr.getSpaces(bbCData.getBuffer()); + fDocHandler->ignorableWhitespace + ( + bbCData.getRawBuffer() + , bbCData.getLen() + , false + ); + } + else + { + fReaderMgr.skipPastSpaces(); + } + } + else + { + emitError(XMLErrs::ExpectedCommentOrPI); + fReaderMgr.skipPastChar(chCloseAngle); + } + } + catch(const EndOfEntityException&) + { + // Some entity leaked out of the content part of the document. Issue + // a warning and keep going. + emitError(XMLErrs::EntityPropogated); + } + } +} + + +// Scans a PI and calls the appropriate callbacks. At entry we have just +// scanned the ' to be a termination of the target + if (fReaderMgr.skippedChar(chCloseAngle)) + break; + } + + // Check for correct surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + if (gotLeadingSurrogate) + { + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + emitError(XMLErrs::Expected2ndSurrogateChar); + } + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) { + + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + + gotLeadingSurrogate = false; + } + + bbTarget.append(nextCh); + } + } + else + { + // No target, but make sure its terminated ok + if (!fReaderMgr.skippedChar(chQuestion)) + { + emitError(XMLErrs::UnterminatedPI); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError(XMLErrs::UnterminatedPI); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + } + + // Point the target pointer at the raw data + targetPtr = bbTarget.getRawBuffer(); + + // If we have a handler, then call it + if (fDocHandler) + { + fDocHandler->docPI + ( + namePtr + , targetPtr + ); + } + + //mark PI is seen within the current element + if (! fElemStack.isEmpty()) + fElemStack.setCommentOrPISeen(); + +} + +// Scans all the input from the start of the file to the root element. +// There does not have to be anything in the prolog necessarily, but usually +// there is at least an XMLDecl. +// +// On exit from here we are either at the end of the file or about to read +// the opening < of the root element. +void XMLScanner::scanProlog() +{ + bool sawDocTypeDecl = false; + // Get a buffer for whitespace processing + XMLBufBid bbCData(&fBufMgr); + + // Loop through the prolog. If there is no content, this could go all + // the way to the end of the file. + try + { + while (true) + { + const XMLCh nextCh = fReaderMgr.peekNextChar(); + + if (nextCh == chOpenAngle) + { + // Ok, it could be the xml decl, a comment, the doc type line, + // or the start of the root element. + if (checkXMLDecl(true)) + { + // There shall be at lease --ONE-- space in between + // the tag 'getLineNumber() != 1) + || (curReader->getColumnNumber() != 7)) + { + emitError(XMLErrs::XMLDeclMustBeFirst); + } + + scanXMLDecl(Decl_XML); + } + else if (fReaderMgr.skippedString(XMLUni::fgPIString)) + { + scanPI(); + } + else if (fReaderMgr.skippedString(XMLUni::fgCommentString)) + { + scanComment(); + } + else if (fReaderMgr.skippedString(XMLUni::fgDocTypeString)) + { + if (sawDocTypeDecl) { + emitError(XMLErrs::DuplicateDocTypeDecl); + } + scanDocTypeDecl(); + sawDocTypeDecl = true; + + // if reusing grammar, this has been validated already in first scan + // skip for performance + if (fValidate && fGrammar && !fGrammar->getValidated()) { + // validate the DTD scan so far + fValidator->preContentValidation(fUseCachedGrammar, true); + } + } + else + { + // Assume its the start of the root element + return; + } + } + else if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) + { + // If we have a document handler then gather up the + // whitespace and call back. Otherwise just skip over spaces. + if (fDocHandler) + { + fReaderMgr.getSpaces(bbCData.getBuffer()); + fDocHandler->ignorableWhitespace + ( + bbCData.getRawBuffer() + , bbCData.getLen() + , false + ); + } + else + { + fReaderMgr.skipPastSpaces(); + } + } + else + { + emitError(XMLErrs::InvalidDocumentStructure); + + // Watch for end of file and break out + if (!nextCh) + break; + else + fReaderMgr.skipPastChar(chCloseAngle); + } + + } + } + catch(const EndOfEntityException&) + { + // We should never get an end of entity here. They should only + // occur within the doc type scanning method, and not leak out to + // here. + emitError + ( + XMLErrs::UnexpectedEOE + , "in prolog" + ); + } +} + + +// Scans the line. This stuff is all sequential so we don't +// do any state machine loop here. We just bull straight through it. It ends +// past the closing bracket. If there is a document handler, then its called +// on the XMLDecl callback. +// +// On entry, the ' +// [77] TextDecl::= '' +void XMLScanner::scanXMLDecl(const DeclTypes type) +{ + // Get us some buffers to use + XMLBufBid bbVersion(&fBufMgr); + XMLBufBid bbEncoding(&fBufMgr); + XMLBufBid bbStand(&fBufMgr); + XMLBufBid bbDummy(&fBufMgr); + XMLBufBid bbName(&fBufMgr); + + // We use this little enum and array to keep up with what we found + // and what order we found them in. This lets us get them free form + // without too much overhead, but still know that they were in the + // wrong order. + enum Strings + { + VersionString + , EncodingString + , StandaloneString + , UnknownString + + , StringCount + }; + int flags[StringCount] = { -1, -1, -1, -1 }; + + // Also set up a list of buffers in the right order so that we know + // where to put stuff. + XMLBuffer* buffers[StringCount] ; + buffers[0] = &bbVersion.getBuffer(); + buffers[1] = &bbEncoding.getBuffer(); + buffers[2] = &bbStand.getBuffer(); + buffers[3] = &bbDummy.getBuffer(); + + int curCount = 0; + Strings curString; + XMLBuffer& nameBuf = bbName.getBuffer(); + while (true) + { + // Skip any spaces + bool skippedSomething; + fReaderMgr.skipPastSpaces(skippedSomething, true); + + // If we are looking at a question mark, then break out + if (fReaderMgr.lookingAtChar(chQuestion)) + break; + + // If this is not the first string, then we require the spaces + if (!skippedSomething && curCount) + emitError(XMLErrs::ExpectedWhitespace); + + // Get characters up to the next whitespace or equal's sign. + if (!scanUpToWSOr(nameBuf, chEqual)) + emitError(XMLErrs::ExpectedDeclString); + + // See if it matches any of our expected strings + if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgVersionString)) + curString = VersionString; + else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgEncodingString)) + curString = EncodingString; + else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgStandaloneString)) + curString = StandaloneString; + else + curString = UnknownString; + + // If its an unknown string, then give that error. Else check to + // see if this one has been done already and give that error. + if (curString == UnknownString) + emitError(XMLErrs::ExpectedDeclString, nameBuf.getRawBuffer()); + else if (flags[curString] != -1) + emitError(XMLErrs::DeclStringRep, nameBuf.getRawBuffer()); + else if (flags[curString] == -1) + flags[curString] = ++curCount; + + // Scan for an equal's sign. If we don't find it, issue an error + // but keep trying to go on. + if (!scanEq(true)) + emitError(XMLErrs::ExpectedEqSign); + + // Get a quote string into the buffer for the string that we are + // currently working on. + if (!getQuotedString(*buffers[curString])) + { + emitError(XMLErrs::ExpectedQuotedString); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // And validate the value according which one it was + const XMLCh* rawValue = buffers[curString]->getRawBuffer(); + if (curString == VersionString) + { + if (XMLString::equals(rawValue, XMLUni::fgVersion1_1)) { + if (type == Decl_XML) { + fXMLVersion = XMLReader::XMLV1_1; + fReaderMgr.setXMLVersion(XMLReader::XMLV1_1); + } + else { + if (fXMLVersion != XMLReader::XMLV1_1) + emitError(XMLErrs::UnsupportedXMLVersion, rawValue); + } + } + else if (XMLString::equals(rawValue, XMLUni::fgVersion1_0)) { + if (type == Decl_XML) { + fXMLVersion = XMLReader::XMLV1_0; + fReaderMgr.setXMLVersion(XMLReader::XMLV1_0); + } + } + else + emitError(XMLErrs::UnsupportedXMLVersion, rawValue); + } + else if (curString == EncodingString) + { + if (!XMLString::isValidEncName(rawValue)) + emitError(XMLErrs::BadXMLEncoding, rawValue); + } + else if (curString == StandaloneString) + { + if (XMLString::equals(rawValue, XMLUni::fgYesString)) + fStandalone = true; + else if (XMLString::equals(rawValue, XMLUni::fgNoString)) + fStandalone = false; + else + { + emitError(XMLErrs::BadStandalone); + //if (!XMLString::compareIString(rawValue, XMLUni::fgYesString)) + //else if (!XMLString::compareIString(rawValue, XMLUni::fgNoString)) + if (buffers[curString]->getLen() == 3 && + (((rawValue[0] == chLatin_y) || (rawValue[0] == chLatin_Y)) && + ((rawValue[1] == chLatin_e) || (rawValue[1] == chLatin_E)) && + ((rawValue[2] == chLatin_s) || (rawValue[2] == chLatin_S)))) + fStandalone = true; + else if (buffers[curString]->getLen() == 2 && + (((rawValue[0] == chLatin_n) || (rawValue[0] == chLatin_N)) && + ((rawValue[1] == chLatin_o) || (rawValue[1] == chLatin_O)))) + fStandalone = false; + } + } + } + + // Make sure that the strings present are in order. We don't care about + // which ones are present at this point, just that any there are in the + // right order. + int curTop = 0; + for (int index = VersionString; index < StandaloneString; index++) + { + if (flags[index] != -1) + { + if (flags[index] != curTop + 1) + { + emitError(XMLErrs::DeclStringsInWrongOrder); + break; + } + curTop = flags[index]; + } + } + + // If its an XML decl, the version must be present. + // If its a Text decl, then encoding must be present AND standalone must not be present. + if ((type == Decl_XML) && (flags[VersionString] == -1)) + emitError(XMLErrs::XMLVersionRequired); + else if (type == Decl_Text) { + if (flags[StandaloneString] != -1) + emitError(XMLErrs::StandaloneNotLegal); + if (flags[EncodingString] == -1) + emitError(XMLErrs::EncodingRequired); + } + + if (!fReaderMgr.skippedChar(chQuestion)) + { + emitError(XMLErrs::UnterminatedXMLDecl); + fReaderMgr.skipPastChar(chCloseAngle); + } + else if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError(XMLErrs::UnterminatedXMLDecl); + fReaderMgr.skipPastChar(chCloseAngle); + } + + // Do this before we possibly update the reader with the + // actual encoding string. Otherwise, we will pass the wrong thing + // for the last parameter! + const XMLCh* actualEnc = fReaderMgr.getCurrentEncodingStr(); + + // Ok, we've now seen the real encoding string, if there was one, so + // lets call back on the current reader and tell it what the real + // encoding string was. If it fails, that's because it represents some + // sort of contradiction with the autosensed format, and it keeps the + // original encoding. + // + // NOTE: This can fail for a number of reasons, such as a bogus encoding + // name or because its in flagrant contradiction of the auto-sensed + // format. + if (flags[EncodingString] != -1) + { + if (!fReaderMgr.getCurrentReader()->setEncoding(bbEncoding.getRawBuffer())) + emitError(XMLErrs::ContradictoryEncoding, bbEncoding.getRawBuffer()); + else + actualEnc = bbEncoding.getRawBuffer(); + } + + // If we have a document handler then call the XML Decl callback. + if (type == Decl_XML) + { + if (fDocHandler) + fDocHandler->XMLDecl + ( + bbVersion.getRawBuffer() + , bbEncoding.getRawBuffer() + , bbStand.getRawBuffer() + , actualEnc + ); + } + else if (type == Decl_Text) + { + if (fDocTypeHandler) + fDocTypeHandler->TextDecl + ( + bbVersion.getRawBuffer() + , bbEncoding.getRawBuffer() + ); + } +} + +const XMLCh* XMLScanner::getURIText(const unsigned int uriId) const +{ + if (fURIStringPool->exists(uriId)) { + // Look up the URI in the string pool and return its id + const XMLCh* value = fURIStringPool->getValueForId(uriId); + if (!value) + return XMLUni::fgZeroLenString; + + return value; + } + else + return XMLUni::fgZeroLenString; +} + +bool XMLScanner::getURIText( const unsigned int uriId + , XMLBuffer& uriBufToFill) const +{ + if (fURIStringPool->exists(uriId)) { + // Look up the URI in the string pool and return its id + const XMLCh* value = fURIStringPool->getValueForId(uriId); + if (!value) + return false; + + uriBufToFill.set(value); + return true; + } + else + return false; +} + +bool XMLScanner::checkXMLDecl(bool startWithAngle) { + + // [23] XMLDecl ::= '' + // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') + // + // [3] S ::= (#x20 | #x9 | #xD | #xA)+ + if (startWithAngle) { + if (fReaderMgr.peekString(XMLUni::fgXMLDeclString)) { + if (fReaderMgr.skippedString(XMLUni::fgXMLDeclStringSpace) + || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringHTab) + || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringLF) + || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringCR)) + { + return true; + } + } + else if (fReaderMgr.skippedString(XMLUni::fgXMLDeclStringSpaceU) + || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringHTabU) + || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringLFU) + || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringCRU)) + { + // Just in case, check for upper case. If found, issue + // an error, but keep going. + emitError(XMLErrs::XMLDeclMustBeLowerCase); + return true; + } + } + else { + if (fReaderMgr.peekString(XMLUni::fgXMLString)) { + if (fReaderMgr.skippedString(XMLUni::fgXMLStringSpace) + || fReaderMgr.skippedString(XMLUni::fgXMLStringHTab) + || fReaderMgr.skippedString(XMLUni::fgXMLStringLF) + || fReaderMgr.skippedString(XMLUni::fgXMLStringCR)) + { + return true; + } + } + else if (fReaderMgr.skippedString(XMLUni::fgXMLStringSpaceU) + || fReaderMgr.skippedString(XMLUni::fgXMLStringHTabU) + || fReaderMgr.skippedString(XMLUni::fgXMLStringLFU) + || fReaderMgr.skippedString(XMLUni::fgXMLStringCRU)) + { + // Just in case, check for upper case. If found, issue + // an error, but keep going. + emitError(XMLErrs::XMLDeclMustBeLowerCase); + return true; + } + } + + return false; +} + + +// --------------------------------------------------------------------------- +// XMLScanner: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* XMLScanner::loadGrammar(const XMLCh* const systemId + , const short grammarType + , const bool toCache) +{ + InputSource* srcToUse = 0; + + if (fEntityHandler){ + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr.getLastExtEntityInfo(lastInfo); + XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity, + systemId, 0, XMLUni::fgZeroLenString, lastInfo.systemId, + &fReaderMgr); + srcToUse = fEntityHandler->resolveEntity(&resourceIdentifier); + } + + // First we try to parse it as a URL. If that fails, we assume its + // a file and try it that way. + if (!srcToUse) { + if (fDisableDefaultEntityResolution) + return 0; + + try + { + // Create a temporary URL. Since this is the primary document, + // it has to be fully qualified. If not, then assume we are just + // mistaking a file for a URL. + XMLURL tmpURL(fMemoryManager); + + if (XMLURL::parse(systemId, tmpURL)) { + + if (tmpURL.isRelative()) + { + if (!fStandardUriConformant) + srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager); + else { + // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr + // emit the error directly + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return 0; + } + } + else + { + if (fStandardUriConformant && tmpURL.hasInvalidChar()) { + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return 0; + } + srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager); + } + } + else + { + if (!fStandardUriConformant) + srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager); + else { + // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr + // emit the error directly + // lazy bypass ... since all MalformedURLException are fatal, no need to check the type + MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL); + fInException = true; + emitError + ( + XMLErrs::XMLException_Fatal + , e.getCode() + , e.getMessage() + ); + return 0; + } + } + } + catch(const XMLException& excToCatch) + { + // For any other XMLException, + // emit the error and catch any user exception thrown from here. + fInException = true; + if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) + emitError + ( + XMLErrs::XMLException_Warning + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) + emitError + ( + XMLErrs::XMLException_Fatal + , excToCatch.getCode() + , excToCatch.getMessage() + ); + else + emitError + ( + XMLErrs::XMLException_Error + , excToCatch.getCode() + , excToCatch.getMessage() + ); + return 0; + } + } + + Janitor janSrc(srcToUse); + return loadGrammar(*srcToUse, grammarType, toCache); +} + +Grammar* XMLScanner::loadGrammar(const char* const systemId + , const short grammarType + , const bool toCache) +{ + // We just delegate this to the XMLCh version after transcoding + XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager); + ArrayJanitor janBuf(tmpBuf, fMemoryManager); + return loadGrammar(tmpBuf, grammarType, toCache); +} + + +// --------------------------------------------------------------------------- +// XMLScanner: Setter methods +// --------------------------------------------------------------------------- +void XMLScanner::setURIStringPool(XMLStringPool* const stringPool) +{ + fURIStringPool = stringPool; + fEmptyNamespaceId = fURIStringPool->addOrFind(XMLUni::fgZeroLenString); + fUnknownNamespaceId = fURIStringPool->addOrFind(XMLUni::fgUnknownURIName); + fXMLNamespaceId = fURIStringPool->addOrFind(XMLUni::fgXMLURIName); + fXMLNSNamespaceId = fURIStringPool->addOrFind(XMLUni::fgXMLNSURIName); +} + +// --------------------------------------------------------------------------- +// XMLScanner: Private helper methods +// --------------------------------------------------------------------------- + +/*** + * In reusing grammars (cacheing grammar from parse, or use cached grammar), internal + * dtd is allowed conditionally. + * + * In the case of cacheing grammar from parse, it is NOT allowed. + * + * In the case of use cached grammar, + * if external dtd is present and it is parsed before, then it is not allowed, + * otherwise it is allowed. + * + ***/ +void XMLScanner::checkInternalDTD(bool hasExtSubset + ,const XMLCh* const sysId + ,const XMLCh* const pubId) +{ + if (fToCacheGrammar) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_CantHaveIntSS, fMemoryManager); + + if (fUseCachedGrammar && hasExtSubset && !fIgnoreCachedDTD) + { + InputSource* sysIdSrc = resolveSystemId(sysId, pubId); + if (sysIdSrc) { + Janitor janSysIdSrc(sysIdSrc); + Grammar* grammar = fGrammarResolver->getGrammar(sysIdSrc->getSystemId()); + + if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType) + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_CantHaveIntSS, fMemoryManager); + } + } + } + +} + +// This method is called after the content scan to insure that all the +// ID/IDREF attributes match up (i.e. that all IDREFs refer to IDs.) This is +// an XML 1.0 rule, so we can do here in the core. + +void XMLScanner::checkIDRefs() +{ + // Iterate the id ref list. If we find any entries here which are used + // but not declared, then that's an error. + RefHashTableOfEnumerator refEnum(fValidationContext->getIdRefList(), false, fMemoryManager); + while (refEnum.hasMoreElements()) + { + // Get a ref to the current element + const XMLRefInfo& curRef = refEnum.nextElement(); + + // If its used but not declared, then its an error + if (!curRef.getDeclared() && curRef.getUsed() && fValidate) + fValidator->emitError(XMLValid::IDNotDeclared, curRef.getRefName()); + } +} + + +// This just does a simple check that the passed progressive scan token is +// legal for this scanner. +bool XMLScanner::isLegalToken(const XMLPScanToken& toCheck) +{ + return ((fScannerId == toCheck.fScannerId) + && (fSequenceId == toCheck.fSequenceId)); +} + + +// This method will handle figuring out what the next top level token is +// in the input stream. It will return an enumerated value that indicates +// what it believes the next XML level token must be. It will eat as many +// chars are required to figure out what is next. +XMLScanner::XMLTokens XMLScanner::senseNextToken(XMLSize_t& orgReader) +{ + // Get the next character and use it to guesstimate what the next token + // is going to be. We turn on end of entity exceptions when we do this + // in order to catch the scenario where the current entity ended at + // the > of some markup. + XMLCh nextCh=0; + + XMLReader* curReader=fReaderMgr.getCurrentReader(); + // avoid setting up the ThrowEOEJanitor if we know that we have data in the current reader + if(curReader && curReader->charsLeftInBuffer()>0) + nextCh = fReaderMgr.peekNextChar(); + else + { + ThrowEOEJanitor janMgr(&fReaderMgr, true); + nextCh = fReaderMgr.peekNextChar(); + } + + // If it's not a '<' we must be in content (unless it's a EOF) + // + // This includes entity references '&' of some sort. These must + // be character data because that's the only place a reference can + // occur in content. + if (nextCh != chOpenAngle) + return nextCh?Token_CharData:Token_EOF; + + // Ok it had to have been a '<' character. So get it out of the reader + // and store the reader number where we saw it, passing it back to the + // caller. + fReaderMgr.getNextChar(); + orgReader = fReaderMgr.getCurrentReaderNum(); + + // Ok, so lets go through the things that it could be at this point which + // are all some form of markup. + switch(fReaderMgr.peekNextChar()) + { + case chForwardSlash: + { + fReaderMgr.getNextChar(); + return Token_EndTag; + } + case chBang: + { + static const XMLCh gCDATAStr[] = + { + chBang, chOpenSquare, chLatin_C, chLatin_D, chLatin_A + , chLatin_T, chLatin_A, chNull + }; + + static const XMLCh gCommentString[] = + { + chBang, chDash, chDash, chNull + }; + + if (fReaderMgr.skippedString(gCDATAStr)) + return Token_CData; + + if (fReaderMgr.skippedString(gCommentString)) + return Token_Comment; + + emitError(XMLErrs::ExpectedCommentOrCDATA); + return Token_Unknown; + } + case chQuestion: + { + // It must be a PI + fReaderMgr.getNextChar(); + return Token_PI; + } + } + // Assume its an element name, so return with a start tag token. If it + // turns out not to be, then it will fail when it cannot get a valid tag. + return Token_StartTag; +} + +// --------------------------------------------------------------------------- +// XMLScanner: Private parsing methods +// --------------------------------------------------------------------------- + +// This guy just scans out a single or double quoted string of characters. +// It does not pass any judgement on the contents and assumes that it is +// illegal to have another quote of the same kind inside the string's +// contents. +// +// NOTE: This is for simple stuff like the strings in the XMLDecl which +// cannot have any entities inside them. So this guy does not handle any +// end of entity stuff. +bool XMLScanner::getQuotedString(XMLBuffer& toFill) +{ + // Reset the target buffer + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr.skipIfQuote(quoteCh)) + return false; + + XMLCh nextCh; + // Get another char and see if it matches the starting quote char + while ((nextCh=fReaderMgr.getNextChar())!=quoteCh) + { + // We should never get either an end of file null char here. If we + // do, just fail. It will be handled more gracefully in the higher + // level code that called us. + if (!nextCh) + return false; + + // Else add it to the buffer + toFill.append(nextCh); + } + return true; +} + + +// This method scans a character reference and returns the character that +// was refered to. It assumes that we've already scanned the &# characters +// that prefix the numeric code. +bool XMLScanner::scanCharRef(XMLCh& toFill, XMLCh& second) +{ + bool gotOne = false; + unsigned int value = 0; + + // Set the radix. Its supposed to be a lower case x if hex. But, in + // order to recover well, we check for an upper and put out an error + // for that. + unsigned int radix = 10; + if (fReaderMgr.skippedChar(chLatin_x)) + { + radix = 16; + } + else if (fReaderMgr.skippedChar(chLatin_X)) + { + emitError(XMLErrs::HexRadixMustBeLowerCase); + radix = 16; + } + + while (true) + { + const XMLCh nextCh = fReaderMgr.peekNextChar(); + + // Watch for EOF + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + // Break out on the terminating semicolon + if (nextCh == chSemiColon) + { + fReaderMgr.getNextChar(); + break; + } + + // Convert this char to a binary value, or bail out if its not + // one. + unsigned int nextVal; + if ((nextCh >= chDigit_0) && (nextCh <= chDigit_9)) + nextVal = (unsigned int)(nextCh - chDigit_0); + else if ((nextCh >= chLatin_A) && (nextCh <= chLatin_F)) + nextVal= (unsigned int)(10 + (nextCh - chLatin_A)); + else if ((nextCh >= chLatin_a) && (nextCh <= chLatin_f)) + nextVal = (unsigned int)(10 + (nextCh - chLatin_a)); + else + { + // Return a zero + toFill = 0; + + // If we got at least a sigit, then do an unterminated ref error. + // Else, do an expected a numerical ref thing. + if (gotOne) + emitError(XMLErrs::UnterminatedCharRef); + else + emitError(XMLErrs::ExpectedNumericalCharRef); + + // Return failure + return false; + } + + // Make sure its valid for the radix. If not, then just eat the + // digit and go on after issueing an error. Else, update the + // running value with this new digit. + if (nextVal >= radix) + { + XMLCh tmpStr[2]; + tmpStr[0] = nextCh; + tmpStr[1] = chNull; + emitError(XMLErrs::BadDigitForRadix, tmpStr); + } + else + { + value = (value * radix) + nextVal; + // Guard against overflow. + if (value > 0x10FFFF) { + // Character reference was not in the valid range + emitError(XMLErrs::InvalidCharacterRef); + return false; + } + } + + // Indicate that we got at least one good digit + gotOne = true; + + // And eat the last char + fReaderMgr.getNextChar(); + } + + // Return the char (or chars) + // And check if the character expanded is valid or not + if (value >= 0x10000 && value <= 0x10FFFF) + { + value -= 0x10000; + toFill = XMLCh((value >> 10) + 0xD800); + second = XMLCh((value & 0x3FF) + 0xDC00); + } + else if (value <= 0xFFFD) + { + toFill = XMLCh(value); + second = 0; + if (!fReaderMgr.getCurrentReader()->isXMLChar(toFill) && !fReaderMgr.getCurrentReader()->isControlChar(toFill)) { + // Character reference was not in the valid range + emitError(XMLErrs::InvalidCharacterRef); + return false; + } + } + else { + // Character reference was not in the valid range + emitError(XMLErrs::InvalidCharacterRef); + return false; + } + + return true; +} + + +// We get here after the '' It will calls the appropriate handler with the comment +// text, if one is provided. A comment can be in either the document or +// the DTD, so the fInDocument flag is used to know which handler to send +// it to. +void XMLScanner::scanComment() +{ + + enum States + { + InText + , OneDash + , TwoDashes + }; + + // Get a buffer for this + XMLBufBid bbComment(&fBufMgr); + + // Get the comment text into a temp buffer. Be sure to use temp buffer + // two here, since its to be used for stuff that is potentially longer + // than just a name. + States curState = InText; + bool gotLeadingSurrogate = false; + while (true) + { + // Get the next character + const XMLCh nextCh = fReaderMgr.getNextChar(); + + // Watch for an end of file + if (!nextCh) + { + emitError(XMLErrs::UnterminatedComment); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + // Check for correct surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + if (gotLeadingSurrogate) + emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + if (gotLeadingSurrogate) + { + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + emitError(XMLErrs::Expected2ndSurrogateChar); + } + // Its got to at least be a valid XML character + else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh)) { + + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + + gotLeadingSurrogate = false; + } + + if (curState == InText) + { + // If its a dash, go to OneDash state. Otherwise take as text + if (nextCh == chDash) + curState = OneDash; + else + bbComment.append(nextCh); + } + else if (curState == OneDash) + { + // If its another dash, then we change to the two dashes states. + // Otherwise, we have to put in the deficit dash and the new + // character and go back to InText. + if (nextCh == chDash) + { + curState = TwoDashes; + } + else + { + bbComment.append(chDash); + bbComment.append(nextCh); + curState = InText; + } + } + else if (curState == TwoDashes) + { + // The next character must be the closing bracket + if (nextCh != chCloseAngle) + { + emitError(XMLErrs::IllegalSequenceInComment); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + break; + } + } + + // If we have an available handler, call back with the comment. + if (fDocHandler) + { + fDocHandler->docComment + ( + bbComment.getRawBuffer() + ); + } + + //mark comment is seen within the current element + if (! fElemStack.isEmpty()) + fElemStack.setCommentOrPISeen(); + +} + + +// Most equal signs can have white space around them, so this little guy +// just makes the calling code cleaner by eating whitespace. +bool XMLScanner::scanEq(bool inDecl) +{ + if(inDecl) + { + bool skippedSomething; + fReaderMgr.skipPastSpaces(skippedSomething, inDecl); + if (fReaderMgr.skippedChar(chEqual)) + { + fReaderMgr.skipPastSpaces(skippedSomething, inDecl); + return true; + } + } + else + { + fReaderMgr.skipPastSpaces(); + if (fReaderMgr.skippedChar(chEqual)) + { + fReaderMgr.skipPastSpaces(); + return true; + } + } + return false; +} + + +XMLSize_t +XMLScanner::scanUpToWSOr(XMLBuffer& toFill, const XMLCh chEndChar) +{ + fReaderMgr.getUpToCharOrWS(toFill, chEndChar); + return toFill.getLen(); +} + +unsigned int *XMLScanner::getNewUIntPtr() +{ + // this method hands back a new pointer initialized to 0 + unsigned int *retVal; + if(fUIntPoolCol < 64) + { + retVal = fUIntPool[fUIntPoolRow]+fUIntPoolCol; + fUIntPoolCol++; + return retVal; + } + // time to grow the pool... + if(fUIntPoolRow+1 == fUIntPoolRowTotal) + { + // and time to add some space for new rows: + fUIntPoolRowTotal <<= 1; + unsigned int **newArray = (unsigned int **)fMemoryManager->allocate(sizeof(unsigned int *) * fUIntPoolRowTotal ); + memcpy(newArray, fUIntPool, (fUIntPoolRow+1) * sizeof(unsigned int *)); + fMemoryManager->deallocate(fUIntPool); + fUIntPool = newArray; + // need to 0 out new elements we won't need: + for (unsigned int i=fUIntPoolRow+2; iallocate(sizeof(unsigned int) << 6); + memset(fUIntPool[fUIntPoolRow], 0, sizeof(unsigned int) << 6); + // point to next element + fUIntPoolCol = 1; + return fUIntPool[fUIntPoolRow]; +} + +void XMLScanner::resetUIntPool() +{ + // to reuse the unsigned int pool--and the hashtables that use it-- + // simply reinitialize everything to 0's + for(unsigned int i = 0; i<= fUIntPoolRow; i++) + memset(fUIntPool[i], 0, sizeof(unsigned int) << 6); +} + +void XMLScanner::recreateUIntPool() +{ + // this allows a bloated unsigned int pool to be dispensed with + + // first, delete old fUIntPool + for (unsigned int i=0; i<=fUIntPoolRow; i++) + { + fMemoryManager->deallocate(fUIntPool[i]); + } + fMemoryManager->deallocate(fUIntPool); + + fUIntPoolRow = fUIntPoolCol = 0; + fUIntPoolRowTotal = 2; + fUIntPool = (unsigned int **)fMemoryManager->allocate(sizeof(unsigned int *) * fUIntPoolRowTotal); + fUIntPool[0] = (unsigned int *)fMemoryManager->allocate(sizeof(unsigned int) << 6); + memset(fUIntPool[fUIntPoolRow], 0, sizeof(unsigned int) << 6); + fUIntPool[1] = 0; +} + +unsigned int XMLScanner::resolvePrefix( const XMLCh* const prefix + , const ElemStack::MapModes mode) +{ + // + // If the prefix is empty, and we are in attribute mode, then we assign + // it to the empty namespace because the default namespace does not + // apply to attributes. + // + if (!*prefix) + { + if(mode == ElemStack::Mode_Attribute) + return fEmptyNamespaceId; + } + // Watch for the special namespace prefixes. We always map these to + // special URIs. 'xml' gets mapped to the official URI that its defined + // to map to by the NS spec. xmlns gets mapped to a special place holder + // URI that we define (so that it maps to something checkable.) + else + { + if (XMLString::equals(prefix, XMLUni::fgXMLNSString)) + return fXMLNSNamespaceId; + else if (XMLString::equals(prefix, XMLUni::fgXMLString)) + return fXMLNamespaceId; + } + + // Ask the element stack to search up itself for a mapping for the + // passed prefix. + bool unknown; + unsigned int uriId = fElemStack.mapPrefixToURI(prefix, unknown); + + // If it was unknown, then the URI was faked in but we have to issue an error + if (unknown) + emitError(XMLErrs::UnknownPrefix, prefix); + + // check to see if uriId is empty; in XML 1.1 an emptynamespace is okay unless + // we are trying to use it. + if (*prefix && + mode == ElemStack::Mode_Element && + fXMLVersion != XMLReader::XMLV1_0 && + uriId == fElemStack.getEmptyNamespaceId()) + emitError(XMLErrs::UnknownPrefix, prefix); + + return uriId; +} + +unsigned int +XMLScanner::resolveQName( const XMLCh* const qName + , XMLBuffer& prefixBuf + , const ElemStack::MapModes mode + , int& prefixColonPos) +{ + prefixColonPos = XMLString::indexOf(qName, chColon); + return resolveQNameWithColon(qName, prefixBuf, mode, prefixColonPos); +} + +unsigned int +XMLScanner::resolveQNameWithColon( const XMLCh* const qName + , XMLBuffer& prefixBuf + , const ElemStack::MapModes mode + , const int prefixColonPos) +{ + // Lets split out the qName into a URI and name buffer first. The URI + // can be empty. + if (prefixColonPos == -1) + { + // Its all name with no prefix, so put the whole thing into the name + // buffer. Then map the empty string to a URI, since the empty string + // represents the default namespace. This will either return some + // explicit URI which the default namespace is mapped to, or the + // the default global namespace. + prefixBuf.reset(); + return resolvePrefix(XMLUni::fgZeroLenString, mode); + } + else + { + // Copy the chars up to but not including the colon into the prefix + // buffer. + prefixBuf.set(qName, prefixColonPos); + return resolvePrefix(prefixBuf.getRawBuffer(), mode); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XMLScanner.hpp b/include/xercesc/internal/XMLScanner.hpp new file mode 100644 index 0000000..fc70233 --- /dev/null +++ b/include/xercesc/internal/XMLScanner.hpp @@ -0,0 +1,1432 @@ +/* + * 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: XMLScanner.hpp 882548 2009-11-20 13:44:14Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLSCANNER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class InputSource; +class XMLDocumentHandler; +class XMLEntityHandler; +class ErrorHandler; +class DocTypeHandler; +class XMLPScanToken; +class XMLStringPool; +class Grammar; +class XMLValidator; +class MemoryManager; +class PSVIHandler; + + +struct PSVIElemContext +{ + bool fIsSpecified; + bool fErrorOccurred; + int fElemDepth; + int fFullValidationDepth; + int fNoneValidationDepth; + DatatypeValidator* fCurrentDV; + ComplexTypeInfo* fCurrentTypeInfo; + const XMLCh* fNormalizedValue; +}; + +// This is the mondo scanner class, which does the vast majority of the +// work of parsing. It handles reading in input and spitting out events +// to installed handlers. +class XMLPARSER_EXPORT XMLScanner : public XMemory, public XMLBufferFullHandler +{ +public : + // ----------------------------------------------------------------------- + // Public class types + // + // NOTE: These should really be private, but some of the compilers we + // have to deal with are too stupid to understand this. + // + // DeclTypes + // Used by scanXMLDecl() to know what type of decl it should scan. + // Text decls have slightly different rules from XMLDecls. + // + // EntityExpRes + // These are the values returned from the entity expansion method, + // to indicate how it went. + // + // XMLTokens + // These represent the possible types of input we can get while + // scanning content. + // + // ValScheme + // This indicates what the scanner should do in terms of validation. + // 'Auto' means if there is any int/ext subset, then validate. Else, + // don't. + // ----------------------------------------------------------------------- + enum DeclTypes + { + Decl_Text + , Decl_XML + }; + + enum EntityExpRes + { + EntityExp_Pushed + , EntityExp_Returned + , EntityExp_Failed + }; + + enum XMLTokens + { + Token_CData + , Token_CharData + , Token_Comment + , Token_EndTag + , Token_EOF + , Token_PI + , Token_StartTag + , Token_Unknown + }; + + enum ValSchemes + { + Val_Never + , Val_Always + , Val_Auto + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + XMLScanner + ( + XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + XMLScanner + ( + XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~XMLScanner(); + + + // ----------------------------------------------------------------------- + // Error emitter methods + // ----------------------------------------------------------------------- + bool emitErrorWillThrowException(const XMLErrs::Codes toEmit); + void emitError(const XMLErrs::Codes toEmit); + void emitError + ( + const XMLErrs::Codes toEmit + , const XMLCh* const text1 + , const XMLCh* const text2 = 0 + , const XMLCh* const text3 = 0 + , const XMLCh* const text4 = 0 + ); + void emitError + ( + const XMLErrs::Codes toEmit + , const char* const text1 + , const char* const text2 = 0 + , const char* const text3 = 0 + , const char* const text4 = 0 + ); + void emitError + ( + const XMLErrs::Codes toEmit + , const XMLExcepts::Codes originalErrorCode + , const XMLCh* const text1 = 0 + , const XMLCh* const text2 = 0 + , const XMLCh* const text3 = 0 + , const XMLCh* const text4 = 0 + + ); + + // ----------------------------------------------------------------------- + // Implementation of XMLBufferFullHandler interface + // ----------------------------------------------------------------------- + + virtual bool bufferFull(XMLBuffer& toSend) + { + sendCharData(toSend); + return true; + } + + virtual Grammar::GrammarType getCurrentGrammarType() const; + + // ----------------------------------------------------------------------- + // Public pure virtual methods + // ----------------------------------------------------------------------- + virtual const XMLCh* getName() const = 0; + virtual NameIdPool* getEntityDeclPool() = 0; + virtual const NameIdPool* getEntityDeclPool() const = 0; + virtual void scanDocument + ( + const InputSource& src + ) = 0; + virtual bool scanNext(XMLPScanToken& toFill) = 0; + virtual Grammar* loadGrammar + ( + const InputSource& src + , const short grammarType + , const bool toCache = false + ) = 0; + + virtual void resetCachedGrammar (); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + const XMLDocumentHandler* getDocHandler() const; + XMLDocumentHandler* getDocHandler(); + const DocTypeHandler* getDocTypeHandler() const; + DocTypeHandler* getDocTypeHandler(); + bool getDoNamespaces() const; + ValSchemes getValidationScheme() const; + bool getDoSchema() const; + bool getValidationSchemaFullChecking() const; + bool getIdentityConstraintChecking() const; + const XMLEntityHandler* getEntityHandler() const; + XMLEntityHandler* getEntityHandler(); + const XMLErrorReporter* getErrorReporter() const; + XMLErrorReporter* getErrorReporter(); + const ErrorHandler* getErrorHandler() const; + ErrorHandler* getErrorHandler(); + const PSVIHandler* getPSVIHandler() const; + PSVIHandler* getPSVIHandler(); + bool getExitOnFirstFatal() const; + bool getValidationConstraintFatal() const; + RefHashTableOf* getIDRefList(); + const RefHashTableOf* getIDRefList() const; + + ValidationContext* getValidationContext(); + + bool getInException() const; + /*bool getLastExtLocation + ( + XMLCh* const sysIdToFill + , const unsigned int maxSysIdChars + , XMLCh* const pubIdToFill + , const unsigned int maxPubIdChars + , XMLSSize_t& lineToFill + , XMLSSize_t& colToFill + ) const;*/ + const Locator* getLocator() const; + const ReaderMgr* getReaderMgr() const; + XMLFilePos getSrcOffset() const; + bool getStandalone() const; + const XMLValidator* getValidator() const; + XMLValidator* getValidator(); + int getErrorCount(); + const XMLStringPool* getURIStringPool() const; + XMLStringPool* getURIStringPool(); + bool getHasNoDTD() const; + XMLCh* getExternalSchemaLocation() const; + XMLCh* getExternalNoNamespaceSchemaLocation() const; + SecurityManager* getSecurityManager() const; + bool getLoadExternalDTD() const; + bool getLoadSchema() const; + bool getNormalizeData() const; + bool isCachingGrammarFromParse() const; + bool isUsingCachedGrammarInParse() const; + bool getCalculateSrcOfs() const; + Grammar* getRootGrammar() const; + XMLReader::XMLVersion getXMLVersion() const; + MemoryManager* getMemoryManager() const; + ValueVectorOf* getNamespaceContext() const; + unsigned int getPrefixId(const XMLCh* const prefix) const; + const XMLCh* getPrefixForId(unsigned int prefId) const; + + // Return is a reference so that we can return it as void* from + // getProperty. + // + const XMLSize_t& getLowWaterMark() const; + + bool getGenerateSyntheticAnnotations() const; + bool getValidateAnnotations() const; + bool getIgnoreCachedDTD() const; + bool getIgnoreAnnotations() const; + bool getDisableDefaultEntityResolution() const; + bool getSkipDTDValidation() const; + bool getHandleMultipleImports() const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** + * When an attribute name has no prefix, unlike elements, it is not mapped + * to the global namespace. So, in order to have something to map it to + * for practical purposes, a id for an empty URL is created and used for + * such names. + * + * @return The URL pool id of the URL for an empty URL "". + */ + unsigned int getEmptyNamespaceId() const; + + /** + * When a prefix is found that has not been mapped, an error is issued. + * However, if the parser has been instructed not to stop on the first + * fatal error, it needs to be able to continue. To do so, it will map + * that prefix tot his magic unknown namespace id. + * + * @return The URL pool id of the URL for the unknown prefix + * namespace. + */ + unsigned int getUnknownNamespaceId() const; + + /** + * The prefix 'xml' is a magic prefix, defined by the XML spec and + * requiring no prior definition. This method returns the id for the + * intrinsically defined URL for this prefix. + * + * @return The URL pool id of the URL for the 'xml' prefix. + */ + unsigned int getXMLNamespaceId() const; + + /** + * The prefix 'xmlns' is a magic prefix, defined by the namespace spec + * and requiring no prior definition. This method returns the id for the + * intrinsically defined URL for this prefix. + * + * @return The URL pool id of the URL for the 'xmlns' prefix. + */ + unsigned int getXMLNSNamespaceId() const; + + /** + * This method find the passed URI id in its URI pool and + * copy the text of that URI into the passed buffer. + */ + bool getURIText + ( + const unsigned int uriId + , XMLBuffer& uriBufToFill + ) const; + + const XMLCh* getURIText(const unsigned int uriId) const; + + /* tell if the validator comes from user */ + bool isValidatorFromUser(); + + /* tell if standard URI are forced */ + bool getStandardUriConformant() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void addGlobalPrefix(const XMLCh* const prefix, const unsigned int uriId); + void setDocHandler(XMLDocumentHandler* const docHandler); + void setDocTypeHandler(DocTypeHandler* const docTypeHandler); + void setDoNamespaces(const bool doNamespaces); + void setEntityHandler(XMLEntityHandler* const docTypeHandler); + void setErrorReporter(XMLErrorReporter* const errHandler); + void setErrorHandler(ErrorHandler* const handler); + void setPSVIHandler(PSVIHandler* const handler); + void setURIStringPool(XMLStringPool* const stringPool); + void setExitOnFirstFatal(const bool newValue); + void setValidationConstraintFatal(const bool newValue); + void setValidationScheme(const ValSchemes newScheme); + void setValidator(XMLValidator* const valToAdopt); + void setDoSchema(const bool doSchema); + void setValidationSchemaFullChecking(const bool schemaFullChecking); + void setIdentityConstraintChecking(const bool identityConstraintChecking); + void setHasNoDTD(const bool hasNoDTD); + void cacheGrammarFromParse(const bool newValue); + void useCachedGrammarInParse(const bool newValue); + void setRootElemName(XMLCh* rootElemName); + void setExternalSchemaLocation(const XMLCh* const schemaLocation); + void setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation); + void setExternalSchemaLocation(const char* const schemaLocation); + void setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation); + void setSecurityManager(SecurityManager* const securityManager); + void setLoadExternalDTD(const bool loadDTD); + void setLoadSchema(const bool loadSchema); + void setNormalizeData(const bool normalizeData); + void setCalculateSrcOfs(const bool newValue); + void setParseSettings(XMLScanner* const refScanner); + void setStandardUriConformant(const bool newValue); + void setInputBufferSize(const XMLSize_t bufferSize); + void setLowWaterMark(XMLSize_t newValue); + + void setGenerateSyntheticAnnotations(const bool newValue); + void setValidateAnnotations(const bool newValue); + void setIgnoredCachedDTD(const bool newValue); + void setIgnoreAnnotations(const bool newValue); + void setDisableDefaultEntityResolution(const bool newValue); + void setSkipDTDValidation(const bool newValue); + void setHandleMultipleImports(const bool newValue); + + // ----------------------------------------------------------------------- + // Mutator methods + // ----------------------------------------------------------------------- + void incrementErrorCount(void); // For use by XMLValidator + + // ----------------------------------------------------------------------- + // Document scanning methods + // + // scanDocument() does the entire source document. scanFirst(), + // scanNext(), and scanReset() support a progressive parse. + // ----------------------------------------------------------------------- + void scanDocument + ( + const XMLCh* const systemId + ); + void scanDocument + ( + const char* const systemId + ); + + bool scanFirst + ( + const InputSource& src + , XMLPScanToken& toFill + ); + bool scanFirst + ( + const XMLCh* const systemId + , XMLPScanToken& toFill + ); + bool scanFirst + ( + const char* const systemId + , XMLPScanToken& toFill + ); + + void scanReset(XMLPScanToken& toFill); + + bool checkXMLDecl(bool startWithAngle); + + // ----------------------------------------------------------------------- + // Grammar preparsing methods + // ----------------------------------------------------------------------- + Grammar* loadGrammar + ( + const XMLCh* const systemId + , const short grammarType + , const bool toCache = false + ); + Grammar* loadGrammar + ( + const char* const systemId + , const short grammarType + , const bool toCache = false + ); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + unsigned int resolveQName + ( + const XMLCh* const qName + , XMLBuffer& prefixBufToFill + , const ElemStack::MapModes mode + , int& prefixColonPos + ); + +protected: + // ----------------------------------------------------------------------- + // Protected pure virtual methods + // ----------------------------------------------------------------------- + virtual void scanCDSection() = 0; + virtual void scanCharData(XMLBuffer& toToUse) = 0; + virtual EntityExpRes scanEntityRef + ( + const bool inAttVal + , XMLCh& firstCh + , XMLCh& secondCh + , bool& escaped + ) = 0; + virtual void scanDocTypeDecl() = 0; + virtual void scanReset(const InputSource& src) = 0; + virtual void sendCharData(XMLBuffer& toSend) = 0; + + //return owned by the caller + virtual InputSource* resolveSystemId(const XMLCh* const /*sysId*/ + ,const XMLCh* const /*pubId*/) {return 0;}; + + // ----------------------------------------------------------------------- + // Protected scanning methods + // ----------------------------------------------------------------------- + bool scanCharRef(XMLCh& toFill, XMLCh& second); + void scanComment(); + bool scanEq(bool inDecl = false); + void scanMiscellaneous(); + void scanPI(); + void scanProlog(); + void scanXMLDecl(const DeclTypes type); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void checkInternalDTD(bool hasExtSubset, const XMLCh* const sysId, const XMLCh* const pubId); + void checkIDRefs(); + bool isLegalToken(const XMLPScanToken& toCheck); + XMLTokens senseNextToken(XMLSize_t& orgReader); + void initValidator(XMLValidator* theValidator); + inline void resetValidationContext(); + unsigned int *getNewUIntPtr(); + void resetUIntPool(); + void recreateUIntPool(); + unsigned int resolvePrefix + ( + const XMLCh* const prefix + , const ElemStack::MapModes mode + ); + unsigned int resolveQNameWithColon + ( + const XMLCh* const qName + , XMLBuffer& prefixBufToFill + , const ElemStack::MapModes mode + , const int prefixColonPos + ); + + inline + void setAttrDupChkRegistry + ( + const XMLSize_t &attrNumber + , bool &toUseHashTable + ); + + // ----------------------------------------------------------------------- + // Data members + // + // fBufferSize + // Maximum input buffer size + // + // fLowWaterMark + // The low water mark for the raw byte buffer. + // + // fAttrList + // Every time we get a new element start tag, we have to pass to + // the document handler the attributes found. To make it more + // efficient we keep this ref vector of XMLAttr objects around. We + // just reuse it over and over, allowing it to grow to meet the + // peak need. + // + // fBufMgr + // This is a manager for temporary buffers used during scanning. + // For efficiency we must use a set of static buffers, but we have + // to insure that they are not incorrectly reused. So this manager + // provides the smarts to hand out buffers as required. + // + // fDocHandler + // The client code's document handler. If zero, then no document + // handler callouts are done. We don't adopt it. + // + // fDocTypeHandler + // The client code's document type handler (used by DTD Validator). + // + // fDoNamespaces + // This flag indicates whether the client code wants us to do + // namespaces or not. If the installed validator indicates that it + // has to do namespaces, then this is ignored. + // + // fEntityHandler + // The client code's entity handler. If zero, then no entity handler + // callouts are done. We don't adopt it. + // + // fErrorReporter + // The client code's error reporter. If zero, then no error reporter + // callouts are done. We don't adopt it. + // + // fErrorHandler + // The client code's error handler. Need to store this info for + // Schema parse error handling. + // + // fPSVIHandler + // The client code's PSVI handler. + // + // fExitOnFirstFatal + // This indicates whether we bail out on the first fatal XML error + // or not. It defaults to true, which is the strict XML way, but it + // can be changed. + // + // fValidationConstraintFatal + // This indicates whether we treat validation constraint errors as + // fatal errors or not. It defaults to false, but it can be changed. + // + // fIDRefList + // This is a list of XMLRefInfo objects. This member lets us do all + // needed ID-IDREF balancing checks. + // + // fInException + // To avoid a circular freakout when we catch an exception and emit + // it, which would normally throw again if the 'fail on first error' + // flag is one. + // + // fReaderMgr + // This is the reader manager, from which we get characters. It + // manages the reader stack for us, and provides a lot of convenience + // methods to do specialized checking for chars, sequences of chars, + // skipping chars, etc... + // + // fScannerId + // fSequenceId + // These are used for progressive parsing, to make sure that the + // client code does the right thing at the right time. + // + // fStandalone + // Indicates whether the document is standalone or not. Defaults to + // no, but can be overridden in the XMLDecl. + // + // fHasNoDTD + // Indicates the document has no DTD or has only an internal DTD subset + // which contains no parameter entity references. + // + // fValidate + // Indicates whether any validation should be done. This is defined + // by the existence of a Grammar together with fValScheme. + // + // fValidator + // The installed validator. We look at them via the abstract + // validator interface, and don't know what it actual is. + // Either point to user's installed validator, or fDTDValidator + // or fSchemaValidator. + // + // fValidatorFromUser + // This flag indicates whether the validator was installed from + // user. If false, then the validator was created by the Scanner. + // + // fValScheme + // This is the currently set validation scheme. It defaults to + // 'never', but can be set by the client. + // + // fErrorCount + // The number of errors we've encountered. + // + // fDoSchema + // This flag indicates whether the client code wants Schema to + // be processed or not. + // + // fSchemaFullChecking + // This flag indicates whether the client code wants full Schema + // constraint checking. + // + // fIdentityConstraintChecking + // This flag indicates whether the client code wants Identity + // Constraint checking, defaulted to true to maintain backward + // compatibility (to minimize supprise) + // + // fAttName + // fAttValue + // fCDataBuf + // fNameBuf + // fQNameBuf + // fPrefixBuf + // For the most part, buffers are obtained from the fBufMgr object + // on the fly. However, for the start tag scan, we have a set of + // fixed buffers for performance reasons. These are used a lot and + // there are a number of them, so asking the buffer manager each + // time for new buffers is a bit too much overhead. + // + // fEmptyNamespaceId + // This is the id of the empty namespace URI. This is a special one + // because of the xmlns="" type of deal. We have to quickly sense + // that its the empty namespace. + // + // fUnknownNamespaceId + // This is the id of the namespace URI which is assigned to the + // global namespace. Its for debug purposes only, since there is no + // real global namespace URI. Its set by the derived class. + // + // fXMLNamespaceId + // fXMLNSNamespaceId + // These are the ids of the namespace URIs which are assigned to the + // 'xml' and 'xmlns' special prefixes. The former is officially + // defined but the latter is not, so we just provide one for debug + // purposes. + // + // fSchemaNamespaceId + // This is the id of the schema namespace URI. + // + // fGrammarResolver + // Grammar Pool that stores all the grammars. Key is namespace for + // schema and system id for external DTD. When caching a grammar, if + // a grammar is already in the pool, it will be replaced with the + // new parsed one. + // + // fGrammar + // Current Grammar used by the Scanner and Validator + // + // fRootGrammar + // The grammar where the root element is declared. + // + // fGrammarType + // Current Grammar Type. Store this value instead of calling getGrammarType + // all the time for faster performance. + // + // fURIStringPool + // This is a pool for URIs with unique ids assigned. We use a standard + // string pool class. This pool is going to be shared by all Grammar. + // Use only if namespace is turned on. + // + // fRootElemName + // No matter we are using DTD or Schema Grammar, if a DOCTYPE exists, + // we need to verify the root element name. So store the rootElement + // that is used in the DOCTYPE in the Scanner instead of in the DTDGrammar + // where it used to + // + // fExternalSchemaLocation + // The list of Namespace/SchemaLocation that was specified externally + // using setExternalSchemaLocation. + // + // fExternalNoNamespaceSchemaLocation + // The no target namespace XML Schema Location that was specified + // externally using setExternalNoNamespaceSchemaLocation. + // + // fSecurityManager + // The SecurityManager instance; as and when set by the application. + // + // fEntityExpansionLimit + // The number of entity expansions to be permitted while processing this document + // Only meaningful when fSecurityManager != 0 + // + // fEntityExpansionCount + // The number of general entities expanded so far in this document. + // Only meaningful when fSecurityManager != null + // + // fLoadExternalDTD + // This flag indicates whether the external DTD be loaded or not + // + // fLoadSchema + // This flag indicates whether the parser should attempt to load + // schemas if they cannot be found in the grammar pool. + // + // fNormalizeData + // This flag indicates whether the parser should perform datatype + // normalization that is defined in the schema. + // + // fCalculateSrcOfs + // This flag indicates the parser should calculate the source offset. + // Turning this on may impact performance. + // + // fStandardUriConformant + // This flag controls whether we force conformant URI + // + // fXMLVersion + // Enum to indicate if the main doc is XML 1.1 or XML 1.0 conformant + // fUIntPool + // pool of unsigned integers to help with duplicate attribute + // detection and filling in default/fixed attributes + // fUIntPoolRow + // current row in fUIntPool + // fUIntPoolCol + // current column in row + // fUIntPoolRowTotal + // total number of rows in table + // + // fMemoryManager + // Pluggable memory manager for dynamic allocation/deallocation. + // + // ----------------------------------------------------------------------- + XMLSize_t fBufferSize; + XMLSize_t fLowWaterMark; + bool fStandardUriConformant; + bool fCalculateSrcOfs; + bool fDoNamespaces; + bool fExitOnFirstFatal; + bool fValidationConstraintFatal; + bool fInException; + bool fStandalone; + bool fHasNoDTD; + bool fValidate; + bool fValidatorFromUser; + bool fDoSchema; + bool fSchemaFullChecking; + bool fIdentityConstraintChecking; + bool fToCacheGrammar; + bool fUseCachedGrammar; + bool fLoadExternalDTD; + bool fLoadSchema; + bool fNormalizeData; + bool fGenerateSyntheticAnnotations; + bool fValidateAnnotations; + bool fIgnoreCachedDTD; + bool fIgnoreAnnotations; + bool fDisableDefaultEntityResolution; + bool fSkipDTDValidation; + bool fHandleMultipleImports; + int fErrorCount; + XMLSize_t fEntityExpansionLimit; + XMLSize_t fEntityExpansionCount; + unsigned int fEmptyNamespaceId; + unsigned int fUnknownNamespaceId; + unsigned int fXMLNamespaceId; + unsigned int fXMLNSNamespaceId; + unsigned int fSchemaNamespaceId; + unsigned int ** fUIntPool; + unsigned int fUIntPoolRow; + unsigned int fUIntPoolCol; + unsigned int fUIntPoolRowTotal; + XMLUInt32 fScannerId; + XMLUInt32 fSequenceId; + RefVectorOf* fAttrList; + RefHash2KeysTableOf* fAttrDupChkRegistry; + XMLDocumentHandler* fDocHandler; + DocTypeHandler* fDocTypeHandler; + XMLEntityHandler* fEntityHandler; + XMLErrorReporter* fErrorReporter; + ErrorHandler* fErrorHandler; + PSVIHandler* fPSVIHandler; + ValidationContext *fValidationContext; + bool fEntityDeclPoolRetrieved; + ReaderMgr fReaderMgr; + XMLValidator* fValidator; + ValSchemes fValScheme; + GrammarResolver* const fGrammarResolver; + MemoryManager* const fGrammarPoolMemoryManager; + Grammar* fGrammar; + Grammar* fRootGrammar; + XMLStringPool* fURIStringPool; + XMLCh* fRootElemName; + XMLCh* fExternalSchemaLocation; + XMLCh* fExternalNoNamespaceSchemaLocation; + SecurityManager* fSecurityManager; + XMLReader::XMLVersion fXMLVersion; + MemoryManager* fMemoryManager; + XMLBufferMgr fBufMgr; + XMLBuffer fAttNameBuf; + XMLBuffer fAttValueBuf; + XMLBuffer fCDataBuf; + XMLBuffer fQNameBuf; + XMLBuffer fPrefixBuf; + XMLBuffer fURIBuf; + XMLBuffer fWSNormalizeBuf; + ElemStack fElemStack; + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLScanner(); + XMLScanner(const XMLScanner&); + XMLScanner& operator=(const XMLScanner&); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void commonInit(); + void cleanUp(); + + // ----------------------------------------------------------------------- + // Private scanning methods + // ----------------------------------------------------------------------- + bool getQuotedString(XMLBuffer& toFill); + XMLSize_t scanUpToWSOr + ( + XMLBuffer& toFill + , const XMLCh chEndChar + ); +}; + +// --------------------------------------------------------------------------- +// XMLScanner: Getter methods +// --------------------------------------------------------------------------- +inline const XMLDocumentHandler* XMLScanner::getDocHandler() const +{ + return fDocHandler; +} + +inline XMLDocumentHandler* XMLScanner::getDocHandler() +{ + return fDocHandler; +} + +inline const DocTypeHandler* XMLScanner::getDocTypeHandler() const +{ + return fDocTypeHandler; +} + +inline DocTypeHandler* XMLScanner::getDocTypeHandler() +{ + return fDocTypeHandler; +} + +inline bool XMLScanner::getDoNamespaces() const +{ + return fDoNamespaces; +} + +inline const XMLEntityHandler* XMLScanner::getEntityHandler() const +{ + return fEntityHandler; +} + +inline XMLEntityHandler* XMLScanner::getEntityHandler() +{ + return fEntityHandler; +} + +inline const XMLErrorReporter* XMLScanner::getErrorReporter() const +{ + return fErrorReporter; +} + +inline XMLErrorReporter* XMLScanner::getErrorReporter() +{ + return fErrorReporter; +} + +inline const ErrorHandler* XMLScanner::getErrorHandler() const +{ + return fErrorHandler; +} + +inline ErrorHandler* XMLScanner::getErrorHandler() +{ + return fErrorHandler; +} + +inline const PSVIHandler* XMLScanner::getPSVIHandler() const +{ + return fPSVIHandler; +} + +inline PSVIHandler* XMLScanner::getPSVIHandler() +{ + return fPSVIHandler; +} + +inline bool XMLScanner::getExitOnFirstFatal() const +{ + return fExitOnFirstFatal; +} + +inline bool XMLScanner::getValidationConstraintFatal() const +{ + return fValidationConstraintFatal; +} + +inline bool XMLScanner::getInException() const +{ + return fInException; +} + +inline RefHashTableOf* XMLScanner::getIDRefList() +{ + return fValidationContext->getIdRefList(); +} + +inline const RefHashTableOf* XMLScanner::getIDRefList() const +{ + return fValidationContext->getIdRefList(); +} + +inline ValidationContext* XMLScanner::getValidationContext() +{ + if (!fEntityDeclPoolRetrieved) + { + fValidationContext->setEntityDeclPool(getEntityDeclPool()); + fEntityDeclPoolRetrieved = true; + } + + return fValidationContext; +} + +inline const Locator* XMLScanner::getLocator() const +{ + return &fReaderMgr; +} + +inline const ReaderMgr* XMLScanner::getReaderMgr() const +{ + return &fReaderMgr; +} + +inline XMLFilePos XMLScanner::getSrcOffset() const +{ + return fReaderMgr.getSrcOffset(); +} + +inline bool XMLScanner::getStandalone() const +{ + return fStandalone; +} + +inline XMLScanner::ValSchemes XMLScanner::getValidationScheme() const +{ + return fValScheme; +} + +inline const XMLValidator* XMLScanner::getValidator() const +{ + return fValidator; +} + +inline XMLValidator* XMLScanner::getValidator() +{ + return fValidator; +} + +inline bool XMLScanner::getDoSchema() const +{ + return fDoSchema; +} + +inline bool XMLScanner::getValidationSchemaFullChecking() const +{ + return fSchemaFullChecking; +} + +inline bool XMLScanner::getIdentityConstraintChecking() const +{ + return fIdentityConstraintChecking; +} + +inline int XMLScanner::getErrorCount() +{ + return fErrorCount; +} + +inline bool XMLScanner::isValidatorFromUser() +{ + return fValidatorFromUser; +} + +inline unsigned int XMLScanner::getEmptyNamespaceId() const +{ + return fEmptyNamespaceId; +} + +inline unsigned int XMLScanner::getUnknownNamespaceId() const +{ + return fUnknownNamespaceId; +} + +inline unsigned int XMLScanner::getXMLNamespaceId() const +{ + return fXMLNamespaceId; +} + +inline unsigned int XMLScanner::getXMLNSNamespaceId() const +{ + return fXMLNSNamespaceId; +} + +inline const XMLStringPool* XMLScanner::getURIStringPool() const +{ + return fURIStringPool; +} + +inline XMLStringPool* XMLScanner::getURIStringPool() +{ + return fURIStringPool; +} + +inline bool XMLScanner::getHasNoDTD() const +{ + return fHasNoDTD; +} + +inline XMLCh* XMLScanner::getExternalSchemaLocation() const +{ + return fExternalSchemaLocation; +} + +inline XMLCh* XMLScanner::getExternalNoNamespaceSchemaLocation() const +{ + return fExternalNoNamespaceSchemaLocation; +} + +inline SecurityManager* XMLScanner::getSecurityManager() const +{ + return fSecurityManager; +} + +inline bool XMLScanner::getLoadExternalDTD() const +{ + return fLoadExternalDTD; +} + +inline bool XMLScanner::getLoadSchema() const +{ + return fLoadSchema; +} + +inline bool XMLScanner::getNormalizeData() const +{ + return fNormalizeData; +} + +inline bool XMLScanner::isCachingGrammarFromParse() const +{ + return fToCacheGrammar; +} + +inline bool XMLScanner::isUsingCachedGrammarInParse() const +{ + return fUseCachedGrammar; +} + +inline bool XMLScanner::getCalculateSrcOfs() const +{ + return fCalculateSrcOfs; +} + +inline Grammar* XMLScanner::getRootGrammar() const +{ + return fRootGrammar; +} + +inline bool XMLScanner::getStandardUriConformant() const +{ + return fStandardUriConformant; +} + +inline XMLReader::XMLVersion XMLScanner::getXMLVersion() const +{ + return fXMLVersion; +} + +inline MemoryManager* XMLScanner::getMemoryManager() const +{ + return fMemoryManager; +} + +inline ValueVectorOf* XMLScanner::getNamespaceContext() const +{ + return fElemStack.getNamespaceMap(); +} + +inline unsigned int XMLScanner::getPrefixId(const XMLCh* const prefix) const +{ + return fElemStack.getPrefixId(prefix); +} + +inline const XMLCh* XMLScanner::getPrefixForId(unsigned int prefId) const +{ + return fElemStack.getPrefixForId(prefId); +} + +inline bool XMLScanner::getGenerateSyntheticAnnotations() const +{ + return fGenerateSyntheticAnnotations; +} + +inline bool XMLScanner::getValidateAnnotations() const +{ + return fValidateAnnotations; +} + +inline const XMLSize_t& XMLScanner::getLowWaterMark() const +{ + return fLowWaterMark; +} + +inline bool XMLScanner::getIgnoreCachedDTD() const +{ + return fIgnoreCachedDTD; +} + +inline bool XMLScanner::getIgnoreAnnotations() const +{ + return fIgnoreAnnotations; +} + +inline bool XMLScanner::getDisableDefaultEntityResolution() const +{ + return fDisableDefaultEntityResolution; +} + +inline bool XMLScanner::getSkipDTDValidation() const +{ + return fSkipDTDValidation; +} + +inline bool XMLScanner::getHandleMultipleImports() const +{ + return fHandleMultipleImports; +} + +// --------------------------------------------------------------------------- +// XMLScanner: Setter methods +// --------------------------------------------------------------------------- +inline void XMLScanner::addGlobalPrefix(const XMLCh* const prefix, const unsigned int uriId) +{ + fElemStack.addGlobalPrefix(prefix, uriId); +} + +inline void XMLScanner::setDocHandler(XMLDocumentHandler* const docHandler) +{ + fDocHandler = docHandler; +} + +inline void XMLScanner::setDocTypeHandler(DocTypeHandler* const docTypeHandler) +{ + fDocTypeHandler = docTypeHandler; +} + +inline void XMLScanner::setErrorHandler(ErrorHandler* const handler) +{ + fErrorHandler = handler; +} + +inline void XMLScanner::setPSVIHandler(PSVIHandler* const handler) +{ + fPSVIHandler = handler; +} + +inline void XMLScanner::setEntityHandler(XMLEntityHandler* const entityHandler) +{ + fEntityHandler = entityHandler; + fReaderMgr.setEntityHandler(entityHandler); +} + +inline void XMLScanner::setErrorReporter(XMLErrorReporter* const errHandler) +{ + fErrorReporter = errHandler; +} + +inline void XMLScanner::setExitOnFirstFatal(const bool newValue) +{ + fExitOnFirstFatal = newValue; +} + + +inline void XMLScanner::setValidationConstraintFatal(const bool newValue) +{ + fValidationConstraintFatal = newValue; +} + +inline void XMLScanner::setValidationScheme(const ValSchemes newScheme) +{ + fValScheme = newScheme; + + // validation flag for Val_Auto is set to false by default, + // and will be turned to true if a grammar is seen + if (fValScheme == Val_Always) + fValidate = true; + else + fValidate = false; +} + +inline void XMLScanner::setDoSchema(const bool doSchema) +{ + fDoSchema = doSchema; +} + +inline void XMLScanner::setDoNamespaces(const bool doNamespaces) +{ + fDoNamespaces = doNamespaces; +} + +inline void XMLScanner::setValidationSchemaFullChecking(const bool schemaFullChecking) +{ + fSchemaFullChecking = schemaFullChecking; +} + +inline void XMLScanner::setIdentityConstraintChecking(const bool identityConstraintChecking) +{ + fIdentityConstraintChecking = identityConstraintChecking; +} + +inline void XMLScanner::setHasNoDTD(const bool hasNoDTD) +{ + fHasNoDTD = hasNoDTD; +} + +inline void XMLScanner::setRootElemName(XMLCh* rootElemName) +{ + fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName; + fRootElemName = XMLString::replicate(rootElemName, fMemoryManager); +} + +inline void XMLScanner::setExternalSchemaLocation(const XMLCh* const schemaLocation) +{ + fMemoryManager->deallocate(fExternalSchemaLocation);//delete [] fExternalSchemaLocation; + fExternalSchemaLocation = XMLString::replicate(schemaLocation, fMemoryManager); +} + +inline void XMLScanner::setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation) +{ + fMemoryManager->deallocate(fExternalNoNamespaceSchemaLocation);//delete [] fExternalNoNamespaceSchemaLocation; + fExternalNoNamespaceSchemaLocation = XMLString::replicate(noNamespaceSchemaLocation, fMemoryManager); +} + +inline void XMLScanner::setExternalSchemaLocation(const char* const schemaLocation) +{ + fMemoryManager->deallocate(fExternalSchemaLocation);//delete [] fExternalSchemaLocation; + fExternalSchemaLocation = XMLString::transcode(schemaLocation, fMemoryManager); +} + +inline void XMLScanner::setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation) +{ + fMemoryManager->deallocate(fExternalNoNamespaceSchemaLocation);//delete [] fExternalNoNamespaceSchemaLocation; + fExternalNoNamespaceSchemaLocation = XMLString::transcode(noNamespaceSchemaLocation, fMemoryManager); +} + +inline void XMLScanner::setSecurityManager(SecurityManager* const securityManager) +{ + fSecurityManager = securityManager; + if(securityManager != 0) + { + fEntityExpansionLimit = securityManager->getEntityExpansionLimit(); + fEntityExpansionCount = 0; + } +} + +inline void XMLScanner::setLoadExternalDTD(const bool loadDTD) +{ + fLoadExternalDTD = loadDTD; +} + +inline void XMLScanner::setLoadSchema(const bool loadSchema) +{ + fLoadSchema = loadSchema; +} + +inline void XMLScanner::setNormalizeData(const bool normalizeData) +{ + fNormalizeData = normalizeData; +} + +inline void XMLScanner::cacheGrammarFromParse(const bool newValue) +{ + fToCacheGrammar = newValue; +} + +inline void XMLScanner::useCachedGrammarInParse(const bool newValue) +{ + fUseCachedGrammar = newValue; +} + +inline void XMLScanner::setCalculateSrcOfs(const bool newValue) +{ + fCalculateSrcOfs = newValue; +} + +inline void XMLScanner::setStandardUriConformant(const bool newValue) +{ + fStandardUriConformant = newValue; + fReaderMgr.setStandardUriConformant(newValue); +} + +inline void XMLScanner::setGenerateSyntheticAnnotations(const bool newValue) +{ + fGenerateSyntheticAnnotations = newValue; +} + +inline void XMLScanner::setValidateAnnotations(const bool newValue) +{ + fValidateAnnotations = newValue; +} + +inline void XMLScanner::setInputBufferSize(const XMLSize_t bufferSize) +{ + fBufferSize = bufferSize; + fCDataBuf.setFullHandler(this, fBufferSize); +} + +inline void XMLScanner::setLowWaterMark(XMLSize_t newValue) +{ + fLowWaterMark = newValue; +} + +inline void XMLScanner::setIgnoredCachedDTD(const bool newValue) +{ + fIgnoreCachedDTD = newValue; +} + +inline void XMLScanner::setIgnoreAnnotations(const bool newValue) +{ + fIgnoreAnnotations = newValue; +} + +inline void XMLScanner::setDisableDefaultEntityResolution(const bool newValue) +{ + fDisableDefaultEntityResolution = newValue; +} + +inline void XMLScanner::setSkipDTDValidation(const bool newValue) +{ + fSkipDTDValidation = newValue; +} + +inline void XMLScanner::setHandleMultipleImports(const bool newValue) +{ + fHandleMultipleImports = newValue; +} + +// --------------------------------------------------------------------------- +// XMLScanner: Mutator methods +// --------------------------------------------------------------------------- +inline void XMLScanner::incrementErrorCount() +{ + ++fErrorCount; +} + +inline void XMLScanner::resetValidationContext() +{ + fValidationContext->clearIdRefList(); + fValidationContext->setEntityDeclPool(0); + fEntityDeclPoolRetrieved = false; +} + +inline void XMLScanner::setAttrDupChkRegistry(const XMLSize_t &attrNumber + , bool &toUseHashTable) +{ + // once the attribute exceed 100, we use hash table to check duplication + if (attrNumber > 100) + { + toUseHashTable = true; + + if (!fAttrDupChkRegistry) + { + fAttrDupChkRegistry = new (fMemoryManager) RefHash2KeysTableOf + ( + 2*attrNumber+1, false, fMemoryManager + ); + } + else + { + fAttrDupChkRegistry->removeAll(); + } + } + +} + +inline Grammar::GrammarType XMLScanner::getCurrentGrammarType() const +{ + return Grammar::UnKnown; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XMLScannerResolver.cpp b/include/xercesc/internal/XMLScannerResolver.cpp new file mode 100644 index 0000000..356faf7 --- /dev/null +++ b/include/xercesc/internal/XMLScannerResolver.cpp @@ -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: XMLScannerResolver.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLScannerResolver: Public static methods +// --------------------------------------------------------------------------- +XMLScanner* +XMLScannerResolver::getDefaultScanner( XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) +{ + return new (manager) IGXMLScanner(valToAdopt, grammarResolver, manager); +} + +XMLScanner* +XMLScannerResolver::resolveScanner( const XMLCh* const scannerName + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) +{ + if (XMLString::equals(scannerName, XMLUni::fgWFXMLScanner)) + return new (manager) WFXMLScanner(valToAdopt, grammarResolver, manager); + else if (XMLString::equals(scannerName, XMLUni::fgIGXMLScanner)) + return new (manager) IGXMLScanner(valToAdopt, grammarResolver, manager); + else if (XMLString::equals(scannerName, XMLUni::fgSGXMLScanner)) + return new (manager) SGXMLScanner(valToAdopt, grammarResolver, manager); + else if (XMLString::equals(scannerName, XMLUni::fgDGXMLScanner)) + return new (manager) DGXMLScanner(valToAdopt, grammarResolver, manager); + + // REVISIT: throw an exception or return a default one? + return 0; +} + +XMLScanner* +XMLScannerResolver::resolveScanner( const XMLCh* const scannerName + , XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager) +{ + if (XMLString::equals(scannerName, XMLUni::fgWFXMLScanner)) + return new (manager) WFXMLScanner(docHandler, docTypeHandler, entityHandler, errReporter, valToAdopt, grammarResolver, manager); + else if (XMLString::equals(scannerName, XMLUni::fgIGXMLScanner)) + return new (manager) IGXMLScanner(docHandler, docTypeHandler, entityHandler, errReporter, valToAdopt, grammarResolver, manager); + else if (XMLString::equals(scannerName, XMLUni::fgSGXMLScanner)) + return new (manager) SGXMLScanner(docHandler, docTypeHandler, entityHandler, errReporter, valToAdopt, grammarResolver, manager); + else if (XMLString::equals(scannerName, XMLUni::fgDGXMLScanner)) + return new (manager) DGXMLScanner(docHandler, docTypeHandler, entityHandler, errReporter, valToAdopt, grammarResolver, manager); + + // REVISIT: throw an exception or return a default one? + return 0; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XMLScannerResolver.hpp b/include/xercesc/internal/XMLScannerResolver.hpp new file mode 100644 index 0000000..8b6f897 --- /dev/null +++ b/include/xercesc/internal/XMLScannerResolver.hpp @@ -0,0 +1,79 @@ +/* + * 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: XMLScannerResolver.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLSCANNERRESOLVER_HPP) +#define XERCESC_INCLUDE_GUARD_XMLSCANNERRESOLVER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLValidator; +class XMLDocumentHandler; +class XMLErrorReporter; +class DocTypeHandler; +class XMLEntityHandler; + +class XMLPARSER_EXPORT XMLScannerResolver +{ +public: + // ----------------------------------------------------------------------- + // Public class methods + // ----------------------------------------------------------------------- + static XMLScanner* resolveScanner + ( + const XMLCh* const scannerName + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + static XMLScanner* resolveScanner + ( + const XMLCh* const scannerName + , XMLDocumentHandler* const docHandler + , DocTypeHandler* const docTypeHandler + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errReporter + , XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + static XMLScanner* getDefaultScanner + ( + XMLValidator* const valToAdopt + , GrammarResolver* const grammarResolver + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + +private : + + // ----------------------------------------------------------------------- + // Unimplemented constructor and destructor + // ----------------------------------------------------------------------- + XMLScannerResolver(); + ~XMLScannerResolver(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XProtoType.cpp b/include/xercesc/internal/XProtoType.cpp new file mode 100644 index 0000000..2dc8092 --- /dev/null +++ b/include/xercesc/internal/XProtoType.cpp @@ -0,0 +1,108 @@ +/* + * 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: XProtoType.cpp 834826 2009-11-11 10:03:53Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*** + * + * write the length of the class name + * write the class name + * + ***/ +void XProtoType::store(XSerializeEngine& serEng) const +{ + XMLSize_t strLen = XMLString::stringLen((char*)fClassName); + serEng << (unsigned long)strLen; + serEng.write(fClassName, strLen * sizeof(XMLByte)); +} + +/*** + * + * To verify that the content in the binary stream + * is the same as this class + * + ***/ +void XProtoType::load(XSerializeEngine& serEng + , XMLByte* const inName + , MemoryManager* const manager) +{ + if (!inName) + { + ThrowXMLwithMemMgr(XSerializationException + , XMLExcepts::XSer_ProtoType_Null_ClassName, manager); + } + + // read and check class name length + XMLSize_t inNameLen = XMLString::stringLen((char*)inName); + XMLSize_t classNameLen = 0; + serEng >> (unsigned long&)classNameLen; + + if (classNameLen != inNameLen) + { + XMLCh value1[17]; + XMLCh value2[17]; + XMLString::sizeToText(inNameLen, value1, 16, 10, manager); + XMLString::sizeToText(classNameLen, value2, 16, 10, manager); + + ThrowXMLwithMemMgr2(XSerializationException + , XMLExcepts::XSer_ProtoType_NameLen_Dif + , value1 + , value2 + , manager); + } + + // read and check class name + XMLByte className[256]; + serEng.read(className, classNameLen*sizeof(XMLByte)); + className[classNameLen] = '\0'; + + if ( !XMLString::equals((char*)className, (char*)inName)) + { + //we don't have class name exceed this length in xerces + XMLCh name1[256]; + XMLCh name2[256]; + XMLCh *tmp = XMLString::transcode((char*)inName, manager); + XMLString::copyNString(name1, tmp, 255); + manager->deallocate(tmp); + tmp = XMLString::transcode((char*)className, manager); + XMLString::copyNString(name2, tmp, 255); + manager->deallocate(tmp); + + ThrowXMLwithMemMgr2(XSerializationException + , XMLExcepts::XSer_ProtoType_Name_Dif + , name1 + , name2 + , manager); + } + + return; + +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/internal/XProtoType.hpp b/include/xercesc/internal/XProtoType.hpp new file mode 100644 index 0000000..9b5559d --- /dev/null +++ b/include/xercesc/internal/XProtoType.hpp @@ -0,0 +1,93 @@ +/* + * 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: XProtoType.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XPROTOTYPE_HPP) +#define XERCESC_INCLUDE_GUARD_XPROTOTYPE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XSerializeEngine; +class XSerializable; + +class XMLUTIL_EXPORT XProtoType +{ +public: + + void store(XSerializeEngine& serEng) const; + + static void load(XSerializeEngine& serEng + , XMLByte* const name + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // ------------------------------------------------------------------------------- + // data + // + // fClassName: + // name of the XSerializable derivatives + // + // fCreateObject: + // pointer to the factory method (createObject()) + // of the XSerializable derivatives + // + // ------------------------------------------------------------------------------- + + XMLByte* fClassName; + + XSerializable* (*fCreateObject)(MemoryManager*); + +}; + +#define DECL_XPROTOTYPE(class_name) \ +static XProtoType class##class_name; \ +static XSerializable* createObject(MemoryManager* manager); + +/*** + * For non-abstract class + ***/ +#define IMPL_XPROTOTYPE_TOCREATE(class_name) \ +IMPL_XPROTOTYPE_INSTANCE(class_name) \ +XSerializable* class_name::createObject(MemoryManager* manager) \ +{return new (manager) class_name(manager);} + +/*** +* For abstract class + ***/ +#define IMPL_XPROTOTYPE_NOCREATE(class_name) \ +IMPL_XPROTOTYPE_INSTANCE(class_name) \ +XSerializable* class_name::createObject(MemoryManager*) \ +{return 0;} + + +/*** + * Helper Macro + ***/ +#define XPROTOTYPE_CLASS(class_name) ((XProtoType*)(&class_name::class##class_name)) + +#define IMPL_XPROTOTYPE_INSTANCE(class_name) \ +XProtoType class_name::class##class_name = \ +{(XMLByte*) #class_name, class_name::createObject }; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XSAXMLScanner.cpp b/include/xercesc/internal/XSAXMLScanner.cpp new file mode 100644 index 0000000..3cbe5a0 --- /dev/null +++ b/include/xercesc/internal/XSAXMLScanner.cpp @@ -0,0 +1,725 @@ +/* + * 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: XSAXMLScanner.cpp 833045 2009-11-05 13:21:27Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +#include +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSAXMLScanner: Constructors and Destructor +// --------------------------------------------------------------------------- +XSAXMLScanner::XSAXMLScanner( GrammarResolver* const grammarResolver + , XMLStringPool* const uriStringPool + , SchemaGrammar* const xsaGrammar + , MemoryManager* const manager) : + + SGXMLScanner(0, grammarResolver, manager) +{ + fSchemaGrammar = xsaGrammar; + setURIStringPool(uriStringPool); +} + +XSAXMLScanner::~XSAXMLScanner() +{ +} + +// --------------------------------------------------------------------------- +// XSAXMLScanner: SGXMLScanner virtual methods +// --------------------------------------------------------------------------- +// This method will kick off the scanning of the primary content of the +void XSAXMLScanner::scanEndTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the end of the root element. + gotData = true; + + // Check if the element stack is empty. If so, then this is an unbalanced + // element (i.e. more ends than starts, perhaps because of bad text + // causing one to be skipped.) + if (fElemStack.isEmpty()) + { + emitError(XMLErrs::MoreEndThanStartTags); + fReaderMgr.skipPastChar(chCloseAngle); + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager); + } + + // Pop the stack of the element we are supposed to be ending. Remember + // that we don't own this. The stack just keeps them and reuses them. + unsigned int uriId = fElemStack.getCurrentURI(); + + // Make sure that its the end of the element that we expect + const XMLCh *elemName = fElemStack.getCurrentSchemaElemName(); + const ElemStack::StackElem* topElem = fElemStack.popTop(); + if (!fReaderMgr.skippedStringLong(elemName)) + { + emitError + ( + XMLErrs::ExpectedEndOfTagX, elemName + ); + fReaderMgr.skipPastChar(chCloseAngle); + return; + } + + // See if it was the root element, to avoid multiple calls below + const bool isRoot = fElemStack.isEmpty(); + + // Make sure we are back on the same reader as where we started + if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum()) + emitError(XMLErrs::PartialTagMarkupError); + + // Skip optional whitespace + fReaderMgr.skipPastSpaces(); + + // Make sure we find the closing bracket + if (!fReaderMgr.skippedChar(chCloseAngle)) + { + emitError + ( + XMLErrs::UnterminatedEndTag, topElem->fThisElement->getFullName() + ); + } + + // If validation is enabled, then lets pass him the list of children and + // this element and let him validate it. + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent + ( + topElem->fThisElement + , topElem->fChildren + , topElem->fChildCount + , &failure + ); + + if (!res) + { + // One of the elements is not valid for the content. NOTE that + // if no children were provided but the content model requires + // them, it comes back with a zero value. But we cannot use that + // to index the child array in this case, and have to put out a + // special message. + if (!topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::EmptyNotValidForContent + , topElem->fThisElement->getFormattedContentModel() + ); + } + else if (failure >= topElem->fChildCount) + { + fValidator->emitError + ( + XMLValid::NotEnoughElemsForCM + , topElem->fThisElement->getFormattedContentModel() + ); + } + else + { + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , topElem->fChildren[failure]->getRawName() + , topElem->fThisElement->getFormattedContentModel() + ); + } + } + } + + // now we can reset the datatype buffer, since the + // application has had a chance to copy the characters somewhere else + ((SchemaValidator *)fValidator)->clearDatatypeBuffer(); + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + if (topElem->fPrefixColonPos != -1) + fPrefixBuf.set(elemName, topElem->fPrefixColonPos); + else + fPrefixBuf.reset(); + fDocHandler->endElement + ( + *topElem->fThisElement + , uriId + , isRoot + , fPrefixBuf.getRawBuffer() + ); + } + + // If this was the root, then done with content + gotData = !isRoot; + + if (gotData) { + + // Restore the grammar + fGrammar = fElemStack.getCurrentGrammar(); + fGrammarType = fGrammar->getGrammarType(); + fValidator->setGrammar(fGrammar); + + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } +} + +bool XSAXMLScanner::scanStartTag(bool& gotData) +{ + // Assume we will still have data until proven otherwise. It will only + // ever be false if this is the root and its empty. + gotData = true; + + // Reset element content + fContent.reset(); + + // The current position is after the open bracket, so we need to read in + // in the element name. + int prefixColonPos; + if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos)) + { + if (fQNameBuf.isEmpty()) + emitError(XMLErrs::ExpectedElementName); + else + emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer()); + fReaderMgr.skipToChar(chOpenAngle); + return false; + } + + // See if its the root element + const bool isRoot = fElemStack.isEmpty(); + + // Skip any whitespace after the name + fReaderMgr.skipPastSpaces(); + + // First we have to do the rawest attribute scan. We don't do any + // normalization of them at all, since we don't know yet what type they + // might be (since we need the element decl in order to do that.) + const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer(); + bool isEmpty; + XMLSize_t attCount = rawAttrScan(qnameRawBuf, *fRawAttrList, isEmpty); + + // save the contentleafname and currentscope before addlevel, for later use + ContentLeafNameTypeVector* cv = 0; + XMLContentModel* cm = 0; + unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE; + bool laxThisOne = false; + if (!isRoot) + { + // schema validator will have correct type if validating + SchemaElementDecl* tempElement = (SchemaElementDecl*) + fElemStack.topElement()->fThisElement; + SchemaElementDecl::ModelTypes modelType = tempElement->getModelType(); + ComplexTypeInfo *currType = 0; + + if (fValidate) + { + currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo(); + if (currType) + modelType = (SchemaElementDecl::ModelTypes)currType->getContentType(); + else // something must have gone wrong + modelType = SchemaElementDecl::Any; + } + else { + currType = tempElement->getComplexTypeInfo(); + } + + if ((modelType == SchemaElementDecl::Mixed_Simple) + || (modelType == SchemaElementDecl::Mixed_Complex) + || (modelType == SchemaElementDecl::Children)) + { + cm = currType->getContentModel(); + cv = cm->getContentLeafNameTypeVector(); + currentScope = fElemStack.getCurrentScope(); + } + else if (modelType == SchemaElementDecl::Any) { + laxThisOne = true; + } + } + + // Now, since we might have to update the namespace map for this element, + // but we don't have the element decl yet, we just tell the element stack + // to expand up to get ready. + XMLSize_t elemDepth = fElemStack.addLevel(); + fElemStack.setValidationFlag(fValidate); + fElemStack.setPrefixColonPos(prefixColonPos); + + // Make an initial pass through the list and find any xmlns attributes or + // schema attributes. + if (attCount) + scanRawAttrListforNameSpaces(attCount); + + // Resolve the qualified name to a URI and name so that we can look up + // the element decl for this element. We have now update the prefix to + // namespace map so we should get the correct element now. + unsigned int uriId = resolveQNameWithColon + ( + qnameRawBuf, fPrefixBuf, ElemStack::Mode_Element, prefixColonPos + ); + + //if schema, check if we should lax or skip the validation of this element + bool parentValidation = fValidate; + if (cv) { + QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager); + // elementDepth will be > 0, as cv is only constructed if element is not + // root. + laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1); + } + + // Look up the element now in the grammar. This will get us back a + // generic element decl object. We tell him to fault one in if he does + // not find it. + bool wasAdded = false; + const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1]; + XMLElementDecl* elemDecl = fGrammar->getElemDecl + ( + uriId, nameRawBuf, qnameRawBuf, currentScope + ); + + if (!elemDecl) + { + // URI is different, so we try to switch grammar + if (uriId != fURIStringPool->getId(fGrammar->getTargetNamespace())) { + switchGrammar(getURIText(uriId), laxThisOne); + } + + // look for a global element declaration + elemDecl = fGrammar->getElemDecl( + uriId, nameRawBuf, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE + ); + + if (!elemDecl) + { + // if still not found, look in list of undeclared elements + elemDecl = fElemNonDeclPool->getByKey( + nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE); + + if (!elemDecl) + { + elemDecl = new (fMemoryManager) SchemaElementDecl + ( + fPrefixBuf.getRawBuffer(), nameRawBuf, uriId + , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + + elemDecl->setId (fElemNonDeclPool->put( + (void*)elemDecl->getBaseName(), + uriId, + (int)Grammar::TOP_LEVEL_SCOPE, + (SchemaElementDecl*)elemDecl)); + + wasAdded = true; + } + } + } + + // We do something different here according to whether we found the + // element or not. + bool bXsiTypeSet= (fValidator)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false; + if (wasAdded || !elemDecl->isDeclared()) + { + if (laxThisOne && !bXsiTypeSet) { + fValidate = false; + fElemStack.setValidationFlag(fValidate); + } + + // If validating then emit an error + if (fValidate) + { + // This is to tell the reuse Validator that this element was + // faulted-in, was not an element in the grammar pool originally + elemDecl->setCreateReason(XMLElementDecl::JustFaultIn); + + if(!bXsiTypeSet) + fValidator->emitError + ( + XMLValid::ElementNotDefined, elemDecl->getFullName() + ); + } + } + + // Now we can update the element stack to set the current element + // decl. We expanded the stack above, but couldn't store the element + // decl because we didn't know it yet. + fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum()); + fElemStack.setCurrentURI(uriId); + + if (isRoot) { + fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager); + } + + // Validate the element + if (fValidate) { + fValidator->validateElement(elemDecl); + } + + // squirrel away the element's QName, so that we can do an efficient + // end-tag match + fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer()); + + ComplexTypeInfo* typeinfo = (fValidate) + ? ((SchemaValidator*)fValidator)->getCurrentTypeInfo() + : ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo(); + + if (typeinfo) + { + currentScope = typeinfo->getScopeDefined(); + + // switch grammar if the typeinfo has a different grammar + XMLCh* typeName = typeinfo->getTypeName(); + int comma = XMLString::indexOf(typeName, chComma); + if (comma > 0) + { + XMLBufBid bbPrefix(&fBufMgr); + XMLBuffer& prefixBuf = bbPrefix.getBuffer(); + + prefixBuf.append(typeName, comma); + switchGrammar(prefixBuf.getRawBuffer(), laxThisOne); + } + } + fElemStack.setCurrentScope(currentScope); + + // Set element next state + if (elemDepth >= fElemStateSize) { + resizeElemState(); + } + + fElemState[elemDepth] = 0; + fElemLoopState[elemDepth] = 0; + fElemStack.setCurrentGrammar(fGrammar); + + // If this is the first element and we are validating, check the root + // element. + if (!isRoot && parentValidation) { + fElemStack.addChild(elemDecl->getElementName(), true); + } + + // Now lets get the fAttrList filled in. This involves faulting in any + // defaulted and fixed attributes and normalizing the values of any that + // we got explicitly. + // + // We update the attCount value with the total number of attributes, but + // it goes in with the number of values we got during the raw scan of + // explictly provided attrs above. + attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList); + + if(attCount) + { + // clean up after ourselves: + // clear the map used to detect duplicate attributes + fUndeclaredAttrRegistry->removeAll(); + } + + // Since the element may have default values, call start tag now regardless if it is empty or not + // If we have a document handler, then tell it about this start tag + if (fDocHandler) + { + fDocHandler->startElement + ( + *elemDecl, uriId, fPrefixBuf.getRawBuffer(), *fAttrList + , attCount, false, isRoot + ); + } // may be where we output something... + + // If empty, validate content right now if we are validating and then + // pop the element stack top. Else, we have to update the current stack + // top's namespace mapping elements. + if (isEmpty) + { + // Pop the element stack back off since it'll never be used now + fElemStack.popTop(); + + // If validating, then insure that its legal to have no content + if (fValidate) + { + XMLSize_t failure; + bool res = fValidator->checkContent(elemDecl, 0, 0, &failure); + if (!res) + { + // REVISIT: in the case of xsi:type, this may + // return the wrong string... + fValidator->emitError + ( + XMLValid::ElementNotValidForContent + , elemDecl->getFullName() + , elemDecl->getFormattedContentModel() + ); + } + } + + // If we have a doc handler, tell it about the end tag + if (fDocHandler) + { + fDocHandler->endElement + ( + *elemDecl, uriId, isRoot, fPrefixBuf.getRawBuffer() + ); + } + + // If the elem stack is empty, then it was an empty root + if (isRoot) { + gotData = false; + } + else + { + // Restore the grammar + fGrammar = fElemStack.getCurrentGrammar(); + fGrammarType = fGrammar->getGrammarType(); + fValidator->setGrammar(fGrammar); + + // Restore the validation flag + fValidate = fElemStack.getValidationFlag(); + } + } + + return true; +} + +// --------------------------------------------------------------------------- +// XSAXMLScanner: XMLScanner virtual methods +// --------------------------------------------------------------------------- +// This method will reset the scanner data structures, and related plugged +// in stuff, for a new scan session. We get the input source for the primary +// XML entity, create the reader for it, and push it on the stack so that +// upon successful return from here we are ready to go. +void XSAXMLScanner::scanReset(const InputSource& src) +{ + fGrammar = fSchemaGrammar; + fGrammarType = Grammar::SchemaGrammarType; + fRootGrammar = fSchemaGrammar; + + fValidator->setGrammar(fGrammar); + + // Reset validation + fValidate = true; + + // And for all installed handlers, send reset events. This gives them + // a chance to flush any cached data. + if (fDocHandler) + fDocHandler->resetDocument(); + if (fEntityHandler) + fEntityHandler->resetEntities(); + if (fErrorReporter) + fErrorReporter->resetErrors(); + + // Clear out the id reference list + resetValidationContext(); + + // Reset the Root Element Name + if (fRootElemName) { + fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName; + } + + fRootElemName = 0; + + // Reset the element stack, and give it the latest ids for the special + // URIs it has to know about. + fElemStack.reset + ( + fEmptyNamespaceId, fUnknownNamespaceId, fXMLNamespaceId, fXMLNSNamespaceId + ); + + if (!fSchemaNamespaceId) + fSchemaNamespaceId = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI); + + // Reset some status flags + fInException = false; + fStandalone = false; + fErrorCount = 0; + fHasNoDTD = true; + fSeeXsi = false; + fDoNamespaces = true; + fDoSchema = true; + + // Reset the validators + fSchemaValidator->reset(); + fSchemaValidator->setErrorReporter(fErrorReporter); + fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal); + fSchemaValidator->setGrammarResolver(fGrammarResolver); + + // Handle the creation of the XML reader object for this input source. + // This will provide us with transcoding and basic lexing services. + XMLReader* newReader = fReaderMgr.createReader + ( + src + , true + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , fCalculateSrcOfs + , fLowWaterMark + ); + + if (!newReader) { + if (src.getIssueFatalErrorIfNotFound()) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); + else + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); + } + + // Push this read onto the reader manager + fReaderMgr.pushReader(newReader, 0); + + // and reset security-related things if necessary: + if(fSecurityManager != 0) + { + fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit(); + fEntityExpansionCount = 0; + } + fElemCount = 0; + if (fUIntPoolRowTotal >= 32) + { // 8 KB tied up with validating attributes... + fAttDefRegistry->removeAll(); + recreateUIntPool(); + } + else + { + // note that this will implicitly reset the values of the hashtables, + // though their buckets will still be tied up + resetUIntPool(); + } + fUndeclaredAttrRegistry->removeAll(); +} + + +void XSAXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount) +{ + // Make an initial pass through the list and find any xmlns attributes or + // schema attributes. + // When we find one, send it off to be used to update the element stack's + // namespace mappings. + XMLSize_t index = 0; + for (index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + + // If either the key begins with "xmlns:" or its just plain + // "xmlns", then use it to update the map. + if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6) + || XMLString::equals(rawPtr, XMLUni::fgXMLNSString)) + { + const XMLCh* valuePtr = curPair->getValue(); + + updateNSMap(rawPtr, valuePtr, fRawAttrColonList[index]); + + // if the schema URI is seen in the the valuePtr, set the boolean seeXsi + if (XMLString::equals(valuePtr, SchemaSymbols::fgURI_XSI)) { + fSeeXsi = true; + } + } + } + + // walk through the list again to deal with "xsi:...." + if (fSeeXsi) + { + // Schema Xsi Type yyyy (e.g. xsi:type="yyyyy") + XMLBufBid bbXsi(&fBufMgr); + XMLBuffer& fXsiType = bbXsi.getBuffer(); + + QName attName(fMemoryManager); + + for (index = 0; index < attCount; index++) + { + // each attribute has the prefix:suffix="value" + const KVStringPair* curPair = fRawAttrList->elementAt(index); + const XMLCh* rawPtr = curPair->getKey(); + + attName.setName(rawPtr, fEmptyNamespaceId); + const XMLCh* prefPtr = attName.getPrefix(); + + // if schema URI has been seen, scan for the schema location and uri + // and resolve the schema grammar; or scan for schema type + if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) { + + const XMLCh* valuePtr = curPair->getValue(); + const XMLCh* suffPtr = attName.getLocalPart(); + + if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE)) + { + // normalize the attribute according to schema whitespace facet + DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME); + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiType, true); + } + else if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL)) + { + // normalize the attribute according to schema whitespace facet + XMLBuffer& fXsiNil = fBufMgr.bidOnBuffer(); + DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN); + ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true); + if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE)) + ((SchemaValidator*)fValidator)->setNillable(true); + else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE)) + ((SchemaValidator*)fValidator)->setNillable(false); + else + emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr); + fBufMgr.releaseBuffer(fXsiNil); + } + } + } + + if (!fXsiType.isEmpty()) + { + int colonPos = -1; + unsigned int uriId = resolveQName + ( + fXsiType.getRawBuffer(), fPrefixBuf, ElemStack::Mode_Element, colonPos + ); + ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fXsiType.getRawBuffer() + colonPos + 1, uriId); + } + } +} + +void XSAXMLScanner::switchGrammar( const XMLCh* const uriStr + , bool laxValidate) +{ + Grammar* tempGrammar = 0; + + if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + tempGrammar = fSchemaGrammar; + } + else { + tempGrammar = fGrammarResolver->getGrammar(uriStr); + } + + if (tempGrammar && tempGrammar->getGrammarType() == Grammar::SchemaGrammarType) + { + fGrammar = tempGrammar; + fGrammarType = Grammar::SchemaGrammarType; + fValidator->setGrammar(fGrammar); + } + else if(!laxValidate) { + fValidator->emitError(XMLValid::GrammarNotFound, uriStr); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XSAXMLScanner.hpp b/include/xercesc/internal/XSAXMLScanner.hpp new file mode 100644 index 0000000..bde27f1 --- /dev/null +++ b/include/xercesc/internal/XSAXMLScanner.hpp @@ -0,0 +1,98 @@ +/* + * 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: XSAXMLScanner.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSAXMLSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_XSAXMLSCANNER_HPP + +#include + + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This is a scanner class, which processes/validates contents of XML Schema +// Annotations. It's intended for internal use only. +// +class XMLPARSER_EXPORT XSAXMLScanner : public SGXMLScanner +{ +public : + // ----------------------------------------------------------------------- + // Destructor + // ----------------------------------------------------------------------- + virtual ~XSAXMLScanner(); + + // ----------------------------------------------------------------------- + // XMLScanner public virtual methods + // ----------------------------------------------------------------------- + virtual const XMLCh* getName() const; + +protected: + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + /** + * The grammar representing the XML Schema annotation (xsaGrammar) is + * passed in by the caller. The scanner will own it and is responsible + * for deleting it. + */ + XSAXMLScanner + ( + GrammarResolver* const grammarResolver + , XMLStringPool* const uriStringPool + , SchemaGrammar* const xsaGrammar + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + friend class TraverseSchema; + + // ----------------------------------------------------------------------- + // XMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual void scanReset(const InputSource& src); + + // ----------------------------------------------------------------------- + // SGXMLScanner virtual methods + // ----------------------------------------------------------------------- + virtual bool scanStartTag(bool& gotData); + virtual void scanEndTag(bool& gotData); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSAXMLScanner(); + XSAXMLScanner(const XSAXMLScanner&); + XSAXMLScanner& operator=(const XSAXMLScanner&); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void scanRawAttrListforNameSpaces(XMLSize_t attCount); + void switchGrammar(const XMLCh* const newGrammarNameSpace, bool laxValidate); +}; + +inline const XMLCh* XSAXMLScanner::getName() const +{ + return XMLUni::fgXSAXMLScanner; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XSObjectFactory.cpp b/include/xercesc/internal/XSObjectFactory.cpp new file mode 100644 index 0000000..3ac9a6e --- /dev/null +++ b/include/xercesc/internal/XSObjectFactory.cpp @@ -0,0 +1,1056 @@ +/* + * 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 $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static XMLCh regexSeparator[] = {chPipe, chNull}; + + +// --------------------------------------------------------------------------- +// XSObjectFactory: Constructors and Destructor +// --------------------------------------------------------------------------- +XSObjectFactory::XSObjectFactory(MemoryManager* const manager) + : fMemoryManager(manager) + , fXercesToXSMap(0) + , fDeleteVector(0) +{ + fDeleteVector = new (manager) RefVectorOf(20, true, manager); + fXercesToXSMap = new (manager) RefHashTableOf ( + 109, false, manager); +} + +XSObjectFactory::~XSObjectFactory() +{ + delete fXercesToXSMap; + delete fDeleteVector; +} + +// --------------------------------------------------------------------------- +// XSObjectFactory: factory methods +// --------------------------------------------------------------------------- +XSParticle* +XSObjectFactory::createModelGroupParticle(const ContentSpecNode* const rootNode, + XSModel* const xsModel) +{ + if (rootNode == 0) + return 0; + + ContentSpecNode::NodeTypes nodeType = rootNode->getType(); + if (nodeType == ContentSpecNode::All + || nodeType == ContentSpecNode::ModelGroupChoice + || nodeType == ContentSpecNode::ModelGroupSequence) + { + XSParticleList* particleList = new (fMemoryManager) RefVectorOf (4, true, fMemoryManager); + XSAnnotation* annot = getAnnotationFromModel(xsModel, rootNode); + XSModelGroup* modelGroup = 0; + + if (nodeType == ContentSpecNode::All) + { + modelGroup = new (fMemoryManager) XSModelGroup(XSModelGroup::COMPOSITOR_ALL, particleList, annot, xsModel, fMemoryManager); + buildAllParticles(rootNode, particleList, xsModel); + } + else + { + if (nodeType == ContentSpecNode::ModelGroupChoice) + modelGroup = new (fMemoryManager) XSModelGroup(XSModelGroup::COMPOSITOR_CHOICE, particleList, annot, xsModel, fMemoryManager); + else + modelGroup = new (fMemoryManager) XSModelGroup(XSModelGroup::COMPOSITOR_SEQUENCE, particleList, annot, xsModel, fMemoryManager); + + buildChoiceSequenceParticles(rootNode->getFirst(), particleList, xsModel); + buildChoiceSequenceParticles(rootNode->getSecond(), particleList, xsModel); + } + + int m = rootNode->getMaxOccurs(); + XSParticle* groupParticle = new (fMemoryManager) XSParticle + ( + XSParticle::TERM_MODELGROUP + , xsModel + , modelGroup + , (XMLSize_t)rootNode->getMinOccurs() + , (XMLSize_t)m + , m == -1 + , fMemoryManager + ); + + return groupParticle; + } + else + return 0; +} + +void XSObjectFactory::buildAllParticles(const ContentSpecNode* const rootNode, + XSParticleList* const particleList, + XSModel* const xsModel) +{ + // Get the type of spec node our current node is + const ContentSpecNode::NodeTypes nodeType = rootNode->getType(); + + if (nodeType == ContentSpecNode::All) + { + const ContentSpecNode* rightNode = rootNode->getSecond(); + + buildAllParticles(rootNode->getFirst(), particleList, xsModel); + if (rightNode) + buildAllParticles(rightNode, particleList, xsModel); + } + else if (nodeType == ContentSpecNode::Leaf) + { + XSParticle* elemParticle = createElementParticle(rootNode, xsModel); + if (elemParticle) + particleList->addElement(elemParticle); + } +} + +void XSObjectFactory::buildChoiceSequenceParticles(const ContentSpecNode* const rootNode, + XSParticleList* const particleList, + XSModel* const xsModel) +{ + if (rootNode) + { + const ContentSpecNode::NodeTypes nodeType = rootNode->getType(); + + if (nodeType == ContentSpecNode::Sequence) + { + buildChoiceSequenceParticles(rootNode->getFirst(), particleList, xsModel); + buildChoiceSequenceParticles(rootNode->getSecond(), particleList, xsModel); + } + else if (nodeType == ContentSpecNode::Choice) + { + buildChoiceSequenceParticles(rootNode->getFirst(), particleList, xsModel); + buildChoiceSequenceParticles(rootNode->getSecond(), particleList, xsModel); + } + else if ((nodeType & 0x0f) == ContentSpecNode::Any + || (nodeType & 0x0f) == ContentSpecNode::Any_Other + || (nodeType & 0x0f) == ContentSpecNode::Any_NS + || nodeType == ContentSpecNode::Any_NS_Choice) + { + XSParticle* wildcardParticle = createWildcardParticle(rootNode, xsModel); + if (wildcardParticle) + particleList->addElement(wildcardParticle); + } + else if (nodeType == ContentSpecNode::Leaf) + { + XSParticle* elemParticle = createElementParticle(rootNode, xsModel); + if (elemParticle) + particleList->addElement(elemParticle); + } + // must be a model group + else + { + XSParticle* xsParticle = createModelGroupParticle(rootNode, xsModel); + if (xsParticle) + particleList->addElement(xsParticle); + } + } +} + +XSParticle* +XSObjectFactory::createElementParticle(const ContentSpecNode* const rootNode, + XSModel* const xsModel) +{ + if (rootNode->getElementDecl()) + { + XSElementDeclaration* xsElemDecl = addOrFind( + (SchemaElementDecl*) rootNode->getElementDecl(), xsModel); + + if (xsElemDecl) + { + int m = rootNode->getMaxOccurs(); + XSParticle* particle = new (fMemoryManager) XSParticle + ( + XSParticle::TERM_ELEMENT + , xsModel + , xsElemDecl + , (XMLSize_t)rootNode->getMinOccurs() + , (XMLSize_t)m + , m == -1 + , fMemoryManager + ); + + return particle; + } + } + + return 0; +} + +XSParticle* +XSObjectFactory::createWildcardParticle(const ContentSpecNode* const rootNode, + XSModel* const xsModel) +{ + XSWildcard* xsWildcard = createXSWildcard(rootNode, xsModel); + if (xsWildcard) + { + int m = rootNode->getMaxOccurs(); + XSParticle* particle = new (fMemoryManager) XSParticle + ( + XSParticle::TERM_WILDCARD + , xsModel + , xsWildcard + , (XMLSize_t)rootNode->getMinOccurs() + , (XMLSize_t)m + , m == -1 + , fMemoryManager + ); + + return particle; + } + + return 0; +} + +XSAttributeDeclaration* +XSObjectFactory::addOrFind(SchemaAttDef* const attDef, + XSModel* const xsModel, + XSComplexTypeDefinition* const enclosingTypeDef) +{ + XSAttributeDeclaration* xsObj = (XSAttributeDeclaration*) xsModel->getXSObject(attDef); + if (xsObj) + { + if (xsObj->getScope() == XSConstants::SCOPE_LOCAL + && xsObj->getEnclosingCTDefinition() == 0 + && enclosingTypeDef) + xsObj->setEnclosingCTDefinition(enclosingTypeDef); + } + else + { + XSSimpleTypeDefinition* xsType = 0; + if (attDef->getDatatypeValidator()) + xsType = addOrFind(attDef->getDatatypeValidator(), xsModel); + + XSConstants::SCOPE scope = XSConstants::SCOPE_ABSENT; + XSComplexTypeDefinition* enclosingCTDefinition = 0; + + if (attDef->getPSVIScope() == PSVIDefs::SCP_GLOBAL) + scope = XSConstants::SCOPE_GLOBAL; + else if (attDef->getPSVIScope() == PSVIDefs::SCP_LOCAL) + { + scope = XSConstants::SCOPE_LOCAL; + enclosingCTDefinition = enclosingTypeDef; + } + + xsObj = new (fMemoryManager) XSAttributeDeclaration + ( + attDef + , xsType + , getAnnotationFromModel(xsModel, attDef) + , xsModel + , scope + , enclosingCTDefinition + , fMemoryManager + ); + putObjectInMap(attDef, xsObj); + } + + return xsObj; +} + +XSSimpleTypeDefinition* +XSObjectFactory::addOrFind(DatatypeValidator* const validator, + XSModel* const xsModel, + bool isAnySimpleType) +{ + XSSimpleTypeDefinition* xsObj = (XSSimpleTypeDefinition*) xsModel->getXSObject(validator); + if (!xsObj) + { + XSTypeDefinition* baseType = 0; + XSSimpleTypeDefinitionList* memberTypes = 0; + XSSimpleTypeDefinition* primitiveOrItemType = 0; + XSSimpleTypeDefinition::VARIETY typeVariety = XSSimpleTypeDefinition::VARIETY_ATOMIC; + bool primitiveTypeSelf = false; + + //REVISIT: the getFixed method is protected so added friend XSObjectFactory + // to DatatypeValidator class... + DatatypeValidator::ValidatorType dvType = validator->getType(); + DatatypeValidator* baseDV = validator->getBaseValidator(); + + if (dvType == DatatypeValidator::Union) + { + typeVariety = XSSimpleTypeDefinition::VARIETY_UNION; + RefVectorOf* membersDV = ((UnionDatatypeValidator*)validator)->getMemberTypeValidators(); + XMLSize_t size = membersDV->size(); + if (size) + { + memberTypes = new (fMemoryManager) RefVectorOf(size, false, fMemoryManager); + for (XMLSize_t i=0; iaddElement(addOrFind(membersDV->elementAt(i), xsModel)); + } + + if (baseDV) + { + baseType = addOrFind(baseDV, xsModel); + } + else + { + baseType = (XSSimpleTypeDefinition*) xsModel->getTypeDefinition + ( + SchemaSymbols::fgDT_ANYSIMPLETYPE + , SchemaSymbols::fgURI_SCHEMAFORSCHEMA + ); + } + } + else if (dvType == DatatypeValidator::List) + { + typeVariety = XSSimpleTypeDefinition::VARIETY_LIST; + if (baseDV->getType() == DatatypeValidator::List) + { + baseType = addOrFind(baseDV, xsModel); + primitiveOrItemType = ((XSSimpleTypeDefinition*) baseType)->getItemType(); + } + else + { + baseType = (XSSimpleTypeDefinition*) xsModel->getTypeDefinition + ( + SchemaSymbols::fgDT_ANYSIMPLETYPE + , SchemaSymbols::fgURI_SCHEMAFORSCHEMA + ); + primitiveOrItemType = addOrFind(baseDV, xsModel); + } + } + else if (!isAnySimpleType) + { + if (baseDV) + { + baseType = addOrFind(baseDV, xsModel); + primitiveOrItemType = ((XSSimpleTypeDefinition*) baseType)->getPrimitiveType(); + } + else // built-in + { + baseType = (XSSimpleTypeDefinition*) xsModel->getTypeDefinition + ( + SchemaSymbols::fgDT_ANYSIMPLETYPE + , SchemaSymbols::fgURI_SCHEMAFORSCHEMA + ); + primitiveTypeSelf = true; + } + } + else + { + baseType = xsModel->getTypeDefinition(SchemaSymbols::fgATTVAL_ANYTYPE, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + } + + xsObj = new (fMemoryManager) XSSimpleTypeDefinition + ( + validator + , typeVariety + , baseType + , primitiveOrItemType + , memberTypes + , getAnnotationFromModel(xsModel, validator) + , xsModel + , fMemoryManager + ); + putObjectInMap(validator, xsObj); + + if (primitiveTypeSelf) + xsObj->setPrimitiveType(xsObj); + + // process facets + processFacets(validator, xsModel, xsObj); + } + + return xsObj; +} + +XSElementDeclaration* +XSObjectFactory::addOrFind(SchemaElementDecl* const elemDecl, + XSModel* const xsModel, + XSComplexTypeDefinition* const enclosingTypeDef) +{ + XSElementDeclaration* xsObj = (XSElementDeclaration*) xsModel->getXSObject(elemDecl); + if (xsObj) + { + if (!xsObj->getEnclosingCTDefinition() && enclosingTypeDef) + xsObj->setEnclosingCTDefinition(enclosingTypeDef); + } + else + { + XSElementDeclaration* xsSubElem = 0; + XSTypeDefinition* xsType = 0; + XSNamedMap* icMap = 0; + + if (elemDecl->getSubstitutionGroupElem()) + xsSubElem = addOrFind(elemDecl->getSubstitutionGroupElem(), xsModel); + + // defer checking for complexTypeInfo until later as it could + // eventually need this elemement + // but don't check simple type unless no complexTypeInfo present + if (!elemDecl->getComplexTypeInfo() && elemDecl->getDatatypeValidator()) + xsType = addOrFind(elemDecl->getDatatypeValidator(), xsModel); + + XMLSize_t count = elemDecl->getIdentityConstraintCount(); + if (count) + { + //REVISIT: size of hash table.... + icMap = new (fMemoryManager) XSNamedMap + ( + count + , 29 + , xsModel->getURIStringPool() + , false + , fMemoryManager + ); + + for (XMLSize_t i = 0; i < count; i++) + { + XSIDCDefinition* icDef = addOrFind + ( + elemDecl->getIdentityConstraintAt(i) + , xsModel + ); + if (icDef) + { + icMap->addElement + ( + icDef + , icDef->getName() + , icDef->getNamespace() + ); + } + } + } + + XSConstants::SCOPE elemScope = XSConstants::SCOPE_ABSENT; + if (elemDecl->getPSVIScope() == PSVIDefs::SCP_LOCAL) + elemScope = XSConstants::SCOPE_LOCAL; + else if (elemDecl->getPSVIScope() == PSVIDefs::SCP_GLOBAL) + elemScope = XSConstants::SCOPE_GLOBAL; + + xsObj = new (fMemoryManager) XSElementDeclaration + ( + elemDecl + , xsType + , xsSubElem + , getAnnotationFromModel(xsModel, elemDecl) + , icMap + , xsModel + , elemScope + , enclosingTypeDef + , fMemoryManager + ); + putObjectInMap(elemDecl, xsObj); + + if (elemDecl->getComplexTypeInfo()) + { + xsType = addOrFind(elemDecl->getComplexTypeInfo(), xsModel); + xsObj->setTypeDefinition(xsType); + } + else if (!xsType) + { + xsType = xsModel->getTypeDefinition + ( + SchemaSymbols::fgATTVAL_ANYTYPE + , SchemaSymbols::fgURI_SCHEMAFORSCHEMA + ); + xsObj->setTypeDefinition(xsType); + } + } + + return xsObj; +} + +XSComplexTypeDefinition* +XSObjectFactory::addOrFind(ComplexTypeInfo* const typeInfo, + XSModel* const xsModel) +{ + XSComplexTypeDefinition* xsObj = (XSComplexTypeDefinition*) xsModel->getXSObject(typeInfo); + if (!xsObj) + { + XSWildcard* xsWildcard = 0; + XSSimpleTypeDefinition* xsSimpleType = 0; + XSAttributeUseList* xsAttList = 0; + XSTypeDefinition* xsBaseType = 0; + XSParticle* xsParticle = 0; + + if (typeInfo->getAttWildCard()) + xsWildcard = createXSWildcard(typeInfo->getAttWildCard(), xsModel); + + if ((typeInfo->getContentType() == SchemaElementDecl::Simple) && + (typeInfo->getDatatypeValidator())) + xsSimpleType = addOrFind(typeInfo->getDatatypeValidator(), xsModel); + + XMLSize_t attCount=0; + if (typeInfo->hasAttDefs()) + { + SchemaAttDefList& attDefList = (SchemaAttDefList&) typeInfo->getAttDefList(); + attCount = attDefList.getAttDefCount(); + xsAttList = new (fMemoryManager) RefVectorOf(attCount, false, fMemoryManager); + // create list now put fill it in after we put complextype into map + // otherwise we may encounter an infinite loop: complextype needs to + // addorfind attdef, which does an addorfind on the enclosingCTdefintion. + } + + // compute fBase + bool isAnyType = false; + if (typeInfo->getBaseComplexTypeInfo() == typeInfo) // case of anyType + isAnyType = true; + else if (typeInfo->getBaseComplexTypeInfo()) + xsBaseType = addOrFind(typeInfo->getBaseComplexTypeInfo(), xsModel); + else if (typeInfo->getBaseDatatypeValidator()) + xsBaseType = addOrFind(typeInfo->getBaseDatatypeValidator(), xsModel); + else // base is anyType + xsBaseType = xsModel->getTypeDefinition(SchemaSymbols::fgATTVAL_ANYTYPE, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + + // compute particle + ContentSpecNode* contentSpec = typeInfo->getContentSpec(); + if (contentSpec) + xsParticle = createModelGroupParticle(contentSpec, xsModel); + + xsObj = new (fMemoryManager) XSComplexTypeDefinition + ( + typeInfo + , xsWildcard + , xsSimpleType + , xsAttList + , xsBaseType + , xsParticle + , getAnnotationFromModel(xsModel, typeInfo) + , xsModel + , fMemoryManager + ); + putObjectInMap(typeInfo, xsObj); + + if (isAnyType) + xsObj->setBaseType(xsObj); + + if (typeInfo->hasAttDefs()) + { + // now create the xsattributedeclarations... + SchemaAttDefList& attDefList = (SchemaAttDefList&) typeInfo->getAttDefList(); + for(unsigned int i=0; iput(&attDef, xsAttDecl); + } + else + xsAttDecl = addOrFind(&attDef, xsModel, xsObj); + + if (attDef.getDefaultType() != XMLAttDef::Prohibited) { + + XSAttributeUse* attUse = createXSAttributeUse(xsAttDecl, xsModel); + xsAttList->addElement(attUse); + processAttUse(&attDef, attUse); + } + } + } + + // process local elements + XMLSize_t elemCount = typeInfo->elementCount(); + for (XMLSize_t j=0; jelementAt(j); + + if (elemDecl->getEnclosingScope() == typeInfo->getScopeDefined() + && elemDecl->getPSVIScope() == PSVIDefs::SCP_LOCAL) + addOrFind(elemDecl, xsModel, xsObj); + } + } + + return xsObj; +} + +XSIDCDefinition* XSObjectFactory::addOrFind(IdentityConstraint* const ic, + XSModel* const xsModel) +{ + XSIDCDefinition* xsObj = (XSIDCDefinition*) xsModel->getXSObject(ic); + if (!xsObj) + { + XSIDCDefinition* keyIC = 0; + StringList* stringList = 0; + XMLSize_t fieldCount = ic->getFieldCount(); + + if (fieldCount) + { + stringList = new (fMemoryManager) RefArrayVectorOf( + fieldCount, true, fMemoryManager); + + for(XMLSize_t i=0; igetFieldAt(i)->getXPath()->getExpression() + , fMemoryManager + ); + stringList->addElement(expr); + } + } + + if (ic->getType() == IdentityConstraint::ICType_KEYREF) + keyIC = addOrFind(((IC_KeyRef*) ic)->getKey(), xsModel); + + xsObj= new (fMemoryManager) XSIDCDefinition + ( + ic + , keyIC + , getAnnotationFromModel(xsModel, ic) + , stringList + , xsModel + , fMemoryManager + ); + putObjectInMap(ic, xsObj); + } + + return xsObj; +} + +XSNotationDeclaration* XSObjectFactory::addOrFind(XMLNotationDecl* const notDecl, + XSModel* const xsModel) +{ + XSNotationDeclaration* xsObj = (XSNotationDeclaration*) xsModel->getXSObject(notDecl); + if (!xsObj) + { + xsObj = new (fMemoryManager) XSNotationDeclaration + ( + notDecl + , getAnnotationFromModel(xsModel, notDecl) + , xsModel + , fMemoryManager + ); + putObjectInMap(notDecl, xsObj); + } + + return xsObj; +} + +XSAttributeUse* +XSObjectFactory::createXSAttributeUse(XSAttributeDeclaration* const xsAttDecl, + XSModel* const xsModel) +{ + XSAttributeUse* attrUse = new (fMemoryManager) XSAttributeUse(xsAttDecl, xsModel, fMemoryManager); + fDeleteVector->addElement(attrUse); + + return attrUse; +} + +XSWildcard* +XSObjectFactory::createXSWildcard(SchemaAttDef* const attDef, + XSModel* const xsModel) +{ + XSAnnotation* annot = (attDef->getBaseAttDecl()) + ? getAnnotationFromModel(xsModel, attDef->getBaseAttDecl()) + : getAnnotationFromModel(xsModel, attDef); + + XSWildcard* xsWildcard = new (fMemoryManager) XSWildcard + ( + attDef + , annot + , xsModel + , fMemoryManager + ); + fDeleteVector->addElement(xsWildcard); + + return xsWildcard; +} + +XSWildcard* +XSObjectFactory::createXSWildcard(const ContentSpecNode* const rootNode, + XSModel* const xsModel) +{ + XSWildcard* xsWildcard = new (fMemoryManager) XSWildcard + ( + rootNode + , getAnnotationFromModel(xsModel, rootNode) + , xsModel + , fMemoryManager + ); + fDeleteVector->addElement(xsWildcard); + + return xsWildcard; +} + +XSModelGroupDefinition* +XSObjectFactory::createXSModelGroupDefinition(XercesGroupInfo* const groupInfo, + XSModel* const xsModel) +{ + XSParticle* particle = createModelGroupParticle( + groupInfo->getContentSpec(), xsModel); + + XSModelGroupDefinition* xsObj = new (fMemoryManager) XSModelGroupDefinition + ( + groupInfo + , particle + , getAnnotationFromModel(xsModel, groupInfo) + , xsModel + , fMemoryManager + ); + fDeleteVector->addElement(xsObj); + + // process local elements + XMLSize_t elemCount = groupInfo->elementCount(); + for (XMLSize_t j=0; jelementAt(j); + + if (elemDecl->getEnclosingScope() == groupInfo->getScope()) + addOrFind(elemDecl, xsModel); + } + + return xsObj; +} + + +XSAttributeGroupDefinition* +XSObjectFactory::createXSAttGroupDefinition(XercesAttGroupInfo* const attGroupInfo, + XSModel* const xsModel) +{ + XSAttributeUseList* xsAttList = 0; + XSWildcard* xsWildcard = 0; + XMLSize_t attCount = attGroupInfo->attributeCount(); + + if (attCount) + { + xsAttList = new (fMemoryManager) RefVectorOf(attCount, false, fMemoryManager); + for (XMLSize_t i=0; i < attCount; i++) + { + SchemaAttDef* attDef = attGroupInfo->attributeAt(i); + XSAttributeDeclaration* xsAttDecl = 0; + + if (attDef->getBaseAttDecl()) + xsAttDecl = addOrFind(attDef->getBaseAttDecl(), xsModel); + else + xsAttDecl = addOrFind(attDef, xsModel); + + if (xsAttDecl && (attDef->getDefaultType() != XMLAttDef::Prohibited)) // just for sanity + { + XSAttributeUse* attUse = createXSAttributeUse(xsAttDecl, xsModel); + xsAttList->addElement(attUse); + processAttUse(attDef, attUse); + } + } + } + + if (attGroupInfo->getCompleteWildCard()) + xsWildcard = createXSWildcard(attGroupInfo->getCompleteWildCard(), xsModel); + + XSAttributeGroupDefinition* xsObj = new (fMemoryManager) XSAttributeGroupDefinition + ( + attGroupInfo + , xsAttList + , xsWildcard + , getAnnotationFromModel(xsModel, attGroupInfo) + , xsModel + , fMemoryManager + ); + fDeleteVector->addElement(xsObj); + + return xsObj; +} + +XSAnnotation* XSObjectFactory::getAnnotationFromModel(XSModel* const xsModel, + const void* const key) +{ + XSNamespaceItemList* namespaceItemList = xsModel->getNamespaceItems(); + + XSAnnotation* annot = 0; + for (unsigned int i=0; isize(); i++) + { + XSNamespaceItem* nsItem = namespaceItemList->elementAt(i); + if (nsItem->fGrammar) + { + annot = nsItem->fGrammar->getAnnotation(key); + if (annot) + return annot; + } + } + + if (xsModel->fParent) + return getAnnotationFromModel(xsModel->fParent, key); + return 0; +} + + +void XSObjectFactory::putObjectInMap(void* key, XSObject* const object) +{ + fXercesToXSMap->put(key, object); + fDeleteVector->addElement(object); +} + +void XSObjectFactory::processFacets(DatatypeValidator* const dv, + XSModel* const xsModel, + XSSimpleTypeDefinition* const xsST) +{ + // NOTE: XSMultiValueFacetList is not owned by XSModel! + // NOTE: XSFacetList is not owned by XSModel! + bool isFixed = false; + int dvFacetsDefined = dv->getFacetsDefined(); + int dvFixedFacets = dv->getFixed(); + int definedFacets = 0; + int fixedFacets = 0; + XSMultiValueFacetList* xsMultiFacetList = 0; + StringList* patternList = 0; + XSFacetList* xsFacetList = new (fMemoryManager) RefVectorOf(4, false, fMemoryManager); + + if (isMultiValueFacetDefined(dv)) + xsMultiFacetList = new (fMemoryManager) RefVectorOf(2, false, fMemoryManager); + + if (dvFacetsDefined & DatatypeValidator::FACET_ENUMERATION) + { + RefArrayVectorOf* enumList = (RefArrayVectorOf*) dv->getEnumString(); + + if (dvFixedFacets & DatatypeValidator::FACET_ENUMERATION) + { + isFixed = true; + fixedFacets |= XSSimpleTypeDefinition::FACET_ENUMERATION; + } + + XSMultiValueFacet* mvFacet = new (fMemoryManager) XSMultiValueFacet( + XSSimpleTypeDefinition::FACET_ENUMERATION , enumList, isFixed + , getAnnotationFromModel(xsModel, enumList), xsModel, fMemoryManager + ); + + fDeleteVector->addElement(mvFacet); + xsMultiFacetList->addElement(mvFacet); + definedFacets |= XSSimpleTypeDefinition::FACET_ENUMERATION; + } + + if (dv->getFacets()) + { + RefHashTableOfEnumerator e(dv->getFacets(), false, fMemoryManager); + while (e.hasMoreElements()) + { + KVStringPair& pair = e.nextElement(); + XMLCh* key = pair.getKey(); + XSSimpleTypeDefinition::FACET facetType; + XSAnnotation* annot = getAnnotationFromModel(xsModel, &pair); + + if (XMLString::equals(key, SchemaSymbols::fgELT_MAXINCLUSIVE)) + { + facetType = XSSimpleTypeDefinition::FACET_MAXINCLUSIVE; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_MAXINCLUSIVE) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MAXEXCLUSIVE)) + { + facetType = XSSimpleTypeDefinition::FACET_MAXEXCLUSIVE; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_MAXEXCLUSIVE) !=0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MININCLUSIVE)) + { + facetType = XSSimpleTypeDefinition::FACET_MININCLUSIVE; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_MININCLUSIVE) !=0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MINEXCLUSIVE)) + { + facetType = XSSimpleTypeDefinition::FACET_MINEXCLUSIVE; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_MINEXCLUSIVE) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_LENGTH)) + { + facetType = XSSimpleTypeDefinition::FACET_LENGTH; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_LENGTH) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MINLENGTH)) + { + facetType = XSSimpleTypeDefinition::FACET_MINLENGTH; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_MINLENGTH) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MAXLENGTH)) + { + facetType = XSSimpleTypeDefinition::FACET_MAXLENGTH; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_MAXLENGTH) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_TOTALDIGITS)) + { + facetType = XSSimpleTypeDefinition::FACET_TOTALDIGITS; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_TOTALDIGITS) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_FRACTIONDIGITS)) + { + facetType = XSSimpleTypeDefinition::FACET_FRACTIONDIGITS; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_FRACTIONDIGITS) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_WHITESPACE)) + { + facetType = XSSimpleTypeDefinition::FACET_WHITESPACE; + isFixed = ((dvFixedFacets & DatatypeValidator::FACET_WHITESPACE) != 0); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN) && xsMultiFacetList) + { + XMLStringTokenizer tokenizer(dv->getPattern(), regexSeparator, fMemoryManager); + patternList = new (fMemoryManager) RefArrayVectorOf( + tokenizer.countTokens(), true, fMemoryManager + ); + + while (tokenizer.hasMoreTokens()) + patternList->addElement(XMLString::replicate(tokenizer.nextToken(), fMemoryManager)); + + if (dvFixedFacets & DatatypeValidator::FACET_PATTERN) + { + isFixed = true; + fixedFacets |= XSSimpleTypeDefinition::FACET_PATTERN; + } + + XSMultiValueFacet* mvFacet = new (fMemoryManager) XSMultiValueFacet( + XSSimpleTypeDefinition::FACET_PATTERN, patternList + , isFixed, annot, xsModel, fMemoryManager + ); + fDeleteVector->addElement(mvFacet); + xsMultiFacetList->addElement(mvFacet); + definedFacets |= XSSimpleTypeDefinition::FACET_PATTERN; + continue; + } + else + { + // REVISIT: hmm... what about XSSimpleTypeDefinition::FACET_NONE + // don't think I need to create an empty Facet? + continue; + } + + XSFacet* xsFacet = new (fMemoryManager) XSFacet( + facetType, pair.getValue(), isFixed, annot, xsModel, fMemoryManager); + + fDeleteVector->addElement(xsFacet); + xsFacetList->addElement(xsFacet); + definedFacets |= facetType; + if (isFixed) + fixedFacets |= facetType; + } + } + + // add whistespace facet if missing + if ((definedFacets & XSSimpleTypeDefinition::FACET_WHITESPACE) == 0) + { + XSFacet* xsFacet = new (fMemoryManager) XSFacet( + XSSimpleTypeDefinition::FACET_WHITESPACE + , dv->getWSstring(dv->getWSFacet()) + , false, 0, xsModel, fMemoryManager); + + fDeleteVector->addElement(xsFacet); + xsFacetList->addElement(xsFacet); + definedFacets |= XSSimpleTypeDefinition::FACET_WHITESPACE; + } + + // inherit facets from base + + if (xsST->getBaseType() && xsST->getBaseType()->getTypeCategory() == XSTypeDefinition::SIMPLE_TYPE) + { + XSSimpleTypeDefinition* baseST = (XSSimpleTypeDefinition*) xsST->getBaseType(); + XSFacetList* baseFacets = baseST->getFacets(); + + for (unsigned int i=0; isize(); i++) + { + XSFacet* bFacet = baseFacets->elementAt(i); + if ((definedFacets & bFacet->getFacetKind()) == 0) + { + definedFacets |= bFacet->getFacetKind(); + xsFacetList->addElement(bFacet); + if (bFacet->isFixed()) + fixedFacets |= bFacet->getFacetKind(); + } + } + + if (baseST->getMultiValueFacets() && xsMultiFacetList) + { + XSMultiValueFacetList* baseMVFacets = baseST->getMultiValueFacets(); + for (unsigned int j=0; jsize(); j++) + { + XSMultiValueFacet* bFacet = baseMVFacets->elementAt(j); + if ((definedFacets & bFacet->getFacetKind()) == 0) + { + definedFacets |= bFacet->getFacetKind(); + xsMultiFacetList->addElement(bFacet); + if (bFacet->isFixed()) + fixedFacets |= bFacet->getFacetKind(); + } + } + } + } + + xsST->setFacetInfo(definedFacets, fixedFacets, xsFacetList, xsMultiFacetList, patternList); +} + +void XSObjectFactory::processAttUse(SchemaAttDef* const attDef, + XSAttributeUse* const xsAttUse) +{ + bool isRequired = false; + XSConstants::VALUE_CONSTRAINT constraintType = XSConstants::VALUE_CONSTRAINT_NONE; + + if (attDef->getDefaultType() == XMLAttDef::Default) + { + constraintType = XSConstants::VALUE_CONSTRAINT_DEFAULT; + } + else if ((attDef->getDefaultType() == XMLAttDef::Fixed) || + (attDef->getDefaultType() == XMLAttDef::Required_And_Fixed)) + { + constraintType = XSConstants::VALUE_CONSTRAINT_FIXED; + } + + if (attDef->getDefaultType() == XMLAttDef::Required || + attDef->getDefaultType() == XMLAttDef::Required_And_Fixed) + isRequired = true; + + xsAttUse->set(isRequired, constraintType, attDef->getValue()); +} + +bool XSObjectFactory::isMultiValueFacetDefined(DatatypeValidator* const dv) +{ + DatatypeValidator* tmpDV = dv; + + while (tmpDV) + { + if ((tmpDV->getFacetsDefined() & DatatypeValidator::FACET_PATTERN) + || (tmpDV->getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION)) + return true; + + tmpDV = tmpDV->getBaseValidator(); + } + + return false; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XSObjectFactory.hpp b/include/xercesc/internal/XSObjectFactory.hpp new file mode 100644 index 0000000..3621e0b --- /dev/null +++ b/include/xercesc/internal/XSObjectFactory.hpp @@ -0,0 +1,237 @@ +/* + * 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: XSObjectFactory.hpp 678409 2008-07-21 13:08:10Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSOBJECTFACTORY_HPP) +#define XERCESC_INCLUDE_GUARD_XSOBJECTFACTORY_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XSObject; +class XSAttributeUse; +class XSAttributeDeclaration; +class XSModel; +class XSElementDeclaration; +class XSSimpleTypeDefinition; +class XSComplexTypeDefinition; +class XSModelGroupDefinition; +class XSAttributeGroupDefinition; +class XSWildcard; +class XSParticle; +class XSAnnotation; +class XSNamespaceItem; +class XSNotationDeclaration; +class SchemaAttDef; +class SchemaElementDecl; +class DatatypeValidator; +class ContentSpecNode; +class ComplexTypeInfo; +class XercesGroupInfo; +class XercesAttGroupInfo; +class XSIDCDefinition; +class IdentityConstraint; +class XMLNotationDecl; + +/** + * Factory class to create various XSObject(s) + * Used by XSModel + */ +class XMLPARSER_EXPORT XSObjectFactory : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + XSObjectFactory(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~XSObjectFactory(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and destructor + // ----------------------------------------------------------------------- + XSObjectFactory(const XSObjectFactory&); + XSObjectFactory& operator=(const XSObjectFactory&); + + // ----------------------------------------------------------------------- + // factory methods + // ----------------------------------------------------------------------- + XSParticle* createModelGroupParticle + ( + const ContentSpecNode* const node + , XSModel* const xsModel + ); + + XSAttributeDeclaration* addOrFind + ( + SchemaAttDef* const attDef + , XSModel* const xsModel + , XSComplexTypeDefinition* const enclosingTypeDef = 0 + ); + + XSSimpleTypeDefinition* addOrFind + ( + DatatypeValidator* const validator + , XSModel* const xsModel + , bool isAnySimpleType = false + ); + + XSElementDeclaration* addOrFind + ( + SchemaElementDecl* const elemDecl + , XSModel* const xsModel + , XSComplexTypeDefinition* const enclosingTypeDef = 0 + ); + + XSComplexTypeDefinition* addOrFind + ( + ComplexTypeInfo* const typeInfo + , XSModel* const xsModel + ); + + XSIDCDefinition* addOrFind + ( + IdentityConstraint* const ic + , XSModel* const xsModel + ); + + XSNotationDeclaration* addOrFind + ( + XMLNotationDecl* const notDecl + , XSModel* const xsModel + ); + + XSAttributeUse* createXSAttributeUse + ( + XSAttributeDeclaration* const xsAttDecl + , XSModel* const xsModel + ); + XSWildcard* createXSWildcard + ( + SchemaAttDef* const attDef + , XSModel* const xsModel + ); + + XSWildcard* createXSWildcard + ( + const ContentSpecNode* const rootNode + , XSModel* const xsModel + ); + + XSModelGroupDefinition* createXSModelGroupDefinition + ( + XercesGroupInfo* const groupInfo + , XSModel* const xsModel + ); + + XSAttributeGroupDefinition* createXSAttGroupDefinition + ( + XercesAttGroupInfo* const attGroupInfo + , XSModel* const xsModel + ); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + // creates a particle corresponding to an element + XSParticle* createElementParticle + ( + const ContentSpecNode* const rootNode + , XSModel* const xsModel + ); + + // creates a particle corresponding to a wildcard + XSParticle* createWildcardParticle + ( + const ContentSpecNode* const rootNode + , XSModel* const xsModel + ); + + XSAnnotation* getAnnotationFromModel + ( + XSModel* const xsModel + , const void* const key + ); + + void buildAllParticles + ( + const ContentSpecNode* const rootNode + , XSParticleList* const particleList + , XSModel* const xsModel + ); + + void buildChoiceSequenceParticles + ( + const ContentSpecNode* const rootNode + , XSParticleList* const particleList + , XSModel* const xsModel + ); + + void putObjectInMap + ( + void* key + , XSObject* const object + ); + + XSObject* getObjectFromMap + ( + void* key + ); + + void processFacets + ( + DatatypeValidator* const dv + , XSModel* const xsModel + , XSSimpleTypeDefinition* const xsST + ); + + void processAttUse + ( + SchemaAttDef* const attDef + , XSAttributeUse* const xsAttUse + ); + + bool isMultiValueFacetDefined(DatatypeValidator* const dv); + + // make XSModel our friend + friend class XSModel; + + // ----------------------------------------------------------------------- + // Private Data Members + // + // fMemoryManager + // The memory manager used to create various XSObject(s). + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + RefHashTableOf* fXercesToXSMap; + RefVectorOf* fDeleteVector; +}; + +inline XSObject* XSObjectFactory::getObjectFromMap(void* key) +{ + return fXercesToXSMap->get(key); +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XSerializable.hpp b/include/xercesc/internal/XSerializable.hpp new file mode 100644 index 0000000..5e3a33c --- /dev/null +++ b/include/xercesc/internal/XSerializable.hpp @@ -0,0 +1,117 @@ +/* + * 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: XSerializable.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSERIALIZABLE_HPP) +#define XERCESC_INCLUDE_GUARD_XSERIALIZABLE_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT XSerializable +{ +public : + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + virtual ~XSerializable() {} ; + + // ----------------------------------------------------------------------- + // Serialization Interface + // ----------------------------------------------------------------------- + virtual bool isSerializable() const = 0; + + virtual void serialize(XSerializeEngine& ) = 0; + + virtual XProtoType* getProtoType() const = 0; + +protected: + XSerializable() {} + XSerializable(const XSerializable& ) {} + +private: + // ----------------------------------------------------------------------- + // Unimplemented assignment operator + // ----------------------------------------------------------------------- + XSerializable& operator=(const XSerializable&); + +}; + +inline void XSerializable::serialize(XSerializeEngine& ) +{ +} + +/*** + * Macro to be included in XSerializable derivatives' + * declaration's public section + ***/ +#define DECL_XSERIALIZABLE(class_name) \ +public: \ +\ +DECL_XPROTOTYPE(class_name) \ +\ +virtual bool isSerializable() const ; \ +virtual XProtoType* getProtoType() const; \ +virtual void serialize(XSerializeEngine&); \ +\ +inline friend XSerializeEngine& operator>>(XSerializeEngine& serEng \ + , class_name*& objPtr) \ +{objPtr = (class_name*) serEng.read(XPROTOTYPE_CLASS(class_name)); \ + return serEng; \ +}; + +/*** + * Macro to be included in the implementation file + * of XSerializable derivatives' which is instantiable + ***/ +#define IMPL_XSERIALIZABLE_TOCREATE(class_name) \ +IMPL_XPROTOTYPE_TOCREATE(class_name) \ +IMPL_XSERIAL(class_name) + +/*** + * Macro to be included in the implementation file + * of XSerializable derivatives' which is UN-instantiable + ***/ +#define IMPL_XSERIALIZABLE_NOCREATE(class_name) \ +IMPL_XPROTOTYPE_NOCREATE(class_name) \ +IMPL_XSERIAL(class_name) + +/*** + * Helper Macro + ***/ +#define IMPL_XSERIAL(class_name) \ +bool class_name::isSerializable() const \ +{return true; } \ +XProtoType* class_name::getProtoType() const \ +{return XPROTOTYPE_CLASS(class_name); } + +#define IS_EQUIVALENT(lptr, rptr) \ + if (lptr == rptr) \ + return true; \ + if (( lptr && !rptr) || (!lptr && rptr)) \ + return false; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/internal/XSerializationException.hpp b/include/xercesc/internal/XSerializationException.hpp new file mode 100644 index 0000000..fccf15e --- /dev/null +++ b/include/xercesc/internal/XSerializationException.hpp @@ -0,0 +1,34 @@ +/* + * 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: XSerializationException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSERIALIZATION_EXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_XSERIALIZATION_EXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(XSerializationException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XSerializeEngine.cpp b/include/xercesc/internal/XSerializeEngine.cpp new file mode 100644 index 0000000..c66cfe1 --- /dev/null +++ b/include/xercesc/internal/XSerializeEngine.cpp @@ -0,0 +1,1158 @@ +/* + * 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: XSerializeEngine.cpp 834826 2009-11-11 10:03:53Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +#include +#include +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +const bool XSerializeEngine::toWriteBufferLen = true; +const bool XSerializeEngine::toReadBufferLen = true; + +static const unsigned long noDataFollowed = (unsigned long)-1; + +static const XSerializeEngine::XSerializedObjectId_t fgNullObjectTag = 0; // indicating null ptrs +static const XSerializeEngine::XSerializedObjectId_t fgNewClassTag = 0xFFFFFFFF; // indicating new class +static const XSerializeEngine::XSerializedObjectId_t fgTemplateObjTag = 0xFFFFFFFE; // indicating template object +static const XSerializeEngine::XSerializedObjectId_t fgClassMask = 0x80000000; // indicates class tag +static const XSerializeEngine::XSerializedObjectId_t fgMaxObjectCount = 0x3FFFFFFD; + +#define TEST_THROW_ARG1(condition, data, err_msg) \ +if (condition) \ +{ \ + XMLCh value1[64]; \ + XMLString::sizeToText(data, value1, 65, 10, getMemoryManager()); \ + ThrowXMLwithMemMgr1(XSerializationException \ + , err_msg \ + , value1 \ + , getMemoryManager()); \ +} + +#define TEST_THROW_ARG2(condition, data1, data2, err_msg) \ +if (condition) \ +{ \ + XMLCh value1[64]; \ + XMLCh value2[64]; \ + XMLString::sizeToText(data1, value1, 65, 10, getMemoryManager()); \ + XMLString::sizeToText(data2, value2, 65, 10, getMemoryManager()); \ + ThrowXMLwithMemMgr2(XSerializationException \ + , err_msg \ + , value1 \ + , value2 \ + , getMemoryManager()); \ +} + +// --------------------------------------------------------------------------- +// Constructor and Destructor +// --------------------------------------------------------------------------- +XSerializeEngine::~XSerializeEngine() +{ + if (isStoring()) + { + flush(); + delete fStorePool; + } + else + { + delete fLoadPool; + } + + getMemoryManager()->deallocate(fBufStart); + +} + +XSerializeEngine::XSerializeEngine(BinInputStream* inStream + , XMLGrammarPool* const gramPool + , XMLSize_t bufSize) +:fStoreLoad(mode_Load) +,fStorerLevel(0) +,fGrammarPool(gramPool) +,fInputStream(inStream) +,fOutputStream(0) +,fBufCount(0) +,fBufSize(bufSize) +,fBufStart( (XMLByte*) gramPool->getMemoryManager()->allocate(bufSize)) +,fBufEnd(0) +,fBufCur(fBufStart) +,fBufLoadMax(fBufStart) +,fStorePool(0) +,fLoadPool( new (gramPool->getMemoryManager()) ValueVectorOf(29, gramPool->getMemoryManager(), false)) +,fObjectCount(0) +{ + /*** + * initialize buffer from the inStream + ***/ + fillBuffer(); + +} + +XSerializeEngine::XSerializeEngine(BinOutputStream* outStream + , XMLGrammarPool* const gramPool + , XMLSize_t bufSize) +:fStoreLoad(mode_Store) +,fStorerLevel(0) +,fGrammarPool(gramPool) +,fInputStream(0) +,fOutputStream(outStream) +,fBufCount(0) +,fBufSize(bufSize) +,fBufStart((XMLByte*) gramPool->getMemoryManager()->allocate(bufSize)) +,fBufEnd(fBufStart+bufSize) +,fBufCur(fBufStart) +,fBufLoadMax(0) +,fStorePool( new (gramPool->getMemoryManager()) RefHashTableOf(29, true, gramPool->getMemoryManager()) ) +,fLoadPool(0) +,fObjectCount(0) +{ + resetBuffer(); + + //initialize store pool + fStorePool->put(0, new (gramPool->getMemoryManager()) XSerializedObjectId(fgNullObjectTag)); + +} + +void XSerializeEngine::flush() +{ + if (isStoring()) + flushBuffer(); + +} + +// --------------------------------------------------------------------------- +// Storing +// --------------------------------------------------------------------------- +void XSerializeEngine::write(XSerializable* const objectToWrite) +{ + ensureStoring(); + //don't ensurePointer here !!! + + XSerializedObjectId_t objIndex = 0; + + if (!objectToWrite) // null pointer + { + *this << fgNullObjectTag; + } + else if (0 != (objIndex = lookupStorePool((void*) objectToWrite))) + { + // writing an object reference tag + *this << objIndex; + } + else + { + // write protoType first + XProtoType* protoType = objectToWrite->getProtoType(); + write(protoType); + + // put the object into StorePool + addStorePool((void*)objectToWrite); + + // ask the object to serialize itself + objectToWrite->serialize(*this); + } + +} + +void XSerializeEngine::write(XProtoType* const protoType) +{ + ensureStoring(); + ensurePointer(protoType); + + XSerializedObjectId_t objIndex = lookupStorePool((void*)protoType); + + if (objIndex) + { + //protoType seen in the store pool + *this << (fgClassMask | objIndex); + } + else + { + // store protoType + *this << fgNewClassTag; + protoType->store(*this); + addStorePool((void*)protoType); + } + +} + +/*** + * +***/ +void XSerializeEngine::write(const XMLCh* const toWrite + , XMLSize_t writeLen) +{ + write((XMLByte*)toWrite, (sizeof(XMLCh)/sizeof(XMLByte)) * writeLen); +} + + +void XSerializeEngine::write(const XMLByte* const toWrite + , XMLSize_t writeLen) +{ + ensureStoring(); + ensurePointer((void*)toWrite); + ensureStoreBuffer(); + + if (writeLen == 0) + return; + + /*** + * If the available space is sufficient, write it up + ***/ + XMLSize_t bufAvail = fBufEnd - fBufCur; + + if (writeLen <= bufAvail) + { + memcpy(fBufCur, toWrite, writeLen); + fBufCur += writeLen; + return; + } + + const XMLByte* tempWrite = (const XMLByte*) toWrite; + XMLSize_t writeRemain = writeLen; + + // fill up the avaiable space and flush + memcpy(fBufCur, tempWrite, bufAvail); + tempWrite += bufAvail; + writeRemain -= bufAvail; + flushBuffer(); + + // write chunks of fBufSize + while (writeRemain >= fBufSize) + { + memcpy(fBufCur, tempWrite, fBufSize); + tempWrite += fBufSize; + writeRemain -= fBufSize; + flushBuffer(); + } + + // write the remaining if any + if (writeRemain) + { + memcpy(fBufCur, tempWrite, writeRemain); + fBufCur += writeRemain; + } + +} + +/*** + * + * Storage scheme (normal): + * + * < + * 1st integer: bufferLen (optional) + * 2nd integer: dataLen + * bytes following: + * > + * + * Storage scheme (special): + * < + * only integer: noDataFollowed + * > + */ + +void XSerializeEngine::writeString(const XMLCh* const toWrite + , const XMLSize_t bufferLen + , bool toWriteBufLen) +{ + if (toWrite) + { + if (toWriteBufLen) + *this<<(unsigned long)bufferLen; + + XMLSize_t strLen = XMLString::stringLen(toWrite); + *this<<(unsigned long)strLen; + + write(toWrite, strLen); + } + else + { + *this<fCreateObject(getMemoryManager()); + Assert((objRet != 0), XMLExcepts::XSer_CreateObject_Fail); + + // put it into load pool + addLoadPool(objRet); + + // de-serialize it + objRet->serialize(*this); + + } + + return objRet; +} + +bool XSerializeEngine::read(XProtoType* const protoType + , XSerializedObjectId_t* objectTagRet) +{ + ensureLoading(); + ensurePointer(protoType); + + XSerializedObjectId_t obTag; + + *this >> obTag; + + // object reference tag found + if (!(obTag & fgClassMask)) + { + *objectTagRet = obTag; + return false; + } + + if (obTag == fgNewClassTag) + { + // what follows fgNewClassTag is the prototype object info + // for the object anticipated, go and verify the info + XProtoType::load(*this, protoType->fClassName, getMemoryManager()); + + addLoadPool((void*)protoType); + } + else + { + // what follows class tag is an XSerializable object + XSerializedObjectId_t classIndex = (obTag & ~fgClassMask); + XSerializedObjectId_t loadPoolSize = (XSerializedObjectId_t)fLoadPool->size(); + + if ((classIndex == 0 ) || (classIndex > loadPoolSize)) + { + XMLCh value1[64]; + XMLCh value2[64]; + XMLString::binToText(classIndex, value1, 65, 10, getMemoryManager()); + XMLString::binToText(loadPoolSize, value2, 65, 10, getMemoryManager()); + ThrowXMLwithMemMgr2(XSerializationException + , XMLExcepts::XSer_Inv_ClassIndex + , value1 + , value2 + , getMemoryManager()); + } + + ensurePointer(lookupLoadPool(classIndex)); + } + + return true; +} + +void XSerializeEngine::read(XMLCh* const toRead + , XMLSize_t readLen) +{ + read((XMLByte*)toRead, (sizeof(XMLCh)/sizeof(XMLByte))*readLen); +} + +void XSerializeEngine::read(XMLByte* const toRead + , XMLSize_t readLen) +{ + ensureLoading(); + ensurePointer(toRead); + ensureLoadBuffer(); + + if (readLen == 0) + return; + + /*** + * If unread is sufficient, read it up + ***/ + XMLSize_t dataAvail = fBufLoadMax - fBufCur; + + if (readLen <= dataAvail) + { + memcpy(toRead, fBufCur, readLen); + fBufCur += readLen; + return; + } + + /*** + * + * fillBuffer will discard anything left in the buffer + * before it asks the inputStream to fill in the buffer, + * so we need to readup everything in the buffer before + * calling fillBuffer + * + ***/ + XMLByte* tempRead = (XMLByte*) toRead; + XMLSize_t readRemain = readLen; + + // read the unread + memcpy(tempRead, fBufCur, dataAvail); + tempRead += dataAvail; + readRemain -= dataAvail; + + // read chunks of fBufSize + while (readRemain >= fBufSize) + { + fillBuffer(); + memcpy(tempRead, fBufCur, fBufSize); + tempRead += fBufSize; + readRemain -= fBufSize; + } + + // read the remaining if any + if (readRemain) + { + fillBuffer(); + memcpy(tempRead, fBufCur, readRemain); + fBufCur += readRemain; + } + +} + +/*** + * + * Storage scheme (normal): + * + * < + * 1st integer: bufferLen (optional) + * 2nd integer: dataLen + * bytes following: + * > + * + * Storage scheme (special): + * < + * only integer: noDataFollowed + * > + */ +void XSerializeEngine::readString(XMLCh*& toRead + , XMLSize_t& bufferLen + , XMLSize_t& dataLen + , bool toReadBufLen) +{ + /*** + * Check if any data written + ***/ + unsigned long tmp; + *this>>tmp; + bufferLen=tmp; + + if (bufferLen == noDataFollowed) + { + toRead = 0; + bufferLen = 0; + dataLen = 0; + return; + } + + if (toReadBufLen) + { + *this>>tmp; + dataLen=tmp; + } + else + { + dataLen = bufferLen++; + } + + toRead = (XMLCh*) getMemoryManager()->allocate(bufferLen * sizeof(XMLCh)); + read(toRead, dataLen); + toRead[dataLen] = 0; +} + +void XSerializeEngine::readString(XMLByte*& toRead + , XMLSize_t& bufferLen + , XMLSize_t& dataLen + , bool toReadBufLen) +{ + /*** + * Check if any data written + ***/ + unsigned long tmp; + *this>>tmp; + bufferLen=tmp; + if (bufferLen == noDataFollowed) + { + toRead = 0; + bufferLen = 0; + dataLen = 0; + return; + } + + if (toReadBufLen) + { + *this>>tmp; + dataLen=tmp; + } + else + { + dataLen = bufferLen++; + } + + toRead = (XMLByte*) getMemoryManager()->allocate(bufferLen * sizeof(XMLByte)); + read(toRead, dataLen); + toRead[dataLen] = 0; + +} + +// --------------------------------------------------------------------------- +// Insertion & Extraction +// --------------------------------------------------------------------------- + +XSerializeEngine& XSerializeEngine::operator<<(XMLCh xch) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(XMLCh))); + + alignBufCur(sizeof(XMLCh)); + *(XMLCh*)fBufCur = xch; + fBufCur += sizeof(XMLCh); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(XMLCh& xch) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(XMLCh))); + + alignBufCur(sizeof(XMLCh)); + xch = *(XMLCh*)fBufCur; + fBufCur += sizeof(XMLCh); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(XMLByte by) +{ + checkAndFlushBuffer(sizeof(XMLByte)); + + *(XMLByte*)fBufCur = by; + fBufCur += sizeof(XMLByte); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(XMLByte& by) +{ + checkAndFillBuffer(sizeof(XMLByte)); + + by = *(XMLByte*)fBufCur; + fBufCur += sizeof(XMLByte); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(bool b) +{ + checkAndFlushBuffer(sizeof(bool)); + + *(bool*)fBufCur = b; + fBufCur += sizeof(bool); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(bool& b) +{ + checkAndFillBuffer(sizeof(bool)); + + b = *(bool*)fBufCur; + fBufCur += sizeof(bool); + return *this; +} + +void XSerializeEngine::writeSize (XMLSize_t t) +{ + checkAndFlushBuffer(sizeof(t)); + + memcpy(fBufCur, &t, sizeof(t)); + fBufCur += sizeof(t); +} + +void XSerializeEngine::writeInt64 (XMLInt64 t) +{ + checkAndFlushBuffer(sizeof(t)); + + memcpy(fBufCur, &t, sizeof(t)); + fBufCur += sizeof(t); +} + +void XSerializeEngine::writeUInt64 (XMLUInt64 t) +{ + checkAndFlushBuffer(sizeof(t)); + + memcpy(fBufCur, &t, sizeof(t)); + fBufCur += sizeof(t); +} + +void XSerializeEngine::readSize (XMLSize_t& t) +{ + checkAndFillBuffer(sizeof(t)); + + memcpy(&t, fBufCur, sizeof(t)); + fBufCur += sizeof(t); +} + +void XSerializeEngine::readInt64 (XMLInt64& t) +{ + checkAndFillBuffer(sizeof(t)); + + memcpy(&t, fBufCur, sizeof(t)); + fBufCur += sizeof(t); +} + +void XSerializeEngine::readUInt64 (XMLUInt64& t) +{ + checkAndFillBuffer(sizeof(t)); + + memcpy(&t, fBufCur, sizeof(t)); + fBufCur += sizeof(t); +} + +XSerializeEngine& XSerializeEngine::operator<<(char ch) +{ + return XSerializeEngine::operator<<((XMLByte)ch); +} + +XSerializeEngine& XSerializeEngine::operator>>(char& ch) +{ + return XSerializeEngine::operator>>((XMLByte&)ch); +} + +XSerializeEngine& XSerializeEngine::operator<<(short sh) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(short))); + + alignBufCur(sizeof(short)); + *(short*)fBufCur = sh; + fBufCur += sizeof(short); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(short& sh) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(short))); + + alignBufCur(sizeof(short)); + sh = *(short*)fBufCur; + fBufCur += sizeof(short); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(int i) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(int))); + + alignBufCur(sizeof(int)); + *(int*)fBufCur = i; + fBufCur += sizeof(int); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(int& i) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(int))); + + alignBufCur(sizeof(int)); + i = *(int*)fBufCur; + fBufCur += sizeof(int); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(unsigned int ui) +{ + + checkAndFlushBuffer(calBytesNeeded(sizeof(unsigned int))); + + alignBufCur(sizeof(unsigned int)); + *(unsigned int*)fBufCur = ui; + fBufCur += sizeof(unsigned int); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(unsigned int& ui) +{ + + checkAndFillBuffer(calBytesNeeded(sizeof(unsigned int))); + + alignBufCur(sizeof(unsigned int)); + ui = *(unsigned int*)fBufCur; + fBufCur += sizeof(unsigned int); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(long l) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(long))); + + alignBufCur(sizeof(long)); + *(long*)fBufCur = l; + fBufCur += sizeof(long); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(long& l) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(long))); + + alignBufCur(sizeof(long)); + l = *(long*)fBufCur; + fBufCur += sizeof(long); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(unsigned long ul) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(unsigned long))); + + alignBufCur(sizeof(unsigned long)); + *(unsigned long*)fBufCur = ul; + fBufCur += sizeof(unsigned long); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(unsigned long& ul) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(unsigned long))); + + alignBufCur(sizeof(unsigned long)); + ul = *(unsigned long*)fBufCur; + fBufCur += sizeof(unsigned long); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(float f) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(float))); + + alignBufCur(sizeof(float)); + *(float*)fBufCur = *(float*)&f; + fBufCur += sizeof(float); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(float& f) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(float))); + + alignBufCur(sizeof(float)); + *(float*)&f = *(float*)fBufCur; + fBufCur += sizeof(float); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator<<(double d) +{ + checkAndFlushBuffer(calBytesNeeded(sizeof(double))); + + alignBufCur(sizeof(double)); + *(double*)fBufCur = *(double*)&d; + fBufCur += sizeof(double); + return *this; +} + +XSerializeEngine& XSerializeEngine::operator>>(double& d) +{ + checkAndFillBuffer(calBytesNeeded(sizeof(double))); + + alignBufCur(sizeof(double)); + *(double*)&d = *(double*)fBufCur; + fBufCur += sizeof(double); + return *this; +} + +// --------------------------------------------------------------------------- +// StorePool/LoadPool Opertions +// --------------------------------------------------------------------------- +XSerializeEngine::XSerializedObjectId_t +XSerializeEngine::lookupStorePool(void* const objToLookup) const +{ + //0 indicating object is not in the StorePool + XSerializedObjectId* data = fStorePool->get(objToLookup); + return (XSerializeEngine::XSerializedObjectId_t) (data ? data->getValue() : 0); + +} + +void XSerializeEngine::addStorePool(void* const objToAdd) +{ + pumpCount(); + fStorePool->put(objToAdd, new (fGrammarPool->getMemoryManager()) XSerializedObjectId(fObjectCount)); +} + +XSerializable* XSerializeEngine::lookupLoadPool(XSerializedObjectId_t objectTag) const +{ + + /*** + * an object tag read from the binary refering to + * an object beyond the upper most boundary of the load pool + ***/ + + if (objectTag > fLoadPool->size()) + { + XMLCh value1[64]; + XMLCh value2[64]; + XMLString::binToText(objectTag, value1, 65, 10, getMemoryManager()); + XMLString::sizeToText(fLoadPool->size(), value2, 65, 10, getMemoryManager()); + ThrowXMLwithMemMgr2(XSerializationException + , XMLExcepts::XSer_LoadPool_UppBnd_Exceed + , value1 + , value2 + , getMemoryManager()); + } + + if (objectTag == 0) + return 0; + + /*** + * A non-null object tag starts from 1 while fLoadPool starts from 0 + ***/ + return (XSerializable*) fLoadPool->elementAt(objectTag - 1); +} + +void XSerializeEngine::addLoadPool(void* const objToAdd) +{ + + TEST_THROW_ARG2( (fLoadPool->size() != fObjectCount) + , fObjectCount + , fLoadPool->size() + , XMLExcepts::XSer_LoadPool_NoTally_ObjCnt + ) + + pumpCount(); + fLoadPool->addElement(objToAdd); + +} + +void XSerializeEngine::pumpCount() +{ + if (fObjectCount >= fgMaxObjectCount) + { + XMLCh value1[64]; + XMLCh value2[64]; + XMLString::sizeToText(fObjectCount, value1, 65, 10, getMemoryManager()); + XMLString::binToText(fgMaxObjectCount, value2, 65, 10, getMemoryManager()); + ThrowXMLwithMemMgr2(XSerializationException + , XMLExcepts::XSer_ObjCount_UppBnd_Exceed + , value1 + , value2 + , getMemoryManager()); + } + + fObjectCount++; + +} + +// --------------------------------------------------------------------------- +// Buffer Opertions +// --------------------------------------------------------------------------- +/*** + * + * Though client may need only miniBytesNeeded, we always request + * a full size reading from our inputStream. + * + * Whatever possibly left in the buffer is abandoned, such as in + * the case of CheckAndFillBuffer() + * + ***/ +void XSerializeEngine::fillBuffer() +{ + ensureLoading(); + ensureLoadBuffer(); + + resetBuffer(); + + XMLSize_t bytesRead = fInputStream->readBytes(fBufStart, fBufSize); + + /*** + * InputStream MUST fill in the exact amount of bytes as requested + * to do: combine the checking and create a new exception code later + ***/ + TEST_THROW_ARG2( (bytesRead < fBufSize) + , bytesRead + , fBufSize + , XMLExcepts::XSer_InStream_Read_LT_Req + ) + + TEST_THROW_ARG2( (bytesRead > fBufSize) + , bytesRead + , fBufSize + , XMLExcepts::XSer_InStream_Read_OverFlow + ) + + fBufLoadMax = fBufStart + fBufSize; + fBufCur = fBufStart; + + ensureLoadBuffer(); + + fBufCount++; +} + +/*** + * + * Flush out whatever left in the buffer, from + * fBufStart to fBufEnd. + * + ***/ +void XSerializeEngine::flushBuffer() +{ + ensureStoring(); + ensureStoreBuffer(); + + fOutputStream->writeBytes(fBufStart, fBufSize); + fBufCur = fBufStart; + + resetBuffer(); + ensureStoreBuffer(); + + fBufCount++; +} + +inline void XSerializeEngine::checkAndFlushBuffer(XMLSize_t bytesNeedToWrite) +{ + TEST_THROW_ARG1( (bytesNeedToWrite <= 0) + , bytesNeedToWrite + , XMLExcepts::XSer_Inv_checkFlushBuffer_Size + ) + + // fBufStart ... fBufCur ...fBufEnd + if ((fBufCur + bytesNeedToWrite) > fBufEnd) + flushBuffer(); +} + +inline void XSerializeEngine::checkAndFillBuffer(XMLSize_t bytesNeedToRead) +{ + + TEST_THROW_ARG1( (bytesNeedToRead <= 0) + , bytesNeedToRead + , XMLExcepts::XSer_Inv_checkFillBuffer_Size + ) + + // fBufStart ... fBufCur ...fBufLoadMax + if ((fBufCur + bytesNeedToRead) > fBufLoadMax) + { + fillBuffer(); + } + +} + +inline void XSerializeEngine::ensureStoreBuffer() const +{ + XMLSize_t a = (XMLSize_t) (fBufCur - fBufStart); + XMLSize_t b = (XMLSize_t) (fBufEnd - fBufCur); + + TEST_THROW_ARG2 ( !((fBufStart <= fBufCur) && (fBufCur <= fBufEnd)) + , a + , b + , XMLExcepts::XSer_StoreBuffer_Violation + ) + +} + +inline void XSerializeEngine::ensureLoadBuffer() const +{ + XMLSize_t a = (XMLSize_t) (fBufCur - fBufStart); + XMLSize_t b = (XMLSize_t) (fBufLoadMax - fBufCur); + + TEST_THROW_ARG2 ( !((fBufStart <= fBufCur) && (fBufCur <= fBufLoadMax)) + , a + , b + , XMLExcepts::XSer_LoadBuffer_Violation + ) + +} + +inline void XSerializeEngine::ensurePointer(void* const ptr) const +{ + + TEST_THROW_ARG1( (ptr == 0) + , 0 + , XMLExcepts::XSer_Inv_Null_Pointer + ) + +} + +inline void XSerializeEngine::resetBuffer() +{ + memset(fBufStart, 0, fBufSize * sizeof(XMLByte)); +} + +// --------------------------------------------------------------------------- +// Template object +// --------------------------------------------------------------------------- +/*** + * + * Search the store pool to see if the address has been seen before or not. + * + * If yes, write the corresponding object Tag to the internal buffer + * and return true. + * + * Otherwise, add the address to the store pool and return false + * to notifiy the client application code to store the template object. + * + ***/ +bool XSerializeEngine::needToStoreObject(void* const templateObjectToWrite) +{ + ensureStoring(); //don't ensurePointer here !!! + + XSerializedObjectId_t objIndex = 0; + + if (!templateObjectToWrite) + { + *this << fgNullObjectTag; // null pointer + return false; + } + else if (0 != (objIndex = lookupStorePool(templateObjectToWrite))) + { + *this << objIndex; // write an object reference tag + return false; + } + else + { + *this << fgTemplateObjTag; // write fgTemplateObjTag to denote that actual + // template object follows + addStorePool(templateObjectToWrite); // put the address into StorePool + return true; + } + +} + +bool XSerializeEngine::needToLoadObject(void** templateObjectToRead) +{ + ensureLoading(); + + XSerializedObjectId_t obTag; + + *this >> obTag; + + if (obTag == fgTemplateObjTag) + { + /*** + * what follows fgTemplateObjTag is the actual template object + * We need the client application to create a template object + * and register it through registerObject(), and deserialize + * template object + ***/ + return true; + } + else + { + /*** + * We hava a reference to an existing template object, get it. + */ + *templateObjectToRead = lookupLoadPool(obTag); + return false; + } + +} + +void XSerializeEngine::registerObject(void* const templateObjectToRegister) +{ + ensureLoading(); + addLoadPool(templateObjectToRegister); +} + +XMLGrammarPool* XSerializeEngine::getGrammarPool() const +{ + return fGrammarPool; +} + +XMLStringPool* XSerializeEngine::getStringPool() const +{ + return fGrammarPool->getURIStringPool(); +} + +MemoryManager* XSerializeEngine::getMemoryManager() const +{ + //todo: changed to return fGrammarPool->getMemoryManager() + return fGrammarPool ? fGrammarPool->getMemoryManager() : XMLPlatformUtils::fgMemoryManager; +} + +// +// Based on the current position (fBufCur), calculated the needed size +// to read/write +// +inline XMLSize_t XSerializeEngine::alignAdjust(XMLSize_t size) const +{ + XMLSize_t remainder = (XMLSize_t) fBufCur % size; + return (remainder == 0) ? 0 : (size - remainder); +} + +// Adjust the fBufCur +inline void XSerializeEngine::alignBufCur(XMLSize_t size) +{ + fBufCur+=alignAdjust(size); + assert(((XMLSize_t) fBufCur % size)==0); +} + +inline XMLSize_t XSerializeEngine::calBytesNeeded(XMLSize_t size) const +{ + return (alignAdjust(size) + size); +} + +void XSerializeEngine::trace(char* /*funcName*/) const +{ + return; + +/* + if (isStoring()) + printf("\n funcName=<%s>, storing, count=<%lu>, postion=<%lu>\n", funcName, fBufCount, getBufCurAccumulated()); + else + printf("\n funcName=<%s>, loading, count=<%lu>, postion=<%lu>\n", funcName, fBufCount, getBufCurAccumulated()); +*/ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XSerializeEngine.hpp b/include/xercesc/internal/XSerializeEngine.hpp new file mode 100644 index 0000000..88a4ecc --- /dev/null +++ b/include/xercesc/internal/XSerializeEngine.hpp @@ -0,0 +1,841 @@ +/* + * 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: XSerializeEngine.hpp 679296 2008-07-24 08:13:42Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSERIALIZE_ENGINE_HPP) +#define XERCESC_INCLUDE_GUARD_XSERIALIZE_ENGINE_HPP + +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XSerializable; +class XProtoType; +class MemoryManager; +class XSerializedObjectId; +class BinOutputStream; +class BinInputStream; +class XMLGrammarPool; +class XMLGrammarPoolImpl; +class XMLStringPool; + +class XMLUTIL_EXPORT XSerializeEngine +{ +public: + + enum { mode_Store + , mode_Load + }; + + + static const bool toReadBufferLen; + + typedef unsigned int XSerializedObjectId_t; + + /*** + * + * Destructor + * + ***/ + ~XSerializeEngine(); + + /*** + * + * Constructor for de-serialization(loading) + * + * Application needs to make sure that the instance of + * BinInputStream, persists beyond the life of this + * SerializeEngine. + * + * Param + * inStream input stream + * gramPool Grammar Pool + * bufSize the size of the internal buffer + * + ***/ + XSerializeEngine(BinInputStream* inStream + , XMLGrammarPool* const gramPool + , XMLSize_t bufSize = 8192 ); + + + /*** + * + * Constructor for serialization(storing) + * + * Application needs to make sure that the instance of + * BinOutputStream, persists beyond the life of this + * SerializeEngine. + * + * Param + * outStream output stream + * gramPool Grammar Pool + * bufSize the size of the internal buffer + * + ***/ + XSerializeEngine(BinOutputStream* outStream + , XMLGrammarPool* const gramPool + , XMLSize_t bufSize = 8192 ); + + /*** + * + * When serialization, flush out the internal buffer + * + * Return: + * + ***/ + void flush(); + + /*** + * + * Checking if the serialize engine is doing serialization(storing) + * + * Return: true, if it is + * false, otherwise + * + ***/ + inline bool isStoring() const; + + /*** + * + * Checking if the serialize engine is doing de-serialization(loading) + * + * Return: true, if it is + * false, otherwise + * + ***/ + inline bool isLoading() const; + + /*** + * + * Get the GrammarPool + * + * Return: XMLGrammarPool + * + ***/ + XMLGrammarPool* getGrammarPool() const; + + /*** + * + * Get the StringPool + * + * Return: XMLStringPool + * + ***/ + XMLStringPool* getStringPool() const; + + /*** + * + * Get the embeded Memory Manager + * + * Return: MemoryManager + * + ***/ + MemoryManager* getMemoryManager() const; + + /*** + * + * Get the storer level (the level of the serialize engine + * which created the binary stream that this serialize engine + * is loading). + * + * The level returned is meaningful only when + * the engine isLoading. + * + * Return: level + * + ***/ + inline unsigned int getStorerLevel() const; + + /*** + * + * Write object to the internal buffer. + * + * Param + * objectToWrite: the object to be serialized + * + * Return: + * + ***/ + void write(XSerializable* const objectToWrite); + + /*** + * + * Write prototype info to the internal buffer. + * + * Param + * protoType: instance of prototype + * + * Return: + * + ***/ + void write(XProtoType* const protoType); + + /*** + * + * Write a stream of XMLByte to the internal buffer. + * + * Param + * toWrite: the stream of XMLByte to write + * writeLen: the length of the stream + * + * Return: + * + ***/ + void write(const XMLByte* const toWrite + , XMLSize_t writeLen); + + /*** + * + * Write a stream of XMLCh to the internal buffer. + * + * Param + * toWrite: the stream of XMLCh to write + * writeLen: the length of the stream + * + * Return: + * + ***/ + void write(const XMLCh* const toWrite + , XMLSize_t writeLen); + + /*** + * + * Write a stream of XMLCh to the internal buffer. + * + * Write the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toWrite: the stream of XMLCh to write + * bufferLen: the maximum size of the buffer + * toWriteBufLen: specify if the bufferLen need to be written or not + * + * Return: + * + ***/ + void writeString(const XMLCh* const toWrite + , const XMLSize_t bufferLen = 0 + , bool toWriteBufLen = false); + + /*** + * + * Write a stream of XMLByte to the internal buffer. + * + * Write the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toWrite: the stream of XMLByte to write + * bufferLen: the maximum size of the buffer + * toWriteBufLen: specify if the bufferLen need to be written or not + * + * Return: + * + ***/ + void writeString(const XMLByte* const toWrite + , const XMLSize_t bufferLen = 0 + , bool toWriteBufLen = false); + + static const bool toWriteBufferLen; + + /*** + * + * Read/Create object from the internal buffer. + * + * Param + * protoType: an instance of prototype of the object anticipated + * + * Return: to object read/created + * + ***/ + XSerializable* read(XProtoType* const protoType); + + /*** + * + * Read prototype object from the internal buffer. + * Verify if the same prototype object found in buffer. + * + * Param + * protoType: an instance of prototype of the object anticipated + * objTag: the object Tag to an existing object + * + * Return: true : if matching found + * false : otherwise + * + ***/ + bool read(XProtoType* const protoType + , XSerializedObjectId_t* objTag); + + /*** + * + * Read XMLByte stream from the internal buffer. + * + * Param + * toRead: the buffer to hold the XMLByte stream + * readLen: the length of the XMLByte to read in + * + * Return: + * + ***/ + void read(XMLByte* const toRead + , XMLSize_t readLen); + + /*** + * + * Read XMLCh stream from the internal buffer. + * + * Param + * toRead: the buffer to hold the XMLCh stream + * readLen: the length of the XMLCh to read in + * + * Return: + * + ***/ + void read(XMLCh* const toRead + , XMLSize_t readLen); + + /*** + * + * Read a stream of XMLCh from the internal buffer. + * + * Read the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toRead: the pointer to the buffer to hold the XMLCh stream + * bufferLen: the size of the buffer created + * dataLen: the length of the stream + * toReadBufLen: specify if the bufferLen need to be read or not + * + * Return: + * + ***/ + void readString(XMLCh*& toRead + , XMLSize_t& bufferLen + , XMLSize_t& dataLen + , bool toReadBufLen = false); + + /*** + * + * Read a stream of XMLCh from the internal buffer. + * + * Read the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toRead: the pointer to the buffer to hold the XMLCh stream + * bufferLen: the size of the buffer created + * + * Return: + * + ***/ + inline void readString(XMLCh*& toRead + , XMLSize_t& bufferLen); + + /*** + * + * Read a stream of XMLCh from the internal buffer. + * + * Param + * toRead: the pointer to the buffer to hold the XMLCh stream + * + * Return: + * + ***/ + inline void readString(XMLCh*& toRead); + + /*** + * + * Read a stream of XMLByte from the internal buffer. + * + * Read the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toRead: the pointer to the buffer to hold the XMLByte stream + * bufferLen: the size of the buffer created + * dataLen: the length of the stream + * toReadBufLen: specify if the bufferLen need to be read or not + * + * Return: + * + ***/ + void readString(XMLByte*& toRead + , XMLSize_t& bufferLen + , XMLSize_t& dataLen + , bool toReadBufLen = false); + + + /*** + * + * Read a stream of XMLByte from the internal buffer. + * + * Read the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toRead: the pointer to the buffer to hold the XMLByte stream + * bufferLen: the size of the buffer created + * + * Return: + * + ***/ + inline void readString(XMLByte*& toRead + , XMLSize_t& bufferLen); + + /*** + * + * Read a stream of XMLByte from the internal buffer. + * + * Read the bufferLen first if requested, then the length + * of the stream followed by the stream. + * + * Param + * toRead: the pointer to the buffer to hold the XMLByte stream + * bufferLen: the size of the buffer created + * dataLen: the length of the stream + * toReadBufLen: specify if the bufferLen need to be read or not + * + * Return: + * + ***/ + inline void readString(XMLByte*& toRead); + + /*** + * + * Check if the template object has been stored or not + * + * Param + * objectPtr: the template object pointer + * + * Return: true : the object has NOT been stored yet + * false : otherwise + * + ***/ + bool needToStoreObject(void* const templateObjectToWrite); + + /*** + * + * Check if the template object has been loaded or not + * + * Param + * objectPtr: the address of the template object pointer + * + * Return: true : the object has NOT been loaded yet + * false : otherwise + * + ***/ + bool needToLoadObject(void** templateObjectToRead); + + /*** + * + * In the case of needToLoadObject() return true, the client + * application needs to instantiate an expected template object, and + * register the address to the engine. + * + * Param + * objectPtr: the template object pointer newly instantiated + * + * Return: + * + ***/ + void registerObject(void* const templateObjectToRegister); + + /*** + * + * Insertion operator for serializable classes + * + ***/ + + friend XSerializeEngine& operator<<(XSerializeEngine& + , XSerializable* const ); + + /*** + * + * Insertion operators for + * . basic Xerces data types + * . built-in types + * + ***/ + XSerializeEngine& operator<<(XMLByte); + XSerializeEngine& operator<<(XMLCh); + + XSerializeEngine& operator<<(char); + XSerializeEngine& operator<<(short); + XSerializeEngine& operator<<(int); + XSerializeEngine& operator<<(unsigned int); + XSerializeEngine& operator<<(long); + XSerializeEngine& operator<<(unsigned long); + XSerializeEngine& operator<<(float); + XSerializeEngine& operator<<(double); + XSerializeEngine& operator<<(bool); + + // These cannot be done as operators since on some platforms they + // may collide with int/long types. + // + void writeSize (XMLSize_t); + void writeInt64 (XMLInt64); + void writeUInt64 (XMLUInt64); + + + /*** + * + * Extraction operators for + * . basic Xerces data types + * . built-in types + * + ***/ + XSerializeEngine& operator>>(XMLByte&); + XSerializeEngine& operator>>(XMLCh&); + + XSerializeEngine& operator>>(char&); + XSerializeEngine& operator>>(short&); + XSerializeEngine& operator>>(int&); + XSerializeEngine& operator>>(unsigned int&); + XSerializeEngine& operator>>(long&); + XSerializeEngine& operator>>(unsigned long&); + XSerializeEngine& operator>>(float&); + XSerializeEngine& operator>>(double&); + XSerializeEngine& operator>>(bool&); + + void readSize (XMLSize_t&); + void readInt64 (XMLInt64&); + void readUInt64 (XMLUInt64&); + + /*** + * + * Getters + * + ***/ + inline + XMLSize_t getBufSize() const; + + inline + XMLSize_t getBufCur() const; + + inline + XMLSize_t getBufCurAccumulated() const; + + inline + unsigned long getBufCount() const; + + void trace(char*) const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSerializeEngine(); + XSerializeEngine(const XSerializeEngine&); + XSerializeEngine& operator=(const XSerializeEngine&); + + /*** + * + * Store Pool Opertions + * + ***/ + XSerializedObjectId_t lookupStorePool(void* const objectPtr) const; + void addStorePool(void* const objectPtr); + + /*** + * + * Load Pool Opertions + * + ***/ + XSerializable* lookupLoadPool(XSerializedObjectId_t objectTag) const; + void addLoadPool(void* const objectPtr); + + /*** + * + * Intenal Buffer Operations + * + ***/ + inline void checkAndFillBuffer(XMLSize_t bytesNeedToRead); + + inline void checkAndFlushBuffer(XMLSize_t bytesNeedToWrite); + + void fillBuffer(); + + void flushBuffer(); + + void pumpCount(); + + inline void resetBuffer(); + + /*** + * + * Helper + * + ***/ + inline void ensureStoring() const; + + inline void ensureLoading() const; + + inline void ensureStoreBuffer() const; + + inline void ensureLoadBuffer() const; + + inline void ensurePointer(void* const) const; + + inline void Assert(bool toEval + , const XMLExcepts::Codes toThrow) const; + + + inline XMLSize_t calBytesNeeded(XMLSize_t) const; + + inline XMLSize_t alignAdjust(XMLSize_t) const; + + inline void alignBufCur(XMLSize_t); + + // Make XTemplateSerializer friend of XSerializeEngine so that + // we can call lookupStorePool and lookupLoadPool in the case of + // annotations. + friend class XTemplateSerializer; + + // ------------------------------------------------------------------------------- + // data + // + // fStoreLoad: + // Indicator: storing(serialization) or loading(de-serialization) + // + // fStorerLevel: + // The level of the serialize engine which created the binary + // stream that this serialize engine is loading + // + // It is set by GrammarPool when loading + // + // fGrammarPool: + // Thw owning GrammarPool which instantiate this SerializeEngine + // instance + // + // fInputStream: + // Binary stream to read from (de-serialization), provided + // by client application, not owned. + // + // fOutputStream: + // Binary stream to write to (serialization), provided + // by client application, not owned. + // + // fBufSize: + // The size of the internal buffer + // + // fBufStart/fBufEnd: + // + // The internal buffer. + // fBufEnd: + // one beyond the last valid cell + // fBufEnd === (fBufStart + fBufSize) + // + // fBufCur: + // The cursor of the buffer + // + // fBufLoadMax: + // Indicating the end of the valid content in the buffer + // + // fStorePool: + // Object collection for storing + // + // fLoadPool: + // Object collection for loading + // + // fMapCount: + // ------------------------------------------------------------------------------- + const short fStoreLoad; + unsigned int fStorerLevel; + + XMLGrammarPool* const fGrammarPool; + BinInputStream* const fInputStream; + BinOutputStream* const fOutputStream; + + unsigned long fBufCount; + + //buffer + const XMLSize_t fBufSize; + XMLByte* const fBufStart; + XMLByte* const fBufEnd; + XMLByte* fBufCur; + XMLByte* fBufLoadMax; + + + + /*** + * Map for storing object + * + * key: XSerializable* + * XProtoType* + * + * value: XMLInteger*, owned + * + ***/ + RefHashTableOf* fStorePool; + + /*** + * Vector for loading object, objects are NOT owned + * + * data: XSerializable* + * XProtoType* + * + ***/ + ValueVectorOf* fLoadPool; + + /*** + * object counter + ***/ + XSerializedObjectId_t fObjectCount; + + //to allow grammar pool to set storer level when loading + friend class XMLGrammarPoolImpl; +}; + +inline bool XSerializeEngine::isStoring() const +{ + return (fStoreLoad == mode_Store); +} + +inline bool XSerializeEngine::isLoading() const +{ + return (fStoreLoad == mode_Load); +} + +inline XSerializeEngine& operator<<(XSerializeEngine& serEng + , XSerializable* const serObj) +{ + serEng.write(serObj); + return serEng; +} + +inline void XSerializeEngine::ensureStoring() const +{ + Assert(isStoring(), XMLExcepts::XSer_Storing_Violation); +} + +inline void XSerializeEngine::ensureLoading() const +{ + Assert(isLoading(), XMLExcepts::XSer_Loading_Violation); +} + + + +inline void XSerializeEngine::Assert(bool toEval + , const XMLExcepts::Codes toThrow) const +{ + if (!toEval) + { + ThrowXMLwithMemMgr(XSerializationException, toThrow, getMemoryManager()); + } + +} + +inline void XSerializeEngine::readString(XMLCh*& toRead + , XMLSize_t& bufferLen) +{ + XMLSize_t dummyDataLen; + readString(toRead, bufferLen, dummyDataLen); +} + +inline void XSerializeEngine::readString(XMLCh*& toRead) +{ + XMLSize_t dummyBufferLen; + XMLSize_t dummyDataLen; + readString(toRead, dummyBufferLen, dummyDataLen); +} + +inline void XSerializeEngine::readString(XMLByte*& toRead + , XMLSize_t& bufferLen) +{ + XMLSize_t dummyDataLen; + readString(toRead, bufferLen, dummyDataLen); +} + +inline void XSerializeEngine::readString(XMLByte*& toRead) +{ + XMLSize_t dummyBufferLen; + XMLSize_t dummyDataLen; + readString(toRead, dummyBufferLen, dummyDataLen); +} + +inline +XMLSize_t XSerializeEngine::getBufSize() const +{ + return fBufSize; +} + +inline +XMLSize_t XSerializeEngine::getBufCur() const +{ + return (fBufCur-fBufStart); +} + +inline +XMLSize_t XSerializeEngine::getBufCurAccumulated() const +{ + return (fBufCount - (isStoring() ? 0: 1)) * fBufSize + (fBufCur-fBufStart); +} + +inline +unsigned long XSerializeEngine::getBufCount() const +{ + return fBufCount; +} + +inline +unsigned int XSerializeEngine::getStorerLevel() const +{ + return fStorerLevel; +} + +/*** + * Ought to be nested class + ***/ +class XSerializedObjectId : public XMemory +{ +public: + + ~XSerializedObjectId(){}; + +private: + + inline XSerializedObjectId(XSerializeEngine::XSerializedObjectId_t val): + fData(val) { }; + + inline XSerializeEngine::XSerializedObjectId_t getValue() const {return fData; }; + + friend class XSerializeEngine; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSerializedObjectId(); + XSerializedObjectId(const XSerializedObjectId&); + XSerializedObjectId& operator=(const XSerializedObjectId&); + + XSerializeEngine::XSerializedObjectId_t fData; + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/internal/XTemplateSerializer.cpp b/include/xercesc/internal/XTemplateSerializer.cpp new file mode 100644 index 0000000..b07454c --- /dev/null +++ b/include/xercesc/internal/XTemplateSerializer.cpp @@ -0,0 +1,2322 @@ +/* + * 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. + */ + + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/*** + * internal class meant to be comsumed by XTemplateSerializer only + * the size can not grow + ***/ +#ifdef XERCES_DEBUG_SORT_GRAMMAR + +class KeySet : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Contructors and Destructor + // ----------------------------------------------------------------------- + KeySet + ( + const XMLCh* const strKey + , const int intKey1 + , const int intKey2 + , MemoryManager* const manager + ); + + ~KeySet(); + + // ----------------------------------------------------------------------- + // Public operators + // ----------------------------------------------------------------------- + inline void getKeys(const XMLCh*&, int&, int&) const; + void print() const; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + KeySet(const KeySet&); + KeySet& operator=(const KeySet&); + + // ----------------------------------------------------------------------- + // Data members + // reference only + // ----------------------------------------------------------------------- + const XMLCh* const fStrKey; + const int fIntKey1; + const int fIntKey2; + MemoryManager* fMemoryManager; + +}; + +KeySet::KeySet(const XMLCh* const strKey + , const int intKey1 + , const int intKey2 + , MemoryManager* const manager) +:fStrKey(strKey) +,fIntKey1(intKey1) +,fIntKey2(intKey2) +,fMemoryManager(manager) +{ +} + +KeySet::~KeySet() +{ +} + +inline +void KeySet::getKeys(const XMLCh*& strKey, int& intKey1, int& intKey2) const +{ + strKey = fStrKey; + intKey1 = fIntKey1; + intKey2 = fIntKey2; +} + +void KeySet::print() const +{ + char* tmpStr = XMLString::transcode(fStrKey, fMemoryManager); + printf("tmpStr=<%s>, intKey1=<%d>, intKey2=<%d>\n", tmpStr, fIntKey1, fIntKey2); + XMLString::release(&tmpStr, fMemoryManager); +} + +static int compareKeySet(const void* keyl, const void* keyr) +{ + const KeySet* pairl=*(const KeySet**)keyl; + const KeySet* pairr=*(const KeySet**)keyr; + + const XMLCh* strKeyl = 0; + int intKeyl_1 = 0; + int intKeyl_2 = 0; + pairl->getKeys(strKeyl, intKeyl_1, intKeyl_2); + + const XMLCh* strKeyr = 0; + int intKeyr_1 = 0; + int intKeyr_2 = 0; + pairr->getKeys(strKeyr, intKeyr_1, intKeyr_2); + + int compareValue = XMLString::compareString(strKeyl, strKeyr); + + if (compareValue !=0) + return compareValue; + + compareValue = intKeyl_1 - intKeyr_1; + if (compareValue !=0) + return compareValue; + + return (intKeyl_2 - intKeyr_2); + +} + +class SortArray : public XMemory +{ +private : + // ----------------------------------------------------------------------- + // Contructors and Destructor + // ----------------------------------------------------------------------- + SortArray + ( + const XMLSize_t size + , MemoryManager* const manager + ); + + ~SortArray(); + + // ----------------------------------------------------------------------- + // Public operators + // ----------------------------------------------------------------------- + inline const KeySet* elementAt(const XMLSize_t index) const; + void addElement(const KeySet* const keySet); + void sort(); + void dump() const; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SortArray(const SortArray&); + SortArray& operator=(const SortArray&); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + XMLSize_t fCur; //point to the current available slot + XMLSize_t fSize; + const KeySet** fElemList; //owning objects + MemoryManager* fMemoryManager; + + friend class XTemplateSerializer; + +}; + +SortArray::SortArray(const XMLSize_t size + , MemoryManager* const manager ) +:fCur(0) +,fSize(size) +,fMemoryManager(manager) +{ + fElemList = (const KeySet**) fMemoryManager->allocate(size * sizeof (KeySet*)); +} + +SortArray::~SortArray() +{ + for (XMLSize_t i=0; i< fSize; i++) + delete fElemList[i]; + + fMemoryManager->deallocate(fElemList); +} + +inline +const KeySet* SortArray::elementAt(const XMLSize_t index) const +{ + assert(index < fCur); + return fElemList[index]; +} + +void SortArray::addElement(const KeySet* const keySet) +{ + assert(fCur < fSize); + fElemList[fCur++]=keySet; +} + +void SortArray::sort() +{ + assert(fCur == fSize); + //dump(); + qsort(fElemList, fSize, sizeof (KeySet*), compareKeySet); + //dump(); +} + +void SortArray::dump() const +{ + printf("\n fSize=<%d>, fCur=<%d>\n", fSize, fCur); + for (XMLSize_t i = 0; i < fCur; i++) + fElemList[i]->print(); +} + +#define GET_NEXT_KEYSET() \ + const KeySet* keySet = sortArray.elementAt(i); \ + const XMLCh* strKey = 0; \ + int intKey1 = 0; \ + int intKey2 = 0; \ + keySet->getKeys(strKey, intKey1, intKey2); + +#define SORT_KEYSET_ONEKEY(MM) \ + SortArray sortArray(itemNumber, MM); \ + while (e.hasMoreElements()) \ + { \ + KeySet* keySet = new (MM) KeySet((XMLCh*) e.nextElementKey(), 0, 0, MM); \ + sortArray.addElement(keySet); \ + } \ + sortArray.sort(); + +#define SORT_KEYSET_TWOKEYS(MM) \ + SortArray sortArray(itemNumber, MM); \ + while (e.hasMoreElements()) \ + { \ + XMLCh* strKey; \ + int intKey; \ + e.nextElementKey((void*&)strKey, intKey); \ + KeySet* keySet = new (MM) KeySet(strKey, intKey, 0, MM); \ + sortArray.addElement(keySet); \ + } \ + sortArray.sort(); + +#endif + +/********************************************************** + * + * ValueVectorOf + * + * SchemaElementDecl* + * unsigned int + * + ***********************************************************/ +void XTemplateSerializer::storeObject(ValueVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorSize = objToStore->size(); + serEng.writeSize (vectorSize); + + for ( XMLSize_t i = 0; i < vectorSize; i++) + { + SchemaElementDecl*& data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toCallDestructor + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + ValueVectorOf( + initSize + , serEng.getMemoryManager() + , toCallDestructor + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorSize = 0; + serEng.readSize (vectorSize); + + for (XMLSize_t i = 0; i < vectorSize; i++) + { + SchemaElementDecl* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } +} + +void XTemplateSerializer::storeObject(ValueVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorSize = objToStore->size(); + serEng.writeSize (vectorSize); + + for (XMLSize_t i = 0; i < vectorSize; i++) + { + unsigned int& data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toCallDestructor + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + ValueVectorOf( + initSize + , serEng.getMemoryManager() + , toCallDestructor + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorSize = 0; + serEng.readSize (vectorSize); + + for (XMLSize_t i = 0; i < vectorSize; i++) + { + unsigned int data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } + +} + +/********************************************************** + * + * RefArrayVectorOf + * + * XMLCh + * + ***********************************************************/ + +void XTemplateSerializer::storeObject(RefArrayVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorSize = objToStore->size(); + serEng.writeSize (vectorSize); + + for (XMLSize_t i = 0; i < vectorSize; i++) + { + serEng.writeString(objToStore->elementAt(i)); + } + } + +} + +void XTemplateSerializer::loadObject(RefArrayVectorOf** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefArrayVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorSize = 0; + serEng.readSize (vectorSize); + + for (XMLSize_t i = 0; i < vectorSize; i++) + { + XMLCh* data; + serEng.readString(data); + (*objToLoad)->addElement(data); + } + } + +} + +/********************************************************** + * + * RefVectorOf + * + * SchemaAttDef + * SchemaElementDecl + * ContentSpecNode + * IC_Field + * DatatypeValidator + * IdentityConstraint + * XMLNumber + * XercesLocationPath + * XercesStep + * + ***********************************************************/ + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + SchemaAttDef* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + SchemaAttDef* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + SchemaElementDecl* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + SchemaElementDecl* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + ContentSpecNode* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + ContentSpecNode* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + IC_Field* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + IC_Field* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + DatatypeValidator* data = objToStore->elementAt(i); + DatatypeValidator::storeDV(serEng, data); + } + } + +} + +void XTemplateSerializer::loadObject(RefVectorOf** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + DatatypeValidator* data; + data = DatatypeValidator::loadDV(serEng); + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + IdentityConstraint* data = objToStore->elementAt(i); + IdentityConstraint::storeIC(serEng, data); + } + } + +} + +void XTemplateSerializer::loadObject(RefVectorOf** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + IdentityConstraint* data; + data = IdentityConstraint::loadIC(serEng); + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + XMLNumber* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XMLNumber::NumberType numType + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + XMLNumber* data; + data = XMLNumber::loadNumber(numType , serEng); + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for ( XMLSize_t i = 0; i < vectorLength; i++) + { + XercesLocationPath* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + XercesLocationPath* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } + +} + +void XTemplateSerializer::storeObject(RefVectorOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + XMLSize_t vectorLength = objToStore->size(); + serEng.writeSize (vectorLength); + + for (XMLSize_t i = 0; i < vectorLength; i++) + { + XercesStep* data = objToStore->elementAt(i); + serEng<** objToLoad + , int initSize + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + RefVectorOf( + initSize + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t vectorLength = 0; + serEng.readSize (vectorLength); + for (XMLSize_t i = 0 ; i < vectorLength; i++) + { + XercesStep* data; + serEng>>data; + (*objToLoad)->addElement(data); + } + } + +} + +/********************************************************** + * + * RefHashTableOf + * + * KVStringPair + * XMLAttDef + * DTDAttDef + * ComplexTypeInfo + * XercesGroupInfo + * XercesAttGroupInfo + * XMLRefInfo + * DatatypeValidator + * Grammar + * XSAnnotation + * + ***********************************************************/ +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + KVStringPair* data = objToStore->get(strKey); + serEng<get(e.nextElementKey()); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + KVStringPair* data; + serEng>>data; + + (*objToLoad)->put((void*)data->getKey(), data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + XMLAttDef* data = objToStore->get(strKey); + serEng<get(e.nextElementKey()); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + //This is used solely by SchemaGrammar and by all means it must be + //SchemaAttDef, ideally we may change it to RefHashTableOf + //later on. + //Affected files IGXMLScanner, SGXMLScanner, SchemaGrammar, TraverseSchema + //XMLAttDef* data; + SchemaAttDef* data; + serEng>>data; + + (*objToLoad)->put((void*)data->getAttName()->getLocalPart(), data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + DTDAttDef* data = objToStore->get(strKey); + serEng<get(e.nextElementKey()); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + DTDAttDef* data; + serEng>>data; + + (*objToLoad)->put((void*)data->getFullName(), data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + ComplexTypeInfo* data = objToStore->get(strKey); + serEng<get(e.nextElementKey()); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + ComplexTypeInfo* data; + serEng>>data; + + (*objToLoad)->put((void*)data->getTypeName(), data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + unsigned int id = serEng.getStringPool()->getId(strKey); + serEng<get(strKey); + serEng<getId(key); + + // key = StringPool->getValueForId(XercesGroupInfo::getNameSpaceId()) + // + chComma + // + StringPool->getValueForId(XercesGroupInfo::getNameId()) + // + // and the key is guranteed in the StringPool + // + // + // if (id == 0) + // { + // throw exception + // } + // + + serEng<get(key); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + unsigned int id; + serEng>>id; + + XMLCh* key = (XMLCh*) serEng.getStringPool()->getValueForId(id); + + XercesGroupInfo* data; + serEng>>data; + + (*objToLoad)->put((void*)key, data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + XercesAttGroupInfo* data = objToStore->get(strKey); + serEng<get(e.nextElementKey()); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + XercesAttGroupInfo* data; + serEng>>data; + + XMLCh* key = (XMLCh*) serEng.getStringPool()->getValueForId(data->getNameId()); + (*objToLoad)->put((void*)key, data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + serEng.writeString(strKey); + + XMLRefInfo* data = objToStore->get(strKey); + serEng<get(key); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + XMLCh* key; + serEng.readString(key); + + XMLRefInfo* data; + serEng>>data; + + (*objToLoad)->put((void*)key, data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + + if (serEng.needToStoreObject(objToStore)) + { + + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + DatatypeValidator* data = objToStore->get(strKey); + DatatypeValidator::storeDV(serEng, data); + } +#else + while (e.hasMoreElements()) + { + /*** + * to do: verify valid id + * + * XMLCh* key = (XMLCh*) e.nextElementKey(); + * unsigned int id = serEng.getStringPool()->getId(key); + * if (id == 0) + * throw exception + ***/ + DatatypeValidator* data = objToStore->get(e.nextElementKey()); + DatatypeValidator::storeDV(serEng, data); + } +#endif + } +} + +void XTemplateSerializer::loadObject(RefHashTableOf** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + DatatypeValidator* data; + data = DatatypeValidator::loadDV(serEng); + + /*** + * restore the key + ***/ + XMLCh* typeUri = (XMLCh*) data->getTypeUri(); + XMLCh* typeLocal = (XMLCh*) data->getTypeLocalName(); + XMLSize_t uriLen = XMLString::stringLen(typeUri); + XMLSize_t localLen = XMLString::stringLen(typeLocal); + XMLCh* typeKey = (XMLCh*) serEng.getMemoryManager()->allocate + ( + (uriLen + localLen + 2) * sizeof(XMLCh) + ); + // "typeuri,typeLocal" + XMLString::moveChars(typeKey, typeUri, uriLen+1); + typeKey[uriLen] = chComma; + XMLString::moveChars(&typeKey[uriLen+1], typeLocal, localLen+1); + typeKey[uriLen + localLen + 1] = chNull; + ArrayJanitor janName(typeKey, serEng.getMemoryManager()); + + /* + * get the string from string pool + * + * to do: + ***/ + unsigned int id = serEng.getStringPool()->getId(typeKey); + XMLCh* refKey = (XMLCh*) serEng.getStringPool()->getValueForId(id); + + (*objToLoad)->put((void*)refKey, data); + } + } +} + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + XMLSize_t itemNumber = 0; + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_ONEKEY(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + Grammar* data = objToStore->get(strKey); + Grammar::storeGrammar(serEng, data); + } +#else + while (e.hasMoreElements()) + { + Grammar* data = objToStore->get(e.nextElementKey()); + Grammar::storeGrammar(serEng, data); + } +#endif + + } +} + +void XTemplateSerializer::loadObject(RefHashTableOf** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + Grammar* data; + data = Grammar::loadGrammar(serEng); + + XMLCh* key = (XMLCh*) data->getGrammarDescription()->getGrammarKey(); + (*objToLoad)->put(key, data); + } + } +} + + +void XTemplateSerializer::storeObject(RefHashTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHashTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //get the total item number + unsigned int itemNumber = 0; + while (e.hasMoreElements()) + { + void* key = e.nextElementKey(); + XSerializeEngine::XSerializedObjectId_t keyId = serEng.lookupStorePool(key); + + if (keyId) + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + + //to sort the key + //though keyId is not supposed to be involved in compare + //we merely use the KeySet to encap both the string key and keyid + SortArray sortArray(itemNumber, objToStore->getMemoryManager()); + while (e.hasMoreElements()) + { + void* key = e.nextElementKey(); + XSerializeEngine::XSerializedObjectId_t keyId = serEng.lookupStorePool(key); + + if (keyId) + { + KeySet* keySet = + new (objToStore->getMemoryManager()) KeySet((XMLCh*)key, keyId, 0, objToStore->getMemoryManager()); + sortArray.addElement(keySet); + } + + } + + sortArray.sort(); + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + XSerializeEngine::XSerializedObjectId_t keyId = (XSerializeEngine::XSerializedObjectId_t)intKey1; + XSAnnotation* data = objToStore->get(strKey); + + serEng< ids(16, serEng.getMemoryManager()); + ValueVectorOf keys(16, serEng.getMemoryManager()); + + while (e.hasMoreElements()) + { + void* key = e.nextElementKey(); + XSerializeEngine::XSerializedObjectId_t keyId = serEng.lookupStorePool(key); + + if (keyId) + { + ids.addElement(keyId); + keys.addElement(key); + } + } + + XMLSize_t itemNumber = ids.size(); + serEng.writeSize (itemNumber); + + for (XMLSize_t i=0; iget(keys.elementAt(i)); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHashTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + XMLSize_t itemIndex; + XSerializeEngine::XSerializedObjectId_t keyId; + void* key; + XSAnnotation* data; + if (!serEng.fGrammarPool->getIgnoreSerializedAnnotations()) { + for (itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + serEng>>keyId; + key = serEng.lookupLoadPool(keyId); + serEng>>data; + (*objToLoad)->put(key, data); + } + } + else { + for (itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + serEng>>keyId; + key = serEng.lookupLoadPool(keyId); + serEng>>data; + delete data; + } + } + } +} + +/********************************************************** + * + * RefHash2KeysTableOf + * + * SchemaAttDef + * ElemVector + * + ***********************************************************/ +void XTemplateSerializer::storeObject(RefHash2KeysTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + XMLSize_t itemNumber = 0; + + RefHash2KeysTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + //to sort the key + SORT_KEYSET_TWOKEYS(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + SchemaAttDef* data = objToStore->get(strKey, intKey1); + serEng<get(key1, key2); + serEng<** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHash2KeysTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + SchemaAttDef* data; + serEng>>data; + + XMLCh* key1 = data->getAttName()->getLocalPart(); + int key2 = data->getAttName()->getURI(); + //key2==data->getId() + (*objToLoad)->put((void*)key1, key2, data); + + } + + } + +} + +void XTemplateSerializer::storeObject(RefHash2KeysTableOf* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + XMLSize_t itemNumber = 0; + + RefHash2KeysTableOfEnumerator e(objToStore, false, objToStore->getMemoryManager()); + + while (e.hasMoreElements()) + { + e.nextElement(); + itemNumber++; + } + + serEng.writeSize (itemNumber); + e.Reset(); + +#ifdef XERCES_DEBUG_SORT_GRAMMAR + + //to sort the key + SORT_KEYSET_TWOKEYS(serEng.getMemoryManager()) + + //to store the data + for (XMLSize_t i=0; i < itemNumber; i++) + { + GET_NEXT_KEYSET() + + serEng.writeString(strKey); + serEng<get(strKey, intKey1); + storeObject(data, serEng); + } +#else + + while (e.hasMoreElements()) + { + void* key1; + int key2; + + e.nextElementKey(key1, key2); + serEng.writeString((const XMLCh*)key1); + serEng<get(key1, key2); + storeObject(data, serEng); + + } +#endif + } + +} + +void XTemplateSerializer::loadObject(RefHash2KeysTableOf** objToLoad + , int + , bool toAdopt + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHash2KeysTableOf( + hashModulus + , toAdopt + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + XMLCh* key1; + serEng.readString(key1); + + int key2; + serEng>>key2; + + ElemVector* data = 0; + + //don't call destructor + loadObject(&data, 8, false, serEng); + + /*** + * + * There must be one element in the vector whose + * susbititutionGroupElem matches the (key1,key2) + * + ***/ + + // bool FOUND=false; + + XMLSize_t vectorSize = data->size(); + for ( XMLSize_t i = 0; i < vectorSize; i++) + { + SchemaElementDecl*& elem = data->elementAt(i); + SchemaElementDecl* subElem = elem->getSubstitutionGroupElem(); + XMLCh* elemName = subElem->getBaseName(); + int uri = subElem->getURI(); + if (XMLString::equals(elemName, key1) && + (uri == key2) ) + { + //release the temp + serEng.getMemoryManager()->deallocate(key1); + key1 = elemName; + //FOUND=true; + break; + } + } + + /*** + * if (!FOUND) + * { + * throw exception + * } + ***/ + + (*objToLoad)->put((void*)key1, key2, data); + + } + + } +} + +/********************************************************** + * + * RefHash3KeysIdPool + * + * SchemaElementDecl + * + * maintain the same order through id + ***********************************************************/ +void XTemplateSerializer::storeObject(RefHash3KeysIdPool* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + serEng.writeSize (objToStore->getHashModulus()); + + RefHash3KeysIdPoolEnumerator e(objToStore, false, objToStore->getMemoryManager()); + + serEng.writeSize (e.size()); + + void* strkey; + int key1; + int key2; + /* Update to store key2 separately as for the putGroupElemDecl the key is not the + enclosing scope but another value. */ + while (e.hasMoreKeys()) + { + e.nextElementKey(strkey, key1, key2); + serEng<getByKey(strkey, key1, key2); + serEng<** objToLoad + , int + , bool toAdopt + , int initSize2 + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + XMLSize_t hashModulus; + serEng.readSize (hashModulus); + + if (!*objToLoad) + { + *objToLoad = new (serEng.getMemoryManager()) + RefHash3KeysIdPool( + hashModulus + , toAdopt + , initSize2 + , serEng.getMemoryManager()); + } + + serEng.registerObject(*objToLoad); + + XMLSize_t itemNumber = 0; + serEng.readSize (itemNumber); + + int scopeKey; + SchemaElementDecl* elemDecl; + for (XMLSize_t itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + serEng>>scopeKey; + serEng>>elemDecl; + + (*objToLoad)->put(elemDecl->getBaseName() + , elemDecl->getURI() + , scopeKey + , elemDecl); + } + + } + +} + +/********************************************************** + * + * NameIdPool + * no NameIdPool::nextElementKey() + * + * DTDElementDecl + * DTDEntityDecl + * XMLNotationDecl + * + * maintain the same order through id + ***********************************************************/ +void XTemplateSerializer::storeObject(NameIdPool* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + NameIdPoolEnumerator e(objToStore, objToStore->getMemoryManager()); + + serEng<<(unsigned int)e.size(); + + while (e.hasMoreElements()) + { + DTDElementDecl& data = e.nextElement(); + data.serialize(serEng); + } + } + +} + +void XTemplateSerializer::loadObject(NameIdPool** objToLoad + , int initSize + , int initSize2 + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + NameIdPool( + initSize + , initSize2 + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + unsigned int itemNumber = 0; + serEng >> itemNumber; + + for (unsigned int itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + DTDElementDecl* data = new (serEng.getMemoryManager()) + DTDElementDecl(serEng.getMemoryManager()); + data->serialize(serEng); + (*objToLoad)->put(data); + } + } +} + +void XTemplateSerializer::storeObject(NameIdPool* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + NameIdPoolEnumerator e(objToStore, objToStore->getMemoryManager()); + + serEng<<(unsigned int)e.size(); + + while (e.hasMoreElements()) + { + DTDEntityDecl& data = e.nextElement(); + data.serialize(serEng); + } + } +} + +void XTemplateSerializer::loadObject(NameIdPool** objToLoad + , int initSize + , int initSize2 + , XSerializeEngine& serEng) +{ + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + NameIdPool( + initSize + , initSize2 + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + unsigned int itemNumber = 0; + serEng >> itemNumber; + + for (unsigned int itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + DTDEntityDecl* data = new (serEng.getMemoryManager()) + DTDEntityDecl(serEng.getMemoryManager()); + data->serialize(serEng); + (*objToLoad)->put(data); + } + } +} + +void XTemplateSerializer::storeObject(NameIdPool* const objToStore + , XSerializeEngine& serEng) +{ + if (serEng.needToStoreObject(objToStore)) + { + NameIdPoolEnumerator e(objToStore, objToStore->getMemoryManager()); + + serEng<<(unsigned int)e.size(); + + while (e.hasMoreElements()) + { + XMLNotationDecl& data = e.nextElement(); + data.serialize(serEng); + } + } +} + +void XTemplateSerializer::loadObject(NameIdPool** objToLoad + , int initSize + , int initSize2 + , XSerializeEngine& serEng) +{ + + if (serEng.needToLoadObject((void**)objToLoad)) + { + if (!*objToLoad) + { + if (initSize < 0) + initSize = 16; + + *objToLoad = new (serEng.getMemoryManager()) + NameIdPool( + initSize + , initSize2 + , serEng.getMemoryManager() + ); + } + + serEng.registerObject(*objToLoad); + + unsigned int itemNumber = 0; + serEng >> itemNumber; + + for (unsigned int itemIndex = 0; itemIndex < itemNumber; itemIndex++) + { + XMLNotationDecl* data = new (serEng.getMemoryManager()) + XMLNotationDecl(serEng.getMemoryManager()); + data->serialize(serEng); + (*objToLoad)->put(data); + } + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/internal/XTemplateSerializer.hpp b/include/xercesc/internal/XTemplateSerializer.hpp new file mode 100644 index 0000000..a980629 --- /dev/null +++ b/include/xercesc/internal/XTemplateSerializer.hpp @@ -0,0 +1,365 @@ +/* + * 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: XTemplateSerializer.hpp 678409 2008-07-21 13:08:10Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XTEMPLATE_SERIALIZER_HPP) +#define XERCESC_INCLUDE_GUARD_XTEMPLATE_SERIALIZER_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT XTemplateSerializer +{ +public: + + /********************************************************** + * + * ValueVectorOf + * + * SchemaElementDecl* + * unsigned int + * + ***********************************************************/ + static void storeObject(ValueVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(ValueVectorOf** tempObjToRead + , int initSize + , bool toCallDestructor + , XSerializeEngine& serEng); + + static void storeObject(ValueVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(ValueVectorOf** tempObjToRead + , int initSize + , bool toCallDestructor + , XSerializeEngine& serEng); + + /********************************************************** + * + * RefArrayVectorOf + * + * XMLCh + * + ***********************************************************/ + static void storeObject(RefArrayVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefArrayVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + /********************************************************** + * + * RefVectorOf + * + * SchemaAttDef + * SchemaElementDecl + * ContentSpecNode + * IC_Field + * DatatypeValidator + * IdentityConstraint + * XMLNumber + * XercesLocationPath + * XercesStep + * + ***********************************************************/ + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XMLNumber::NumberType numType + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefVectorOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefVectorOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + /********************************************************** + * + * RefHashTableOf + * + * KVStringPair + * XMLAttDef + * DTDAttDef + * ComplexTypeInfo + * XercesGroupInfo + * XercesAttGroupInfo + * XMLRefInfo + * DatatypeValidator + * Grammar + * XSAnnotation + * + ***********************************************************/ + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHashTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHashTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + /********************************************************** + * + * RefHash2KeysTableOf + * + * SchemaAttDef + * ElemVector + * + ***********************************************************/ + static void storeObject(RefHash2KeysTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHash2KeysTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + static void storeObject(RefHash2KeysTableOf* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHash2KeysTableOf** tempObjToRead + , int initSize + , bool toAdopt + , XSerializeEngine& serEng); + + /********************************************************** + * + * RefHash3KeysIdPool + * + * SchemaElementDecl + * + ***********************************************************/ + static void storeObject(RefHash3KeysIdPool* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(RefHash3KeysIdPool** tempObjToRead + , int initSize + , bool toAdopt + , int initSize2 + , XSerializeEngine& serEng); + + /********************************************************** + * + * NameIdPool + * + * DTDElementDecl + * DTDEntityDecl + * XMLNotationDecl + * + ***********************************************************/ + static void storeObject(NameIdPool* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(NameIdPool** tempObjToRead + , int initSize + , int initSize2 + , XSerializeEngine& serEng); + + static void storeObject(NameIdPool* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(NameIdPool** tempObjToRead + , int initSize + , int initSize2 + , XSerializeEngine& serEng); + + static void storeObject(NameIdPool* const tempObjToWrite + , XSerializeEngine& serEng); + + static void loadObject(NameIdPool** tempObjToRead + , int initSize + , int initSize2 + , XSerializeEngine& serEng); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ~XTemplateSerializer(); + XTemplateSerializer(); + XTemplateSerializer(const XTemplateSerializer&); + XTemplateSerializer& operator=(const XTemplateSerializer&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/parsers/AbstractDOMParser.cpp b/include/xercesc/parsers/AbstractDOMParser.cpp new file mode 100644 index 0000000..ee803e4 --- /dev/null +++ b/include/xercesc/parsers/AbstractDOMParser.cpp @@ -0,0 +1,1784 @@ +/* + * 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. + */ + +/** +* This file contains code to build the DOM tree. It registers a document +* handler with the scanner. In these handler methods, appropriate DOM nodes +* are created and added to the DOM tree. +* +* $Id: AbstractDOMParser.cpp 935358 2010-04-18 15:40:35Z borisk $ +* +*/ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Constructors and Destructor +// --------------------------------------------------------------------------- + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ResetInProgressType; + + +AbstractDOMParser::AbstractDOMParser( XMLValidator* const valToAdopt + , MemoryManager* const manager + , XMLGrammarPool* const gramPool) : + + fCreateEntityReferenceNodes(true) +, fIncludeIgnorableWhitespace(true) +, fWithinElement(false) +, fParseInProgress(false) +, fCreateCommentNodes(true) +, fDocumentAdoptedByUser(false) +, fCreateSchemaInfo(false) +, fDoXInclude(false) +, fScanner(0) +, fImplementationFeatures(0) +, fCurrentParent(0) +, fCurrentNode(0) +, fCurrentEntity(0) +, fDocument(0) +, fDocumentType(0) +, fDocumentVector(0) +, fGrammarResolver(0) +, fURIStringPool(0) +, fValidator(valToAdopt) +, fMemoryManager(manager) +, fGrammarPool(gramPool) +, fBufMgr(manager) +, fInternalSubset(fBufMgr.bidOnBuffer()) +, fPSVIHandler(0) +{ + CleanupType cleanup(this, &AbstractDOMParser::cleanUp); + + try + { + initialize(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +AbstractDOMParser::~AbstractDOMParser() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Initialize/CleanUp methods +// --------------------------------------------------------------------------- +void AbstractDOMParser::initialize() +{ + // Create grammar resolver and string pool to pass to the scanner + fGrammarResolver = new (fMemoryManager) GrammarResolver(fGrammarPool, fMemoryManager); + fURIStringPool = fGrammarResolver->getStringPool(); + + // Create a scanner and tell it what validator to use. Then set us + // as the document event handler so we can fill the DOM document. + fScanner = XMLScannerResolver::getDefaultScanner(fValidator, fGrammarResolver, fMemoryManager); + fScanner->setDocHandler(this); + fScanner->setDocTypeHandler(this); + fScanner->setURIStringPool(fURIStringPool); + + this->reset(); +} + +void AbstractDOMParser::cleanUp() +{ + if (fDocumentVector) + delete fDocumentVector; + + if (!fDocumentAdoptedByUser && fDocument) + fDocument->release(); + + delete fScanner; + delete fGrammarResolver; + // grammar pool *always* owns this + //delete fURIStringPool; + fMemoryManager->deallocate(fImplementationFeatures); + + if (fValidator) + delete fValidator; +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Utilities +// --------------------------------------------------------------------------- +void AbstractDOMParser::reset() +{ + // if fDocument exists already, store the old pointer in the vector for deletion later + if (fDocument && !fDocumentAdoptedByUser) { + if (!fDocumentVector) { + // allocate the vector if not exists yet + fDocumentVector = new (fMemoryManager) RefVectorOf(10, true, fMemoryManager) ; + } + fDocumentVector->addElement(fDocument); + } + + fDocument = 0; + resetDocType(); + fCurrentParent = 0; + fCurrentNode = 0; + fCurrentEntity = 0; + fWithinElement = false; + fDocumentAdoptedByUser = false; + fInternalSubset.reset(); +} + + +void AbstractDOMParser::resetInProgress() +{ + fParseInProgress = false; +} + + +void AbstractDOMParser::resetPool() +{ + // We cannot enter here while a regular parse is in progress. + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + if (fDocumentVector) + fDocumentVector->removeAllElements(); + + if (!fDocumentAdoptedByUser && fDocument) + fDocument->release(); + + fDocument = 0; +} + +bool AbstractDOMParser::isDocumentAdopted() const +{ + return fDocumentAdoptedByUser; +} + +DOMDocument* AbstractDOMParser::adoptDocument() +{ + fDocumentAdoptedByUser = true; + return fDocument; +} + + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Getter methods +// --------------------------------------------------------------------------- +DOMDocument* AbstractDOMParser::getDocument() +{ + return fDocument; +} + +const XMLValidator& AbstractDOMParser::getValidator() const +{ + return *fScanner->getValidator(); +} + +bool AbstractDOMParser::getDoNamespaces() const +{ + return fScanner->getDoNamespaces(); +} + +bool AbstractDOMParser::getGenerateSyntheticAnnotations() const +{ + return fScanner->getGenerateSyntheticAnnotations(); +} + +bool AbstractDOMParser::getValidateAnnotations() const +{ + return fScanner->getValidateAnnotations(); +} + +bool AbstractDOMParser::getExitOnFirstFatalError() const +{ + return fScanner->getExitOnFirstFatal(); +} + +bool AbstractDOMParser::getValidationConstraintFatal() const +{ + return fScanner->getValidationConstraintFatal(); +} + +AbstractDOMParser::ValSchemes AbstractDOMParser::getValidationScheme() const +{ + const XMLScanner::ValSchemes scheme = fScanner->getValidationScheme(); + + if (scheme == XMLScanner::Val_Always) + return Val_Always; + else if (scheme == XMLScanner::Val_Never) + return Val_Never; + + return Val_Auto; +} + +bool AbstractDOMParser::getDoSchema() const +{ + return fScanner->getDoSchema(); +} + +bool AbstractDOMParser::getValidationSchemaFullChecking() const +{ + return fScanner->getValidationSchemaFullChecking(); +} + +bool AbstractDOMParser::getIdentityConstraintChecking() const +{ + return fScanner->getIdentityConstraintChecking(); +} + +XMLSize_t AbstractDOMParser::getErrorCount() const +{ + return fScanner->getErrorCount(); +} + +XMLCh* AbstractDOMParser::getExternalSchemaLocation() const +{ + return fScanner->getExternalSchemaLocation(); +} + +XMLCh* AbstractDOMParser::getExternalNoNamespaceSchemaLocation() const +{ + return fScanner->getExternalNoNamespaceSchemaLocation(); +} + +SecurityManager* AbstractDOMParser::getSecurityManager() const +{ + return fScanner->getSecurityManager(); +} + +// Return it as a reference so that we cn return as void* from getParameter. +// +const XMLSize_t& AbstractDOMParser::getLowWaterMark() const +{ + return fScanner->getLowWaterMark(); +} + +bool AbstractDOMParser::getLoadExternalDTD() const +{ + return fScanner->getLoadExternalDTD(); +} + +bool AbstractDOMParser::getLoadSchema() const +{ + return fScanner->getLoadSchema(); +} + +bool AbstractDOMParser::getCalculateSrcOfs() const +{ + return fScanner->getCalculateSrcOfs(); +} + +bool AbstractDOMParser::getStandardUriConformant() const +{ + return fScanner->getStandardUriConformant(); +} + +bool AbstractDOMParser::getIgnoreAnnotations() const +{ + return fScanner->getIgnoreAnnotations(); +} + +bool AbstractDOMParser::getDisableDefaultEntityResolution() const +{ + return fScanner->getDisableDefaultEntityResolution(); +} + +bool AbstractDOMParser::getSkipDTDValidation() const +{ + return fScanner->getSkipDTDValidation(); +} + +bool AbstractDOMParser::getHandleMultipleImports() const +{ + return fScanner->getHandleMultipleImports(); +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Setter methods +// --------------------------------------------------------------------------- +void AbstractDOMParser::setPSVIHandler(PSVIHandler* const handler) +{ + fPSVIHandler = handler; + if (fPSVIHandler) { + fScanner->setPSVIHandler(this); + } + else if(!fCreateSchemaInfo) { + fScanner->setPSVIHandler(0); + } +} + + +void AbstractDOMParser::setDoNamespaces(const bool newState) +{ + fScanner->setDoNamespaces(newState); +} + +void AbstractDOMParser::setGenerateSyntheticAnnotations(const bool newState) +{ + fScanner->setGenerateSyntheticAnnotations(newState); +} + +void AbstractDOMParser::setValidateAnnotations(const bool newState) +{ + fScanner->setValidateAnnotations(newState); +} + +void AbstractDOMParser::setExitOnFirstFatalError(const bool newState) +{ + fScanner->setExitOnFirstFatal(newState); +} + +void AbstractDOMParser::setValidationConstraintFatal(const bool newState) +{ + fScanner->setValidationConstraintFatal(newState); +} + +void AbstractDOMParser::setValidationScheme(const ValSchemes newScheme) +{ + if (newScheme == Val_Never) + fScanner->setValidationScheme(XMLScanner::Val_Never); + else if (newScheme == Val_Always) + fScanner->setValidationScheme(XMLScanner::Val_Always); + else + fScanner->setValidationScheme(XMLScanner::Val_Auto); +} + +void AbstractDOMParser::setDoSchema(const bool newState) +{ + fScanner->setDoSchema(newState); +} + +void AbstractDOMParser::setValidationSchemaFullChecking(const bool schemaFullChecking) +{ + fScanner->setValidationSchemaFullChecking(schemaFullChecking); +} + +void AbstractDOMParser::setIdentityConstraintChecking(const bool identityConstraintChecking) +{ + fScanner->setIdentityConstraintChecking(identityConstraintChecking); +} + +void AbstractDOMParser::setExternalSchemaLocation(const XMLCh* const schemaLocation) +{ + fScanner->setExternalSchemaLocation(schemaLocation); +} +void AbstractDOMParser::setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation) +{ + fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation); +} + +void AbstractDOMParser::setExternalSchemaLocation(const char* const schemaLocation) +{ + fScanner->setExternalSchemaLocation(schemaLocation); +} +void AbstractDOMParser::setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation) +{ + fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation); +} + +void AbstractDOMParser::setSecurityManager(SecurityManager* const securityManager) +{ + // since this could impact various components, don't permit it to change + // during a parse + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + fScanner->setSecurityManager(securityManager); +} + +void AbstractDOMParser::setLowWaterMark(XMLSize_t lwm) +{ + fScanner->setLowWaterMark(lwm); +} + +void AbstractDOMParser::setLoadExternalDTD(const bool newState) +{ + fScanner->setLoadExternalDTD(newState); +} + +void AbstractDOMParser::setLoadSchema(const bool newState) +{ + fScanner->setLoadSchema(newState); +} + +void AbstractDOMParser::setCalculateSrcOfs(const bool newState) +{ + fScanner->setCalculateSrcOfs(newState); +} + +void AbstractDOMParser::setStandardUriConformant(const bool newState) +{ + fScanner->setStandardUriConformant(newState); +} + +void AbstractDOMParser::useScanner(const XMLCh* const scannerName) +{ + XMLScanner* tempScanner = XMLScannerResolver::resolveScanner + ( + scannerName + , fValidator + , fGrammarResolver + , fMemoryManager + ); + + if (tempScanner) { + + tempScanner->setParseSettings(fScanner); + tempScanner->setURIStringPool(fURIStringPool); + delete fScanner; + fScanner = tempScanner; + } +} + +void AbstractDOMParser::setCreateSchemaInfo(const bool create) +{ + fCreateSchemaInfo = create; + if(fCreateSchemaInfo) + fScanner->setPSVIHandler(this); + else if(!fPSVIHandler) + fScanner->setPSVIHandler(0); +} + +void AbstractDOMParser::setIgnoreAnnotations(const bool newValue) +{ + fScanner->setIgnoreAnnotations(newValue); +} + +void AbstractDOMParser::setDisableDefaultEntityResolution(const bool newValue) +{ + fScanner->setDisableDefaultEntityResolution(newValue); +} + +void AbstractDOMParser::setSkipDTDValidation(const bool newValue) +{ + fScanner->setSkipDTDValidation(newValue); +} + +void AbstractDOMParser::setHandleMultipleImports(const bool newValue) +{ + fScanner->setHandleMultipleImports(newValue); +} + +void AbstractDOMParser::setDocument(DOMDocument* toSet) +{ + fDocument = (DOMDocumentImpl *)toSet; +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Parsing methods +// --------------------------------------------------------------------------- +void AbstractDOMParser::parse(const InputSource& source) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &AbstractDOMParser::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(source); + + if (fDoXInclude && getErrorCount()==0){ + DOMDocument *doc = getDocument(); + // after XInclude, the document must be normalized + if(doc) + doc->normalizeDocument(); + } + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void AbstractDOMParser::parse(const XMLCh* const systemId) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &AbstractDOMParser::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(systemId); + + if (fDoXInclude && getErrorCount()==0){ + DOMDocument *doc = getDocument(); + // after XInclude, the document must be normalized + if(doc) + doc->normalizeDocument(); + } + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void AbstractDOMParser::parse(const char* const systemId) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &AbstractDOMParser::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(systemId); + + if (fDoXInclude && getErrorCount()==0){ + DOMDocument *doc = getDocument(); + // after XInclude, the document must be normalized + if(doc) + doc->normalizeDocument(); + } + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + + + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Progressive parse methods +// --------------------------------------------------------------------------- +bool AbstractDOMParser::parseFirst( const XMLCh* const systemId + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(systemId, toFill); +} + +bool AbstractDOMParser::parseFirst( const char* const systemId + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(systemId, toFill); +} + +bool AbstractDOMParser::parseFirst( const InputSource& source + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(source, toFill); +} + +bool AbstractDOMParser::parseNext(XMLPScanToken& token) +{ + return fScanner->scanNext(token); +} + +void AbstractDOMParser::parseReset(XMLPScanToken& token) +{ + // Reset the scanner, and then reset the parser + fScanner->scanReset(token); + reset(); +} + + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Implementation of PSVIHandler interface +// --------------------------------------------------------------------------- +void AbstractDOMParser::handleElementPSVI(const XMLCh* const localName + , const XMLCh* const uri + , PSVIElement * elementInfo) +{ + // associate the info now; if the user wants, she can override what we did + if(fCreateSchemaInfo) + { + DOMTypeInfoImpl* typeInfo=new (getDocument()) DOMTypeInfoImpl(); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Validity, elementInfo->getValidity()); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Validation_Attempted, elementInfo->getValidationAttempted()); + if(elementInfo->getTypeDefinition()) + { + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Type, elementInfo->getTypeDefinition()->getTypeCategory()); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Anonymous, elementInfo->getTypeDefinition()->getAnonymous()); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Namespace, + fDocument->getPooledString(elementInfo->getTypeDefinition()->getNamespace())); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Name, + fDocument->getPooledString(elementInfo->getTypeDefinition()->getName())); + } + else if(elementInfo->getValidity()==PSVIItem::VALIDITY_VALID) + { + // if we are valid but we don't have a type validator, we are xs:anyType + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Type, XSTypeDefinition::COMPLEX_TYPE); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Anonymous, false); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Namespace, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Name, SchemaSymbols::fgATTVAL_ANYTYPE); + } + if(elementInfo->getMemberTypeDefinition()) + { + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Anonymous, elementInfo->getMemberTypeDefinition()->getAnonymous()); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Namespace, + fDocument->getPooledString(elementInfo->getMemberTypeDefinition()->getNamespace())); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Name, + fDocument->getPooledString(elementInfo->getMemberTypeDefinition()->getName())); + } + if(elementInfo->getElementDeclaration()) + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Nil, elementInfo->getElementDeclaration()->getNillable()); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Schema_Default, fDocument->getPooledString(elementInfo->getSchemaDefault())); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Schema_Normalized_Value, fDocument->getPooledString(elementInfo->getSchemaNormalizedValue())); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Schema_Specified, true); + ((DOMElementNSImpl*)fCurrentParent)->setSchemaTypeInfo(typeInfo); + } + if(fPSVIHandler) + fPSVIHandler->handleElementPSVI(localName, uri, elementInfo); +} + +void AbstractDOMParser::handlePartialElementPSVI(const XMLCh* const localName + , const XMLCh* const uri + , PSVIElement * elementInfo) +{ + if(fPSVIHandler) + fPSVIHandler->handlePartialElementPSVI(localName, uri, elementInfo); +} + +void AbstractDOMParser::handleAttributesPSVI( const XMLCh* const localName + , const XMLCh* const uri + , PSVIAttributeList * psviAttributes) +{ + if(fCreateSchemaInfo) + { + for (XMLSize_t index=0; index < psviAttributes->getLength(); index++) { + XERCES_CPP_NAMESPACE_QUALIFIER PSVIAttribute *attrInfo=psviAttributes->getAttributePSVIAtIndex(index); + XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* pAttrNode=fCurrentNode->getAttributes()->getNamedItemNS(psviAttributes->getAttributeNamespaceAtIndex(index), + psviAttributes->getAttributeNameAtIndex(index)); + if(pAttrNode!=NULL) + { + DOMTypeInfoImpl* typeInfo=new (getDocument()) DOMTypeInfoImpl(); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Validity, attrInfo->getValidity()); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Validation_Attempted, attrInfo->getValidationAttempted()); + if(attrInfo->getTypeDefinition()) + { + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Type, XSTypeDefinition::SIMPLE_TYPE); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Anonymous, attrInfo->getTypeDefinition()->getAnonymous()); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Namespace, + fDocument->getPooledString(attrInfo->getTypeDefinition()->getNamespace())); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Name, + fDocument->getPooledString(attrInfo->getTypeDefinition()->getName())); + } + else if(attrInfo->getValidity()==PSVIItem::VALIDITY_VALID) + { + // if we are valid but we don't have a type validator, we are xs:anySimpleType + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Type, XSTypeDefinition::SIMPLE_TYPE); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Anonymous, false); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Namespace, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Type_Definition_Name, SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + if(attrInfo->getMemberTypeDefinition()) + { + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Anonymous, attrInfo->getMemberTypeDefinition()->getAnonymous()); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Namespace, + fDocument->getPooledString(attrInfo->getMemberTypeDefinition()->getNamespace())); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Member_Type_Definition_Name, + fDocument->getPooledString(attrInfo->getMemberTypeDefinition()->getName())); + } + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Schema_Default, fDocument->getPooledString(attrInfo->getSchemaDefault())); + typeInfo->setStringProperty(DOMPSVITypeInfo::PSVI_Schema_Normalized_Value, fDocument->getPooledString(attrInfo->getSchemaNormalizedValue())); + typeInfo->setNumericProperty(DOMPSVITypeInfo::PSVI_Schema_Specified, true); + ((DOMAttrImpl*)pAttrNode)->setSchemaTypeInfo(typeInfo); + } + } + } + // associate the info now; if the user wants, she can override what we did + if(fPSVIHandler) + fPSVIHandler->handleAttributesPSVI(localName, uri, psviAttributes); +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Implementation of XMLDocumentHandler interface +// --------------------------------------------------------------------------- +void AbstractDOMParser::docCharacters( const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + // Ignore chars outside of content + if (!fWithinElement) + return; + + if (cdataSection == true) + { + DOMCDATASection *node = createCDATASection (chars, length); + castToParentImpl (fCurrentParent)->appendChildFast (node); + fCurrentNode = node; + } + else + { + if (fCurrentNode->getNodeType() == DOMNode::TEXT_NODE) + { + DOMTextImpl *node = (DOMTextImpl*)fCurrentNode; + node->appendData(chars, length); + } + else + { + DOMText *node = createText (chars, length); + castToParentImpl (fCurrentParent)->appendChildFast (node); + fCurrentNode = node; + } + } +} + + +void AbstractDOMParser::docComment(const XMLCh* const comment) +{ + if (fCreateCommentNodes) { + DOMComment *dcom = fDocument->createComment(comment); + castToParentImpl (fCurrentParent)->appendChildFast (dcom); + fCurrentNode = dcom; + } +} + + +void AbstractDOMParser::docPI( const XMLCh* const target + , const XMLCh* const data) +{ + DOMProcessingInstruction *pi = fDocument->createProcessingInstruction + ( + target + , data + ); + castToParentImpl (fCurrentParent)->appendChildFast (pi); + fCurrentNode = pi; +} + + +void AbstractDOMParser::endEntityReference(const XMLEntityDecl&) +{ + if (!fCreateEntityReferenceNodes) + return; + + DOMEntityReferenceImpl *erImpl = 0; + + if (fCurrentParent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) + erImpl = (DOMEntityReferenceImpl *) fCurrentParent; + + fCurrentNode = fCurrentParent; + fCurrentParent = fCurrentNode->getParentNode (); + + // When the document is invalid but we continue parsing, we may + // end up seeing more 'end' events than the 'start' ones. + // + if (fCurrentParent == 0 && fDocument != 0) + { + fCurrentNode = fDocument->getDocumentElement (); + fCurrentParent = fCurrentNode; + } + + if (erImpl) + erImpl->setReadOnly(true, true); +} + + +void AbstractDOMParser::endElement( const XMLElementDecl& + , const unsigned int + , const bool + , const XMLCh* const) +{ + fCurrentNode = fCurrentParent; + fCurrentParent = fCurrentNode->getParentNode (); + + // When the document is invalid but we continue parsing, we may + // end up seeing more 'end' events than the 'start' ones. + // + if (fCurrentParent == 0 && fDocument != 0) + { + fCurrentNode = fDocument->getDocumentElement (); + fCurrentParent = fCurrentNode; + } + + // If we've hit the end of content, clear the flag. + // + if (fCurrentParent == fDocument) + fWithinElement = false; + + if(fDoXInclude && + (XIncludeUtils::isXIIncludeDOMNode(fCurrentNode) || + ((XIncludeUtils::isXIFallbackDOMNode(fCurrentNode) && + !XMLString::equals(fCurrentParent->getNamespaceURI(), XIncludeUtils::fgXIIIncludeNamespaceURI))))) + { + XIncludeUtils xiu((XMLErrorReporter *) this); + // process the XInclude node, then update the fCurrentNode with the new content + if(xiu.parseDOMNodeDoingXInclude(fCurrentNode, fDocument, getScanner()->getEntityHandler())) + fCurrentNode = fCurrentParent->getLastChild(); + } +} + + +void AbstractDOMParser::ignorableWhitespace( const XMLCh* const chars + , const XMLSize_t length + , const bool) +{ + // Ignore chars before the root element + if (!fWithinElement || !fIncludeIgnorableWhitespace) + return; + + // revisit. Not safe to slam in a null like this. + XMLCh savedChar = chars[length]; + XMLCh *ncChars = (XMLCh *)chars; // cast off const + ncChars[length] = chNull; + + if (fCurrentNode->getNodeType() == DOMNode::TEXT_NODE) + { + DOMText *node = (DOMText *)fCurrentNode; + node->appendData(chars); + } + else + { + DOMTextImpl *node = (DOMTextImpl *)fDocument->createTextNode(chars); + node->setIgnorableWhitespace(true); + castToParentImpl (fCurrentParent)->appendChildFast (node); + + fCurrentNode = node; + } + ncChars[length] = savedChar; +} + + +void AbstractDOMParser::resetDocument() +{ + // + // The reset methods are called before a new parse event occurs. + // Reset this parsers state to clear out anything that may be left + // from a previous use, in particular the DOM document itself. + // + this->reset(); +} + + +void AbstractDOMParser::startDocument() +{ + if(fImplementationFeatures == 0) + fDocument = (DOMDocumentImpl *)DOMImplementation::getImplementation()->createDocument(fMemoryManager); + else + fDocument = (DOMDocumentImpl *)DOMImplementationRegistry::getDOMImplementation(fImplementationFeatures)->createDocument(fMemoryManager); + + // Just set the document as the current parent and current node + fCurrentParent = fDocument; + fCurrentNode = fDocument; + // set DOM error checking off + fDocument->setErrorChecking(false); + fDocument->setDocumentURI(fScanner->getLocator()->getSystemId()); + fDocument->setInputEncoding(fScanner->getReaderMgr()->getCurrentEncodingStr()); +} + + +void AbstractDOMParser::endDocument() +{ + // set DOM error checking back on + fDocument->setErrorChecking(true); + + // DOM L2 does not support editing DocumentType nodes + if (fDocumentType && fScanner -> getDoNamespaces()) + fDocumentType->setReadOnly(true, true); +} + + +void AbstractDOMParser::startElement(const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot) +{ + DOMElement *elem; + DOMElementImpl *elemImpl; + const XMLCh* namespaceURI = 0; + bool doNamespaces = fScanner->getDoNamespaces(); + + // Create the element name. Here we are going to bypass the + // DOMDocument::createElement() interface and instantiate the + // required types directly in order to avoid name checking + // overhead. + // + if (doNamespaces) + { + //DOM Level 2, doNamespaces on + // + const XMLCh* localName = elemDecl.getBaseName(); + + if (urlId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix + + namespaceURI = fScanner->getURIText(urlId); //get namespaceURI + + if (elemPrefix && *elemPrefix) + { + XMLBufBid elemQName(&fBufMgr); + + elemQName.set(elemPrefix); + elemQName.append(chColon); + elemQName.append(localName); + + elem = createElementNS ( + namespaceURI, elemPrefix, localName, elemQName.getRawBuffer()); + } + else + elem = createElementNS (namespaceURI, 0, localName, localName); + } + else + elem = createElementNS (namespaceURI, 0, localName, localName); + } + else + { //DOM Level 1 + elem = createElement (elemDecl.getFullName()); + } + + elemImpl = (DOMElementImpl *) elem; + + if (attrCount) + { + unsigned int xmlnsNSId = fScanner->getXMLNSNamespaceId(); + unsigned int emptyNSId = fScanner->getEmptyNamespaceId(); + + DOMAttrMapImpl* map = elemImpl->fAttributes; + map->reserve (attrCount); + + for (XMLSize_t index = 0; index < attrCount; ++index) + { + const XMLAttr* oneAttrib = attrList.elementAt(index); + DOMAttrImpl *attr = 0; + + if (doNamespaces) + { + //DOM Level 2, doNamespaces on + // + unsigned int attrURIId = oneAttrib->getURIId(); + const XMLCh* localName = oneAttrib->getName(); + const XMLCh* prefix = oneAttrib->getPrefix(); + namespaceURI = 0; + + if ((prefix==0 || *prefix==0) && XMLString::equals(localName, XMLUni::fgXMLNSString)) + { + // xmlns=... + attrURIId = xmlnsNSId; + } + if (attrURIId != emptyNSId) + { + //TagName has a prefix + namespaceURI = fScanner->getURIText(attrURIId); + } + + attr = (DOMAttrImpl*) createAttrNS (namespaceURI, + prefix, + localName, + oneAttrib->getQName()); + + map->setNamedItemNSFast(attr); + } + else + { + attr = (DOMAttrImpl*) createAttr (oneAttrib->getName()); + map->setNamedItemFast(attr); + } + + attr->setValueFast(oneAttrib->getValue()); + + // Attributes of type ID. If this is one, add it to the hashtable of IDs + // that is constructed for use by GetElementByID(). + // + if (oneAttrib->getType()==XMLAttDef::ID) + { + if (fDocument->fNodeIDMap == 0) + fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument); + fDocument->fNodeIDMap->add(attr); + attr->fNode.isIdAttr(true); + } + + attr->setSpecified(oneAttrib->getSpecified()); + + // store DTD validation information + if(fCreateSchemaInfo) + { + switch(oneAttrib->getType()) + { + case XMLAttDef::CData: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedCDATAAttribute); break; + case XMLAttDef::ID: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDAttribute); break; + case XMLAttDef::IDRef: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFAttribute); break; + case XMLAttDef::IDRefs: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFSAttribute); break; + case XMLAttDef::Entity: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITYAttribute); break; + case XMLAttDef::Entities: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITIESAttribute); break; + case XMLAttDef::NmToken: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENAttribute); break; + case XMLAttDef::NmTokens: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENSAttribute); break; + case XMLAttDef::Notation: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNOTATIONAttribute); break; + case XMLAttDef::Enumeration: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENUMERATIONAttribute); break; + default: attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdNotValidatedAttribute); break; + } + } + } + } + + //Set up the default attributes if any. + // + if (elemDecl.hasAttDefs()) + { + XMLAttDefList* defAttrs = &elemDecl.getAttDefList(); + XMLAttDef* attr = 0; + DOMAttrImpl * insertAttr = 0; + + for(XMLSize_t i=0; igetAttDefCount(); i++) + { + attr = &defAttrs->getAttDef(i); + + const XMLAttDef::DefAttTypes defType = attr->getDefaultType(); + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + + if (doNamespaces) + { + // DOM Level 2 wants all namespace declaration attributes + // to be bound to "http://www.w3.org/2000/xmlns/" + // So as long as the XML parser doesn't do it, it needs to + // be done here. + const XMLCh* qualifiedName = attr->getFullName(); + XMLBufBid bbPrefixQName(&fBufMgr); + XMLBuffer& prefixBuf = bbPrefixQName.getBuffer(); + int colonPos = -1; + unsigned int uriId = fScanner->resolveQName(qualifiedName, prefixBuf, ElemStack::Mode_Attribute, colonPos); + + const XMLCh* namespaceURI = 0; + if (XMLString::equals(qualifiedName, XMLUni::fgXMLNSString)) //for xmlns=... + uriId = fScanner->getXMLNSNamespaceId(); + if (uriId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix + namespaceURI = fScanner->getURIText(uriId); + } + + insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS(namespaceURI, // NameSpaceURI + qualifiedName); // qualified name + + DOMAttr* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr); + if (remAttr) + remAttr->release(); + } + else + { + // Namespaces is turned off... + insertAttr = (DOMAttrImpl *) fDocument->createAttribute(attr->getFullName()); + + DOMNode* remAttr = elemImpl->setDefaultAttributeNode(insertAttr); + if (remAttr) + remAttr->release(); + } + //need to do this before the get as otherwise we overwrite any value in the attr + if (attr->getValue() != 0) + { + insertAttr->setValueFast(attr->getValue()); + insertAttr->setSpecified(false); + } + + // store DTD validation information + if(fCreateSchemaInfo) + { + switch(attr->getType()) + { + case XMLAttDef::CData: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedCDATAAttribute); break; + case XMLAttDef::ID: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDAttribute); break; + case XMLAttDef::IDRef: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFAttribute); break; + case XMLAttDef::IDRefs: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFSAttribute); break; + case XMLAttDef::Entity: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITYAttribute); break; + case XMLAttDef::Entities: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITIESAttribute); break; + case XMLAttDef::NmToken: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENAttribute); break; + case XMLAttDef::NmTokens: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENSAttribute); break; + case XMLAttDef::Notation: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNOTATIONAttribute); break; + case XMLAttDef::Enumeration: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENUMERATIONAttribute); break; + default: insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdNotValidatedAttribute); break; + } + } + } + + insertAttr = 0; + attr->reset(); + } + } + + if (fCurrentParent != fDocument) + castToParentImpl (fCurrentParent)->appendChildFast (elem); + else + fCurrentParent->appendChild (elem); + + fCurrentParent = elem; + fCurrentNode = elem; + fWithinElement = true; + + // If an empty element, do end right now (no endElement() will be called) + if (isEmpty) + endElement(elemDecl, urlId, isRoot, elemPrefix); +} + + +void AbstractDOMParser::startEntityReference(const XMLEntityDecl& entDecl) +{ + const XMLCh * entName = entDecl.getName(); + DOMNamedNodeMap *entities = fDocumentType->getEntities(); + DOMEntityImpl* entity = (DOMEntityImpl*)entities->getNamedItem(entName); + if (entity) + entity->setInputEncoding(fScanner->getReaderMgr()->getCurrentEncodingStr()); + fCurrentEntity = entity; + + + // Following line has been moved up so that erImpl is only declared + // and used if create entity ref flag is true + if (fCreateEntityReferenceNodes == true) { + DOMEntityReference *er = fDocument->createEntityReferenceByParser(entName); + + //set the readOnly flag to false before appending node, will be reset + // in endEntityReference + DOMEntityReferenceImpl *erImpl = (DOMEntityReferenceImpl *) er; + erImpl->setReadOnly(false, true); + + castToParentImpl (fCurrentParent)->appendChildFast (er); + + fCurrentParent = er; + fCurrentNode = er; + + // this entityRef needs to be stored in Entity map too. + // We'd decide later whether the entity nodes should be created by a + // separated method in parser or not. For now just stick it in if + // the ref nodes are created + if (entity) + entity->setEntityRef(er); + } +} + + +void AbstractDOMParser::XMLDecl(const XMLCh* const version + , const XMLCh* const encoding + , const XMLCh* const standalone + , const XMLCh* const actualEncStr) +{ + fDocument->setXmlStandalone(XMLString::equals(XMLUni::fgYesString, standalone)); + fDocument->setXmlVersion(version); + fDocument->setXmlEncoding(encoding); + fDocument->setInputEncoding(actualEncStr); +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Helper methods +// --------------------------------------------------------------------------- + +//doctypehandler interfaces +void AbstractDOMParser::attDef +( + const DTDElementDecl& elemDecl + , const DTDAttDef& attDef + , const bool +) +{ + if (fDocumentType->isIntSubsetReading()) + { + if (elemDecl.hasAttDefs()) + { + fInternalSubset.append(attDef.getFullName()); + + // Get the type and display it + const XMLAttDef::AttTypes type = attDef.getType(); + switch(type) + { + case XMLAttDef::CData : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgCDATAString); + break; + case XMLAttDef::ID : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgIDString); + break; + case XMLAttDef::IDRef : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgIDRefString); + break; + case XMLAttDef::IDRefs : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgIDRefsString); + break; + case XMLAttDef::Entity : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgEntityString); + break; + case XMLAttDef::Entities : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgEntitiesString); + break; + case XMLAttDef::NmToken : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgNmTokenString); + break; + case XMLAttDef::NmTokens : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgNmTokensString); + break; + + case XMLAttDef::Notation : + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgNotationString); + break; + + case XMLAttDef::Enumeration : + { + fInternalSubset.append(chSpace); + const XMLCh* enumString = attDef.getEnumeration(); + XMLSize_t length = XMLString::stringLen(enumString); + if (length > 0) { + + fInternalSubset.append(chOpenParen ); + for(XMLSize_t i=0; iisIntSubsetReading()) + { + if (comment != 0) + { + fInternalSubset.append(XMLUni::fgCommentString); + fInternalSubset.append(chSpace); + fInternalSubset.append(comment); + fInternalSubset.append(chSpace); + fInternalSubset.append(chDash); + fInternalSubset.append(chDash); + fInternalSubset.append(chCloseAngle); + } + } +} + +void AbstractDOMParser::doctypeDecl +( + const DTDElementDecl& elemDecl + , const XMLCh* const publicId + , const XMLCh* const systemId + , const bool + , const bool +) +{ + fDocumentType = (DOMDocumentTypeImpl *) fDocument->createDocumentType(elemDecl.getFullName(), publicId, systemId); + fDocument->setDocumentType(fDocumentType); + +} + +void AbstractDOMParser::doctypePI +( + const XMLCh* const target + , const XMLCh* const data +) +{ + if (fDocumentType->isIntSubsetReading()) + { + //add these chars to internalSubset variable + fInternalSubset.append(chOpenAngle); + fInternalSubset.append(chQuestion); + fInternalSubset.append(target); + fInternalSubset.append(chSpace); + fInternalSubset.append(data); + fInternalSubset.append(chQuestion); + fInternalSubset.append(chCloseAngle); + } +} + + +void AbstractDOMParser::doctypeWhitespace +( + const XMLCh* const chars + , const XMLSize_t length +) +{ + if (fDocumentType->isIntSubsetReading()) + fInternalSubset.append(chars, length); +} + +void AbstractDOMParser::elementDecl +( + const DTDElementDecl& decl + , const bool +) +{ + if (fDocumentType->isIntSubsetReading()) + { + fInternalSubset.append(chOpenAngle); + fInternalSubset.append(chBang); + fInternalSubset.append(XMLUni::fgElemString); + fInternalSubset.append(chSpace); + fInternalSubset.append(decl.getFullName()); + + //get the ContentSpec information + const XMLCh* contentModel = decl.getFormattedContentModel(); + if (contentModel != 0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(contentModel); + } + + fInternalSubset.append(chCloseAngle); + } +} + +void AbstractDOMParser::endAttList +( + const DTDElementDecl& elemDecl +) +{ + if (fDocumentType->isIntSubsetReading()) + { + //print the closing angle + fInternalSubset.append(chCloseAngle); + } + + // this section sets up default attributes. + // default attribute nodes are stored in a NamedNodeMap DocumentTypeImpl::elements + // default attribute data attached to the document is used to conform to the + // DOM spec regarding creating element nodes & removing attributes with default values + // see DocumentTypeImpl + if (elemDecl.hasAttDefs()) + { + XMLAttDefList* defAttrs = &elemDecl.getAttDefList(); + XMLAttDef* attr = 0; + + DOMAttrImpl * insertAttr = 0; + DOMElement *elem = fDocument->createElement(elemDecl.getFullName()); + DOMElementImpl *elemImpl = (DOMElementImpl *) elem; + bool doNamespaces = fScanner->getDoNamespaces(); + + for(XMLSize_t i=0; igetAttDefCount(); i++) + { + attr = &defAttrs->getAttDef(i); + if (attr->getValue() != 0) + { + if (doNamespaces) + { + // DOM Level 2 wants all namespace declaration attributes + // to be bound to "http://www.w3.org/2000/xmlns/" + // So as long as the XML parser doesn't do it, it needs to + // done here. + const XMLCh* qualifiedName = attr->getFullName(); + int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); + + XMLBufBid bbQName(&fBufMgr); + XMLBuffer& buf = bbQName.getBuffer(); + static const XMLCh XMLNS[] = { + chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull}; + + if (index > 0) { + // there is prefix + // map to XML URI for all cases except when prefix == "xmlns" + XMLCh* prefix; + XMLCh temp[1000]; + + if (index > 999) + prefix = (XMLCh*) fMemoryManager->allocate + ( + (index + 1) * sizeof(XMLCh) + );//new XMLCh[index+1]; + else + prefix = temp; + + XMLString::subString(prefix ,qualifiedName, 0, index, fMemoryManager); + + if (XMLString::equals(prefix,XMLNS)) + buf.append(XMLUni::fgXMLNSURIName); + else + buf.append(XMLUni::fgXMLURIName); + + if (index > 999) + fMemoryManager->deallocate(prefix);//delete [] prefix; + } + else { + // No prefix + if (XMLString::equals(qualifiedName,XMLNS)) + buf.append(XMLUni::fgXMLNSURIName); + } + + insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS( + buf.getRawBuffer(), // NameSpaceURI + qualifiedName); // qualified name + + DOMNode* remAttr = elemImpl->setAttributeNodeNS(insertAttr); + if (remAttr) + remAttr->release(); + } + else + { + // Namespaces is turned off... + insertAttr = (DOMAttrImpl *) fDocument->createAttribute(attr->getFullName()); + DOMNode* remAttr = elemImpl->setAttributeNode(insertAttr); + if (remAttr) + remAttr->release(); + } + + insertAttr->setValueFast(attr->getValue()); + insertAttr->setSpecified(false); + } + } + DOMNode* rem = fDocumentType->getElements()->setNamedItem(elemImpl); + if (rem) + rem->release(); + } +} + +void AbstractDOMParser::endIntSubset() +{ + fDocumentType->setInternalSubset(fInternalSubset.getRawBuffer()); + // the buffer shouldn't be released as it is reused in the next parse + // fBufMgr.releaseBuffer(fInternalSubset); + fDocumentType->fIntSubsetReading = false; +} + +void AbstractDOMParser::endExtSubset() +{ +} + +void AbstractDOMParser::entityDecl +( + const DTDEntityDecl& entityDecl + , const bool + , const bool +) +{ + DOMEntityImpl* entity = (DOMEntityImpl *) fDocument->createEntity(entityDecl.getName()); + + entity->setPublicId(entityDecl.getPublicId()); + entity->setSystemId(entityDecl.getSystemId()); + entity->setNotationName(entityDecl.getNotationName()); + entity->setBaseURI(entityDecl.getBaseURI()); + + DOMEntityImpl *previousDef = (DOMEntityImpl *) + fDocumentType->getEntities()->setNamedItem( entity ); + + if (previousDef) + previousDef->release(); + + if (fDocumentType->isIntSubsetReading()) + { + //add thes chars to internalSubset variable + fInternalSubset.append(chOpenAngle); + fInternalSubset.append(chBang); + fInternalSubset.append(XMLUni::fgEntityString); + fInternalSubset.append(chSpace); + + fInternalSubset.append(entityDecl.getName()); + + const XMLCh* id = entity->getPublicId(); + if (id != 0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgPubIDString); + fInternalSubset.append(chSpace); + fInternalSubset.append(chDoubleQuote); + fInternalSubset.append(id); + fInternalSubset.append(chDoubleQuote); + } + id = entity->getSystemId(); + if (id != 0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgSysIDString); + fInternalSubset.append(chSpace); + fInternalSubset.append(chDoubleQuote); + fInternalSubset.append(id); + fInternalSubset.append(chDoubleQuote); + + } + id = entity->getNotationName(); + if (id != 0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgNDATAString); + fInternalSubset.append(chSpace); + fInternalSubset.append(id); + } + id = entityDecl.getValue(); + if (id !=0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(chDoubleQuote); + fInternalSubset.append(id); + fInternalSubset.append(chDoubleQuote); + } + + fInternalSubset.append(chCloseAngle); + } + +} + +void AbstractDOMParser::resetDocType() +{ + fDocumentType = 0; +} + +void AbstractDOMParser::notationDecl +( + const XMLNotationDecl& notDecl + , const bool +) +{ + DOMNotationImpl* notation = (DOMNotationImpl *)fDocument->createNotation(notDecl.getName()); + notation->setPublicId(notDecl.getPublicId()); + notation->setSystemId(notDecl.getSystemId()); + notation->setBaseURI(notDecl.getBaseURI()); + + DOMNode* rem = fDocumentType->getNotations()->setNamedItem( notation ); + if (rem) + rem->release(); + + if (fDocumentType->isIntSubsetReading()) + { + //add thes chars to internalSubset variable + fInternalSubset.append(chOpenAngle); + fInternalSubset.append(chBang); + fInternalSubset.append(XMLUni::fgNotationString); + fInternalSubset.append(chSpace); + + fInternalSubset.append(notDecl.getName()); + + const XMLCh* id = notation->getPublicId(); + if (id != 0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgPubIDString); + fInternalSubset.append(chSpace); + fInternalSubset.append(chDoubleQuote); + fInternalSubset.append(id); + fInternalSubset.append(chDoubleQuote); + } + id = notation->getSystemId(); + if (id != 0) { + fInternalSubset.append(chSpace); + fInternalSubset.append(XMLUni::fgSysIDString); + fInternalSubset.append(chSpace); + fInternalSubset.append(chDoubleQuote); + fInternalSubset.append(id); + fInternalSubset.append(chDoubleQuote); + + } + fInternalSubset.append(chCloseAngle); + } +} + +void AbstractDOMParser::startAttList +( + const DTDElementDecl& elemDecl +) +{ + if (fDocumentType->isIntSubsetReading()) + { + fInternalSubset.append(chOpenAngle); + fInternalSubset.append(chBang); + fInternalSubset.append(XMLUni::fgAttListString); + fInternalSubset.append(chSpace); + fInternalSubset.append(elemDecl.getFullName()); + } +} + +void AbstractDOMParser::startIntSubset() +{ + fDocumentType->fIntSubsetReading = true; +} + +void AbstractDOMParser::startExtSubset() +{ +} + +void AbstractDOMParser::TextDecl +( + const XMLCh* const versionStr + , const XMLCh* const encodingStr +) +{ + if (fCurrentEntity) { + fCurrentEntity->setXmlVersion(versionStr); + fCurrentEntity->setXmlEncoding(encodingStr); + } +} + +DOMCDATASection* AbstractDOMParser:: +createCDATASection (const XMLCh* s, XMLSize_t n) +{ + return new (fDocument, DOMMemoryManager::CDATA_SECTION_OBJECT) + DOMCDATASectionImpl(fDocument, s, n); +} + + +DOMText* AbstractDOMParser:: +createText (const XMLCh* s, XMLSize_t n) +{ + return new (fDocument, DOMMemoryManager::TEXT_OBJECT) + DOMTextImpl(fDocument, s, n); +} + + +DOMElement* AbstractDOMParser:: +createElement (const XMLCh* name) +{ + return new (fDocument, DOMMemoryManager::ELEMENT_OBJECT) + DOMElementImpl(fDocument, name); +} + +DOMElement* AbstractDOMParser:: +createElementNS (const XMLCh* namespaceURI, + const XMLCh* elemPrefix, + const XMLCh* localName, + const XMLCh* qName) +{ + return new (fDocument, DOMMemoryManager::ELEMENT_NS_OBJECT) + DOMElementNSImpl (fDocument, + namespaceURI, + elemPrefix, + localName, + qName); +} + +DOMAttr* AbstractDOMParser:: +createAttr (const XMLCh* name) +{ + return new (fDocument, DOMMemoryManager::ATTR_OBJECT) + DOMAttrImpl(fDocument, name); +} + +DOMAttr* AbstractDOMParser:: +createAttrNS (const XMLCh* namespaceURI, + const XMLCh* elemPrefix, + const XMLCh* localName, + const XMLCh* qName) +{ + return new (fDocument, DOMMemoryManager::ATTR_NS_OBJECT) + DOMAttrNSImpl (fDocument, + namespaceURI, + elemPrefix, + localName, + qName); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/parsers/AbstractDOMParser.hpp b/include/xercesc/parsers/AbstractDOMParser.hpp new file mode 100644 index 0000000..8e66871 --- /dev/null +++ b/include/xercesc/parsers/AbstractDOMParser.hpp @@ -0,0 +1,1900 @@ +/* + * 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: AbstractDOMParser.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ABSTRACTDOMPARSER_HPP) +#define XERCESC_INCLUDE_GUARD_ABSTRACTDOMPARSER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPScanToken; +class XMLScanner; +class XMLValidator; +class DOMDocumentImpl; +class DOMDocumentTypeImpl; +class DOMEntityImpl; +class DOMElement; +class GrammarResolver; +class XMLGrammarPool; +class PSVIHandler; + +/** + * This class implements the Document Object Model (DOM) interface. + * It is used as a base for DOM parsers (i.e. XercesDOMParser, DOMLSParser). + */ +class PARSERS_EXPORT AbstractDOMParser : + + public XMemory + , public XMLDocumentHandler + , public XMLErrorReporter + , public XMLEntityHandler + , public DocTypeHandler + , public PSVIHandler +{ +public : + // ----------------------------------------------------------------------- + // Class types + // ----------------------------------------------------------------------- + /** @name Public constants */ + //@{ + + /** ValScheme enum used in setValidationScheme + * Val_Never: Do not report validation errors. + * Val_Always: The parser will always report validation errors. + * Val_Auto: The parser will report validation errors only if a grammar is specified. + * + * @see #setValidationScheme + */ + enum ValSchemes + { + Val_Never + , Val_Always + , Val_Auto + }; + + //@} + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + + /** + * Destructor + */ + virtual ~AbstractDOMParser(); + + //@} + + // ----------------------------------------------------------------------- + // Utility methods + // ----------------------------------------------------------------------- + + /** @name Utility methods */ + //@{ + /** Reset the parser + * + * This method resets the state of the DOM driver and makes + * it ready for a fresh parse run. + */ + void reset(); + + /** Adopt the DOM document + * + * This method returns the DOMDocument object representing the + * root of the document tree. + * + * The caller will adopt the DOMDocument and thus is responsible to + * call DOMDocument::release() to release the associated memory. + * The parser will not delete it. The ownership is transferred + * from the parser to the caller. + * + * @return The adopted DOMDocument object which represents the entire + * XML document. + */ + DOMDocument* adoptDocument(); + + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** Get the DOM document + * + * This method returns the DOMDocument object representing the + * root of the document tree. This object provides the primary + * access to the document's data. + * + * The returned DOMDocument object is owned by the parser. + * + * @return The DOMDocument object which represents the entire + * XML document. + */ + DOMDocument* getDocument(); + + /** Get a const reference to the validator + * + * This method returns a reference to the parser's installed + * validator. + * + * @return A const reference to the installed validator object. + */ + const XMLValidator& getValidator() const; + + /** + * This method returns an enumerated value that indicates the current + * validation scheme set on this parser. + * + * @return The ValSchemes value current set on this parser. + * @see #setValidationScheme + */ + ValSchemes getValidationScheme() const; + + /** Get the 'do schema' flag + * + * This method returns the state of the parser's schema processing + * flag. + * + * @return true, if the parser is currently configured to + * understand schema, false otherwise. + * + * @see #setDoSchema + */ + bool getDoSchema() const; + + /** Get the 'full schema constraint checking' flag + * + * This method returns the state of the parser's full schema constraint + * checking flag. + * + * @return true, if the parser is currently configured to + * have full schema constraint checking, false otherwise. + * + * @see #setValidationSchemaFullChecking + */ + bool getValidationSchemaFullChecking() const; + + /** Get the identity constraint checking' flag + * + * This method returns the state of the parser's identity constraint + * checking flag. + * + * @return true, if the parser is currently configured to + * have identity constraint checking, false otherwise. + * + * @see setIdentityConstraintChecking + */ + bool getIdentityConstraintChecking() const; + + /** Get error count from the last parse operation. + * + * This method returns the error count from the last parse + * operation. Note that this count is actually stored in the + * scanner, so this method simply returns what the + * scanner reports. + * + * @return number of errors encountered during the latest + * parse operation. + * + */ + XMLSize_t getErrorCount() const; + + /** Get the 'do namespaces' flag + * + * This method returns the state of the parser's namespace processing + * flag. + * + * @return true, if the parser is currently configured to + * understand namespaces, false otherwise. + * + * @see #setDoNamespaces + */ + bool getDoNamespaces() const; + + /** Get the 'exit on first error' flag + * + * This method returns the state of the parser's + * exit-on-First-Fatal-Error flag. If this flag is true, then the + * parse will exit the first time it sees any non-wellformed XML or + * any validity error. The default state is true. + * + * @return true, if the parser is currently configured to + * exit on the first fatal error, false otherwise. + * + * @see #setExitOnFirstFatalError + */ + bool getExitOnFirstFatalError() const; + + /** + * This method returns the state of the parser's + * validation-constraint-fatal flag. + * + * @return true, if the parser is currently configured to + * set validation constraint errors as fatal, false + * otherwise. + * + * @see #setValidationConstraintFatal + */ + bool getValidationConstraintFatal() const; + + /** Get the 'include entity references' flag + * + * This method returns the flag that specifies whether the parser is + * creating entity reference nodes in the DOM tree being produced. + * + * @return The state of the create entity reference node + * flag. + * @see #setCreateEntityReferenceNodes + */ + bool getCreateEntityReferenceNodes()const; + + /** Get the 'include ignorable whitespace' flag. + * + * This method returns the state of the parser's include ignorable + * whitespace flag. + * + * @return 'true' if the include ignorable whitespace flag is set on + * the parser, 'false' otherwise. + * + * @see #setIncludeIgnorableWhitespace + */ + bool getIncludeIgnorableWhitespace() const; + + /** Get the set of Namespace/SchemaLocation that is specified externally. + * + * This method returns the list of Namespace/SchemaLocation that was + * specified using setExternalSchemaLocation. + * + * The parser owns the returned string, and the memory allocated for + * the returned string will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else. + * + * @return a pointer to the list of Namespace/SchemaLocation that was + * specified externally. The pointer spans the same life-time as + * the parser. A null pointer is returned if nothing + * was specified externally. + * + * @see #setExternalSchemaLocation(const XMLCh* const) + */ + XMLCh* getExternalSchemaLocation() const; + + /** Get the noNamespace SchemaLocation that is specified externally. + * + * This method returns the no target namespace XML Schema Location + * that was specified using setExternalNoNamespaceSchemaLocation. + * + * The parser owns the returned string, and the memory allocated for + * the returned string will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else. + * + * @return a pointer to the no target namespace Schema Location that was + * specified externally. The pointer spans the same life-time as + * the parser. A null pointer is returned if nothing + * was specified externally. + * + * @see #setExternalNoNamespaceSchemaLocation(const XMLCh* const) + */ + XMLCh* getExternalNoNamespaceSchemaLocation() const; + + /** Get the SecurityManager instance attached to this parser. + * + * This method returns the security manager + * that was specified using setSecurityManager. + * + * The SecurityManager instance must have been specified by the application; + * this should not be deleted until after the parser has been deleted (or + * a new SecurityManager instance has been supplied to the parser). + * + * @return a pointer to the SecurityManager instance + * specified externally. A null pointer is returned if nothing + * was specified externally. + * + * @see #setSecurityManager + */ + SecurityManager* getSecurityManager() const; + + /** Get the raw buffer low water mark for this parser. + * + * If the number of available bytes in the raw buffer is less than + * the low water mark the parser will attempt to read more data before + * continuing parsing. By default the value for this parameter is 100 + * bytes. You may want to set this parameter to 0 if you would like + * the parser to parse the available data immediately without + * potentially blocking while waiting for more date. + * + * @return current low water mark + * + * @see #setSecurityManager + */ + const XMLSize_t& getLowWaterMark() const; + + /** Get the 'Loading External DTD' flag + * + * This method returns the state of the parser's loading external DTD + * flag. + * + * @return false, if the parser is currently configured to + * ignore external DTD completely, true otherwise. + * + * @see #setLoadExternalDTD + * @see #getValidationScheme + */ + bool getLoadExternalDTD() const; + + /** Get the 'Loading Schema' flag + * + * This method returns the state of the parser's loading schema + * flag. + * + * @return true, if the parser is currently configured to + * automatically load schemas that are not in the + * grammar pool, false otherwise. + * + * @see #setLoadSchema + */ + bool getLoadSchema() const; + + /** Get the 'create comment node' flag + * + * This method returns the flag that specifies whether the parser is + * creating comment nodes in the DOM tree being produced. + * + * @return The state of the create comment node flag. + * @see #setCreateCommentNodes + */ + bool getCreateCommentNodes()const; + + /** + * Get the 'calculate src offset flag' + * + * This method returns the state of the parser's src offset calculation + * when parsing an XML document. + * + * @return true, if the parser is currently configured to + * calculate src offsets, false otherwise. + * + * @see #setCalculateSrcOfs + */ + bool getCalculateSrcOfs() const; + + /** + * Get the 'force standard uri flag' + * + * This method returns the state if the parser forces standard uri + * + * @return true, if the parser is currently configured to + * force standard uri, i.e. malformed uri will be rejected. + * + * @see #setStandardUriConformant + */ + bool getStandardUriConformant() const; + + /** + * This method returns the installed PSVI handler. Suitable + * for 'lvalue' usages. + * + * @return The pointer to the installed PSVI handler object. + */ + PSVIHandler* getPSVIHandler(); + + /** + * This method returns the installed PSVI handler. Suitable + * for 'rvalue' usages. + * + * @return A const pointer to the installed PSVI handler object. + */ + const PSVIHandler* getPSVIHandler() const; + + /** Get the 'associate schema info' flag + * + * This method returns the flag that specifies whether + * the parser is storing schema informations in the element + * and attribute nodes in the DOM tree being produced. + * + * @return The state of the associate schema info flag. + * @see #setCreateSchemaInfo + */ + bool getCreateSchemaInfo() const; + + /** Get the 'do XInclude' flag + * + * This method returns the flag that specifies whether + * the parser will process XInclude nodes + * in the DOM tree being produced. + * + * @return The state of the 'do XInclude' flag. + * @see #setDoXInclude + */ + bool getDoXInclude() const; + + /** Get the 'generate synthetic annotations' flag + * + * @return true, if the parser is currently configured to + * generate synthetic annotations, false otherwise. + * A synthetic XSAnnotation is created when a schema + * component has non-schema attributes but has no + * child annotations so that the non-schema attributes + * can be recovered under PSVI. + * + * @see #setGenerateSyntheticAnnotations + */ + bool getGenerateSyntheticAnnotations() const; + + /** Get the 'validate annotations' flag + * + * @return true, if the parser is currently configured to + * validate annotations, false otherwise. + * + * @see #setValidateAnnotations + */ + bool getValidateAnnotations() const; + + /** Get the 'ignore annotations' flag + * + * @return true, if the parser is currently configured to + * ignore annotations, false otherwise. + * + * @see #setIgnoreAnnotations + */ + bool getIgnoreAnnotations() const; + + /** Get the 'disable default entity resolution' flag + * + * @return true, if the parser is currently configured to + * not perform default entity resolution, false otherwise. + * + * @see #setDisableDefaultEntityResolution + */ + bool getDisableDefaultEntityResolution() const; + + /** Get the 'skip DTD validation' flag + * + * @return true, if the parser is currently configured to + * skip DTD validation, false otherwise. + * + * @see #setSkipDTDValidation + */ + bool getSkipDTDValidation() const; + + /** Get the 'handle multiple schema imports' flag + * + * @return true, if the parser is currently configured to + * import multiple schemas with the same namespace, false otherwise. + * + * @see #setHandleMultipleImports + */ + bool getHandleMultipleImports() const; + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + /** set the 'generate synthetic annotations' flag + * + * @param newValue The value for specifying whether Synthetic Annotations + * should be generated or not. + * A synthetic XSAnnotation is created when a schema + * component has non-schema attributes but has no + * child annotations so that the non-schema attributes + * can be recovered under PSVI. + * + * @see #getGenerateSyntheticAnnotations + */ + void setGenerateSyntheticAnnotations(const bool newValue); + + /** set the 'validlate annotations' flag + * + * @param newValue The value for specifying whether Annotations + * should be validated or not. + * + * @see #getValidateAnnotations + */ + void setValidateAnnotations(const bool newValue); + + /** Set the 'do namespaces' flag + * + * This method allows users to enable or disable the parser's + * namespace processing. When set to true, parser starts enforcing + * all the constraints and rules specified by the NameSpace + * specification. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether NameSpace rules should + * be enforced or not. + * + * @see #getDoNamespaces + */ + void setDoNamespaces(const bool newState); + + /** Set the 'exit on first error' flag + * + * This method allows users to set the parser's behaviour when it + * encounters the first fatal error. If set to true, the parser + * will exit at the first fatal error. If false, then it will + * report the error and continue processing. + * + * The default value is 'true' and the parser exits on the + * first fatal error. + * + * @param newState The value specifying whether the parser should + * continue or exit when it encounters the first + * fatal error. + * + * @see #getExitOnFirstFatalError + */ + void setExitOnFirstFatalError(const bool newState); + + /** + * This method allows users to set the parser's behaviour when it + * encounters a validation constraint error. If set to true, and the + * the parser will treat validation error as fatal and will exit depends on the + * state of "getExitOnFirstFatalError". If false, then it will + * report the error and continue processing. + * + * Note: setting this true does not mean the validation error will be printed with + * the word "Fatal Error". It is still printed as "Error", but the parser + * will exit if "setExitOnFirstFatalError" is set to true. + * + *

The default value is 'false'.

+ * + * @param newState If true, the parser will exit if "setExitOnFirstFatalError" + * is set to true. + * + * @see #getValidationConstraintFatal + * @see #setExitOnFirstFatalError + */ + void setValidationConstraintFatal(const bool newState); + + /** Set the 'include entity references' flag + * + * This method allows the user to specify whether the parser should + * create entity reference nodes in the DOM tree being produced. + * When the 'create' flag is + * true, the parser will create EntityReference nodes in the DOM tree. + * The EntityReference nodes and their child nodes will be read-only. + * When the 'create' flag is false, no EntityReference nodes will be created. + *

The replacement text + * of the entity is included in either case, either as a + * child of the Entity Reference node or in place at the location + * of the reference. + *

The default value is 'true'. + * + * @param create The new state of the create entity reference nodes + * flag. + * @see #getCreateEntityReferenceNodes + */ + void setCreateEntityReferenceNodes(const bool create); + + /** Set the 'include ignorable whitespace' flag + * + * This method allows the user to specify whether a validating parser + * should include ignorable whitespaces as text nodes. It has no effect + * on non-validating parsers which always include non-markup text. + *

When set to true (also the default), ignorable whitespaces will be + * added to the DOM tree as text nodes. The method + * DOMText::isIgnorableWhitespace() will return true for those text + * nodes only. + *

When set to false, all ignorable whitespace will be discarded and + * no text node is added to the DOM tree. Note: applications intended + * to process the "xml:space" attribute should not set this flag to false. + * And this flag also overrides any schema datateye whitespace facets, + * that is, all ignorable whitespace will be discarded even though + * 'preserve' is set in schema datatype whitespace facets. + * + * @param include The new state of the include ignorable whitespace + * flag. + * + * @see #getIncludeIgnorableWhitespace + */ + void setIncludeIgnorableWhitespace(const bool include); + + /** + * This method allows users to set the validation scheme to be used + * by this parser. The value is one of the ValSchemes enumerated values + * defined by this class: + * + *
Val_Never - turn off validation + *
Val_Always - turn on validation + *
Val_Auto - turn on validation if any internal/external + * DTD subset have been seen + * + *

The parser's default state is: Val_Never.

+ * + * @param newScheme The new validation scheme to use. + * + * @see #getValidationScheme + */ + void setValidationScheme(const ValSchemes newScheme); + + /** Set the 'do schema' flag + * + * This method allows users to enable or disable the parser's + * schema processing. When set to false, parser will not process + * any schema found. + * + * The parser's default state is: false. + * + * Note: If set to true, namespace processing must also be turned on. + * + * @param newState The value specifying whether schema support should + * be enforced or not. + * + * @see #getDoSchema + */ + void setDoSchema(const bool newState); + + /** + * This method allows the user to turn full Schema constraint checking on/off. + * Only takes effect if Schema validation is enabled. + * If turned off, partial constraint checking is done. + * + * Full schema constraint checking includes those checking that may + * be time-consuming or memory intensive. Currently, particle unique + * attribution constraint checking and particle derivation restriction checking + * are controlled by this option. + * + * The parser's default state is: false. + * + * @param schemaFullChecking True to turn on full schema constraint checking. + * + * @see #getValidationSchemaFullChecking + */ + void setValidationSchemaFullChecking(const bool schemaFullChecking); + + /** + * This method allows users to enable or disable the parser's identity + * constraint checks. + * + *

By default, the parser does identity constraint checks. + * The default value is true.

+ * + * @param newState The value specifying whether the parser should + * do identity constraint checks or not in the + * input XML document. + * + * @see #getIdentityConstraintChecking + */ + void setIdentityConstraintChecking(const bool newState); + + /** + * This method allows the user to specify a list of schemas to use. + * If the targetNamespace of a schema specified using this method matches + * the targetNamespace of a schema occurring in the instance document in + * the schemaLocation attribute, or if the targetNamespace matches the + * namespace attribute of the "import" element, the schema specified by the + * user using this method will be used (i.e., the schemaLocation attribute + * in the instance document or on the "import" element will be effectively ignored). + * + * If this method is called more than once, only the last one takes effect. + * + * The syntax is the same as for schemaLocation attributes in instance + * documents: e.g, "http://www.example.com file_name.xsd". The user can + * specify more than one XML Schema in the list. + * + * @param schemaLocation the list of schemas to use + * + * @see #getExternalSchemaLocation + */ + + void setExternalSchemaLocation(const XMLCh* const schemaLocation); + + /** + * This method is same as setExternalSchemaLocation(const XMLCh* const). + * It takes native char string as parameter + * + * @param schemaLocation the list of schemas to use + * + * @see #setExternalSchemaLocation(const XMLCh* const) + */ + void setExternalSchemaLocation(const char* const schemaLocation); + + /** + * This method allows the user to specify the no target namespace XML + * Schema Location externally. If specified, the instance document's + * noNamespaceSchemaLocation attribute will be effectively ignored. + * + * If this method is called more than once, only the last one takes effect. + * + * The syntax is the same as for the noNamespaceSchemaLocation attribute + * that may occur in an instance document: e.g."file_name.xsd". + * + * @param noNamespaceSchemaLocation the XML Schema Location with no target namespace + * + * @see #getExternalNoNamespaceSchemaLocation + */ + void setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation); + + /** + * This method is same as setExternalNoNamespaceSchemaLocation(const XMLCh* const). + * It takes native char string as parameter + * + * @param noNamespaceSchemaLocation the XML Schema Location with no target namespace + * + * @see #setExternalNoNamespaceSchemaLocation(const XMLCh* const) + */ + void setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation); + + /** + * This allows an application to set a SecurityManager on + * the parser; this object stores information that various + * components use to limit their consumption of system + * resources while processing documents. + * + * If this method is called more than once, only the last one takes effect. + * It may not be reset during a parse. + * + * + * @param securityManager the SecurityManager instance to + * be used by this parser + * + * @see #getSecurityManager + */ + void setSecurityManager(SecurityManager* const securityManager); + + /** Set the raw buffer low water mark for this parser. + * + * If the number of available bytes in the raw buffer is less than + * the low water mark the parser will attempt to read more data before + * continuing parsing. By default the value for this parameter is 100 + * bytes. You may want to set this parameter to 0 if you would like + * the parser to parse the available data immediately without + * potentially blocking while waiting for more date. + * + * @param lwm new low water mark + * + * @see #getSecurityManager + */ + void setLowWaterMark(XMLSize_t lwm); + + /** Set the 'Loading External DTD' flag + * + * This method allows users to enable or disable the loading of external DTD. + * When set to false, the parser will ignore any external DTD completely + * if the validationScheme is set to Val_Never. + * + * The parser's default state is: true. + * + * This flag is ignored if the validationScheme is set to Val_Always or Val_Auto. + * + * @param newState The value specifying whether external DTD should + * be loaded or not. + * + * @see #getLoadExternalDTD + * @see #setValidationScheme + */ + void setLoadExternalDTD(const bool newState); + + /** Set the 'Loading Schema' flag + * + * This method allows users to enable or disable the loading of schemas. + * When set to false, the parser not attempt to load schemas beyond + * querying the grammar pool for them. + * + * The parser's default state is: true. + * + * @param newState The value specifying whether schemas should + * be loaded if they're not found in the grammar + * pool. + * + * @see #getLoadSchema + * @see #setDoSchema + */ + void setLoadSchema(const bool newState); + + /** Set the 'create comment nodes' flag + * + * This method allows the user to specify whether the parser should + * create comment nodes in the DOM tree being produced. + *

The default value is 'true'. + * + * @param create The new state of the create comment nodes + * flag. + * @see #getCreateCommentNodes + */ + void setCreateCommentNodes(const bool create); + + /** Enable/disable src offset calculation + * + * This method allows users to enable/disable src offset calculation. + * Disabling the calculation will improve performance. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether we should enable or + * disable src offset calculation + * + * @see #getCalculateSrcOfs + */ + void setCalculateSrcOfs(const bool newState); + + /** Force standard uri + * + * This method allows users to tell the parser to force standard uri conformance. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether the parser should reject malformed URI. + * + * @see #getStandardUriConformant + */ + void setStandardUriConformant(const bool newState); + + /** Set the scanner to use when scanning the XML document + * + * This method allows users to set the scanner to use + * when scanning a given XML document. + * + * @param scannerName The name of the desired scanner + */ + void useScanner(const XMLCh* const scannerName); + + /** Set the implementation to use when creating the document + * + * This method allows users to set the implementation to use + * to create the document when parseing. + * + * @param implementationFeatures The names of the desired features the implementation should have. + */ + void useImplementation(const XMLCh* const implementationFeatures); + + /** + * This method installs the user specified PSVI handler on + * the parser. + * + * @param handler A pointer to the PSVI handler to be called + * when the parser comes across 'PSVI' events + * as per the schema specification. + */ + virtual void setPSVIHandler(PSVIHandler* const handler); + + /** Set the 'associate schema info' flag + * + * This method allows users to specify whether + * the parser should store schema informations in the element + * and attribute nodes in the DOM tree being produced. + * + * @param newState The state to set + * @see #getCreateSchemaInfo + */ + void setCreateSchemaInfo(const bool newState); + + /** Set the 'do XInclude' flag + * + * This method allows users to specify whether + * the parser should process XInclude nodes + * in the DOM tree being produced. + * + * @param newState The state to set + * @see #getDoXInclude + */ + void setDoXInclude(const bool newState); + + /** Set the 'ignore annotation' flag + * + * This method gives users the option to not generate XSAnnotations + * when "traversing" a schema. + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setIgnoreAnnotations(const bool newValue); + + /** Set the 'disable default entity resolution' flag + * + * This method gives users the option to not perform default entity + * resolution. If the user's resolveEntity method returns NULL the + * parser will try to resolve the entity on its own. When this option + * is set to true, the parser will not attempt to resolve the entity + * when the resolveEntity method returns NULL. + * + * The parser's default state is false + * + * @param newValue The state to set + * + * @see #EntityResolver + */ + void setDisableDefaultEntityResolution(const bool newValue); + + /** Set the 'skip DTD validation' flag + * + * This method gives users the option to skip DTD validation only when + * schema validation is on (i.e. when performing validation, we will + * ignore the DTD, except for entities, when schema validation is enabled). + * + * NOTE: This option is ignored if schema validation is disabled. + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setSkipDTDValidation(const bool newValue); + + /** Set the 'handle multiple schema imports' flag + * + * This method gives users the ability to import multiple schemas that + * have the same namespace. + * + * NOTE: This option is ignored if schema validation is disabled. + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setHandleMultipleImports(const bool newValue); + //@} + + + // ----------------------------------------------------------------------- + // Parsing methods + // ----------------------------------------------------------------------- + + /** @name Parsing methods */ + //@{ + + /** Parse via an input source object + * + * This method invokes the parsing process on the XML file specified + * by the InputSource parameter. This API is borrowed from the + * SAX Parser interface. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * @see InputSource#InputSource + */ + void parse(const InputSource& source); + + /** Parse via a file path or URL + * + * This method invokes the parsing process on the XML file specified by + * the Unicode string parameter 'systemId'. This method is borrowed + * from the SAX Parser interface. + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML file to be parsed. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * @see #parse(InputSource,...) + */ + void parse(const XMLCh* const systemId); + + /** Parse via a file path or URL (in the local code page) + * + * This method invokes the parsing process on the XML file specified by + * the native char* string parameter 'systemId'. + * + * @param systemId A const char pointer to a native string which + * contains the path to the XML file to be parsed. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * @see #parse(InputSource,...) + */ + void parse(const char* const systemId); + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a Unicode string representing the path + * to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + bool parseFirst + ( + const XMLCh* const systemId + , XMLPScanToken& toFill + ); + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a regular native string representing + * the path to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(InputSource&,...) + */ + bool parseFirst + ( + const char* const systemId + , XMLPScanToken& toFill + ); + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + */ + bool parseFirst + ( + const InputSource& source + , XMLPScanToken& toFill + ); + + /** Continue a progressive parse operation + * + * This method is used to continue with progressive parsing of + * XML files started by a call to 'parseFirst' method. + * + * It parses the XML file and stops as soon as it comes across + * a XML token (as defined in the XML specification). + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the next XML token. + * It indicates the user can go ahead with parsing the rest + * of the file. It returns 'false' to indicate that the parser + * could not find next token as per the XML specification + * production rule. + * + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + bool parseNext(XMLPScanToken& token); + + /** Reset the parser after a progressive parse + * + * If a progressive parse loop exits before the end of the document + * is reached, the parser has no way of knowing this. So it will leave + * open any files or sockets or memory buffers that were in use at + * the time that the parse loop exited. + * + * The next parse operation will cause these open files and such to + * be closed, but the next parse operation might occur at some unknown + * future point. To avoid this problem, you should reset the parser if + * you exit the loop early. + * + * If you exited because of an error, then this cleanup will be done + * for you. Its only when you exit the file prematurely of your own + * accord, because you've found what you wanted in the file most + * likely. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + void parseReset(XMLPScanToken& token); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the PSVIHandler interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the PSVIHandler interface. */ + //@{ + + /** Receive notification of the PSVI properties of an element. + * The scanner will issue this call after the XMLDocumentHandler + * endElement call. Since the scanner will issue the psviAttributes + * call immediately after reading the start tag of an element, all element + * content will be effectively bracketed by these two calls. + * @param localName The name of the element whose end tag was just + * parsed. + * @param uri The namespace to which the element is bound + * @param elementInfo Object containing the element's PSVI properties + */ + virtual void handleElementPSVI + ( + const XMLCh* const localName + , const XMLCh* const uri + , PSVIElement * elementInfo + ); + + virtual void handlePartialElementPSVI + ( + const XMLCh* const localName + , const XMLCh* const uri + , PSVIElement * elementInfo + ); + /** + * Enables PSVI information about attributes to be passed back to the + * application. This callback will be made on *all* + * elements; on elements with no attributes, the final parameter will + * be null. + * @param localName The name of the element upon which start tag + * these attributes were encountered. + * @param uri The namespace to which the element is bound + * @param psviAttributes Object containing the attributes' PSVI properties + * with information to identify them. + */ + virtual void handleAttributesPSVI + ( + const XMLCh* const localName + , const XMLCh* const uri + , PSVIAttributeList * psviAttributes + ); + //@} + + // ----------------------------------------------------------------------- + // Implementation of the XMLDocumentHandler interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLDocumentHandler interface. */ + //@{ + + /** Handle document character events + * + * This method is used to report all the characters scanned by the + * parser. This DOM implementation stores this data in the appropriate + * DOM node, creating one if necessary. + * + * @param chars A const pointer to a Unicode string representing the + * character data. + * @param length The length of the Unicode string returned in 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + */ + virtual void docCharacters + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** Handle a document comment event + * + * This method is used to report any comments scanned by the parser. + * A new comment node is created which stores this data. + * + * @param comment A const pointer to a null terminated Unicode + * string representing the comment text. + */ + virtual void docComment + ( + const XMLCh* const comment + ); + + /** Handle a document PI event + * + * This method is used to report any PI scanned by the parser. A new + * PI node is created and appended as a child of the current node in + * the tree. + * + * @param target A const pointer to a Unicode string representing the + * target of the PI declaration. + * @param data A const pointer to a Unicode string representing the + * data of the PI declaration. See the PI production rule + * in the XML specification for details. + */ + virtual void docPI + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** Handle the end of document event + * + * This method is used to indicate the end of the current document. + */ + virtual void endDocument(); + + /** Handle and end of element event + * + * This method is used to indicate the end tag of an element. The + * DOM parser pops the current element off the top of the element + * stack, and make it the new current element. + * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param isRoot A flag indicating whether this element was the + * root element. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + */ + virtual void endElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const bool isRoot + , const XMLCh* const elemPrefix + ); + + /** Handle and end of entity reference event + * + * This method is used to indicate that an end of an entity reference + * was just scanned. + * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void endEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** Handle an ignorable whitespace vent + * + * This method is used to report all the whitespace characters, which + * are determined to be 'ignorable'. This distinction between characters + * is only made, if validation is enabled. + * + * Any whitespace before content is ignored. If the current node is + * already of type DOMNode::TEXT_NODE, then these whitespaces are + * appended, otherwise a new Text node is created which stores this + * data. Essentially all contiguous ignorable characters are collected + * in one node. + * + * @param chars A const pointer to a Unicode string representing the + * ignorable whitespace character data. + * @param length The length of the Unicode string 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** Handle a document reset event + * + * This method allows the user installed Document Handler to 'reset' + * itself, freeing all the memory resources. The scanner calls this + * method before starting a new parse event. + */ + virtual void resetDocument(); + + /** Handle a start document event + * + * This method is used to report the start of the parsing process. + */ + virtual void startDocument(); + + /** Handle a start element event + * + * This method is used to report the start of an element. It is + * called at the end of the element, by which time all attributes + * specified are also parsed. A new DOM Element node is created + * along with as many attribute nodes as required. This new element + * is added appended as a child of the current node in the tree, and + * then replaces it as the current node (if the isEmpty flag is false.) + * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + * @param attrList A const reference to the object containing the + * list of attributes just scanned for this element. + * @param attrCount A count of number of attributes in the list + * specified by the parameter 'attrList'. + * @param isEmpty A flag indicating whether this is an empty element + * or not. If empty, then no endElement() call will + * be made. + * @param isRoot A flag indicating whether this element was the + * root element. + * @see DocumentHandler#startElement + */ + virtual void startElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot + ); + + /** Handle a start entity reference event + * + * This method is used to indicate the start of an entity reference. + * If the expand entity reference flag is true, then a new + * DOM Entity reference node is created. + * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void startEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** Handle an XMLDecl event + * + * This method is used to report the XML decl scanned by the parser. + * Refer to the XML specification to see the meaning of parameters. + * + * This method is a no-op for this DOM + * implementation. + * + * @param versionStr A const pointer to a Unicode string representing + * version string value. + * @param encodingStr A const pointer to a Unicode string representing + * the encoding string value. + * @param standaloneStr A const pointer to a Unicode string + * representing the standalone string value. + * @param actualEncStr A const pointer to a Unicode string + * representing the actual encoding string + * value. + */ + virtual void XMLDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncStr + ); + + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the deprecated DocTypeHandler interface. + // ----------------------------------------------------------------------- + /** @name Deprecated DocTypeHandler Interfaces */ + //@{ + virtual void attDef + ( + const DTDElementDecl& elemDecl + , const DTDAttDef& attDef + , const bool ignoring + ); + + virtual void doctypeComment + ( + const XMLCh* const comment + ); + + virtual void doctypeDecl + ( + const DTDElementDecl& elemDecl + , const XMLCh* const publicId + , const XMLCh* const systemId + , const bool hasIntSubset + , const bool hasExtSubset = false + ); + + virtual void doctypePI + ( + const XMLCh* const target + , const XMLCh* const data + ); + + virtual void doctypeWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + virtual void elementDecl + ( + const DTDElementDecl& decl + , const bool isIgnored + ); + + virtual void endAttList + ( + const DTDElementDecl& elemDecl + ); + + virtual void endIntSubset(); + + virtual void endExtSubset(); + + virtual void entityDecl + ( + const DTDEntityDecl& entityDecl + , const bool isPEDecl + , const bool isIgnored + ); + + virtual void resetDocType(); + + virtual void notationDecl + ( + const XMLNotationDecl& notDecl + , const bool isIgnored + ); + + virtual void startAttList + ( + const DTDElementDecl& elemDecl + ); + + virtual void startIntSubset(); + + virtual void startExtSubset(); + + virtual void TextDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + ); + + //@} + +protected: + // DOM node creation hooks. Override them if you are using your own + // DOM node types. + // + virtual DOMCDATASection* createCDATASection (const XMLCh*, XMLSize_t); + virtual DOMText* createText (const XMLCh*, XMLSize_t); + + virtual DOMElement* createElement (const XMLCh* name); + virtual DOMElement* createElementNS (const XMLCh* namespaceURI, + const XMLCh* elemPrefix, + const XMLCh* localName, + const XMLCh* qName); + + virtual DOMAttr* createAttr (const XMLCh* name); + virtual DOMAttr* createAttrNS (const XMLCh* namespaceURI, + const XMLCh* elemPrefix, + const XMLCh* localName, + const XMLCh* qName); + + + + +protected : + // ----------------------------------------------------------------------- + // Protected Constructor Methods + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + /** Construct a AbstractDOMParser, with an optional validator + * + * Constructor with an instance of validator class to use for + * validation. If you don't provide a validator, a default one will + * be created for you in the scanner. + * + * @param valToAdopt Pointer to the validator instance to use. The + * parser is responsible for freeing the memory. + * + * @param gramPool Pointer to the grammar pool instance from + * external application (through derivatives). + * The parser does NOT own it. + * + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + AbstractDOMParser + ( + XMLValidator* const valToAdopt = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ); + + //@} + + // ----------------------------------------------------------------------- + // Protected getter methods + // ----------------------------------------------------------------------- + /** @name Protected getter methods */ + //@{ + /** Get the current DOM node + * + * This provides derived classes with access to the current node, i.e. + * the node to which new nodes are being added. + */ + DOMNode* getCurrentNode(); + + /** Get the XML scanner + * + * This provides derived classes with access to the XML scanner. + */ + XMLScanner* getScanner() const; + + /** Get the Grammar resolver + * + * This provides derived classes with access to the grammar resolver. + */ + GrammarResolver* getGrammarResolver() const; + + /** Get the parse in progress flag + * + * This provides derived classes with access to the parse in progress + * flag. + */ + bool getParseInProgress() const; + + MemoryManager* getMemoryManager() const; + + //@} + + + // ----------------------------------------------------------------------- + // Protected setter methods + // ----------------------------------------------------------------------- + + /** @name Protected setter methods */ + //@{ + + /** Set the current DOM node + * + * This method sets the current node maintained inside the parser to + * the one specified. + * + * @param toSet The DOM node which will be the current node. + */ + void setCurrentNode(DOMNode* toSet); + + /** Set the document node + * + * This method sets the DOM Document node to the one specified. + * + * @param toSet The new DOM Document node for this XML document. + */ + void setDocument(DOMDocument* toSet); + + /** Set the parse in progress flag + * + * This method sets the parse in progress flag to true or false. + * + * @param toSet The value of the flag to be set. + */ + void setParseInProgress(const bool toSet); + //@} + + // ----------------------------------------------------------------------- + // Protected Helper methods + // ----------------------------------------------------------------------- + /** @name Protected helper methods */ + //@{ + void resetPool(); + + /** + * Returns true if the user has adopted the document + */ + bool isDocumentAdopted() const; + + //@} + + +private : + // ----------------------------------------------------------------------- + // Initialize/Cleanup methods + // ----------------------------------------------------------------------- + void initialize(); + void cleanUp(); + void resetInProgress(); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + AbstractDOMParser(const AbstractDOMParser&); + AbstractDOMParser& operator=(const AbstractDOMParser&); + +protected: + // ----------------------------------------------------------------------- + // Protected data members + // + // fCurrentNode + // fCurrentParent + // Used to track the current node during nested element events. Since + // the tree must be built from a set of disjoint callbacks, we need + // these to keep up with where we currently are. + // + // fCurrentEntity + // Used to track the current entity decl. If a text decl is seen later on, + // it is used to update the encoding and version information. + // + // fDocument + // The root document object, filled with the document contents. + // + // fCreateEntityReferenceNodes + // Indicates whether entity reference nodes should be created. + // + // fIncludeIgnorableWhitespace + // Indicates whether ignorable whitespace should be added to + // the DOM tree for validating parsers. + // + // fScanner + // The scanner used for this parser. This is created during the + // constructor. + // + // fImplementationFeatures + // The implementation features that we use to get an implementation + // for use in creating the DOMDocument used during parse. If this is + // null then the default DOMImplementation is used + // + // fParseInProgress + // Used to prevent multiple entrance to the parser while its doing + // a parse. + // + // fWithinElement + // A flag to indicate that the parser is within at least one level + // of element processing. + // + // fDocumentType + // Used to store and update the documentType variable information + // in fDocument + // + // fDocumentVector + // Store all the previous fDocument(s) (thus not the current fDocument) + // created in this parser. It is destroyed when the parser is destructed. + // + // fCreateCommentNodes + // Indicates whether comment nodes should be created. + // + // fDocumentAdoptedByUser + // The DOMDocument ownership has been transferred to application + // If set to true, the parser does not own the document anymore + // and thus will not release its memory. + // + // fInternalSubset + // Buffer for storing the internal subset information. + // Once complete (after DOCTYPE is finished scanning), send + // it to DocumentType Node + // + // fGrammarPool + // The grammar pool passed from external application (through derivatives). + // which could be 0, not owned. + // + // fCreateSchemaInfo + // Indicates whether element and attributes will have schema info associated + // + // fDoXinclude + // A bool used to request that XInlcude processing occur on the + // Document the parser parses. + // ----------------------------------------------------------------------- + bool fCreateEntityReferenceNodes; + bool fIncludeIgnorableWhitespace; + bool fWithinElement; + bool fParseInProgress; + bool fCreateCommentNodes; + bool fDocumentAdoptedByUser; + bool fCreateSchemaInfo; + bool fDoXInclude; + XMLScanner* fScanner; + XMLCh* fImplementationFeatures; + DOMNode* fCurrentParent; + DOMNode* fCurrentNode; + DOMEntityImpl* fCurrentEntity; + DOMDocumentImpl* fDocument; + DOMDocumentTypeImpl* fDocumentType; + RefVectorOf* fDocumentVector; + GrammarResolver* fGrammarResolver; + XMLStringPool* fURIStringPool; + XMLValidator* fValidator; + MemoryManager* fMemoryManager; + XMLGrammarPool* fGrammarPool; + XMLBufferMgr fBufMgr; + XMLBuffer& fInternalSubset; + PSVIHandler* fPSVIHandler; +}; + + + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Getter methods +// --------------------------------------------------------------------------- +inline bool AbstractDOMParser::getCreateEntityReferenceNodes() const +{ + return fCreateEntityReferenceNodes; +} + +inline bool AbstractDOMParser::getIncludeIgnorableWhitespace() const +{ + return fIncludeIgnorableWhitespace; +} + +inline bool AbstractDOMParser::getParseInProgress() const +{ + return fParseInProgress; +} + +inline XMLScanner* AbstractDOMParser::getScanner() const +{ + return fScanner; +} + +inline GrammarResolver* AbstractDOMParser::getGrammarResolver() const +{ + return fGrammarResolver; +} + +inline bool AbstractDOMParser::getCreateCommentNodes() const +{ + return fCreateCommentNodes; +} + +inline PSVIHandler* AbstractDOMParser::getPSVIHandler() +{ + return fPSVIHandler; +} + +inline const PSVIHandler* AbstractDOMParser::getPSVIHandler() const +{ + return fPSVIHandler; +} + +inline bool AbstractDOMParser::getCreateSchemaInfo() const +{ + return fCreateSchemaInfo; +} + +inline bool AbstractDOMParser::getDoXInclude() const +{ + return fDoXInclude; +} +// --------------------------------------------------------------------------- +// AbstractDOMParser: Setter methods +// --------------------------------------------------------------------------- +inline void AbstractDOMParser::setCreateEntityReferenceNodes(const bool create) +{ + fCreateEntityReferenceNodes = create; +} + +inline void AbstractDOMParser::setIncludeIgnorableWhitespace(const bool include) +{ + fIncludeIgnorableWhitespace = include; +} + +inline void AbstractDOMParser::setCreateCommentNodes(const bool create) +{ + fCreateCommentNodes = create; +} + +inline void AbstractDOMParser::useImplementation(const XMLCh* const implementationFeatures) +{ + fMemoryManager->deallocate(fImplementationFeatures); + fImplementationFeatures = XMLString::replicate(implementationFeatures, fMemoryManager); +} + +inline void AbstractDOMParser::setDoXInclude(const bool newState) +{ + fDoXInclude = newState; +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Protected getter methods +// --------------------------------------------------------------------------- +inline DOMNode* AbstractDOMParser::getCurrentNode() +{ + return fCurrentNode; +} + +inline MemoryManager* AbstractDOMParser::getMemoryManager() const +{ + return fMemoryManager; +} + +// --------------------------------------------------------------------------- +// AbstractDOMParser: Protected setter methods +// --------------------------------------------------------------------------- +inline void AbstractDOMParser::setCurrentNode(DOMNode* toSet) +{ + fCurrentNode = toSet; +} + +inline void AbstractDOMParser::setParseInProgress(const bool toSet) +{ + fParseInProgress = toSet; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/parsers/DOMLSParserImpl.cpp b/include/xercesc/parsers/DOMLSParserImpl.cpp new file mode 100644 index 0000000..8608780 --- /dev/null +++ b/include/xercesc/parsers/DOMLSParserImpl.cpp @@ -0,0 +1,1379 @@ +/* + * 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. + */ + +/** +* This file contains code to build the DOM tree. It registers a document +* handler with the scanner. In these handler methods, appropriate DOM nodes +* are created and added to the DOM tree. +* +* $Id: DOMLSParserImpl.cpp 882548 2009-11-20 13:44:14Z borisk $ +* +*/ + + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// A filter used to abort processing +// --------------------------------------------------------------------------- +class __AbortFilter : public DOMLSParserFilter +{ +public: + __AbortFilter() {} + virtual FilterAction acceptNode(DOMNode*) { return FILTER_INTERRUPT; } + virtual FilterAction startElement(DOMElement* ) { return FILTER_INTERRUPT; } + virtual DOMNodeFilter::ShowType getWhatToShow() const { return DOMNodeFilter::SHOW_ALL; } +}; + +static __AbortFilter g_AbortFilter; + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Constructors and Destructor +// --------------------------------------------------------------------------- +DOMLSParserImpl::DOMLSParserImpl( XMLValidator* const valToAdopt + , MemoryManager* const manager + , XMLGrammarPool* const gramPool) : + +AbstractDOMParser(valToAdopt, manager, gramPool) +, fEntityResolver(0) +, fXMLEntityResolver(0) +, fErrorHandler(0) +, fFilter(0) +, fCharsetOverridesXMLEncoding(true) +, fUserAdoptsDocument(false) +, fSupportedParameters(0) +, fFilterAction(0) +, fFilterDelayedTextNodes(0) +, fWrapNodesInDocumentFragment(0) +, fWrapNodesContext(0) +{ + // dom spec has different default from scanner's default, so set explicitly + getScanner()->setNormalizeData(false); + + fSupportedParameters=new (fMemoryManager) DOMStringListImpl(48, manager); + fSupportedParameters->add(XMLUni::fgDOMResourceResolver); + fSupportedParameters->add(XMLUni::fgDOMErrorHandler); + fSupportedParameters->add(XMLUni::fgXercesEntityResolver); + fSupportedParameters->add(XMLUni::fgXercesSchemaExternalSchemaLocation); + fSupportedParameters->add(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation); + fSupportedParameters->add(XMLUni::fgXercesSecurityManager); + fSupportedParameters->add(XMLUni::fgXercesScannerName); + fSupportedParameters->add(XMLUni::fgXercesParserUseDocumentFromImplementation); + fSupportedParameters->add(XMLUni::fgDOMCharsetOverridesXMLEncoding); + fSupportedParameters->add(XMLUni::fgDOMDisallowDoctype); + fSupportedParameters->add(XMLUni::fgDOMIgnoreUnknownCharacterDenormalization); + fSupportedParameters->add(XMLUni::fgDOMNamespaces); + fSupportedParameters->add(XMLUni::fgDOMSupportedMediatypesOnly); + fSupportedParameters->add(XMLUni::fgDOMValidate); + fSupportedParameters->add(XMLUni::fgDOMValidateIfSchema); + fSupportedParameters->add(XMLUni::fgDOMWellFormed); + fSupportedParameters->add(XMLUni::fgDOMCanonicalForm); + fSupportedParameters->add(XMLUni::fgDOMCDATASections); + fSupportedParameters->add(XMLUni::fgDOMCheckCharacterNormalization); + fSupportedParameters->add(XMLUni::fgDOMComments); + fSupportedParameters->add(XMLUni::fgDOMDatatypeNormalization); + fSupportedParameters->add(XMLUni::fgDOMElementContentWhitespace); + fSupportedParameters->add(XMLUni::fgDOMEntities); + fSupportedParameters->add(XMLUni::fgDOMNamespaceDeclarations); + fSupportedParameters->add(XMLUni::fgDOMNormalizeCharacters); + fSupportedParameters->add(XMLUni::fgDOMSchemaLocation); + fSupportedParameters->add(XMLUni::fgDOMSchemaType); + fSupportedParameters->add(XMLUni::fgDOMSplitCDATASections); + fSupportedParameters->add(XMLUni::fgDOMInfoset); + fSupportedParameters->add(XMLUni::fgXercesSchema); + fSupportedParameters->add(XMLUni::fgXercesSchemaFullChecking); + fSupportedParameters->add(XMLUni::fgXercesUserAdoptsDOMDocument); + fSupportedParameters->add(XMLUni::fgXercesLoadExternalDTD); + fSupportedParameters->add(XMLUni::fgXercesLoadSchema); + fSupportedParameters->add(XMLUni::fgXercesContinueAfterFatalError); + fSupportedParameters->add(XMLUni::fgXercesValidationErrorAsFatal); + fSupportedParameters->add(XMLUni::fgXercesCacheGrammarFromParse); + fSupportedParameters->add(XMLUni::fgXercesUseCachedGrammarInParse); + fSupportedParameters->add(XMLUni::fgXercesCalculateSrcOfs); + fSupportedParameters->add(XMLUni::fgXercesStandardUriConformant); + fSupportedParameters->add(XMLUni::fgXercesDOMHasPSVIInfo); + fSupportedParameters->add(XMLUni::fgXercesGenerateSyntheticAnnotations); + fSupportedParameters->add(XMLUni::fgXercesValidateAnnotations); + fSupportedParameters->add(XMLUni::fgXercesIdentityConstraintChecking); + fSupportedParameters->add(XMLUni::fgXercesIgnoreCachedDTD); + fSupportedParameters->add(XMLUni::fgXercesIgnoreAnnotations); + fSupportedParameters->add(XMLUni::fgXercesDisableDefaultEntityResolution); + fSupportedParameters->add(XMLUni::fgXercesSkipDTDValidation); + fSupportedParameters->add(XMLUni::fgXercesDoXInclude); + fSupportedParameters->add(XMLUni::fgXercesHandleMultipleImports); + + // LSParser by default does namespace processing + setDoNamespaces(true); +} + + +DOMLSParserImpl::~DOMLSParserImpl() +{ + delete fSupportedParameters; + delete fFilterAction; + delete fFilterDelayedTextNodes; +} + + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Setter methods +// --------------------------------------------------------------------------- +bool DOMLSParserImpl::getBusy() const +{ + return getParseInProgress(); +} + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Setter methods +// --------------------------------------------------------------------------- +void DOMLSParserImpl::setFilter(DOMLSParserFilter* const filter) +{ + fFilter = filter; +} + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: DOMConfiguration methods +// --------------------------------------------------------------------------- +void DOMLSParserImpl::setParameter(const XMLCh* name, const void* value) +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgDOMResourceResolver) == 0) + { + fEntityResolver = (DOMLSResourceResolver*)value; + if (fEntityResolver) { + getScanner()->setEntityHandler(this); + fXMLEntityResolver = 0; + } + else { + getScanner()->setEntityHandler(0); + } + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMErrorHandler) == 0) + { + fErrorHandler = (DOMErrorHandler*)value; + if (fErrorHandler) { + getScanner()->setErrorReporter(this); + } + else { + getScanner()->setErrorReporter(0); + } + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaLocation) == 0) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaType) == 0) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesEntityResolver) == 0) + { + fXMLEntityResolver = (XMLEntityResolver*)value; + if (fXMLEntityResolver) { + getScanner()->setEntityHandler(this); + fEntityResolver = 0; + } + else { + getScanner()->setEntityHandler(0); + } + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0) + { + setExternalSchemaLocation((XMLCh*)value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0) + { + setExternalNoNamespaceSchemaLocation((XMLCh*)value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0) + { + setSecurityManager((SecurityManager*)value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesScannerName) == 0) + { + AbstractDOMParser::useScanner((const XMLCh*) value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesParserUseDocumentFromImplementation) == 0) + { + useImplementation((const XMLCh*) value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLowWaterMark) == 0) + { + setLowWaterMark(*(const XMLSize_t*)value); + } + else + throw DOMException(DOMException::NOT_FOUND_ERR, 0, getMemoryManager()); +} + +void DOMLSParserImpl::setParameter(const XMLCh* name, bool state) +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCharsetOverridesXMLEncoding) == 0) + { + // in fact, setting this has no effect to the parser + fCharsetOverridesXMLEncoding = state; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMDisallowDoctype) == 0) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMIgnoreUnknownCharacterDenormalization) == 0) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaces) == 0) + { + setDoNamespaces(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSupportedMediatypesOnly) == 0) + { + if (state) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMValidate) == 0) + { + if (state) { + if (getValidationScheme() == AbstractDOMParser::Val_Never) + setValidationScheme(AbstractDOMParser::Val_Always); + } + else { + setValidationScheme(AbstractDOMParser::Val_Never); + } + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMValidateIfSchema) == 0) + { + if (state) { + setValidationScheme(AbstractDOMParser::Val_Auto); + } + else { + setValidationScheme(AbstractDOMParser::Val_Never); + } + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMWellFormed) == 0) + { + if(state==false) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCanonicalForm) == 0 ) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCDATASections) == 0 ) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCheckCharacterNormalization) == 0 ) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMComments) == 0) + { + setCreateCommentNodes(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMDatatypeNormalization) == 0) + { + getScanner()->setNormalizeData(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMElementContentWhitespace) == 0) + { + setIncludeIgnorableWhitespace(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMEntities) == 0) + { + setCreateEntityReferenceNodes(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaceDeclarations) == 0) + { + if (state==false) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNormalizeCharacters) == 0) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSplitCDATASections) == 0) + { + // TODO + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMInfoset) == 0) + { + if (!state) + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager()); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0) + { + setDoSchema(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0) + { + setValidationSchemaFullChecking(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUserAdoptsDOMDocument) == 0) + { + if(state) + fUserAdoptsDocument = true; + else + fUserAdoptsDocument = false; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0) + { + setLoadExternalDTD(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadSchema) == 0) + { + setLoadSchema(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0) + { + setExitOnFirstFatalError(!state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0) + { + setValidationConstraintFatal(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0) + { + getScanner()->cacheGrammarFromParse(state); + + if (state) + getScanner()->useCachedGrammarInParse(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0) + { + if (state || !getScanner()->isCachingGrammarFromParse()) + getScanner()->useCachedGrammarInParse(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0) + { + getScanner()->setCalculateSrcOfs(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0) + { + getScanner()->setStandardUriConformant(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDOMHasPSVIInfo) == 0) + { + setCreateSchemaInfo(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0) + { + getScanner()->setGenerateSyntheticAnnotations(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0) + { + getScanner()->setValidateAnnotations(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0) + { + getScanner()->setIdentityConstraintChecking(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0) + { + getScanner()->setIgnoredCachedDTD(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0) + { + getScanner()->setIgnoreAnnotations(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0) + { + getScanner()->setDisableDefaultEntityResolution(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0) + { + getScanner()->setSkipDTDValidation(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDoXInclude) == 0) + { + setDoXInclude(state); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesHandleMultipleImports) == 0) + { + getScanner()->setHandleMultipleImports(state); + } + else + throw DOMException(DOMException::NOT_FOUND_ERR, 0, getMemoryManager()); +} + +const void* DOMLSParserImpl::getParameter(const XMLCh* name) const +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCharsetOverridesXMLEncoding) == 0) + { + return (void*)fCharsetOverridesXMLEncoding; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMDisallowDoctype) == 0) + { + // TODO + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMIgnoreUnknownCharacterDenormalization) == 0) + { + // TODO + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaces) == 0) + { + return (void*)getDoNamespaces(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMResourceResolver) == 0) + { + return fEntityResolver; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSupportedMediatypesOnly) == 0) + { + return (void*)false; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMValidate) == 0) + { + return (void*)(getValidationScheme() != AbstractDOMParser::Val_Never); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMValidateIfSchema) == 0) + { + return (void*)(getValidationScheme() == AbstractDOMParser::Val_Auto); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMWellFormed) == 0) + { + return (void*)true; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCanonicalForm) == 0 ) + { + // TODO + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCDATASections) == 0 ) + { + // TODO + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCheckCharacterNormalization) == 0 ) + { + // TODO + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMComments) == 0) + { + return (void*)getCreateCommentNodes(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMDatatypeNormalization) == 0) + { + return (void*)getScanner()->getNormalizeData(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMElementContentWhitespace) == 0) + { + return (void*)getIncludeIgnorableWhitespace(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMEntities) == 0) + { + return (void*)getCreateEntityReferenceNodes(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMErrorHandler) == 0) + { + return fErrorHandler; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaceDeclarations) == 0) + { + return (void*)true; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMNormalizeCharacters) == 0) + { + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaLocation) == 0) + { + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaType) == 0) + { + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMSplitCDATASections) == 0) + { + return 0; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgDOMInfoset) == 0) + { + return (void*)true; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0) + { + return (void*)getDoSchema(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0) + { + return (void*)getValidationSchemaFullChecking(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0) + { + return (void*)getIdentityConstraintChecking(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0) + { + return (void*)getLoadExternalDTD(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadSchema) == 0) + { + return (void*)getLoadSchema(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0) + { + return (void*)!getExitOnFirstFatalError(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0) + { + return (void*)getValidationConstraintFatal(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0) + { + return (void*)getScanner()->isCachingGrammarFromParse(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0) + { + return (void*)getScanner()->isUsingCachedGrammarInParse(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0) + { + return (void*)getScanner()->getCalculateSrcOfs(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0) + { + return (void*)getScanner()->getStandardUriConformant(); + } + else if(XMLString::compareIStringASCII(name, XMLUni::fgXercesUserAdoptsDOMDocument) == 0) + { + return (void*)fUserAdoptsDocument; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDOMHasPSVIInfo) == 0) + { + return (void*)getCreateSchemaInfo(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0) + { + return (void*)getScanner()->getGenerateSyntheticAnnotations(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0) + { + return (void*)getScanner()->getValidateAnnotations(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0) + { + return (void*)getScanner()->getIgnoreCachedDTD(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0) + { + return (void*)getScanner()->getIgnoreAnnotations(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0) + { + return (void*)getScanner()->getDisableDefaultEntityResolution(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0) + { + return (void*)getScanner()->getSkipDTDValidation(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesHandleMultipleImports) == 0) + { + return (void*)getScanner()->getHandleMultipleImports(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesEntityResolver) == 0) + { + return fXMLEntityResolver; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0) + { + return getExternalSchemaLocation(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0) + { + return getExternalNoNamespaceSchemaLocation(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0) + { + return getSecurityManager(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDoXInclude) == 0) + { + return (void *)getDoXInclude(); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLowWaterMark) == 0) + { + return (void*)&getLowWaterMark(); + } + else + throw DOMException(DOMException::NOT_FOUND_ERR, 0, getMemoryManager()); +} + +bool DOMLSParserImpl::canSetParameter(const XMLCh* name, const void* /*value*/) const +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgDOMResourceResolver) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMErrorHandler) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesEntityResolver) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesScannerName) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesParserUseDocumentFromImplementation) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesLowWaterMark) == 0) + return true; + else if(XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaLocation) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMSchemaType) == 0) + return false; + + return false; +} + +bool DOMLSParserImpl::canSetParameter(const XMLCh* name, bool value) const +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgDOMCharsetOverridesXMLEncoding) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaces) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMValidate) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMValidateIfSchema) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMComments) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMDatatypeNormalization) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMElementContentWhitespace) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMEntities) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadSchema) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesUserAdoptsDOMDocument) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesDOMHasPSVIInfo) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesDoXInclude) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgXercesHandleMultipleImports) == 0) + return true; + else if(XMLString::compareIStringASCII(name, XMLUni::fgDOMDisallowDoctype) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMIgnoreUnknownCharacterDenormalization) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMCanonicalForm) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMCDATASections) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMCheckCharacterNormalization) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMNormalizeCharacters) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMSplitCDATASections) == 0) + return false; + else if(XMLString::compareIStringASCII(name, XMLUni::fgDOMSupportedMediatypesOnly) == 0) + return value?false:true; + else if(XMLString::compareIStringASCII(name, XMLUni::fgDOMWellFormed) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMNamespaceDeclarations) == 0 || + XMLString::compareIStringASCII(name, XMLUni::fgDOMInfoset) == 0) + return value?true:false; + + return false; +} + +const DOMStringList* DOMLSParserImpl::getParameterNames() const +{ + return fSupportedParameters; +} + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Feature methods +// --------------------------------------------------------------------------- +void DOMLSParserImpl::release() +{ + DOMLSParserImpl* builder = (DOMLSParserImpl*) this; + delete builder; +} + +void DOMLSParserImpl::resetDocumentPool() +{ + resetPool(); +} + + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Parsing methods +// --------------------------------------------------------------------------- +DOMDocument* DOMLSParserImpl::parse(const DOMLSInput* source) +{ + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + // remove the abort filter, if present + if(fFilter==&g_AbortFilter) + fFilter=0; + if(fFilterAction) + fFilterAction->removeAll(); + if(fFilterDelayedTextNodes) + fFilterDelayedTextNodes->removeAll(); + + Wrapper4DOMLSInput isWrapper((DOMLSInput*)source, fEntityResolver, false, getMemoryManager()); + + AbstractDOMParser::parse(isWrapper); + + // Disabled until 4.0.0. See XERCESC-1894 for details. + //if(getErrorCount()!=0) + // throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingFailed, fMemoryManager); + + if (fUserAdoptsDocument) + return adoptDocument(); + else + return getDocument(); +} + +DOMDocument* DOMLSParserImpl::parseURI(const XMLCh* const systemId) +{ + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + // remove the abort filter, if present + if(fFilter==&g_AbortFilter) + fFilter=0; + if(fFilterAction) + fFilterAction->removeAll(); + if(fFilterDelayedTextNodes) + fFilterDelayedTextNodes->removeAll(); + + AbstractDOMParser::parse(systemId); + + // Disabled until 4.0.0. See XERCESC-1894 for details. + //if(getErrorCount()!=0) + // throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingFailed, fMemoryManager); + + if (fUserAdoptsDocument) + return adoptDocument(); + else + return getDocument(); +} + +DOMDocument* DOMLSParserImpl::parseURI(const char* const systemId) +{ + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + // remove the abort filter, if present + if(fFilter==&g_AbortFilter) + fFilter=0; + if(fFilterAction) + fFilterAction->removeAll(); + if(fFilterDelayedTextNodes) + fFilterDelayedTextNodes->removeAll(); + + AbstractDOMParser::parse(systemId); + + // Disabled until 4.0.0. See XERCESC-1894 for details. + //if(getErrorCount()!=0) + // throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingFailed, fMemoryManager); + + if (fUserAdoptsDocument) + return adoptDocument(); + else + return getDocument(); +} + +void DOMLSParserImpl::startDocument() +{ + if(fWrapNodesInDocumentFragment) + { + fDocument = (DOMDocumentImpl*)fWrapNodesInDocumentFragment->getOwnerDocument(); + fCurrentParent = fCurrentNode = fWrapNodesInDocumentFragment; + // set DOM error checking off + fDocument->setErrorChecking(false); + + // if we have namespaces in scope, push them down to the reader + ValueHashTableOf inScopeNS(7, fMemoryManager); + DOMNode* cursor = fWrapNodesContext; + while(cursor) + { + if(cursor->getNodeType()==DOMNode::ELEMENT_NODE) + { + DOMNamedNodeMap* attrs = cursor->getAttributes(); + for(XMLSize_t i=0; igetLength(); i++) + { + DOMNode* attr = attrs->item(i); + if(XMLString::equals(attr->getNamespaceURI(), XMLUni::fgXMLNSURIName) && !inScopeNS.containsKey(attr->getLocalName())) + inScopeNS.put((void*)attr->getLocalName(), fScanner->getURIStringPool()->addOrFind(attr->getNodeValue())); + else if(XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString) && !inScopeNS.containsKey(XMLUni::fgZeroLenString)) + inScopeNS.put((void*)XMLUni::fgZeroLenString, fScanner->getURIStringPool()->addOrFind(attr->getNodeValue())); + } + } + cursor = cursor->getParentNode(); + } + ValueHashTableOfEnumerator iter(&inScopeNS, false, fMemoryManager); + while(iter.hasMoreElements()) + { + XMLCh* prefix = (XMLCh*)iter.nextElementKey(); + fScanner->addGlobalPrefix(prefix, inScopeNS.get(prefix)); + } + + // in this case the document URI and the input encoding must be propagated to the context document + if(fWrapNodesAction==ACTION_REPLACE_CHILDREN && fWrapNodesContext->getNodeType()==DOMNode::DOCUMENT_NODE) + { + fDocument->setDocumentURI(fScanner->getLocator()->getSystemId()); + fDocument->setInputEncoding(fScanner->getReaderMgr()->getCurrentEncodingStr()); + } + } + else + AbstractDOMParser::startDocument(); +} + +void DOMLSParserImpl::XMLDecl( const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncStr + ) +{ + if(fWrapNodesInDocumentFragment && !(fWrapNodesAction==ACTION_REPLACE_CHILDREN && fWrapNodesContext->getNodeType()==DOMNode::DOCUMENT_NODE)) + { + // don't change the properties for the context document, unless the context node is a + // DOMDocument node and the action is ACTION_REPLACE_CHILDREN + } + else + AbstractDOMParser::XMLDecl(versionStr, encodingStr, standaloneStr, actualEncStr); +} + +DOMNode* DOMLSParserImpl::parseWithContext(const DOMLSInput* source, + DOMNode* contextNode, + const ActionType action) +{ + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + // remove the abort filter, if present + if(fFilter==&g_AbortFilter) + fFilter=0; + if(fFilterAction) + fFilterAction->removeAll(); + if(fFilterDelayedTextNodes) + fFilterDelayedTextNodes->removeAll(); + + DOMDocumentFragment* holder = contextNode->getOwnerDocument()->createDocumentFragment(); + // When parsing the input stream, the context node (or its parent, depending on where + // the result will be inserted) is used for resolving unbound namespace prefixes + if(action==ACTION_INSERT_BEFORE || action==ACTION_INSERT_AFTER || action==ACTION_REPLACE) + fWrapNodesContext = contextNode->getParentNode(); + else + fWrapNodesContext = contextNode; + fWrapNodesInDocumentFragment = holder; + fWrapNodesAction = action; + // When calling parseWithContext, the values of the following configuration parameters + // will be ignored and their default values will always be used instead: "validate", + // "validate-if-schema", and "element-content-whitespace". + ValSchemes oldValidate = getValidationScheme(); + setValidationScheme(Val_Never); + bool oldElementContentWhitespace = getIncludeIgnorableWhitespace(); + setIncludeIgnorableWhitespace(true); + + Wrapper4DOMLSInput isWrapper((DOMLSInput*)source, fEntityResolver, false, getMemoryManager()); + AbstractDOMParser::parse(isWrapper); + + setValidationScheme(oldValidate); + setIncludeIgnorableWhitespace(oldElementContentWhitespace); + fWrapNodesContext = NULL; + fWrapNodesInDocumentFragment = NULL; + fDocument = NULL; + + if(getErrorCount()!=0) + { + holder->release(); + throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingFailed, fMemoryManager); + } + + DOMNode* result = holder->getFirstChild(); + DOMNode* node, *parent = contextNode->getParentNode(); + switch(action) + { + case ACTION_REPLACE_CHILDREN: + // remove existing children + while((node = contextNode->getFirstChild())!=NULL) + contextNode->removeChild(node)->release(); + // then fall back to behave like an append + case ACTION_APPEND_AS_CHILDREN: + while((node = holder->getFirstChild())!=NULL) + contextNode->appendChild(holder->removeChild(node)); + break; + case ACTION_INSERT_BEFORE: + while((node = holder->getFirstChild())!=NULL) + parent->insertBefore(holder->removeChild(node), contextNode); + break; + case ACTION_INSERT_AFTER: + while((node = holder->getLastChild())!=NULL) + parent->insertBefore(holder->removeChild(node), contextNode->getNextSibling()); + break; + case ACTION_REPLACE: + while((node = holder->getFirstChild())!=NULL) + parent->insertBefore(holder->removeChild(node), contextNode); + parent->removeChild(contextNode)->release(); + break; + } + holder->release(); + + // TODO whenever we add support for DOM Mutation Events: + // As the new data is inserted into the document, at least one mutation event is fired + // per new immediate child or sibling of the context node. + return result; +} + +void DOMLSParserImpl::abort() +{ + fFilter=&g_AbortFilter; +} + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Implementation of the XMLErrorReporter interface +// --------------------------------------------------------------------------- +void DOMLSParserImpl::error( const unsigned int code + , const XMLCh* const + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const + , const XMLFileLoc lineNum + , const XMLFileLoc colNum) +{ + if (fErrorHandler) { + + DOMError::ErrorSeverity severity = DOMError::DOM_SEVERITY_ERROR; + + if (errType == XMLErrorReporter::ErrType_Warning) + severity = DOMError::DOM_SEVERITY_WARNING; + else if (errType == XMLErrorReporter::ErrType_Fatal) + severity = DOMError::DOM_SEVERITY_FATAL_ERROR; + + DOMLocatorImpl location(lineNum, colNum, getCurrentNode(), systemId); + if(getScanner()->getCalculateSrcOfs()) + location.setByteOffset(getScanner()->getSrcOffset()); + DOMErrorImpl domError(severity, errorText, &location); + + // if user return false, we should stop the process, so throw an error + bool toContinueProcess = true; + try + { + toContinueProcess = fErrorHandler->handleError(domError); + } + catch(...) + { + } + if (!toContinueProcess && !getScanner()->getInException()) + throw (XMLErrs::Codes) code; + } +} + +void DOMLSParserImpl::resetErrors() +{ +} + + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Implementation of XMLEntityHandler interface +// --------------------------------------------------------------------------- +InputSource* +DOMLSParserImpl::resolveEntity( XMLResourceIdentifier* resourceIdentifier ) +{ + // + // Just map it to the SAX entity resolver. If there is not one installed, + // return a null pointer to cause the default resolution. + // + if (fEntityResolver) { + DOMLSInput* is = fEntityResolver->resolveResource(resourceIdentifier->getResourceIdentifierType()==XMLResourceIdentifier::ExternalEntity?XMLUni::fgDOMDTDType:XMLUni::fgDOMXMLSchemaType, + resourceIdentifier->getNameSpace(), + resourceIdentifier->getPublicId(), + resourceIdentifier->getSystemId(), + resourceIdentifier->getBaseURI()); + if (is) + return new (getMemoryManager()) Wrapper4DOMLSInput(is, fEntityResolver, true, getMemoryManager()); + } + if (fXMLEntityResolver) { + return(fXMLEntityResolver->resolveEntity(resourceIdentifier)); + } + + return 0; +} + +typedef JanitorMemFunCall ResetParseType; + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Grammar preparsing methods +// --------------------------------------------------------------------------- +Grammar* DOMLSParserImpl::loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + ResetParseType resetParse(this, &DOMLSParserImpl::resetParse); + + Grammar* grammar = 0; + + try + { + setParseInProgress(true); + if (grammarType == Grammar::DTDGrammarType) + getScanner()->setDocTypeHandler(0); + grammar = getScanner()->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetParse.release(); + + throw; + } + + return grammar; +} + +Grammar* DOMLSParserImpl::loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + ResetParseType resetParse(this, &DOMLSParserImpl::resetParse); + + Grammar* grammar = 0; + + try + { + setParseInProgress(true); + if (grammarType == Grammar::DTDGrammarType) + getScanner()->setDocTypeHandler(0); + grammar = getScanner()->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetParse.release(); + + throw; + } + + return grammar; +} + +Grammar* DOMLSParserImpl::loadGrammar(const DOMLSInput* source, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (getParseInProgress()) + throw DOMException(DOMException::INVALID_STATE_ERR, XMLDOMMsg::LSParser_ParseInProgress, fMemoryManager); + + ResetParseType resetParse(this, &DOMLSParserImpl::resetParse); + + Grammar* grammar = 0; + + try + { + setParseInProgress(true); + if (grammarType == Grammar::DTDGrammarType) + getScanner()->setDocTypeHandler(0); + Wrapper4DOMLSInput isWrapper((DOMLSInput*)source, fEntityResolver, false, getMemoryManager()); + grammar = getScanner()->loadGrammar(isWrapper, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetParse.release(); + + throw; + } + + return grammar; +} + +void DOMLSParserImpl::resetCachedGrammarPool() +{ + getGrammarResolver()->resetCachedGrammar(); + getScanner()->resetCachedGrammar(); +} + +void DOMLSParserImpl::resetParse() +{ + if (getScanner()->getDocTypeHandler() == 0) + { + getScanner()->setDocTypeHandler(this); + } + + setParseInProgress(false); +} + +Grammar* DOMLSParserImpl::getGrammar(const XMLCh* const nameSpaceKey) const +{ + return getGrammarResolver()->getGrammar(nameSpaceKey); +} + +Grammar* DOMLSParserImpl::getRootGrammar() const +{ + return getScanner()->getRootGrammar(); +} + +const XMLCh* DOMLSParserImpl::getURIText(unsigned int uriId) const +{ + return getScanner()->getURIText(uriId); +} + +XMLFilePos DOMLSParserImpl::getSrcOffset() const +{ + return getScanner()->getSrcOffset(); +} + +void DOMLSParserImpl::applyFilter(DOMNode* node) +{ + DOMLSParserFilter::FilterAction action; + // if the parent was already rejected, reject this too + if(fFilterAction && fFilterAction->containsKey(fCurrentParent) && fFilterAction->get(fCurrentParent)==DOMLSParserFilter::FILTER_REJECT) + action = DOMLSParserFilter::FILTER_REJECT; + else + action = fFilter->acceptNode(node); + + switch(action) + { + case DOMLSParserFilter::FILTER_ACCEPT: break; + case DOMLSParserFilter::FILTER_REJECT: + case DOMLSParserFilter::FILTER_SKIP: if(node==fCurrentNode) + fCurrentNode = (node->getPreviousSibling()?node->getPreviousSibling():fCurrentParent); + fCurrentParent->removeChild(node); + node->release(); + break; + case DOMLSParserFilter::FILTER_INTERRUPT: throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingAborted, fMemoryManager); + } +} + +void DOMLSParserImpl::docCharacters(const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + AbstractDOMParser::docCharacters(chars, length, cdataSection); + if(fFilter) + { + // send the notification for the previous text node + if(fFilterDelayedTextNodes && fCurrentNode->getPreviousSibling() && fFilterDelayedTextNodes->containsKey(fCurrentNode->getPreviousSibling())) + { + DOMNode* textNode = fCurrentNode->getPreviousSibling(); + fFilterDelayedTextNodes->removeKey(textNode); + applyFilter(textNode); + } + DOMNodeFilter::ShowType whatToShow=fFilter->getWhatToShow(); + if(cdataSection && (whatToShow & DOMNodeFilter::SHOW_CDATA_SECTION)) + { + applyFilter(fCurrentNode); + } + else if(!cdataSection && (whatToShow & DOMNodeFilter::SHOW_TEXT)) + { + if(fFilterDelayedTextNodes==0) + fFilterDelayedTextNodes=new (fMemoryManager) ValueHashTableOf(7, fMemoryManager); + fFilterDelayedTextNodes->put(fCurrentNode, true); + } + } +} + +void DOMLSParserImpl::docComment(const XMLCh* const comment) +{ + if(fFilter) + { + // send the notification for the previous text node + if(fFilterDelayedTextNodes && fFilterDelayedTextNodes->containsKey(fCurrentNode)) + { + fFilterDelayedTextNodes->removeKey(fCurrentNode); + applyFilter(fCurrentNode); + } + } + + AbstractDOMParser::docComment(comment); + if(fFilter) + { + DOMNodeFilter::ShowType whatToShow=fFilter->getWhatToShow(); + if(whatToShow & DOMNodeFilter::SHOW_COMMENT) + applyFilter(fCurrentNode); + } +} + +void DOMLSParserImpl::docPI(const XMLCh* const target + , const XMLCh* const data) +{ + if(fFilter) + { + // send the notification for the previous text node + if(fFilterDelayedTextNodes && fFilterDelayedTextNodes->containsKey(fCurrentNode)) + { + fFilterDelayedTextNodes->removeKey(fCurrentNode); + applyFilter(fCurrentNode); + } + } + + AbstractDOMParser::docPI(target, data); + if(fFilter) + { + DOMNodeFilter::ShowType whatToShow=fFilter->getWhatToShow(); + if(whatToShow & DOMNodeFilter::SHOW_PROCESSING_INSTRUCTION) + applyFilter(fCurrentNode); + } +} + +void DOMLSParserImpl::startEntityReference(const XMLEntityDecl& entDecl) +{ + if(fCreateEntityReferenceNodes && fFilter) + { + // send the notification for the previous text node + if(fFilterDelayedTextNodes && fFilterDelayedTextNodes->containsKey(fCurrentNode)) + { + fFilterDelayedTextNodes->removeKey(fCurrentNode); + applyFilter(fCurrentNode); + } + } + + DOMNode* origParent = fCurrentParent; + AbstractDOMParser::startEntityReference(entDecl); + if (fCreateEntityReferenceNodes && fFilter) + { + if(fFilterAction && fFilterAction->containsKey(origParent) && fFilterAction->get(origParent)==DOMLSParserFilter::FILTER_REJECT) + fFilterAction->put(fCurrentNode, DOMLSParserFilter::FILTER_REJECT); + } +} + +void DOMLSParserImpl::endElement(const XMLElementDecl& elemDecl + , const unsigned int urlId + , const bool isRoot + , const XMLCh* const elemPrefix) +{ + if(fFilter) + { + // send the notification for the previous text node + if(fFilterDelayedTextNodes && fFilterDelayedTextNodes->containsKey(fCurrentNode)) + { + fFilterDelayedTextNodes->removeKey(fCurrentNode); + applyFilter(fCurrentNode); + } + } + + AbstractDOMParser::endElement(elemDecl, urlId, isRoot, elemPrefix); + if(fFilter) + { + DOMNodeFilter::ShowType whatToShow=fFilter->getWhatToShow(); + if(whatToShow & DOMNodeFilter::SHOW_ELEMENT) + { + DOMNode* thisNode = fCurrentNode; + DOMLSParserFilter::FilterAction action; + if(fFilterAction && fFilterAction->containsKey(thisNode)) + { + action = fFilterAction->get(thisNode); + fFilterAction->removeKey(thisNode); + } + else + action = fFilter->acceptNode(thisNode); + switch(action) + { + case DOMLSParserFilter::FILTER_ACCEPT: break; + case DOMLSParserFilter::FILTER_REJECT: fCurrentNode = (thisNode->getPreviousSibling()?thisNode->getPreviousSibling():fCurrentParent); + fCurrentParent->removeChild(thisNode); + thisNode->release(); + break; + case DOMLSParserFilter::FILTER_SKIP: { + DOMNode* child=thisNode->getFirstChild(); + while(child) + { + DOMNode* next=child->getNextSibling(); + fCurrentParent->appendChild(child); + child=next; + } + fCurrentNode = (thisNode->getPreviousSibling()?thisNode->getPreviousSibling():fCurrentParent); + fCurrentParent->removeChild(thisNode); + thisNode->release(); + } + break; + case DOMLSParserFilter::FILTER_INTERRUPT: throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingAborted, fMemoryManager); + } + } + } +} + +void DOMLSParserImpl::startElement(const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot) +{ + if(fFilter) + { + // send the notification for the previous text node + if(fFilterDelayedTextNodes && fFilterDelayedTextNodes->containsKey(fCurrentNode)) + { + fFilterDelayedTextNodes->removeKey(fCurrentNode); + applyFilter(fCurrentNode); + } + } + + DOMNode* origParent = fCurrentParent; + AbstractDOMParser::startElement(elemDecl, urlId, elemPrefix, attrList, attrCount, false, isRoot); + if(fFilter) + { + // if the parent was already rejected, reject this too + if(fFilterAction && fFilterAction->containsKey(origParent) && fFilterAction->get(origParent)==DOMLSParserFilter::FILTER_REJECT) + fFilterAction->put(fCurrentNode, DOMLSParserFilter::FILTER_REJECT); + else + { + DOMLSParserFilter::FilterAction action = fFilter->startElement((DOMElement*)fCurrentNode); + + switch(action) + { + case DOMLSParserFilter::FILTER_ACCEPT: break; + case DOMLSParserFilter::FILTER_REJECT: + case DOMLSParserFilter::FILTER_SKIP: if(fFilterAction==0) + fFilterAction=new (fMemoryManager) ValueHashTableOf(7, fMemoryManager); + fFilterAction->put(fCurrentNode, action); + break; + case DOMLSParserFilter::FILTER_INTERRUPT: throw DOMLSException(DOMLSException::PARSE_ERR, XMLDOMMsg::LSParser_ParsingAborted, fMemoryManager); + } + } + } + if(isEmpty) + endElement(elemDecl, urlId, isRoot, elemPrefix); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/parsers/DOMLSParserImpl.hpp b/include/xercesc/parsers/DOMLSParserImpl.hpp new file mode 100644 index 0000000..005acba --- /dev/null +++ b/include/xercesc/parsers/DOMLSParserImpl.hpp @@ -0,0 +1,715 @@ +/* + * 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: DOMLSParserImpl.hpp 830538 2009-10-28 13:41:11Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOMBUILDERIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_DOMBUILDERIMPL_HPP + + +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLEntityResolver; +class XMLResourceIdentifier; +class DOMStringListImpl; +class DOMLSResourceResolver; + + /** + * Introduced in DOM Level 3 + * + * DOMLSParserImpl provides an implementation of a DOMLSParser interface. + * A DOMLSParser instance is obtained from the DOMImplementationLS interface + * by invoking its createDOMLSParser method. + */ +class PARSERS_EXPORT DOMLSParserImpl : public AbstractDOMParser, + public DOMLSParser, + public DOMConfiguration +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Detructor + // ----------------------------------------------------------------------- + + /** @name Constructors and Destructor */ + //@{ + /** Construct a DOMLSParserImpl, with an optional validator + * + * Constructor with an instance of validator class to use for + * validation. If you don't provide a validator, a default one will + * be created for you in the scanner. + * + * @param valToAdopt Pointer to the validator instance to use. The + * parser is responsible for freeing the memory. + * @param manager The memory manager to be used for memory allocations + * @param gramPool Pointer to the grammar pool instance from + * external application. + * The parser does NOT own it. + * + */ + DOMLSParserImpl + ( + XMLValidator* const valToAdopt = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ); + + /** + * Destructor + */ + virtual ~DOMLSParserImpl(); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of DOMLSParser interface + // ----------------------------------------------------------------------- + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** + * @see DOMLSParser#getDomConfig + */ + virtual DOMConfiguration* getDomConfig(); + + /** + * @see DOMLSParser#getFilter + */ + virtual const DOMLSParserFilter* getFilter() const; + + /** + * @see DOMLSParser#getAsync + */ + virtual bool getAsync() const; + + /** + * @see DOMLSParser#getBusy + */ + virtual bool getBusy() const; + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + /** + * @see DOMLSParser#setFilter + */ + virtual void setFilter(DOMLSParserFilter* const filter); + + //@} + + // ----------------------------------------------------------------------- + // Parsing methods + // ----------------------------------------------------------------------- + /** @name Parsing methods */ + //@{ + + // ----------------------------------------------------------------------- + // Parsing methods + // ----------------------------------------------------------------------- + /** + * @see DOMLSParser#parse + */ + virtual DOMDocument* parse(const DOMLSInput* source); + + /** + * @see DOMLSParser#parseURI + */ + virtual DOMDocument* parseURI(const XMLCh* const uri); + + /** + * @see DOMLSParser#parseURI + */ + virtual DOMDocument* parseURI(const char* const uri); + + /** + * @see DOMLSParser#parseWithContext + */ + virtual DOMNode* parseWithContext + ( + const DOMLSInput* source + , DOMNode* contextNode + , const ActionType action + ); + + /** + * @see DOMLSParser#abort + */ + virtual void abort(); + + + // ----------------------------------------------------------------------- + // Non-standard Extension + // ----------------------------------------------------------------------- + /** @name Non-standard Extension */ + //@{ + + /** + * Called to indicate that this DOMLSParser is no longer in use + * and that the implementation may relinquish any resources associated with it. + * + */ + virtual void release(); + + /** Reset the documents vector pool and release all the associated memory + * back to the system. + * + * When parsing a document using a DOM parser, all memory allocated + * for a DOM tree is associated to the DOM document. + * + * If you do multiple parse using the same DOM parser instance, then + * multiple DOM documents will be generated and saved in a vector pool. + * All these documents (and thus all the allocated memory) + * won't be deleted until the parser instance is destroyed. + * + * If you don't need these DOM documents anymore and don't want to + * destroy the DOM parser instance at this moment, then you can call this method + * to reset the document vector pool and release all the allocated memory + * back to the system. + * + * It is an error to call this method if you are in the middle of a + * parse (e.g. in the mid of a progressive parse). + * + * @exception IOException An exception from the parser if this function + * is called when a parse is in progress. + * + */ + virtual void resetDocumentPool(); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the DOMLSInput parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * @param source A const reference to the DOMLSInput object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no chaching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see DOMLSInput#DOMLSInput + */ + virtual Grammar* loadGrammar(const DOMLSInput* source, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no chaching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no chaching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + virtual Grammar* getGrammar(const XMLCh* const nameSpaceKey) const; + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + virtual Grammar* getRootGrammar() const; + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + virtual const XMLCh* getURIText(unsigned int uriId) const; + + /** + * Clear the cached grammar pool + */ + virtual void resetCachedGrammarPool(); + + /** + * Returns the current src offset within the input source. + * To be used only while parsing is in progress. + * + * @return offset within the input source + */ + virtual XMLFilePos getSrcOffset() const; + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the DOMConfiguration interface. + // ----------------------------------------------------------------------- + /** @name Implementation of the DOMConfiguration interface. */ + //@{ + /** + * Set the value of a parameter. + * + * @param name The name of the parameter to set. + * @param value The new value or null if the user wishes to unset the + * parameter. While the type of the value parameter is defined as + * DOMUserData, the object type must match the type defined + * by the definition of the parameter. For example, if the parameter is + * "error-handler", the value must be of type DOMErrorHandler + * + * @exception DOMException (NOT_SUPPORTED_ERR) Raised when the + * parameter name is recognized but the requested value cannot be set. + * @exception DOMException (NOT_FOUND_ERR) Raised when the + * parameter name is not recognized. + * + * @since DOM level 3 + **/ + virtual void setParameter(const XMLCh* name, const void* value); + virtual void setParameter(const XMLCh* name, bool value); + + /** + * Return the value of a parameter if known. + * + * @param name The name of the parameter. + * @return The current object associated with the specified parameter or + * null if no object has been associated or if the parameter is not + * supported. + * + * @exception DOMException (NOT_FOUND_ERR) Raised when the i + * boolean parameter + * name is not recognized. + * + * @since DOM level 3 + **/ + virtual const void* getParameter(const XMLCh* name) const; + + /** + * Check if setting a parameter to a specific value is supported. + * + * @param name The name of the parameter to check. + * @param value An object. if null, the returned value is true. + * @return true if the parameter could be successfully set to the specified + * value, or false if the parameter is not recognized or the requested value + * is not supported. This does not change the current value of the parameter + * itself. + * + * @since DOM level 3 + **/ + virtual bool canSetParameter(const XMLCh* name, const void* value) const; + virtual bool canSetParameter(const XMLCh* name, bool value) const; + + /** + * The list of the parameters supported by this DOMConfiguration object and + * for which at least one value can be set by the application. + * Note that this list can also contain parameter names defined outside this specification. + * + * @return The list of parameters that can be used with setParameter/getParameter + * @since DOM level 3 + **/ + virtual const DOMStringList* getParameterNames() const; + //@} + + // ----------------------------------------------------------------------- + // Implementation of the XMLErrorReporter interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLErrorReporter interface. */ + //@{ + + /** Handle errors reported from the parser + * + * This method is used to report back errors found while parsing the + * XML file. This method is also borrowed from the SAX specification. + * It calls the corresponding user installed Error Handler method: + * 'fatal', 'error', 'warning' depending on the severity of the error. + * This classification is defined by the XML specification. + * + * @param errCode An integer code for the error. + * @param msgDomain A const pointer to an Unicode string representing + * the message domain to use. + * @param errType An enumeration classifying the severity of the error. + * @param errorText A const pointer to an Unicode string representing + * the text of the error message. + * @param systemId A const pointer to an Unicode string representing + * the system id of the XML file where this error + * was discovered. + * @param publicId A const pointer to an Unicode string representing + * the public id of the XML file where this error + * was discovered. + * @param lineNum The line number where the error occurred. + * @param colNum The column number where the error occurred. + * @see DOMErrorHandler + */ + virtual void error + ( + const unsigned int errCode + , const XMLCh* const msgDomain + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ); + + /** Reset any error data before a new parse + * + * This method allows the user installed Error Handler callback to + * 'reset' itself. + * + * This method is a no-op for this DOM + * implementation. + */ + virtual void resetErrors(); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLEntityHandler interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLEntityHandler interface. */ + //@{ + + /** Handle an end of input source event + * + * This method is used to indicate the end of parsing of an external + * entity file. + * + * This method is a no-op for this DOM + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the XML file being parsed. + * @see InputSource + */ + virtual void endInputSource(const InputSource& inputSource); + + /** Expand a system id + * + * This method allows an installed XMLEntityHandler to further + * process any system id's of enternal entities encountered in + * the XML file being parsed, such as redirection etc. + * + * This method always returns 'false' + * for this DOM implementation. + * + * @param systemId A const pointer to an Unicode string representing + * the system id scanned by the parser. + * @param toFill A pointer to a buffer in which the application + * processed system id is stored. + * @return 'true', if any processing is done, 'false' otherwise. + */ + virtual bool expandSystemId + ( + const XMLCh* const systemId + , XMLBuffer& toFill + ); + + /** Reset any entity handler information + * + * This method allows the installed XMLEntityHandler to reset + * itself. + * + * This method is a no-op for this DOM + * implementation. + */ + virtual void resetEntities(); + + /** Resolve a public/system id + * + * This method allows a user installed entity handler to further + * process any pointers to external entities. The applications can + * implement 'redirection' via this callback. + * + * @param resourceIdentifier An object containing the type of + * resource to be resolved and the associated data members + * corresponding to this type. + * @return The value returned by the user installed resolveEntity + * method or NULL otherwise to indicate no processing was done. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @see XMLEntityHandler + * @see XMLEntityResolver + */ + virtual InputSource* resolveEntity + ( + XMLResourceIdentifier* resourceIdentifier + ); + + /** Handle a 'start input source' event + * + * This method is used to indicate the start of parsing an external + * entity file. + * + * This method is a no-op for this DOM parse + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the external entity + * being parsed. + */ + virtual void startInputSource(const InputSource& inputSource); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the XMLDocumentHandler interface. + // ----------------------------------------------------------------------- + virtual void docCharacters + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + virtual void docComment + ( + const XMLCh* const comment + ); + virtual void docPI + ( + const XMLCh* const target + , const XMLCh* const data + ); + virtual void startEntityReference + ( + const XMLEntityDecl& entDecl + ); + virtual void endElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const bool isRoot + , const XMLCh* const elemPrefix + ); + virtual void startElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot + ); + + // overriden callbacks to implement parseWithContext behavior + virtual void startDocument(); + virtual void XMLDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncStr + ); + + +private : + // ----------------------------------------------------------------------- + // Initialize/Cleanup methods + // ----------------------------------------------------------------------- + void resetParse(); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void applyFilter(DOMNode* node); + + // ----------------------------------------------------------------------- + // Private data members + // + // fEntityResolver + // The installed DOM entity resolver, if any. Null if none. + // + // fXMLEntityResolver + // The installed Xerces entity resolver, if any. Null if none. + // + // fErrorHandler + // The installed DOM error handler, if any. Null if none. + // + // fFilter + // The installed application filter, if any. Null if none. + // + // fCharsetOverridesXMLEncoding + // Indicates if the "charset-overrides-xml-encoding" is set or not + // + // fUserAdoptsDocument + // The DOMDocument ownership has been transferred to application + // If set to true, the parser does not own the document anymore + // and thus will not release its memory. + // + // fSupportedParameters + // A list of the parameters that can be set, including the ones + // specific of Xerces + // + // fFilterAction + // A map of elements rejected by the DOMLSParserFilter::startElement + // callback, used to avoid invoking DOMLSParserFilter::acceptNode + // on its children + // + // fFilterDelayedTextNodes + // As text nodes are filled incrementally, store them in a map + // so that we ask DOMLSParserFilter::acceptNode only once, when it + // is completely created + // + // fWrapNodesInDocumentFragment + // fWrapNodesContext + // fWrapNodesAction + // Variables used to keep the state for parseWithContext API + // + //----------------------------------------------------------------------- + DOMLSResourceResolver* fEntityResolver; + XMLEntityResolver* fXMLEntityResolver; + DOMErrorHandler* fErrorHandler; + DOMLSParserFilter* fFilter; + bool fCharsetOverridesXMLEncoding; + bool fUserAdoptsDocument; + DOMStringListImpl* fSupportedParameters; + ValueHashTableOf* fFilterAction; + ValueHashTableOf* fFilterDelayedTextNodes; + DOMDocumentFragment* fWrapNodesInDocumentFragment; + DOMNode* fWrapNodesContext; + ActionType fWrapNodesAction; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DOMLSParserImpl(const DOMLSParserImpl &); + DOMLSParserImpl & operator = (const DOMLSParserImpl &); +}; + + + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Handlers for the XMLEntityHandler interface +// --------------------------------------------------------------------------- +inline void DOMLSParserImpl::endInputSource(const InputSource&) +{ + // The DOM entity resolver doesn't handle this +} + +inline bool DOMLSParserImpl::expandSystemId(const XMLCh* const, XMLBuffer&) +{ + // The DOM entity resolver doesn't handle this + return false; +} + +inline void DOMLSParserImpl::resetEntities() +{ + // Nothing to do on this one +} + +inline void DOMLSParserImpl::startInputSource(const InputSource&) +{ + // The DOM entity resolver doesn't handle this +} + + +// --------------------------------------------------------------------------- +// DOMLSParserImpl: Getter methods +// --------------------------------------------------------------------------- +inline DOMConfiguration* DOMLSParserImpl::getDomConfig() +{ + return this; +} + +inline bool DOMLSParserImpl::getAsync() const +{ + // We are a synchronous parser + return false; +} + +inline const DOMLSParserFilter* DOMLSParserImpl::getFilter() const +{ + return fFilter; +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/parsers/SAX2XMLFilterImpl.cpp b/include/xercesc/parsers/SAX2XMLFilterImpl.cpp new file mode 100644 index 0000000..54e2fcc --- /dev/null +++ b/include/xercesc/parsers/SAX2XMLFilterImpl.cpp @@ -0,0 +1,416 @@ +/* + * 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: SAX2XMLFilterImpl.cpp 673975 2008-07-04 09:23:56Z borisk $ + */ + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +SAX2XMLFilterImpl::SAX2XMLFilterImpl(SAX2XMLReader* parent) : + fParentReader(0) + , fDocHandler(0) + , fDTDHandler(0) + , fEntityResolver(0) + , fErrorHandler(0) +{ + setParent(parent); +} + +SAX2XMLFilterImpl::~SAX2XMLFilterImpl() +{ +} + +// --------------------------------------------------------------------------- +// SAX2XMLFilterImpl: XMLFilter impl +// --------------------------------------------------------------------------- +void SAX2XMLFilterImpl::setParent(SAX2XMLReader* parent) +{ + if(fParentReader) + { + fParentReader->setEntityResolver(0); + fParentReader->setDTDHandler(0); + fParentReader->setContentHandler(0); + fParentReader->setErrorHandler(0); + } + fParentReader=parent; + if(fParentReader) + { + fParentReader->setEntityResolver(this); + fParentReader->setDTDHandler(this); + fParentReader->setContentHandler(this); + fParentReader->setErrorHandler(this); + } +} + +bool SAX2XMLFilterImpl::getExitOnFirstFatalError() const +{ + if(fParentReader) + fParentReader->getExitOnFirstFatalError(); + return false; +} + +bool SAX2XMLFilterImpl::getValidationConstraintFatal() const +{ + if(fParentReader) + fParentReader->getValidationConstraintFatal(); + return false; +} + +Grammar* SAX2XMLFilterImpl::getRootGrammar() +{ + if(fParentReader) + fParentReader->getRootGrammar(); + return NULL; +} + +const XMLCh* SAX2XMLFilterImpl::getURIText(unsigned int uriId) const +{ + if(fParentReader) + fParentReader->getURIText(uriId); + return NULL; +} + +XMLFilePos SAX2XMLFilterImpl::getSrcOffset() const +{ + if(fParentReader) + fParentReader->getSrcOffset(); + return 0; +} + +// --------------------------------------------------------------------------- +// SAX2XMLFilterImpl Validator functions +// --------------------------------------------------------------------------- +void SAX2XMLFilterImpl::setValidator(XMLValidator* valueToAdopt) +{ + if(fParentReader) + fParentReader->setValidator(valueToAdopt); +} + +XMLValidator* SAX2XMLFilterImpl::getValidator() const +{ + if(fParentReader) + return fParentReader->getValidator(); + return 0; +} + +// --------------------------------------------------------------------------- +// SAX2XMLReader Interface +// --------------------------------------------------------------------------- +XMLSize_t SAX2XMLFilterImpl::getErrorCount() const +{ + if(fParentReader) + return fParentReader->getErrorCount(); + return 0; +} + +void SAX2XMLFilterImpl::setExitOnFirstFatalError(const bool newState) +{ + if(fParentReader) + fParentReader->setExitOnFirstFatalError(newState); +} + +void SAX2XMLFilterImpl::setValidationConstraintFatal(const bool newState) +{ + if(fParentReader) + fParentReader->setValidationConstraintFatal(newState); +} + +void SAX2XMLFilterImpl::parse (const InputSource& source) +{ + if(fParentReader) + fParentReader->parse(source); +} + +void SAX2XMLFilterImpl::parse (const XMLCh* const systemId) +{ + if(fParentReader) + fParentReader->parse(systemId); +} + +void SAX2XMLFilterImpl::parse (const char* const systemId) +{ + if(fParentReader) + fParentReader->parse(systemId); +} + +// --------------------------------------------------------------------------- +// SAX2XMLFilterImpl: Progressive parse methods +// --------------------------------------------------------------------------- +bool SAX2XMLFilterImpl::parseFirst( const XMLCh* const systemId + , XMLPScanToken& toFill) +{ + if(fParentReader) + return fParentReader->parseFirst(systemId, toFill); + return false; +} + +bool SAX2XMLFilterImpl::parseFirst( const char* const systemId + , XMLPScanToken& toFill) +{ + if(fParentReader) + fParentReader->parseFirst(systemId, toFill); + return false; +} + +bool SAX2XMLFilterImpl::parseFirst( const InputSource& source + , XMLPScanToken& toFill) +{ + if(fParentReader) + fParentReader->parseFirst(source, toFill); + return false; +} + +bool SAX2XMLFilterImpl::parseNext(XMLPScanToken& token) +{ + if(fParentReader) + fParentReader->parseNext(token); + return false; +} + +void SAX2XMLFilterImpl::parseReset(XMLPScanToken& token) +{ + if(fParentReader) + fParentReader->parseReset(token); +} + +// --------------------------------------------------------------------------- +// SAX2XMLFilterImpl: Features and Properties +// --------------------------------------------------------------------------- + +void SAX2XMLFilterImpl::setFeature(const XMLCh* const name, const bool value) +{ + if(fParentReader) + fParentReader->setFeature(name,value); +} + +bool SAX2XMLFilterImpl::getFeature(const XMLCh* const name) const +{ + if(fParentReader) + return fParentReader->getFeature(name); + return false; +} + +void SAX2XMLFilterImpl::setProperty(const XMLCh* const name, void* value) +{ + if(fParentReader) + fParentReader->setProperty(name,value); +} + +void* SAX2XMLFilterImpl::getProperty(const XMLCh* const name) const +{ + if(fParentReader) + return fParentReader->getProperty(name); + return NULL; +} + +// --------------------------------------------------------------------------- +// SAX2XMLFilterImpl: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* SAX2XMLFilterImpl::loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + if(fParentReader) + return fParentReader->loadGrammar(systemId, grammarType, toCache); + return NULL; +} + +Grammar* SAX2XMLFilterImpl::loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + if(fParentReader) + return fParentReader->loadGrammar(systemId, grammarType, toCache); + return NULL; +} + +Grammar* SAX2XMLFilterImpl::loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + if(fParentReader) + return fParentReader->loadGrammar(source, grammarType, toCache); + return NULL; +} + +void SAX2XMLFilterImpl::resetCachedGrammarPool() +{ + if(fParentReader) + fParentReader->resetCachedGrammarPool(); +} + +void SAX2XMLFilterImpl::setInputBufferSize(const XMLSize_t bufferSize) +{ + if(fParentReader) + fParentReader->setInputBufferSize(bufferSize); +} + +Grammar* SAX2XMLFilterImpl::getGrammar(const XMLCh* const nameSpaceKey) +{ + if(fParentReader) + return fParentReader->getGrammar(nameSpaceKey); + return NULL; +} + +// ----------------------------------------------------------------------- +// Implementation of the EntityResolver interface +// ----------------------------------------------------------------------- +InputSource* SAX2XMLFilterImpl::resolveEntity(const XMLCh* const publicId + , const XMLCh* const systemId) +{ + if(fEntityResolver) + return fEntityResolver->resolveEntity(publicId, systemId); + return 0; +} + +// ----------------------------------------------------------------------- +// Implementation of the DTDHandler interface +// ----------------------------------------------------------------------- +void SAX2XMLFilterImpl::notationDecl( const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId) +{ + if(fDTDHandler) + fDTDHandler->notationDecl(name, publicId, systemId); +} + +void SAX2XMLFilterImpl::unparsedEntityDecl(const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLCh* const notationName) +{ + if(fDTDHandler) + fDTDHandler->unparsedEntityDecl(name, publicId, systemId, notationName); +} + +void SAX2XMLFilterImpl::resetDocType() +{ + if(fDTDHandler) + fDTDHandler->resetDocType(); +} + +// ----------------------------------------------------------------------- +// Implementation of the ContentHandler interface +// ----------------------------------------------------------------------- + +void SAX2XMLFilterImpl::characters(const XMLCh* const chars + , const XMLSize_t length) +{ + if(fDocHandler) + fDocHandler->characters(chars, length); +} + +void SAX2XMLFilterImpl::endDocument() +{ + if(fDocHandler) + fDocHandler->endDocument(); +} + +void SAX2XMLFilterImpl::endElement(const XMLCh* const uri + , const XMLCh* const localname + , const XMLCh* const qname) +{ + if(fDocHandler) + fDocHandler->endElement(uri, localname, qname); +} + +void SAX2XMLFilterImpl::ignorableWhitespace(const XMLCh* const chars + , const XMLSize_t length) +{ + if(fDocHandler) + fDocHandler->ignorableWhitespace(chars, length); +} + +void SAX2XMLFilterImpl::processingInstruction(const XMLCh* const target + , const XMLCh* const data) +{ + if(fDocHandler) + fDocHandler->processingInstruction(target, data); +} + +void SAX2XMLFilterImpl::setDocumentLocator(const Locator* const locator) +{ + if(fDocHandler) + fDocHandler->setDocumentLocator(locator); +} + +void SAX2XMLFilterImpl::startDocument() +{ + if(fDocHandler) + fDocHandler->startDocument(); +} + +void SAX2XMLFilterImpl::startElement(const XMLCh* const uri + , const XMLCh* const localname + , const XMLCh* const qname + , const Attributes& attrs) +{ + if(fDocHandler) + fDocHandler->startElement(uri, localname, qname, attrs); +} + +void SAX2XMLFilterImpl::startPrefixMapping(const XMLCh* const prefix + , const XMLCh* const uri) +{ + if(fDocHandler) + fDocHandler->startPrefixMapping(prefix, uri); +} + +void SAX2XMLFilterImpl::endPrefixMapping(const XMLCh* const prefix) +{ + if(fDocHandler) + fDocHandler->endPrefixMapping(prefix); +} + +void SAX2XMLFilterImpl::skippedEntity(const XMLCh* const name) +{ + if(fDocHandler) + fDocHandler->skippedEntity(name); +} + +// ----------------------------------------------------------------------- +// Implementation of the ErrorHandler interface +// ----------------------------------------------------------------------- + +void SAX2XMLFilterImpl::warning(const SAXParseException& exc) +{ + if(fErrorHandler) + fErrorHandler->warning(exc); +} + +void SAX2XMLFilterImpl::error(const SAXParseException& exc) +{ + if(fErrorHandler) + fErrorHandler->error(exc); +} + +void SAX2XMLFilterImpl::fatalError(const SAXParseException& exc) +{ + if(fErrorHandler) + fErrorHandler->fatalError(exc); +} + +void SAX2XMLFilterImpl::resetErrors() +{ + if(fErrorHandler) + fErrorHandler->resetErrors(); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/parsers/SAX2XMLFilterImpl.hpp b/include/xercesc/parsers/SAX2XMLFilterImpl.hpp new file mode 100644 index 0000000..33ca34d --- /dev/null +++ b/include/xercesc/parsers/SAX2XMLFilterImpl.hpp @@ -0,0 +1,1445 @@ +/* + * 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: SAX2XMLFilterImpl.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAX2XMLFILTERIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_SAX2XMLFILTERIMPL_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * This class implements the SAX2 'XMLFilterImpl' interface and should be + * used by applications as the base class for their SAX2 filters. + * This implementation simply forwards every call to the parent object. + * + */ + +class PARSERS_EXPORT SAX2XMLFilterImpl : + public SAX2XMLFilter + , public EntityResolver + , public DTDHandler + , public ContentHandler + , public ErrorHandler +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** The default constructor */ + SAX2XMLFilterImpl(SAX2XMLReader* parent); + + /** The destructor */ + ~SAX2XMLFilterImpl() ; + //@} + + //----------------------------------------------------------------------- + // Implementation of SAX2XMLReader Interface + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // The XMLReader interface + //----------------------------------------------------------------------- + /** @name Implementation of SAX 2.0 XMLReader interface's. */ + //@{ + + /** + * This method returns the installed content handler. + * + * @return A pointer to the installed content handler object. + */ + virtual ContentHandler* getContentHandler() const ; + + /** + * This method returns the installed DTD handler. + * + * @return A pointer to the installed DTD handler object. + */ + virtual DTDHandler* getDTDHandler() const ; + + /** + * This method returns the installed entity resolver. + * + * @return A pointer to the installed entity resolver object. + */ + virtual EntityResolver* getEntityResolver() const ; + + /** + * This method returns the installed error handler. + * + * @return A pointer to the installed error handler object. + */ + virtual ErrorHandler* getErrorHandler() const ; + + /** + * Query the current state of any feature in a SAX2 XMLReader. + * + * @param name The unique identifier (URI) of the feature being set. + * @return The current state of the feature. + * @exception SAXNotRecognizedException If the requested feature is not known. + */ + virtual bool getFeature(const XMLCh* const name) const ; + + /** + * Query the current value of a property in a SAX2 XMLReader. + * + * The parser owns the returned pointer. The memory allocated for + * the returned pointer will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else; otherwise you may get unexpected result. Since the returned + * pointer is a generic void pointer, see the SAX2 Programming Guide to learn + * exactly what type of property value each property returns for replication. + * + * @param name The unique identifier (URI) of the property being set. + * @return The current value of the property. The pointer spans the same + * life-time as the parser. A null pointer is returned if nothing + * was specified externally. + * @exception SAXNotRecognizedException If the requested property is not known. + */ + virtual void* getProperty(const XMLCh* const name) const ; + + /** + * Allow an application to register a document event handler. + * + * If the application does not register a document handler, all + * document events reported by the SAX parser will be silently + * ignored (this is the default behaviour implemented by + * HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The document handler. + * @see DocumentHandler#DocumentHandler + * @see HandlerBase#HandlerBase + */ + virtual void setContentHandler(ContentHandler* const handler) ; + + /** + * Allow an application to register a DTD event handler. + * + * If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored (this + * is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the middle + * of a parse, and the SAX parser must begin using the new handler + * immediately. + * + * @param handler The DTD handler. + * @see DTDHandler#DTDHandler + * @see HandlerBase#HandlerBase + */ + virtual void setDTDHandler(DTDHandler* const handler) ; + + /** + * Allow an application to register a custom entity resolver. + * + * If the application does not register an entity resolver, the + * SAX parser will resolve system identifiers and open connections + * to entities itself (this is the default behaviour implemented in + * DefaultHandler). + * + * Applications may register a new or different entity resolver + * in the middle of a parse, and the SAX parser must begin using + * the new resolver immediately. + * + * @param resolver The object for resolving entities. + * @see EntityResolver#EntityResolver + * @see DefaultHandler#DefaultHandler + */ + virtual void setEntityResolver(EntityResolver* const resolver) ; + + /** + * Allow an application to register an error event handler. + * + * If the application does not register an error event handler, + * all error events reported by the SAX parser will be silently + * ignored, except for fatalError, which will throw a SAXException + * (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see ErrorHandler#ErrorHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setErrorHandler(ErrorHandler* const handler) ; + + /** + * Set the state of any feature in a SAX2 XMLReader. + * Supported features in SAX2 for xerces-c are: + *
(See the SAX2 Programming Guide for detail description). + * + *
http://xml.org/sax/features/validation (default: true) + *
http://xml.org/sax/features/namespaces (default: true) + *
http://xml.org/sax/features/namespace-prefixes (default: false) + *
http://apache.org/xml/features/validation/dynamic (default: false) + *
http://apache.org/xml/features/validation/reuse-grammar (default: false) + *
http://apache.org/xml/features/validation/schema (default: true) + *
http://apache.org/xml/features/validation/schema-full-checking (default: false) + *
http://apache.org/xml/features/validating/load-schema (default: true) + *
http://apache.org/xml/features/nonvalidating/load-external-dtd (default: true) + *
http://apache.org/xml/features/continue-after-fatal-error (default: false) + *
http://apache.org/xml/features/validation-error-as-fatal (default: false) + * + * @param name The unique identifier (URI) of the feature. + * @param value The requested state of the feature (true or false). + * @exception SAXNotRecognizedException If the requested feature is not known. + * @exception SAXNotSupportedException Feature modification is not supported during parse + * + */ + virtual void setFeature(const XMLCh* const name, const bool value) ; + + /** + * Set the value of any property in a SAX2 XMLReader. + * Supported properties in SAX2 for xerces-c are: + *
(See the SAX2 Programming Guide for detail description). + * + *
http://apache.org/xml/properties/schema/external-schemaLocation + *
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation. + * + * It takes a void pointer as the property value. Application is required to initialize this void + * pointer to a correct type. See the SAX2 Programming Guide + * to learn exactly what type of property value each property expects for processing. + * Passing a void pointer that was initialized with a wrong type will lead to unexpected result. + * If the same property is set more than once, the last one takes effect. + * + * @param name The unique identifier (URI) of the property being set. + * @param value The requested value for the property. See + * the SAX2 Programming Guide to learn + * exactly what type of property value each property expects for processing. + * Passing a void pointer that was initialized with a wrong type will lead + * to unexpected result. + * @exception SAXNotRecognizedException If the requested property is not known. + * @exception SAXNotSupportedException Property modification is not supported during parse + */ + virtual void setProperty(const XMLCh* const name, void* value) ; + + /** + * Parse an XML document. + * + * The application can use this method to instruct the SAX parser + * to begin parsing an XML document from any valid input + * source (a character stream, a byte stream, or a URI). + * + * Applications may not invoke this method while a parse is in + * progress (they should create a new Parser instead for each + * additional XML document). Once a parse is complete, an + * application may reuse the same Parser object, possibly with a + * different input source. + * + * @param source The input source for the top-level of the + * XML document. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see InputSource#InputSource + * @see #setEntityResolver + * @see #setDTDHandler + * @see #setDocumentHandler + * @see #setErrorHandler + */ + virtual void parse + ( + const InputSource& source + ) ; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(InputSource) + */ + virtual void parse + ( + const XMLCh* const systemId + ) ; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(InputSource) + */ + virtual void parse + ( + const char* const systemId + ) ; + + //@} + + // ----------------------------------------------------------------------- + // SAX 2.0-ext + // ----------------------------------------------------------------------- + /** @name SAX 2.0-ext */ + //@{ + /** + * This method returns the installed declaration handler. + * + * @return A pointer to the installed declaration handler object. + */ + virtual DeclHandler* getDeclarationHandler() const ; + + /** + * This method returns the installed lexical handler. + * + * @return A pointer to the installed lexical handler object. + */ + virtual LexicalHandler* getLexicalHandler() const ; + + /** + * Allow an application to register a declaration event handler. + * + * If the application does not register a declaration handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by DefaultHandler). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The DTD declaration handler. + * @see DeclHandler#DeclHandler + * @see SAXException#SAXException + * @see DefaultHandler#DefaultHandler + */ + virtual void setDeclarationHandler(DeclHandler* const handler) ; + + /** + * Allow an application to register a lexical event handler. + * + * If the application does not register a lexical handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see LexicalHandler#LexicalHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setLexicalHandler(LexicalHandler* const handler) ; + + //@} + + // ----------------------------------------------------------------------- + // Getter Methods + // ----------------------------------------------------------------------- + /** @name Getter Methods (Xerces-C specific) */ + //@{ + /** + * This method is used to get the current validator. + * + * SAX2XMLReader assumes responsibility for the validator. It will be + * deleted when the XMLReader is destroyed. + * + * @return A pointer to the validator. An application should not deleted + * the object returned. + * + */ + virtual XMLValidator* getValidator() const ; + + /** Get error count from the last parse operation. + * + * This method returns the error count from the last parse + * operation. Note that this count is actually stored in the + * scanner, so this method simply returns what the + * scanner reports. + * + * @return number of errors encountered during the latest + * parse operation. + */ + virtual XMLSize_t getErrorCount() const ; + + /** + * This method returns the state of the parser's + * exit-on-First-Fatal-Error flag. + * + *

Or you can query the feature "http://apache.org/xml/features/continue-after-fatal-error" + * which indicates the opposite state.

+ * + * @return true, if the parser is currently configured to + * exit on the first fatal error, false otherwise. + * + * @see #setExitOnFirstFatalError + * @see #getFeature + */ + virtual bool getExitOnFirstFatalError() const ; + + /** + * This method returns the state of the parser's + * validation-constraint-fatal flag. + * + *

Or you can query the feature "http://apache.org/xml/features/validation-error-as-fatal" + * which means the same thing. + * + * @return true, if the parser is currently configured to + * set validation constraint errors as fatal, false + * otherwise. + * + * @see #setValidationContraintFatal + * @see #getFeature + */ + virtual bool getValidationConstraintFatal() const ; + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + virtual Grammar* getGrammar(const XMLCh* const nameSpaceKey); + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + virtual Grammar* getRootGrammar(); + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + virtual const XMLCh* getURIText(unsigned int uriId) const; + + /** + * Returns the current src offset within the input source. + * To be used only while parsing is in progress. + * + * @return offset within the input source + */ + virtual XMLFilePos getSrcOffset() const; + + //@} + + // ----------------------------------------------------------------------- + // Setter Methods + // ----------------------------------------------------------------------- + /** @name Setter Methods (Xerces-C specific) */ + //@{ + /** + * This method is used to set a validator. + * + * SAX2XMLReader assumes responsibility for the validator. It will be + * deleted when the XMLReader is destroyed. + * + * @param valueToAdopt A pointer to the validator that the reader should use. + * + */ + virtual void setValidator(XMLValidator* valueToAdopt) ; + + /** + * This method allows users to set the parser's behaviour when it + * encounters the first fatal error. If set to true, the parser + * will exit at the first fatal error. If false, then it will + * report the error and continue processing. + * + *

The default value is 'true' and the parser exits on the + * first fatal error.

+ * + *

Or you can set the feature "http://apache.org/xml/features/continue-after-fatal-error" + * which has the opposite behaviour.

+ * + *

If both the feature above and this function are used, the latter takes effect.

+ * + * @param newState The value specifying whether the parser should + * continue or exit when it encounters the first + * fatal error. + * + * @see #getExitOnFirstFatalError + * @see #setFeature + */ + virtual void setExitOnFirstFatalError(const bool newState) ; + + /** + * This method allows users to set the parser's behaviour when it + * encounters a validation constraint error. If set to true, and the + * the parser will treat validation error as fatal and will exit depends on the + * state of "getExitOnFirstFatalError". If false, then it will + * report the error and continue processing. + * + * Note: setting this true does not mean the validation error will be printed with + * the word "Fatal Error". It is still printed as "Error", but the parser + * will exit if "setExitOnFirstFatalError" is set to true. + * + *

The default value is 'false'.

+ * + *

Or you can set the feature "http://apache.org/xml/features/validation-error-as-fatal" + * which means the same thing.

+ * + *

If both the feature above and this function are used, the latter takes effect.

+ * + * @param newState If true, the parser will exit if "setExitOnFirstFatalError" + * is set to true. + * + * @see #getValidationConstraintFatal + * @see #setExitOnFirstFatalError + * @see #setFeature + */ + virtual void setValidationConstraintFatal(const bool newState) ; + //@} + + + // ----------------------------------------------------------------------- + // Progressive scan methods + // ----------------------------------------------------------------------- + + /** @name Progressive scan methods */ + //@{ + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a Unicode string representing the path + * to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could parse the + * prolog (which means the token will not be valid.) + * + * @see #parseNext + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseFirst + ( + const XMLCh* const systemId + , XMLPScanToken& toFill + ) ; + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a regular native string representing + * the path to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseFirst + ( + const char* const systemId + , XMLPScanToken& toFill + ) ; + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + */ + virtual bool parseFirst + ( + const InputSource& source + , XMLPScanToken& toFill + ) ; + + /** Continue a progressive parse operation + * + * This method is used to continue with progressive parsing of + * XML files started by a call to 'parseFirst' method. + * + * It parses the XML file and stops as soon as it comes across + * a XML token (as defined in the XML specification). Relevant + * callback handlers are invoked as required by the SAX + * specification. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the next XML token. + * It indicates the user can go ahead with parsing the rest + * of the file. It returns 'false' to indicate that the parser + * could not find next token as per the XML specification + * production rule. + * + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseNext(XMLPScanToken& token) ; + + /** Reset the parser after a progressive parse + * + * If a progressive parse loop exits before the end of the document + * is reached, the parser has no way of knowing this. So it will leave + * open any files or sockets or memory buffers that were in use at + * the time that the parse loop exited. + * + * The next parse operation will cause these open files and such to + * be closed, but the next parse operation might occur at some unknown + * future point. To avoid this problem, you should reset the parser if + * you exit the loop early. + * + * If you exited because of an error, then this cleanup will be done + * for you. Its only when you exit the file prematurely of your own + * accord, because you've found what you wanted in the file most + * likely. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + */ + virtual void parseReset(XMLPScanToken& token) ; + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the grammar preparsing interface + // ----------------------------------------------------------------------- + + /** @name Implementation of Grammar preparsing interface's. */ + //@{ + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the SAX InputSource parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param source A const reference to the SAX InputSource object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see InputSource#InputSource + */ + virtual Grammar* loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Clear the cached grammar pool + */ + virtual void resetCachedGrammarPool(); + + /** Set maximum input buffer size + * + * This method allows users to limit the size of buffers used in parsing + * XML character data. The effect of setting this size is to limit the + * size of a ContentHandler::characters() call. + * + * The parser's default input buffer size is 1 megabyte. + * + * @param bufferSize The maximum input buffer size + */ + void setInputBufferSize(const XMLSize_t bufferSize); + + //@} + + + // ----------------------------------------------------------------------- + // Advanced document handler list maintenance methods + // ----------------------------------------------------------------------- + + /** @name Advanced document handler list maintenance methods */ + //@{ + /** + * This method installs the specified 'advanced' document callback + * handler, thereby allowing the user to customize the processing, + * if they choose to do so. Any number of advanced callback handlers + * maybe installed. + * + *

The methods in the advanced callback interface represent + * Xerces-C extensions. There is no specification for this interface.

+ * + * @param toInstall A pointer to the users advanced callback handler. + * + * @see #removeAdvDocHandler + */ + virtual void installAdvDocHandler(XMLDocumentHandler* const toInstall) ; + + /** + * This method removes the 'advanced' document handler callback from + * the underlying parser scanner. If no handler is installed, advanced + * callbacks are not invoked by the scanner. + * @param toRemove A pointer to the advanced callback handler which + * should be removed. + * + * @see #installAdvDocHandler + */ + virtual bool removeAdvDocHandler(XMLDocumentHandler* const toRemove) ; + //@} + + + // ----------------------------------------------------------------------- + // The XMLFilter interface + // ----------------------------------------------------------------------- + + /** @name Implementation of SAX 2.0 XMLFilter interface's. */ + //@{ + /** + * This method returns the parent XMLReader object. + * + * @return A pointer to the parent XMLReader object. + */ + virtual SAX2XMLReader* getParent() const; + + /** + * Sets the parent XMLReader object; parse requests will be forwarded to this + * object, and callback notifications coming from it will be postprocessed + * + * @param parent The new XMLReader parent. + * @see SAX2XMLReader#SAX2XMLReader + */ + virtual void setParent(SAX2XMLReader* parent); + //@} + + // ----------------------------------------------------------------------- + // Implementation of the EntityResolver interface + // ----------------------------------------------------------------------- + /** @name The EntityResolver interface */ + //@{ + + /** + * Allow the application to resolve external entities. + * + *

The Parser will call this method before opening any external + * entity except the top-level document entity (including the + * external DTD subset, external entities referenced within the + * DTD, and external entities referenced within the document + * element): the application may request that the parser resolve + * the entity itself, that it use an alternative URI, or that it + * use an entirely different input source.

+ * + *

Application writers can use this method to redirect external + * system identifiers to secure and/or local URIs, to look up + * public identifiers in a catalogue, or to read an entity from a + * database or other input source (including, for example, a dialog + * box).

+ * + *

If the system identifier is a URL, the SAX parser must + * resolve it fully before reporting it to the application.

+ * + * @param publicId The public identifier of the external entity + * being referenced, or null if none was supplied. + * @param systemId The system identifier of the external entity + * being referenced. + * @return An InputSource object describing the new input source, + * or null to request that the parser open a regular + * URI connection to the system identifier. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception IOException An IO exception, + * possibly the result of creating a new InputStream + * or Reader for the InputSource. + * @see InputSource#InputSource + */ + virtual InputSource* resolveEntity + ( + const XMLCh* const publicId + , const XMLCh* const systemId + ); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the DTDHandler interface + // ----------------------------------------------------------------------- + /** @name The DTD handler interface */ + //@{ + /** + * Receive notification of a notation declaration event. + * + *

It is up to the application to record the notation for later + * reference, if necessary.

+ * + *

If a system identifier is present, and it is a URL, the SAX + * parser must resolve it fully before passing it to the + * application.

+ * + * @param name The notation name. + * @param publicId The notation's public identifier, or null if + * none was given. + * @param systemId The notation's system identifier, or null if + * none was given. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #unparsedEntityDecl + * @see AttributeList#AttributeList + */ + virtual void notationDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ); + + /** + * Receive notification of an unparsed entity declaration event. + * + *

Note that the notation name corresponds to a notation + * reported by the notationDecl() event. It is up to the + * application to record the entity for later reference, if + * necessary.

+ * + *

If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @param name The unparsed entity's name. + * @param publicId The entity's public identifier, or null if none + * was given. + * @param systemId The entity's system identifier (it must always + * have one). + * @param notationName The name of the associated notation. + * @see #notationDecl + * @see AttributeList#AttributeList + */ + virtual void unparsedEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLCh* const notationName + ); + + /** + * Reset the DocType object on its reuse + * + *

This method helps in reseting the DTD object implementation + * defaults each time the DTD is begun.

+ * + */ + virtual void resetDocType(); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the ContentHandler interface + // ----------------------------------------------------------------------- + /** @name The virtual document handler interface */ + + //@{ + /** + * Receive notification of character data. + * + *

The Parser will call this method to report each chunk of + * character data. SAX parsers may return all contiguous character + * data in a single chunk, or they may split it into several + * chunks; however, all of the characters in any single event + * must come from the same external entity, so that the Locator + * provides useful information.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + *

Note that some parsers will report whitespace using the + * ignorableWhitespace() method rather than this one (validating + * parsers must do so).

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #ignorableWhitespace + * @see Locator#Locator + */ + virtual void characters + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of the end of a document. + * + *

The SAX parser will invoke this method only once, and it will + * be the last method invoked during the parse. The parser shall + * not invoke this method until it has either abandoned parsing + * (because of an unrecoverable error) or reached the end of + * input.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endDocument (); + + /** + * Receive notification of the end of an element. + * + *

The SAX parser will invoke this method at the end of every + * element in the XML document; there will be a corresponding + * startElement() event for every endElement() event (even when the + * element is empty).

+ * + * @param uri The URI of the associated namespace for this element + * @param localname The local part of the element name + * @param qname The QName of this element + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endElement + ( + const XMLCh* const uri, + const XMLCh* const localname, + const XMLCh* const qname + ); + + /** + * Receive notification of ignorable whitespace in element content. + * + *

Validating Parsers must use this method to report each chunk + * of ignorable whitespace (see the W3C XML 1.0 recommendation, + * section 2.10): non-validating parsers may also use this method + * if they are capable of parsing and using content models.

+ * + *

SAX parsers may return all contiguous whitespace in a single + * chunk, or they may split it into several chunks; however, all of + * the characters in any single event must come from the same + * external entity, so that the Locator provides useful + * information.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #characters + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of a processing instruction. + * + *

The Parser will invoke this method once for each processing + * instruction found: note that processing instructions may occur + * before or after the main document element.

+ * + *

A SAX parser should never report an XML declaration (XML 1.0, + * section 2.8) or a text declaration (XML 1.0, section 4.3.1) + * using this method.

+ * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none was supplied. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void processingInstruction + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * Receive an object for locating the origin of SAX document events. + * + * SAX parsers are strongly encouraged (though not absolutely + * required) to supply a locator: if it does so, it must supply + * the locator to the application by invoking this method before + * invoking any of the other methods in the DocumentHandler + * interface. + * + * The locator allows the application to determine the end + * position of any document-related event, even if the parser is + * not reporting an error. Typically, the application will + * use this information for reporting its own errors (such as + * character content that does not match an application's + * business rules). The information returned by the locator + * is probably not sufficient for use with a search engine. + * + * Note that the locator will return correct information only + * during the invocation of the events in this interface. The + * application should not attempt to use it at any other time. + * + * @param locator An object that can return the location of + * any SAX document event. The object is only + * 'on loan' to the client code and they are not + * to attempt to delete or modify it in any way! + * + * @see Locator#Locator + */ + virtual void setDocumentLocator(const Locator* const locator); + + /** + * Receive notification of the beginning of a document. + * + *

The SAX parser will invoke this method only once, before any + * other methods in this interface or in DTDHandler (except for + * setDocumentLocator).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startDocument(); + + /** + * Receive notification of the beginning of an element. + * + *

The Parser will invoke this method at the beginning of every + * element in the XML document; there will be a corresponding + * endElement() event for every startElement() event (even when the + * element is empty). All of the element's content will be + * reported, in order, before the corresponding endElement() + * event.

+ * + *

Note that the attribute list provided will + * contain only attributes with explicit values (specified or + * defaulted): #IMPLIED attributes will be omitted.

+ * + * @param uri The URI of the associated namespace for this element + * @param localname The local part of the element name + * @param qname The QName of this element + * @param attrs The attributes attached to the element, if any. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #endElement + * @see Attributes#Attributes + */ + virtual void startElement + ( + const XMLCh* const uri, + const XMLCh* const localname, + const XMLCh* const qname, + const Attributes& attrs + ); + + /** + * Receive notification of the start of an namespace prefix mapping. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each namespace prefix mapping.

+ * + * @param prefix The namespace prefix used + * @param uri The namespace URI used. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startPrefixMapping + ( + const XMLCh* const prefix, + const XMLCh* const uri + ); + + /** + * Receive notification of the end of an namespace prefix mapping. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each namespace prefix mapping.

+ * + * @param prefix The namespace prefix used + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endPrefixMapping + ( + const XMLCh* const prefix + ); + + /** + * Receive notification of a skipped entity + * + *

The parser will invoke this method once for each entity + * skipped. All processors may skip external entities, + * depending on the values of the features:
+ * http://xml.org/sax/features/external-general-entities
+ * http://xml.org/sax/features/external-parameter-entities

+ * + *

Note: Xerces (specifically) never skips any entities, regardless + * of the above features. This function is never called in the + * Xerces implementation of SAX2.

+ * + *

Introduced with SAX2

+ * + * @param name The name of the skipped entity. If it is a parameter entity, + * the name will begin with %, and if it is the external DTD subset, + * it will be the string [dtd]. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void skippedEntity + ( + const XMLCh* const name + ); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the ErrorHandler interface + // ----------------------------------------------------------------------- + /** @name The error handler interface */ + //@{ + /** + * Receive notification of a warning. + * + *

SAX parsers will use this method to report conditions that + * are not errors or fatal errors as defined by the XML 1.0 + * recommendation. The default behaviour is to take no action.

+ * + *

The SAX parser must continue to provide normal parsing events + * after invoking this method: it should still be possible for the + * application to process the document through to the end.

+ * + * @param exc The warning information encapsulated in a + * SAX parse exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see SAXParseException#SAXParseException + */ + virtual void warning(const SAXParseException& exc); + + /** + * Receive notification of a recoverable error. + * + *

This corresponds to the definition of "error" in section 1.2 + * of the W3C XML 1.0 Recommendation. For example, a validating + * parser would use this callback to report the violation of a + * validity constraint. The default behaviour is to take no + * action.

+ * + *

The SAX parser must continue to provide normal parsing events + * after invoking this method: it should still be possible for the + * application to process the document through to the end. If the + * application cannot do so, then the parser should report a fatal + * error even if the XML 1.0 recommendation does not require it to + * do so.

+ * + * @param exc The error information encapsulated in a + * SAX parse exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see SAXParseException#SAXParseException + */ + virtual void error(const SAXParseException& exc); + + /** + * Receive notification of a non-recoverable error. + * + *

This corresponds to the definition of "fatal error" in + * section 1.2 of the W3C XML 1.0 Recommendation. For example, a + * parser would use this callback to report the violation of a + * well-formedness constraint.

+ * + *

The application must assume that the document is unusable + * after the parser has invoked this method, and should continue + * (if at all) only for the sake of collecting addition error + * messages: in fact, SAX parsers are free to stop reporting any + * other events once this method has been invoked.

+ * + * @param exc The error information encapsulated in a + * SAX parse exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see SAXParseException#SAXParseException + */ + virtual void fatalError(const SAXParseException& exc); + + /** + * Reset the Error handler object on its reuse + * + *

This method helps in reseting the Error handler object + * implementation defaults each time the Error handler is begun.

+ * + */ + virtual void resetErrors(); + + //@} + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SAX2XMLFilterImpl(const SAX2XMLFilterImpl&); + SAX2XMLFilterImpl& operator=(const SAX2XMLFilterImpl&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fParentReader + // The object that we are filtering + // + // fDocHandler + // The installed SAX content handler, if any. Null if none. + // + // fDTDHandler + // The installed SAX DTD handler, if any. Null if none. + // + // fEntityResolver + // The installed SAX entity handler, if any. Null if none. + // + // fErrorHandler + // The installed SAX error handler, if any. Null if none. + // + // ----------------------------------------------------------------------- + SAX2XMLReader* fParentReader; + ContentHandler* fDocHandler; + DTDHandler* fDTDHandler; + EntityResolver* fEntityResolver; + ErrorHandler* fErrorHandler; +}; + + +// --------------------------------------------------------------------------- +// SAX2XMLReader: Getter methods +// --------------------------------------------------------------------------- +inline SAX2XMLReader* SAX2XMLFilterImpl::getParent() const +{ + return fParentReader; +} + +inline ContentHandler* SAX2XMLFilterImpl::getContentHandler() const +{ + return fDocHandler; +} + +inline DTDHandler* SAX2XMLFilterImpl::getDTDHandler() const +{ + return fDTDHandler; +} + +inline EntityResolver* SAX2XMLFilterImpl::getEntityResolver() const +{ + return fEntityResolver; +} + +inline ErrorHandler* SAX2XMLFilterImpl::getErrorHandler() const +{ + return fErrorHandler; +} + +inline LexicalHandler* SAX2XMLFilterImpl::getLexicalHandler() const +{ + return 0; +} + +inline DeclHandler* SAX2XMLFilterImpl::getDeclarationHandler() const +{ + return 0; +} + +inline void SAX2XMLFilterImpl::setContentHandler(ContentHandler* const handler) +{ + fDocHandler = handler; +} + +inline void SAX2XMLFilterImpl::setDTDHandler(DTDHandler* const handler) +{ + fDTDHandler = handler; +} + +inline void SAX2XMLFilterImpl::setErrorHandler(ErrorHandler* const handler) +{ + fErrorHandler = handler; +} + +inline void SAX2XMLFilterImpl::setEntityResolver(EntityResolver* const resolver) +{ + fEntityResolver = resolver; +} + +inline void SAX2XMLFilterImpl::setLexicalHandler(LexicalHandler* const /*handler*/) +{ +} + +inline void SAX2XMLFilterImpl::setDeclarationHandler(DeclHandler* const /*handler*/) +{ +} + +inline void SAX2XMLFilterImpl::installAdvDocHandler(XMLDocumentHandler* const /*toInstall*/) +{ +} + +inline bool SAX2XMLFilterImpl::removeAdvDocHandler(XMLDocumentHandler* const /*toRemove*/) +{ + return false; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/parsers/SAX2XMLReaderImpl.cpp b/include/xercesc/parsers/SAX2XMLReaderImpl.cpp new file mode 100644 index 0000000..32c07c6 --- /dev/null +++ b/include/xercesc/parsers/SAX2XMLReaderImpl.cpp @@ -0,0 +1,1625 @@ +/* + * 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: SAX2XMLReaderImpl.cpp 882548 2009-11-20 13:44:14Z borisk $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +SAX2XMLReader * XMLReaderFactory::createXMLReader( MemoryManager* const manager + , XMLGrammarPool* const gramPool) +{ + SAX2XMLReaderImpl* pImpl=new (manager) SAX2XMLReaderImpl(manager, gramPool); + return pImpl; +} + + +const XMLCh gDTDEntityStr[] = +{ + chOpenSquare, chLatin_d, chLatin_t, chLatin_d, chCloseSquare, chNull +}; + + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ResetInProgressType; + + +SAX2XMLReaderImpl::SAX2XMLReaderImpl(MemoryManager* const manager + , XMLGrammarPool* const gramPool): + + fNamespacePrefix(false) + , fAutoValidation(false) + , fValidation(false) + , fParseInProgress(false) + , fHasExternalSubset(false) + , fElemDepth(0) + , fAdvDHCount(0) + , fAdvDHListSize(32) + , fDocHandler(0) + , fTempAttrVec(0) + , fPrefixesStorage(0) + , fPrefixes(0) + , fPrefixCounts(0) + , fTempQName(0) + , fDTDHandler(0) + , fEntityResolver(0) + , fXMLEntityResolver(0) + , fErrorHandler(0) + , fPSVIHandler(0) + , fLexicalHandler(0) + , fDeclHandler(0) + , fAdvDHList(0) + , fScanner(0) + , fGrammarResolver(0) + , fURIStringPool(0) + , fValidator(0) + , fMemoryManager(manager) + , fGrammarPool(gramPool) +{ + CleanupType cleanup(this, &SAX2XMLReaderImpl::cleanUp); + + try + { + initialize(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +SAX2XMLReaderImpl::~SAX2XMLReaderImpl() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Initialize/Cleanup methods +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::initialize() +{ + // Create grammar resolver and string pool that we pass to the scanner + fGrammarResolver = new (fMemoryManager) GrammarResolver(fGrammarPool, fMemoryManager); + fURIStringPool = fGrammarResolver->getStringPool(); + + // Create a scanner and tell it what validator to use. Then set us + // as the document event handler so we can fill the DOM document. + fScanner = XMLScannerResolver::getDefaultScanner(0, fGrammarResolver, fMemoryManager); + fScanner->setURIStringPool(fURIStringPool); + + // Create the initial advanced handler list array and zero it out + fAdvDHList = (XMLDocumentHandler**) fMemoryManager->allocate + ( + fAdvDHListSize * sizeof(XMLDocumentHandler*) + );//new XMLDocumentHandler*[fAdvDHListSize]; + memset(fAdvDHList, 0, sizeof(void*) * fAdvDHListSize); + + // SAX2 default is for namespaces (feature http://xml.org/sax/features/namespaces) to be on + setDoNamespaces(true) ; + + // default: schema is on + setDoSchema(true); + + fPrefixesStorage = new (fMemoryManager) XMLStringPool(109, fMemoryManager) ; + fPrefixes = new (fMemoryManager) ValueStackOf (30, fMemoryManager) ; + fTempAttrVec = new (fMemoryManager) RefVectorOf (10, false, fMemoryManager) ; + fPrefixCounts = new (fMemoryManager) ValueStackOf(10, fMemoryManager) ; + fTempQName = new (fMemoryManager) XMLBuffer(32, fMemoryManager); +} + + +void SAX2XMLReaderImpl::cleanUp() +{ + fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList; + delete fScanner; + delete fPrefixesStorage; + delete fPrefixes; + delete fTempAttrVec; + delete fPrefixCounts; + delete fGrammarResolver; + delete fTempQName; + // grammar pool must do this + //delete fURIStringPool; +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Advanced document handler list maintenance methods +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::installAdvDocHandler(XMLDocumentHandler* const toInstall) +{ + // See if we need to expand and do so now if needed + if (fAdvDHCount == fAdvDHListSize) + { + // Calc a new size and allocate the new temp buffer + const XMLSize_t newSize = (XMLSize_t)(fAdvDHListSize * 1.5); + XMLDocumentHandler** newList = (XMLDocumentHandler**) fMemoryManager->allocate + ( + newSize * sizeof(XMLDocumentHandler*) + );//new XMLDocumentHandler*[newSize]; + + // Copy over the old data to the new list and zero out the rest + memcpy(newList, fAdvDHList, sizeof(void*) * fAdvDHListSize); + memset + ( + &newList[fAdvDHListSize] + , 0 + , sizeof(void*) * (newSize - fAdvDHListSize) + ); + + // And now clean up the old array and store the new stuff + fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList; + fAdvDHList = newList; + fAdvDHListSize = newSize; + } + + // Add this new guy into the empty slot + fAdvDHList[fAdvDHCount++] = toInstall; + + // + // Install ourself as the document handler with the scanner. We might + // already be, but its not worth checking, just do it. + // + fScanner->setDocHandler(this); +} + + +bool SAX2XMLReaderImpl::removeAdvDocHandler(XMLDocumentHandler* const toRemove) +{ + // If our count is zero, can't be any installed + if (!fAdvDHCount) + return false; + + // + // Search the array until we find this handler. If we find a null entry + // first, we can stop there before the list is kept contiguous. + // + XMLSize_t index; + for (index = 0; index < fAdvDHCount; index++) + { + // + // We found it. We have to keep the list contiguous, so we have to + // copy down any used elements after this one. + // + if (fAdvDHList[index] == toRemove) + { + // + // Optimize if only one entry (pretty common). Otherwise, we + // have to copy them down to compact them. + // + if (fAdvDHCount > 1) + { + index++; + while (index < fAdvDHCount) + fAdvDHList[index - 1] = fAdvDHList[index]; + } + + // Bump down the count and zero out the last one + fAdvDHCount--; + fAdvDHList[fAdvDHCount] = 0; + + // + // If this leaves us with no advanced handlers and there is + // no SAX doc handler installed on us, then remove us from the + // scanner as the document handler. + // + if (!fAdvDHCount && !fDocHandler) + fScanner->setDocHandler(0); + + return true; + } + } + + // Never found it + return false; +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl Validator functions +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::setValidator(XMLValidator* valueToAdopt) +{ + fValidator = valueToAdopt; + fScanner->setValidator(valueToAdopt); +} + +XMLValidator* SAX2XMLReaderImpl::getValidator() const +{ + return fScanner->getValidator(); +} + +// --------------------------------------------------------------------------- +// SAX2XMLReader Interface +// --------------------------------------------------------------------------- +XMLSize_t SAX2XMLReaderImpl::getErrorCount() const +{ + return fScanner->getErrorCount(); +} + +void SAX2XMLReaderImpl::setContentHandler(ContentHandler* const handler) +{ + fDocHandler = handler; + if (fDocHandler) + { + // + // Make sure we are set as the document handler with the scanner. + // We may already be (if advanced handlers are installed), but its + // not worthing checking, just do it. + // + fScanner->setDocHandler(this); + } + else + { + // + // If we don't have any advanced handlers either, then deinstall us + // from the scanner because we don't need document events anymore. + // + if (!fAdvDHCount) + fScanner->setDocHandler(0); + } + +} + +void SAX2XMLReaderImpl::setDTDHandler(DTDHandler* const handler) +{ + fDTDHandler = handler; + if (fDTDHandler) + fScanner->setDocTypeHandler(this); + else + fScanner->setDocTypeHandler(0); +} + + +void SAX2XMLReaderImpl::setErrorHandler(ErrorHandler* const handler) +{ + // + // Store the handler. Then either install or deinstall us as the + // error reporter on the scanner. + // + fErrorHandler = handler; + if (fErrorHandler) { + fScanner->setErrorReporter(this); + fScanner->setErrorHandler(fErrorHandler); + } + else { + fScanner->setErrorReporter(0); + fScanner->setErrorHandler(0); + } +} + +void SAX2XMLReaderImpl::setPSVIHandler(PSVIHandler* const handler) +{ + fPSVIHandler = handler; + if (fPSVIHandler) { + fScanner->setPSVIHandler(fPSVIHandler); + } + else { + fScanner->setPSVIHandler(0); + } +} + +void SAX2XMLReaderImpl::setLexicalHandler(LexicalHandler* const handler) +{ + fLexicalHandler = handler; + if (fLexicalHandler) + fScanner->setDocTypeHandler(this); + else + fScanner->setDocTypeHandler(0); +} + +void SAX2XMLReaderImpl::setDeclarationHandler(DeclHandler* const handler) +{ + fDeclHandler = handler; + if (fDeclHandler) + fScanner->setDocTypeHandler(this); + else + fScanner->setDocTypeHandler(0); +} + + +void SAX2XMLReaderImpl::setEntityResolver(EntityResolver* const resolver) +{ + fEntityResolver = resolver; + if (fEntityResolver) { + fScanner->setEntityHandler(this); + fXMLEntityResolver = 0; + } + else { + fScanner->setEntityHandler(0); + } +} + +void SAX2XMLReaderImpl::setXMLEntityResolver(XMLEntityResolver* const resolver) +{ + fXMLEntityResolver = resolver; + if (fXMLEntityResolver) { + fScanner->setEntityHandler(this); + fEntityResolver = 0; + } + else { + fScanner->setEntityHandler(0); + } +} + +void SAX2XMLReaderImpl::setExitOnFirstFatalError(const bool newState) +{ + fScanner->setExitOnFirstFatal(newState); +} + +void SAX2XMLReaderImpl::setValidationConstraintFatal(const bool newState) +{ + fScanner->setValidationConstraintFatal(newState); +} + +void SAX2XMLReaderImpl::parse (const InputSource& source) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(source); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void SAX2XMLReaderImpl::parse (const XMLCh* const systemId) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(systemId); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void SAX2XMLReaderImpl::parse (const char* const systemId) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(systemId); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Progressive parse methods +// --------------------------------------------------------------------------- +bool SAX2XMLReaderImpl::parseFirst( const XMLCh* const systemId + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(systemId, toFill); +} + +bool SAX2XMLReaderImpl::parseFirst( const char* const systemId + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(systemId, toFill); +} + +bool SAX2XMLReaderImpl::parseFirst( const InputSource& source + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(source, toFill); +} + +bool SAX2XMLReaderImpl::parseNext(XMLPScanToken& token) +{ + return fScanner->scanNext(token); +} + +void SAX2XMLReaderImpl::parseReset(XMLPScanToken& token) +{ + // Reset the scanner + fScanner->scanReset(token); +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Overrides of the XMLDocumentHandler interface +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::docCharacters( const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + // Suppress the chars before the root element. + if (fElemDepth) + { + // Call the installed LexicalHandler. + if (cdataSection && fLexicalHandler) + fLexicalHandler->startCDATA(); + + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->characters(chars, length); + + // Call the installed LexicalHandler. + if (cdataSection && fLexicalHandler) + fLexicalHandler->endCDATA(); + } + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->docCharacters(chars, length, cdataSection); +} + + +void SAX2XMLReaderImpl::docComment(const XMLCh* const commentText) +{ + // Call the installed LexicalHandler. + if (fLexicalHandler) + { + // SAX2 reports comment text like characters -- as an + // array with a length. + fLexicalHandler->comment(commentText, XMLString::stringLen(commentText)); + } + + // + // OK, if there are any installed advanced handlers, + // then let's call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->docComment(commentText); +} + + +void SAX2XMLReaderImpl::XMLDecl( const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncodingStr + ) +{ + // SAX has no way to report this event. But, if there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->XMLDecl( versionStr, + encodingStr, + standaloneStr, + actualEncodingStr ); +} + + +void SAX2XMLReaderImpl::docPI( const XMLCh* const target + , const XMLCh* const data) +{ + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->processingInstruction(target, data); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->docPI(target, data); +} + + +void SAX2XMLReaderImpl::endDocument() +{ + if (fDocHandler) + fDocHandler->endDocument(); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->endDocument(); +} + + +void SAX2XMLReaderImpl::endEntityReference(const XMLEntityDecl& entityDecl) +{ + // Call the installed LexicalHandler. + if (fLexicalHandler) + fLexicalHandler->endEntity(entityDecl.getName()); + + // + // SAX has no way to report this event. But, if there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->endEntityReference(entityDecl); +} + + +void SAX2XMLReaderImpl::ignorableWhitespace(const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + // Do not report the whitespace before the root element. + if (!fElemDepth) + return; + + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->ignorableWhitespace(chars, length); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->ignorableWhitespace(chars, length, cdataSection); +} + + +void SAX2XMLReaderImpl::resetDocument() +{ + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->resetDocument(); + + // Make sure our element depth flag gets set back to zero + fElemDepth = 0; + + // reset prefix counters and prefix map + fPrefixCounts->removeAllElements(); + fPrefixes->removeAllElements(); + fPrefixesStorage->flushAll(); +} + + +void SAX2XMLReaderImpl::startDocument() +{ + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->setDocumentLocator(fScanner->getLocator()); + if(fDocHandler) + fDocHandler->startDocument(); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->startDocument(); +} + + +void SAX2XMLReaderImpl:: +startElement( const XMLElementDecl& elemDecl + , const unsigned int elemURLId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot) +{ + // Bump the element depth counter if not empty + if (!isEmpty) + fElemDepth++; + + if (fDocHandler) + { + const QName* qName=elemDecl.getElementName(); + const XMLCh* baseName=qName->getLocalPart(); + const XMLCh* elemQName = 0; + if(elemPrefix==0 || *elemPrefix==0) + elemQName=baseName; + else if(XMLString::equals(elemPrefix, qName->getPrefix())) + elemQName=qName->getRawName(); + else + { + fTempQName->set(elemPrefix); + fTempQName->append(chColon); + fTempQName->append(baseName); + elemQName=fTempQName->getRawBuffer(); + } + + if (getDoNamespaces()) + { + XMLSize_t numPrefix = 0; + + if (!fNamespacePrefix) + fTempAttrVec->removeAllElements(); + + for (XMLSize_t i = 0; i < attrCount; i++) + { + const XMLCh* nsPrefix = 0; + const XMLCh* nsURI = 0; + + const XMLAttr* tempAttr = attrList.elementAt(i); + const XMLCh* prefix = tempAttr->getPrefix(); + if(prefix && *prefix) + { + if(XMLString::equals(prefix, XMLUni::fgXMLNSString)) + { + nsPrefix = tempAttr->getName(); + nsURI = tempAttr->getValue(); + } + } + else if (XMLString::equals(tempAttr->getName(), XMLUni::fgXMLNSString)) + { + nsPrefix = XMLUni::fgZeroLenString; + nsURI = tempAttr->getValue(); + } + if (!fNamespacePrefix) + { + if (nsURI == 0) + fTempAttrVec->addElement((XMLAttr*)tempAttr); + } + if (nsURI != 0) + { + if(fDocHandler) + fDocHandler->startPrefixMapping(nsPrefix, nsURI); + unsigned int nPrefixId=fPrefixesStorage->addOrFind(nsPrefix); + fPrefixes->push(nPrefixId) ; + numPrefix++; + } + } + fPrefixCounts->push(numPrefix) ; + if (!fNamespacePrefix) + fAttrList.setVector(fTempAttrVec, fTempAttrVec->size(), fScanner); + else + fAttrList.setVector(&attrList, attrCount, fScanner); + + // call startElement() with namespace declarations + if(fDocHandler) + { + fDocHandler->startElement + ( + fScanner->getURIText(elemURLId) + , baseName + , elemQName + , fAttrList + ); + } + } + else // no namespace + { + fAttrList.setVector(&attrList, attrCount, fScanner); + if(fDocHandler) + { + fDocHandler->startElement(XMLUni::fgZeroLenString, + XMLUni::fgZeroLenString, + qName->getRawName(), + fAttrList); + } + } + + + // If its empty, send the end tag event now + if (isEmpty) + { + // call endPrefixMapping appropriately. + if (getDoNamespaces()) + { + if(fDocHandler) + { + fDocHandler->endElement + ( + fScanner->getURIText(elemURLId) + , baseName + , elemQName + ); + } + + XMLSize_t numPrefix = fPrefixCounts->pop(); + for (XMLSize_t i = 0; i < numPrefix; ++i) + { + unsigned int nPrefixId = fPrefixes->pop() ; + if(fDocHandler) + fDocHandler->endPrefixMapping( fPrefixesStorage->getValueForId(nPrefixId) ); + } + } + else + { + if(fDocHandler) + { + fDocHandler->endElement(XMLUni::fgZeroLenString, + XMLUni::fgZeroLenString, + qName->getRawName()); + } + } + } + } + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + { + fAdvDHList[index]->startElement + ( + elemDecl + , elemURLId + , elemPrefix + , attrList + , attrCount + , isEmpty + , isRoot + ); + } +} + +void SAX2XMLReaderImpl::endElement( const XMLElementDecl& elemDecl + , const unsigned int uriId + , const bool isRoot + , const XMLCh* const elemPrefix) +{ + // Just map to the SAX document handler + if (fDocHandler) + { + const QName* qName=elemDecl.getElementName(); + const XMLCh* baseName=qName->getLocalPart(); + const XMLCh* elemQName = 0; + if(elemPrefix==0 || *elemPrefix==0) + elemQName=baseName; + else if(XMLString::equals(elemPrefix, qName->getPrefix())) + elemQName=qName->getRawName(); + else + { + fTempQName->set(elemPrefix); + fTempQName->append(chColon); + fTempQName->append(baseName); + elemQName=fTempQName->getRawBuffer(); + } + + if (getDoNamespaces()) + { + if(fDocHandler) + { + fDocHandler->endElement + ( + fScanner->getURIText(uriId) + , baseName + , elemQName + ); + } + + // get the prefixes back so that we can call endPrefixMapping() + XMLSize_t numPrefix = fPrefixCounts->pop(); + for (XMLSize_t i = 0; i < numPrefix; i++) + { + unsigned int nPrefixId = fPrefixes->pop() ; + if(fDocHandler) + fDocHandler->endPrefixMapping( fPrefixesStorage->getValueForId(nPrefixId) ); + } + } + else + { + if(fDocHandler) + { + fDocHandler->endElement(XMLUni::fgZeroLenString, + XMLUni::fgZeroLenString, + qName->getRawName()); + } + } + } + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->endElement(elemDecl, uriId, isRoot, elemPrefix); + + // + // Dump the element depth down again. Don't let it underflow in case + // of malformed XML. + // + if (fElemDepth) + fElemDepth--; +} + +void SAX2XMLReaderImpl::startEntityReference(const XMLEntityDecl& entityDecl) +{ + // Call the installed LexicalHandler. + if (fLexicalHandler) + fLexicalHandler->startEntity(entityDecl.getName()); + // + // SAX has no way to report this. But, If there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->startEntityReference(entityDecl); +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Overrides of the DocTypeHandler interface +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::attDef( const DTDElementDecl& elemDecl + , const DTDAttDef& attDef + , const bool ignoring) +{ + if (fDeclHandler && !ignoring) { + + XMLAttDef::AttTypes attType = attDef.getType(); + XMLAttDef::DefAttTypes defAttType = attDef.getDefaultType(); + const XMLCh* defAttTypeStr = XMLUni::fgNullString; + bool isEnumeration = (attType == XMLAttDef::Notation || attType == XMLAttDef::Enumeration); + XMLBuffer enumBuf(128, fMemoryManager); + + if (defAttType == XMLAttDef::Fixed || + defAttType == XMLAttDef::Implied || + defAttType == XMLAttDef::Required) { + defAttTypeStr = attDef.getDefAttTypeString(defAttType, fMemoryManager); + } + + if (isEnumeration) { + + const XMLCh* enumString = attDef.getEnumeration(); + XMLSize_t enumLen = XMLString::stringLen(enumString); + + if (attType == XMLAttDef::Notation) { + + enumBuf.set(XMLUni::fgNotationString); + enumBuf.append(chSpace); + } + + enumBuf.append(chOpenParen); + + for (XMLSize_t i=0; iattributeDecl(elemDecl.getFullName(), + attDef.getFullName(), + (isEnumeration) ? enumBuf.getRawBuffer() + : attDef.getAttTypeString(attDef.getType(), fMemoryManager), + defAttTypeStr, + attDef.getValue()); + } +} + + +void SAX2XMLReaderImpl::doctypeComment(const XMLCh* const commentText) +{ + if (fLexicalHandler) + { + // SAX2 reports comment text like characters -- as an + // array with a length. + fLexicalHandler->comment(commentText, XMLString::stringLen(commentText)); + } +} + + +void SAX2XMLReaderImpl::doctypeDecl(const DTDElementDecl& elemDecl + , const XMLCh* const publicId + , const XMLCh* const systemId + , const bool hasIntSubset + , const bool hasExtSubset) +{ + // Call the installed LexicalHandler. + if (fLexicalHandler && (hasIntSubset || hasExtSubset)) + fLexicalHandler->startDTD(elemDecl.getFullName(), publicId, systemId); + + fHasExternalSubset = hasExtSubset; + + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::doctypePI( const XMLCh* const + , const XMLCh* const) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::doctypeWhitespace( const XMLCh* const + , const XMLSize_t) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::elementDecl(const DTDElementDecl& elemDecl, + const bool isIgnored) +{ + if (fDeclHandler && !isIgnored) + fDeclHandler->elementDecl(elemDecl.getFullName(), + elemDecl.getFormattedContentModel()); +} + + +void SAX2XMLReaderImpl::endAttList(const DTDElementDecl&) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::endIntSubset() +{ + // Call the installed LexicalHandler. + if (!fHasExternalSubset && fLexicalHandler) + fLexicalHandler->endDTD(); + + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::endExtSubset() +{ + // Call the installed LexicalHandler. + if (fLexicalHandler) + fLexicalHandler->endEntity(gDTDEntityStr); + if (fLexicalHandler) + fLexicalHandler->endDTD(); + + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::entityDecl( const DTDEntityDecl& entityDecl + , const bool isPEDecl + , const bool isIgnored) +{ + // + // If we have a DTD handler, and this entity is not ignored, and + // its an unparsed entity, then send this one, else if we have a Decl + // handler then send this one. + // + if (!isIgnored) { + + if (entityDecl.isUnparsed()) { + + if (fDTDHandler) { + fDTDHandler->unparsedEntityDecl + ( + entityDecl.getName() + , entityDecl.getPublicId() + , entityDecl.getSystemId() + , entityDecl.getNotationName() + ); + } + } + else if (fDeclHandler) { + + const XMLCh* entityName = entityDecl.getName(); + ArrayJanitor tmpNameJan(0); + + if (isPEDecl) { + + XMLSize_t nameLen = XMLString::stringLen(entityName); + XMLCh* tmpName = (XMLCh*) fMemoryManager->allocate + ( + (nameLen + 2) * sizeof(XMLCh) + );//new XMLCh[nameLen + 2]; + + tmpNameJan.reset(tmpName, fMemoryManager); + tmpName[0] = chPercent; + XMLString::copyString(tmpName + 1, entityName); + entityName = tmpName; + } + + if (entityDecl.isExternal()) { + fDeclHandler->externalEntityDecl + ( + entityName + , entityDecl.getPublicId() + , entityDecl.getSystemId() + ); + } + else { + fDeclHandler->internalEntityDecl + ( + entityName + , entityDecl.getValue() + ); + } + } + } +} + + +void SAX2XMLReaderImpl::resetDocType() +{ + fHasExternalSubset = false; + // Just map to the DTD handler + if (fDTDHandler) + fDTDHandler->resetDocType(); +} + + +void SAX2XMLReaderImpl::notationDecl( const XMLNotationDecl& notDecl + , const bool isIgnored) +{ + if (fDTDHandler && !isIgnored) + { + fDTDHandler->notationDecl + ( + notDecl.getName() + , notDecl.getPublicId() + , notDecl.getSystemId() + ); + } +} + + +void SAX2XMLReaderImpl::startAttList(const DTDElementDecl&) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::startIntSubset() +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAX2XMLReaderImpl::startExtSubset() +{ + if (fLexicalHandler) + fLexicalHandler->startEntity(gDTDEntityStr); +} + + +void SAX2XMLReaderImpl::TextDecl( const XMLCh* const + , const XMLCh* const) +{ + // Unused by SAX DTDHandler interface at this time +} + + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Handlers for the XMLEntityHandler interface +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::endInputSource(const InputSource&) +{ +} + +bool SAX2XMLReaderImpl::expandSystemId(const XMLCh* const, XMLBuffer&) +{ + return false; +} + + +void SAX2XMLReaderImpl::resetEntities() +{ + // Nothing to do for this one +} + +InputSource* SAX2XMLReaderImpl::resolveEntity(XMLResourceIdentifier* resourceIdentifier) +{ + // + // Just map it to the SAX entity resolver. If there is not one installed, + // return a null pointer to cause the default resolution. + // + if (fEntityResolver) + return fEntityResolver->resolveEntity(resourceIdentifier->getPublicId(), + resourceIdentifier->getSystemId()); + if (fXMLEntityResolver) + return fXMLEntityResolver->resolveEntity(resourceIdentifier); + + return 0; +} + +void SAX2XMLReaderImpl::startInputSource(const InputSource&) +{ + // Nothing to do for this one +} + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Overrides of the XMLErrorReporter interface +// --------------------------------------------------------------------------- +void SAX2XMLReaderImpl::resetErrors() +{ + if (fErrorHandler) + fErrorHandler->resetErrors(); +} + + +void SAX2XMLReaderImpl::error( const unsigned int + , const XMLCh* const + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum) +{ + SAXParseException toThrow = SAXParseException + ( + errorText + , publicId + , systemId + , lineNum + , colNum + , fMemoryManager + ); + + if (!fErrorHandler) + { + if (errType == XMLErrorReporter::ErrType_Fatal) + throw toThrow; + else + return; + } + + if (errType == XMLErrorReporter::ErrType_Warning) + fErrorHandler->warning(toThrow); + else if (errType == XMLErrorReporter::ErrType_Fatal) + fErrorHandler->fatalError(toThrow); + else + fErrorHandler->error(toThrow); +} + + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Features and Properties +// --------------------------------------------------------------------------- + +void SAX2XMLReaderImpl::setFeature(const XMLCh* const name, const bool value) +{ + + if (fParseInProgress) + throw SAXNotSupportedException("Feature modification is not supported during parse.", fMemoryManager); + + if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpaces) == 0) + { + setDoNamespaces(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreValidation) == 0) + { + fValidation = value; + if (fValidation) + if (fAutoValidation) + setValidationScheme(Val_Auto); + else + setValidationScheme(Val_Always); + else + setValidationScheme(Val_Never); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpacePrefixes) == 0) + { + fNamespacePrefix = value; + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDynamic) == 0) + { + fAutoValidation = value; + // for auto validation, the sax2 core validation feature must also be enabled. + if (fValidation) + if (fAutoValidation) + setValidationScheme(Val_Auto); + else + setValidationScheme(Val_Always); + else + setValidationScheme(Val_Never); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0) + { + setDoSchema(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0) + { + fScanner->setValidationSchemaFullChecking(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0) + { + fScanner->setIdentityConstraintChecking(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0) + { + fScanner->setLoadExternalDTD(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadSchema) == 0) + { + fScanner->setLoadSchema(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0) + { + fScanner->setExitOnFirstFatal(!value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0) + { + fScanner->setValidationConstraintFatal(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0) + { + fScanner->cacheGrammarFromParse(value); + + if (value) + fScanner->useCachedGrammarInParse(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0) + { + if (value || !fScanner->isCachingGrammarFromParse()) + fScanner->useCachedGrammarInParse(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0) + { + fScanner->setCalculateSrcOfs(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0) + { + fScanner->setStandardUriConformant(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0) + { + fScanner->setGenerateSyntheticAnnotations(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0) + { + fScanner->setValidateAnnotations(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0) + { + fScanner->setIgnoredCachedDTD(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0) + { + fScanner->setIgnoreAnnotations(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0) + { + fScanner->setDisableDefaultEntityResolution(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0) + { + fScanner->setSkipDTDValidation(value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesHandleMultipleImports) == 0) + { + fScanner->setHandleMultipleImports(value); + } + else + throw SAXNotRecognizedException("Unknown Feature", fMemoryManager); +} + +bool SAX2XMLReaderImpl::getFeature(const XMLCh* const name) const +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpaces) == 0) + return getDoNamespaces(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreValidation) == 0) + return fValidation; + else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpacePrefixes) == 0) + return fNamespacePrefix; + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDynamic) == 0) + return fAutoValidation; + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0) + return getDoSchema(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0) + return fScanner->getValidationSchemaFullChecking(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0) + return fScanner->getIdentityConstraintChecking(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0) + return fScanner->getLoadExternalDTD(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadSchema) == 0) + return fScanner->getLoadSchema(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0) + return !fScanner->getExitOnFirstFatal(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0) + return fScanner->getValidationConstraintFatal(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0) + return fScanner->isCachingGrammarFromParse(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0) + return fScanner->isUsingCachedGrammarInParse(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0) + return fScanner->getCalculateSrcOfs(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0) + return fScanner->getStandardUriConformant(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0) + return fScanner->getGenerateSyntheticAnnotations(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0) + return fScanner->getValidateAnnotations(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0) + return fScanner->getIgnoreCachedDTD(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0) + return fScanner->getIgnoreAnnotations(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0) + return fScanner->getDisableDefaultEntityResolution(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0) + return fScanner->getSkipDTDValidation(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesHandleMultipleImports) == 0) + return fScanner->getHandleMultipleImports(); + else + throw SAXNotRecognizedException("Unknown Feature", fMemoryManager); + + return false; +} + +void SAX2XMLReaderImpl::setProperty(const XMLCh* const name, void* value) +{ + if (fParseInProgress) + throw SAXNotSupportedException("Property modification is not supported during parse.", fMemoryManager); + + if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0) + { + fScanner->setExternalSchemaLocation((XMLCh*)value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0) + { + fScanner->setExternalNoNamespaceSchemaLocation((XMLCh*)value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0) + { + fScanner->setSecurityManager((SecurityManager*)value); + } + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLowWaterMark) == 0) + { + fScanner->setLowWaterMark(*(const XMLSize_t*)value); + } + else if (XMLString::equals(name, XMLUni::fgXercesScannerName)) + { + XMLScanner* tempScanner = XMLScannerResolver::resolveScanner + ( + (const XMLCh*) value + , fValidator + , fGrammarResolver + , fMemoryManager + ); + + if (tempScanner) { + + tempScanner->setParseSettings(fScanner); + tempScanner->setURIStringPool(fURIStringPool); + delete fScanner; + fScanner = tempScanner; + } + } + else + throw SAXNotRecognizedException("Unknown Property", fMemoryManager); +} + + +void* SAX2XMLReaderImpl::getProperty(const XMLCh* const name) const +{ + if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0) + return (void*)fScanner->getExternalSchemaLocation(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0) + return (void*)fScanner->getExternalNoNamespaceSchemaLocation(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0) + return (void*)fScanner->getSecurityManager(); + else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLowWaterMark) == 0) + return (void*)&fScanner->getLowWaterMark(); + else if (XMLString::equals(name, XMLUni::fgXercesScannerName)) + return (void*)fScanner->getName(); + else + throw SAXNotRecognizedException("Unknown Property", fMemoryManager); + return 0; +} + + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Private getters and setters for conveniences +// --------------------------------------------------------------------------- + +void SAX2XMLReaderImpl::setValidationScheme(const ValSchemes newScheme) +{ + if (newScheme == Val_Never) + fScanner->setValidationScheme(XMLScanner::Val_Never); + else if (newScheme == Val_Always) + fScanner->setValidationScheme(XMLScanner::Val_Always); + else + fScanner->setValidationScheme(XMLScanner::Val_Auto); +} + +void SAX2XMLReaderImpl::setDoNamespaces(const bool newState) +{ + fScanner->setDoNamespaces(newState); +} + +bool SAX2XMLReaderImpl::getDoNamespaces() const +{ + return fScanner->getDoNamespaces(); +} + +void SAX2XMLReaderImpl::setDoSchema(const bool newState) +{ + fScanner->setDoSchema(newState); +} + +bool SAX2XMLReaderImpl::getDoSchema() const +{ + return fScanner->getDoSchema(); +} + + +// --------------------------------------------------------------------------- +// SAX2XMLReaderImpl: Grammar preparsing +// --------------------------------------------------------------------------- +Grammar* SAX2XMLReaderImpl::loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress); + + Grammar* grammar = 0; + try + { + fParseInProgress = true; + grammar = fScanner->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } + + return grammar; +} + +Grammar* SAX2XMLReaderImpl::loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress); + + Grammar* grammar = 0; + try + { + fParseInProgress = true; + grammar = fScanner->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } + + return grammar; +} + +Grammar* SAX2XMLReaderImpl::loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress); + + Grammar* grammar = 0; + try + { + fParseInProgress = true; + grammar = fScanner->loadGrammar(source, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } + + return grammar; +} + +void SAX2XMLReaderImpl::resetInProgress() +{ + fParseInProgress = false; +} + +void SAX2XMLReaderImpl::resetCachedGrammarPool() +{ + fGrammarResolver->resetCachedGrammar(); + fScanner->resetCachedGrammar(); +} + +void SAX2XMLReaderImpl::setInputBufferSize(const XMLSize_t bufferSize) +{ + fScanner->setInputBufferSize(bufferSize); +} + +Grammar* SAX2XMLReaderImpl::getGrammar(const XMLCh* const nameSpaceKey) +{ + return fGrammarResolver->getGrammar(nameSpaceKey); +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/parsers/SAX2XMLReaderImpl.hpp b/include/xercesc/parsers/SAX2XMLReaderImpl.hpp new file mode 100644 index 0000000..5a6b3e7 --- /dev/null +++ b/include/xercesc/parsers/SAX2XMLReaderImpl.hpp @@ -0,0 +1,1749 @@ +/* + * 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: SAX2XMLReaderImpl.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAX2XMLREADERIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_SAX2XMLREADERIMPL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class ContentHandler; +class LexicalHandler; +class DeclHandler; +class GrammarResolver; +class XMLGrammarPool; +class XMLResourceIdentifier; +class PSVIHandler; + +/** + * This class implements the SAX2 'XMLReader' interface and should be + * used by applications wishing to parse the XML files using SAX2. + * It allows the client program to install SAX2 handlers for event + * callbacks. + * + *

It can be used to instantiate a validating or non-validating + * parser, by setting a member flag.

+ * + * we basically re-use the existing SAX1 parser code, but provide a + * new implementation of XMLContentHandler that raises the new + * SAX2 style events + * + */ + +class PARSERS_EXPORT SAX2XMLReaderImpl : + public XMemory + , public SAX2XMLReader + , public XMLDocumentHandler + , public XMLErrorReporter + , public XMLEntityHandler + , public DocTypeHandler +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** The default constructor */ + SAX2XMLReaderImpl( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ); + + /** The destructor */ + ~SAX2XMLReaderImpl() ; + //@} + + //----------------------------------------------------------------------- + // Implementation of SAX2XMLReader Interface + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // The XMLReader interface + //----------------------------------------------------------------------- + /** @name Implementation of SAX 2.0 XMLReader interface's. */ + //@{ + + /** + * This method returns the installed content handler. + * + * @return A pointer to the installed content handler object. + */ + virtual ContentHandler* getContentHandler() const ; + + /** + * This method returns the installed DTD handler. + * + * @return A pointer to the installed DTD handler object. + */ + virtual DTDHandler* getDTDHandler() const ; + + /** + * This method returns the installed entity resolver. + * + * @return A pointer to the installed entity resolver object. + */ + virtual EntityResolver* getEntityResolver() const ; + + /** + * This method returns the installed entity resolver. + * + * @return A pointer to the installed entity resolver object. + */ + virtual XMLEntityResolver* getXMLEntityResolver() const ; + + /** + * This method returns the installed error handler. + * + * @return A pointer to the installed error handler object. + */ + virtual ErrorHandler* getErrorHandler() const ; + + /** + * This method returns the installed PSVI handler. + * + * @return A pointer to the installed PSVI handler object. + */ + virtual PSVIHandler* getPSVIHandler() const ; + + /** + * Query the current state of any feature in a SAX2 XMLReader. + * + * @param name The unique identifier (URI) of the feature being set. + * @return The current state of the feature. + * @exception SAXNotRecognizedException If the requested feature is not known. + */ + virtual bool getFeature(const XMLCh* const name) const ; + + /** + * Query the current value of a property in a SAX2 XMLReader. + * + * The parser owns the returned pointer. The memory allocated for + * the returned pointer will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else; otherwise you may get unexpected result. Since the returned + * pointer is a generic void pointer, see the SAX2 Programming Guide to learn + * exactly what type of property value each property returns for replication. + * + * @param name The unique identifier (URI) of the property being set. + * @return The current value of the property. The pointer spans the same + * life-time as the parser. A null pointer is returned if nothing + * was specified externally. + * @exception SAXNotRecognizedException If the requested property is not known. + */ + virtual void* getProperty(const XMLCh* const name) const ; + + /** + * Allow an application to register a document event handler. + * + * If the application does not register a document handler, all + * document events reported by the SAX parser will be silently + * ignored (this is the default behaviour implemented by + * HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The document handler. + * @see DocumentHandler#DocumentHandler + * @see HandlerBase#HandlerBase + */ + virtual void setContentHandler(ContentHandler* const handler) ; + + /** + * Allow an application to register a DTD event handler. + * + * If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored (this + * is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the middle + * of a parse, and the SAX parser must begin using the new handler + * immediately. + * + * @param handler The DTD handler. + * @see DTDHandler#DTDHandler + * @see HandlerBase#HandlerBase + */ + virtual void setDTDHandler(DTDHandler* const handler) ; + + /** + * Allow an application to register a custom entity resolver. + * + * If the application does not register an entity resolver, the + * SAX parser will resolve system identifiers and open connections + * to entities itself (this is the default behaviour implemented in + * DefaultHandler). + * + * Applications may register a new or different entity resolver + * in the middle of a parse, and the SAX parser must begin using + * the new resolver immediately. + * + * Any previously set entity resolver is merely dropped, since the parser + * does not own them. If both setEntityResolver and setXMLEntityResolver + * are called, then the last one is used. + * + * @param resolver The object for resolving entities. + * @see EntityResolver#EntityResolver + * @see DefaultHandler#DefaultHandler + */ + virtual void setEntityResolver(EntityResolver* const resolver) ; + + /** Set the entity resolver + * + * This method allows applications to install their own entity + * resolver. By installing an entity resolver, the applications + * can trap and potentially redirect references to external + * entities. + * + * Any previously set entity resolver is merely dropped, since the parser + * does not own them. If both setEntityResolver and setXMLEntityResolver + * are called, then the last one is used. + * + * @param resolver A const pointer to the user supplied entity + * resolver. + * + * @see #getXMLEntityResolver + */ + virtual void setXMLEntityResolver(XMLEntityResolver* const resolver) ; + + /** + * Allow an application to register an error event handler. + * + * If the application does not register an error event handler, + * all error events reported by the SAX parser will be silently + * ignored, except for fatalError, which will throw a SAXException + * (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see ErrorHandler#ErrorHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setErrorHandler(ErrorHandler* const handler) ; + + /** + * This method installs the user specified PSVI handler on + * the parser. + * + * @param handler A pointer to the PSVI handler to be called + * when the parser comes across 'PSVI' events + * as per the schema specification. + */ + virtual void setPSVIHandler(PSVIHandler* const handler); + + /** + * Set the state of any feature in a SAX2 XMLReader. + * Supported features in SAX2 for xerces-c are: + *
(See the SAX2 Programming Guide for detail description). + * + *
http://xml.org/sax/features/validation (default: false) + *
http://xml.org/sax/features/namespaces (default: true) + *
http://xml.org/sax/features/namespace-prefixes (default: false) + *
http://apache.org/xml/features/validation/dynamic (default: false) + *
http://apache.org/xml/features/validation/reuse-grammar (default: false) + *
http://apache.org/xml/features/validation/schema (default: true) + *
http://apache.org/xml/features/validation/schema-full-checking (default: false) + *
http://apache.org/xml/features/validating/load-schema (default: true) + *
http://apache.org/xml/features/nonvalidating/load-external-dtd (default: true) + *
http://apache.org/xml/features/continue-after-fatal-error (default: false) + *
http://apache.org/xml/features/validation-error-as-fatal (default: false) + * + * @param name The unique identifier (URI) of the feature. + * @param value The requested state of the feature (true or false). + * @exception SAXNotRecognizedException If the requested feature is not known. + * @exception SAXNotSupportedException Feature modification is not supported during parse + * + */ + virtual void setFeature(const XMLCh* const name, const bool value) ; + + /** + * Set the value of any property in a SAX2 XMLReader. + * Supported properties in SAX2 for xerces-c are: + *
(See the SAX2 Programming Guide for detail description). + * + *
http://apache.org/xml/properties/schema/external-schemaLocation + *
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation. + * + * It takes a void pointer as the property value. Application is required to initialize this void + * pointer to a correct type. See the SAX2 Programming Guide + * to learn exactly what type of property value each property expects for processing. + * Passing a void pointer that was initialized with a wrong type will lead to unexpected result. + * If the same property is set more than once, the last one takes effect. + * + * @param name The unique identifier (URI) of the property being set. + * @param value The requested value for the property. See + * the SAX2 Programming Guide to learn + * exactly what type of property value each property expects for processing. + * Passing a void pointer that was initialized with a wrong type will lead + * to unexpected result. + * @exception SAXNotRecognizedException If the requested property is not known. + * @exception SAXNotSupportedException Property modification is not supported during parse + */ + virtual void setProperty(const XMLCh* const name, void* value) ; + + /** + * Parse an XML document. + * + * The application can use this method to instruct the SAX parser + * to begin parsing an XML document from any valid input + * source (a character stream, a byte stream, or a URI). + * + * Applications may not invoke this method while a parse is in + * progress (they should create a new Parser instead for each + * additional XML document). Once a parse is complete, an + * application may reuse the same Parser object, possibly with a + * different input source. + * + * @param source The input source for the top-level of the + * XML document. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see InputSource#InputSource + * @see #setEntityResolver + * @see #setDTDHandler + * @see #setDocumentHandler + * @see #setErrorHandler + */ + virtual void parse + ( + const InputSource& source + ) ; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(InputSource) + */ + virtual void parse + ( + const XMLCh* const systemId + ) ; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(InputSource) + */ + virtual void parse + ( + const char* const systemId + ) ; + + //@} + + // ----------------------------------------------------------------------- + // SAX 2.0-ext + // ----------------------------------------------------------------------- + /** @name SAX 2.0-ext */ + //@{ + /** + * This method returns the installed declaration handler. + * + * @return A pointer to the installed declaration handler object. + */ + virtual DeclHandler* getDeclarationHandler() const ; + + /** + * This method returns the installed lexical handler. + * + * @return A pointer to the installed lexical handler object. + */ + virtual LexicalHandler* getLexicalHandler() const ; + + /** + * Allow an application to register a declaration event handler. + * + * If the application does not register a declaration handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by DefaultHandler). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The DTD declaration handler. + * @see DeclHandler#DeclHandler + * @see SAXException#SAXException + * @see DefaultHandler#DefaultHandler + */ + virtual void setDeclarationHandler(DeclHandler* const handler) ; + + /** + * Allow an application to register a lexical event handler. + * + * If the application does not register a lexical handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see LexicalHandler#LexicalHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setLexicalHandler(LexicalHandler* const handler) ; + + //@} + + // ----------------------------------------------------------------------- + // Getter Methods + // ----------------------------------------------------------------------- + /** @name Getter Methods (Xerces-C specific) */ + //@{ + /** + * This method is used to get the current validator. + * + * SAX2XMLReader assumes responsibility for the validator. It will be + * deleted when the XMLReader is destroyed. + * + * @return A pointer to the validator. An application should not deleted + * the object returned. + * + */ + virtual XMLValidator* getValidator() const ; + //@} + + /** Get error count from the last parse operation. + * + * This method returns the error count from the last parse + * operation. Note that this count is actually stored in the + * scanner, so this method simply returns what the + * scanner reports. + * + * @return number of errors encountered during the latest + * parse operation. + */ + virtual XMLSize_t getErrorCount() const ; + + /** + * This method returns the state of the parser's + * exit-on-First-Fatal-Error flag. + * + *

Or you can query the feature "http://apache.org/xml/features/continue-after-fatal-error" + * which indicates the opposite state.

+ * + * @return true, if the parser is currently configured to + * exit on the first fatal error, false otherwise. + * + * @see #setExitOnFirstFatalError + * @see #getFeature + */ + virtual bool getExitOnFirstFatalError() const ; + + /** + * This method returns the state of the parser's + * validation-constraint-fatal flag. + * + *

Or you can query the feature "http://apache.org/xml/features/validation-error-as-fatal" + * which means the same thing. + * + * @return true, if the parser is currently configured to + * set validation constraint errors as fatal, false + * otherwise. + * + * @see #setValidationContraintFatal + * @see #getFeature + */ + virtual bool getValidationConstraintFatal() const ; + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + virtual Grammar* getGrammar(const XMLCh* const nameSpaceKey); + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + virtual Grammar* getRootGrammar(); + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + virtual const XMLCh* getURIText(unsigned int uriId) const; + + /** + * Returns the current src offset within the input source. + * To be used only while parsing is in progress. + * + * @return offset within the input source + */ + virtual XMLFilePos getSrcOffset() const; + + //@} + + // ----------------------------------------------------------------------- + // Setter Methods + // ----------------------------------------------------------------------- + /** @name Setter Methods (Xerces-C specific) */ + //@{ + /** + * This method is used to set a validator. + * + * SAX2XMLReader assumes responsibility for the validator. It will be + * deleted when the XMLReader is destroyed. + * + * @param valueToAdopt A pointer to the validator that the reader should use. + * + */ + virtual void setValidator(XMLValidator* valueToAdopt) ; + + /** + * This method allows users to set the parser's behaviour when it + * encounters the first fatal error. If set to true, the parser + * will exit at the first fatal error. If false, then it will + * report the error and continue processing. + * + *

The default value is 'true' and the parser exits on the + * first fatal error.

+ * + *

Or you can set the feature "http://apache.org/xml/features/continue-after-fatal-error" + * which has the opposite behaviour.

+ * + *

If both the feature above and this function are used, the latter takes effect.

+ * + * @param newState The value specifying whether the parser should + * continue or exit when it encounters the first + * fatal error. + * + * @see #getExitOnFirstFatalError + * @see #setFeature + */ + virtual void setExitOnFirstFatalError(const bool newState) ; + + /** + * This method allows users to set the parser's behaviour when it + * encounters a validation constraint error. If set to true, and the + * the parser will treat validation error as fatal and will exit depends on the + * state of "getExitOnFirstFatalError". If false, then it will + * report the error and continue processing. + * + * Note: setting this true does not mean the validation error will be printed with + * the word "Fatal Error". It is still printed as "Error", but the parser + * will exit if "setExitOnFirstFatalError" is set to true. + * + *

The default value is 'false'.

+ * + *

Or you can set the feature "http://apache.org/xml/features/validation-error-as-fatal" + * which means the same thing.

+ * + *

If both the feature above and this function are used, the latter takes effect.

+ * + * @param newState If true, the parser will exit if "setExitOnFirstFatalError" + * is set to true. + * + * @see #getValidationConstraintFatal + * @see #setExitOnFirstFatalError + * @see #setFeature + */ + virtual void setValidationConstraintFatal(const bool newState) ; + //@} + + + // ----------------------------------------------------------------------- + // Progressive scan methods + // ----------------------------------------------------------------------- + + /** @name Progressive scan methods */ + //@{ + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a Unicode string representing the path + * to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could parse the + * prolog (which means the token will not be valid.) + * + * @see #parseNext + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseFirst + ( + const XMLCh* const systemId + , XMLPScanToken& toFill + ) ; + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a regular native string representing + * the path to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseFirst + ( + const char* const systemId + , XMLPScanToken& toFill + ) ; + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + */ + virtual bool parseFirst + ( + const InputSource& source + , XMLPScanToken& toFill + ) ; + + /** Continue a progressive parse operation + * + * This method is used to continue with progressive parsing of + * XML files started by a call to 'parseFirst' method. + * + * It parses the XML file and stops as soon as it comes across + * a XML token (as defined in the XML specification). Relevant + * callback handlers are invoked as required by the SAX + * specification. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the next XML token. + * It indicates the user can go ahead with parsing the rest + * of the file. It returns 'false' to indicate that the parser + * could not find next token as per the XML specification + * production rule. + * + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseNext(XMLPScanToken& token) ; + + /** Reset the parser after a progressive parse + * + * If a progressive parse loop exits before the end of the document + * is reached, the parser has no way of knowing this. So it will leave + * open any files or sockets or memory buffers that were in use at + * the time that the parse loop exited. + * + * The next parse operation will cause these open files and such to + * be closed, but the next parse operation might occur at some unknown + * future point. To avoid this problem, you should reset the parser if + * you exit the loop early. + * + * If you exited because of an error, then this cleanup will be done + * for you. Its only when you exit the file prematurely of your own + * accord, because you've found what you wanted in the file most + * likely. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + */ + virtual void parseReset(XMLPScanToken& token) ; + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the grammar preparsing interface + // ----------------------------------------------------------------------- + + /** @name Implementation of Grammar preparsing interface's. */ + //@{ + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the SAX InputSource parameter. + * + * + * @param source A const reference to the SAX InputSource object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see InputSource#InputSource + */ + virtual Grammar* loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. + * + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. + * + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Clear the cached grammar pool + */ + virtual void resetCachedGrammarPool(); + + /** Set maximum input buffer size + * + * This method allows users to limit the size of buffers used in parsing + * XML character data. The effect of setting this size is to limit the + * size of a ContentHandler::characters() call. + * + * The parser's default input buffer size is 1 megabyte. + * + * @param bufferSize The maximum input buffer size + */ + virtual void setInputBufferSize(const XMLSize_t bufferSize); + + //@} + + + // ----------------------------------------------------------------------- + // Advanced document handler list maintenance methods + // ----------------------------------------------------------------------- + + /** @name Advanced document handler list maintenance methods */ + //@{ + /** + * This method installs the specified 'advanced' document callback + * handler, thereby allowing the user to customize the processing, + * if they choose to do so. Any number of advanced callback handlers + * maybe installed. + * + *

The methods in the advanced callback interface represent + * Xerces-C extensions. There is no specification for this interface.

+ * + * @param toInstall A pointer to the users advanced callback handler. + * + * @see #removeAdvDocHandler + */ + virtual void installAdvDocHandler(XMLDocumentHandler* const toInstall) ; + + /** + * This method removes the 'advanced' document handler callback from + * the underlying parser scanner. If no handler is installed, advanced + * callbacks are not invoked by the scanner. + * @param toRemove A pointer to the advanced callback handler which + * should be removed. + * + * @see #installAdvDocHandler + */ + virtual bool removeAdvDocHandler(XMLDocumentHandler* const toRemove) ; + //@} + + // ----------------------------------------------------------------------- + // Implementation of the XMLDocumentHandler interface + // ----------------------------------------------------------------------- + /** @name Implementation of the XMLDocumentHandler Interface. */ + //@{ + /** + * This method is used to report all the characters scanned + * by the parser. The driver will invoke the 'characters' + * method of the user installed SAX Document Handler. + * + *

If any advanced callback handlers are installed, the + * corresponding 'docCharacters' method will also be invoked.

+ * + * @param chars A const pointer to a Unicode string representing the + * character data. + * @param length The length of the Unicode string returned in 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + * @see DocumentHandler#characters + */ + virtual void docCharacters + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** + * This method is used to report any comments scanned by the parser. + * This method is a no-op unless, unless an advanced callback handler + * is installed, in which case the corresponding 'docComment' method + * is invoked. + * + * @param comment A const pointer to a null terminated Unicode + * string representing the comment text. + */ + virtual void docComment + ( + const XMLCh* const comment + ); + + /** + * This method is used to report any PI scanned by the parser. + * + *

Any PI's occurring before any 'content' are not reported + * to any SAX handler as per the specification. However, all + * PI's within content are reported via the SAX Document Handler's + * 'processingInstruction' method. + * + *

If any advanced callback handlers are installed, the + * corresponding 'docPI' method will be invoked.

+ * + * @param target A const pointer to a Unicode string representing the + * target of the PI declaration. + * @param data A const pointer to a Unicode string representing the + * data of the PI declaration. See the PI production rule + * in the XML specification for details. + * + * @see DocumentHandler#processingInstruction + */ + virtual void docPI + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * This method is used to indicate the end of root element + * was just scanned by the parser. Corresponding 'endDocument' + * method of the user installed SAX Document Handler will also + * be invoked. + * + *

In addition, if any advanced callback handlers are installed, + * the corresponding 'endDocument' method is invoked.

+ * + * @see DocumentHandler#endDocument + */ + virtual void endDocument(); + + /** + * This method is used to indicate the end tag of an element. + * The driver will invoke the corresponding 'endElement' method of + * the SAX Document Handler interface. + * + *

If any advanced callback handlers are installed, the + * corresponding 'endElement' method is also invoked.

+ * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param isRoot A flag indicating whether this element was the + * root element. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + * @see DocumentHandler#endElement + */ + virtual void endElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const bool isRoot + , const XMLCh* const elemPrefix=0 + ); + + /** + * This method is used to indicate that an end of an entity reference + * was just scanned. + * + *

If any advanced callback handlers are installed, the + * corresponding 'endEntityReference' method is invoked.

+ * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void endEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** + * This method is used to report all the whitespace characters, + * which are determined to be 'ignorable'. This distinction + * between characters is only made, if validation is enabled. + * Corresponding 'ignorableWhitespace' method of the user installed + * SAX Document Handler interface is called. + * + *

Any whitespace before content is not reported to the SAX + * Document Handler method, as per the SAX specification. + * However, if any advanced callback handlers are installed, the + * corresponding 'ignorableWhitespace' method is invoked.

+ * + * @param chars A const pointer to a Unicode string representing the + * ignorable whitespace character data. + * @param length The length of the Unicode string 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + * @see DocumentHandler#ignorableWhitespace + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** + * This method allows the user installed Document Handler and + * any advanced callback handlers to 'reset' themselves. + */ + virtual void resetDocument(); + + /** + * This method is used to report the start of the parsing process. + * The corresponding user installed SAX Document Handler's method + * 'startDocument' is invoked. + * + *

If any advanced callback handlers are installed, then the + * corresponding 'startDocument' method is also called.

+ * + * @see DocumentHandler#startDocument + */ + virtual void startDocument(); + + /** + * This method is used to report the start of an element. It is + * called at the end of the element, by which time all attributes + * specified are also parsed. The corresponding user installed + * SAX Document Handler's method 'startElement' is invoked. + * + *

If any advanced callback handlers are installed, then the + * corresponding 'startElement' method is also called.

+ * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + * @param attrList A const reference to the object containing the + * list of attributes just scanned for this element. + * @param attrCount A count of number of attributes in the list + * specified by the parameter 'attrList'. + * @param isEmpty A flag indicating whether this is an empty element + * or not. + * @param isRoot A flag indicating whether this element was the + * root element. + * @see DocumentHandler#startElement + */ + virtual void startElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot + ); + + /** + * This method is used to indicate the start of an entity reference. + * + *

If any advanced callback handlers are installed, the + * corresponding 'endEntityReference' method is invoked.

+ * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void startEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** + * This method is used to report the XML decl scanned by the parser. + * Refer to the XML specification to see the meaning of parameters. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param versionStr A const pointer to a Unicode string representing + * version string value. + * @param encodingStr A const pointer to a Unicode string representing + * the encoding string value. + * @param standaloneStr A const pointer to a Unicode string + * representing the standalone string value. + * @param actualEncodingStr A const pointer to a Unicode string + * representing the actual encoding string + * value. + */ + virtual void XMLDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncodingStr + ); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLErrorReporter interface + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLErrorReporter Interface. */ + //@{ + /** + * This method is used to report back errors found while parsing the + * XML file. The driver will call the corresponding user installed + * SAX Error Handler methods: 'fatal', 'error', 'warning' depending + * on the severity of the error. This classification is defined by + * the XML specification. + * + * @param errCode An integer code for the error. + * @param msgDomain A const pointer to an Unicode string representing + * the message domain to use. + * @param errType An enumeration classifying the severity of the error. + * @param errorText A const pointer to an Unicode string representing + * the text of the error message. + * @param systemId A const pointer to an Unicode string representing + * the system id of the XML file where this error + * was discovered. + * @param publicId A const pointer to an Unicode string representing + * the public id of the XML file where this error + * was discovered. + * @param lineNum The line number where the error occurred. + * @param colNum The column number where the error occurred. + * @see ErrorHandler + */ + virtual void error + ( + const unsigned int errCode + , const XMLCh* const msgDomain + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ); + + /** + * This method allows the user installed Error Handler + * callback to 'reset' itself. + * + * This method is a no-op for this SAX driver + * implementation. + * + */ + virtual void resetErrors(); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLEntityHandler interface + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLEntityHandler Interface. */ + //@{ + /** + * This method is used to indicate the end of parsing of an external + * entity file. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the XML file being parsed. + * @see InputSource + */ + virtual void endInputSource(const InputSource& inputSource); + + /** + * This method allows an installed XMLEntityHandler to further + * process any system id's of external entities encountered in + * the XML file being parsed, such as redirection etc. + * + * This method always returns 'false' + * for this SAX driver implementation. + * + * @param systemId A const pointer to an Unicode string representing + * the system id scanned by the parser. + * @param toFill A pointer to a buffer in which the application + * processed system id is stored. + * @return 'true', if any processing is done, 'false' otherwise. + */ + virtual bool expandSystemId + ( + const XMLCh* const systemId + , XMLBuffer& toFill + ); + + /** + * This method allows the installed XMLEntityHandler to reset + * itself. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void resetEntities(); + + /** Resolve a public/system id + * + * This method allows a user installed entity handler to further + * process any pointers to external entities. The applications can + * implement 'redirection' via this callback. + * + * @param resourceIdentifier An object containing the type of + * resource to be resolved and the associated data members + * corresponding to this type. + * @return The value returned by the user installed resolveEntity + * method or NULL otherwise to indicate no processing was done. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @see XMLEntityHandler + * @see XMLEntityResolver + */ + virtual InputSource* resolveEntity + ( + XMLResourceIdentifier* resourceIdentifier + ); + + /** + * This method is used to indicate the start of parsing an + * external entity file. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the external entity + * being parsed. + */ + virtual void startInputSource(const InputSource& inputSource); + //@} + + // ----------------------------------------------------------------------- + // Implementation of the Deprecated DocTypeHandler Interface + // ----------------------------------------------------------------------- + + /** @name Implementation of the deprecated DocTypeHandler Interface */ + //@{ + /** + * This method is used to report an attribute definition. + * + * This method is a no-op for this SAX + * driver implementation. + * + * @param elemDecl A const reference to the object containing information + * about the element whose attribute definition was just + * parsed. + * @param attDef A const reference to the object containing information + * attribute definition. + * @param ignore The flag indicating whether this attribute definition + * was ignored by the parser or not. + */ + virtual void attDef + ( + const DTDElementDecl& elemDecl + , const DTDAttDef& attDef + , const bool ignoring + ); + + /** + * This method is used to report a comment occurring within the DTD. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param comment A const pointer to a Unicode string representing the + * text of the comment just parsed. + */ + virtual void doctypeComment + ( + const XMLCh* const comment + ); + + /** + * This method is used to report the DOCTYPE declaration. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param elemDecl A const reference to the object containing information + * about the root element definition declaration of the + * XML document being parsed. + * @param publicId A const pointer to a Unicode string representing the + * public id of the DTD file. + * @param systemId A const pointer to a Unicode string representing the + * system id of the DTD file. + * @param hasIntSubset A flag indicating if this XML file contains any + * internal subset. + * @param hasExtSubset A flag indicating if this XML file contains any + * external subset. Default is false. + */ + virtual void doctypeDecl + ( + const DTDElementDecl& elemDecl + , const XMLCh* const publicId + , const XMLCh* const systemId + , const bool hasIntSubset + , const bool hasExtSubset = false + ); + + /** + * This method is used to report any PI declarations + * occurring inside the DTD definition block. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param target A const pointer to a Unicode string representing the + * target of the PI declaration. + * @param data A const pointer to a Unicode string representing the + * data of the PI declaration. See the PI production rule + * in the XML specification for details. + */ + virtual void doctypePI + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * This method is used to report any whitespaces + * occurring inside the DTD definition block. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param chars A const pointer to a Unicode string representing the + * whitespace characters. + * @param length The length of the whitespace Unicode string. + */ + virtual void doctypeWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * This method is used to report an element declarations + * successfully scanned by the parser. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param decl A const reference to the object containing element + * declaration information. + * @param isIgnored The flag indicating whether this definition was + * ignored by the parser or not. + */ + virtual void elementDecl + ( + const DTDElementDecl& decl + , const bool isIgnored + ); + + /** + * This method is used to report the end of an attribute + * list declaration for an element. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param elemDecl A const reference to the object containing element + * declaration information. + */ + virtual void endAttList + ( + const DTDElementDecl& elemDecl + ); + + /** + * This method is used to report the end of the internal subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void endIntSubset(); + + /** + * This method is used to report the end of the external subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void endExtSubset(); + + /** + * This method is used to report any entity declarations. + * For unparsed entities, this driver will invoke the + * SAX DTDHandler::unparsedEntityDecl callback. + * + * @param entityDecl A const reference to the object containing + * the entity declaration information. + * @param isPEDecl The flag indicating whether this was a + * parameter entity declaration or not. + * @param isIgnored The flag indicating whether this definition + * was ignored by the parser or not. + * + * @see DTDHandler#unparsedEntityDecl + */ + virtual void entityDecl + ( + const DTDEntityDecl& entityDecl + , const bool isPEDecl + , const bool isIgnored + ); + + /** + * This method allows the user installed DTD handler to + * reset itself. + */ + virtual void resetDocType(); + + /** + * This method is used to report any notation declarations. + * If there is a user installed DTDHandler, then the driver will + * invoke the SAX DTDHandler::notationDecl callback. + * + * @param notDecl A const reference to the object containing the notation + * declaration information. + * @param isIgnored The flag indicating whether this definition was ignored + * by the parser or not. + * + * @see DTDHandler#notationDecl + */ + virtual void notationDecl + ( + const XMLNotationDecl& notDecl + , const bool isIgnored + ); + + /** + * This method is used to indicate the start of an element's attribute + * list declaration. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param elemDecl A const reference to the object containing element + * declaration information. + */ + virtual void startAttList + ( + const DTDElementDecl& elemDecl + ); + + /** + * This method is used indicate the start of the internal subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void startIntSubset(); + + /** + * This method is used indicate the start of the external subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void startExtSubset(); + + /** + * This method is used to report the TextDecl. Refer to the XML + * specification for the syntax of a TextDecl. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param versionStr A const pointer to a Unicode string representing + * the version number of the 'version' clause. + * @param encodingStr A const pointer to a Unicode string representing + * the encoding name of the 'encoding' clause. + */ + virtual void TextDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + ); + //@} + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SAX2XMLReaderImpl(const SAX2XMLReaderImpl&); + SAX2XMLReaderImpl& operator=(const SAX2XMLReaderImpl&); + + // ----------------------------------------------------------------------- + // Initialize/Cleanup methods + // ----------------------------------------------------------------------- + void initialize(); + void cleanUp(); + void resetInProgress(); + + // ----------------------------------------------------------------------- + // Private data members + // + // fAttrList + // A temporary implementation of the basic SAX2 Attributes + // interface. We use this one over and over on each startElement + // event to allow SAX-like access to the element attributes. + // + // fDocHandler + // The installed SAX content handler, if any. Null if none. + // + // fnamespacePrefix + // Indicates whether the namespace-prefix feature is on or off. + // + // fautoValidation + // Indicates whether automatic validation is on or off + // + // fValidation + // Indicates whether the 'validation' core features is on or off + // + // fReuseGrammar + // Tells the parser whether it should reuse the grammar or not. + // If true, there cannot be any internal subset. + // + // fPrefixesStorage + // the namespace prefixes will be allocated from this pool + // + // fPrefixes + // A Stack of the current namespace prefixes that need calls to + // endPrefixMapping + // + // fPrefixCounts + // A Stack of the number of prefixes that need endPrefixMapping + // calls for that element + // + // fDTDHandler + // The installed SAX DTD handler, if any. Null if none. + // + // fElemDepth + // This is used to track the element nesting depth, so that we can + // know when we are inside content. This is so we can ignore char + // data outside of content. + // + // fEntityResolver + // The installed SAX entity handler, if any. Null if none. + // + // fErrorHandler + // The installed SAX error handler, if any. Null if none. + // + // fLexicalHandler + // The installed SAX lexical handler, if any. Null if none. + // + // fDecllHandler + // The installed SAX declaration handler, if any. Null if none. + // + // fAdvDHCount + // fAdvDHList + // fAdvDHListSize + // This is an array of pointers to XMLDocumentHandlers, which is + // how we see installed advanced document handlers. There will + // usually not be very many at all, so a simple array is used + // instead of a collection, for performance. It will grow if needed, + // but that is unlikely. + // + // The count is how many handlers are currently installed. The size + // is how big the array itself is (for expansion purposes.) When + // count == size, is time to expand. + // + // fParseInProgress + // This flag is set once a parse starts. It is used to prevent + // multiple entrance or reentrance of the parser. + // + // fScanner + // The scanner being used by this parser. It is created internally + // during construction. + // + // fHasExternalSubset + // Indicate if the document has external DTD subset. + // + // fGrammarPool + // The grammar pool passed from external application (through derivatives). + // which could be 0, not owned. + // + // ----------------------------------------------------------------------- + bool fNamespacePrefix; + bool fAutoValidation; + bool fValidation; + bool fParseInProgress; + bool fHasExternalSubset; + XMLSize_t fElemDepth; + XMLSize_t fAdvDHCount; + XMLSize_t fAdvDHListSize; + VecAttributesImpl fAttrList ; + ContentHandler* fDocHandler ; + RefVectorOf* fTempAttrVec ; + XMLStringPool* fPrefixesStorage ; + ValueStackOf* fPrefixes ; + ValueStackOf* fPrefixCounts ; + XMLBuffer* fTempQName; + DTDHandler* fDTDHandler; + EntityResolver* fEntityResolver; + XMLEntityResolver* fXMLEntityResolver; + ErrorHandler* fErrorHandler; + PSVIHandler* fPSVIHandler; + LexicalHandler* fLexicalHandler; + DeclHandler* fDeclHandler; + XMLDocumentHandler** fAdvDHList; + XMLScanner* fScanner; + GrammarResolver* fGrammarResolver; + XMLStringPool* fURIStringPool; + XMLValidator* fValidator; + MemoryManager* fMemoryManager; + XMLGrammarPool* fGrammarPool; + + // ----------------------------------------------------------------------- + // internal function used to set the state of the parser + // ----------------------------------------------------------------------- + void setValidationScheme(const ValSchemes newScheme); + void setDoNamespaces(const bool newState); + bool getDoNamespaces() const; + void setDoSchema(const bool newState); + bool getDoSchema() const; +}; + + +// --------------------------------------------------------------------------- +// SAX2XMLReader: Getter methods +// --------------------------------------------------------------------------- +inline ContentHandler* SAX2XMLReaderImpl::getContentHandler() const +{ + return fDocHandler; +} + +inline DTDHandler* SAX2XMLReaderImpl::getDTDHandler() const +{ + return fDTDHandler ; +} + +inline EntityResolver* SAX2XMLReaderImpl::getEntityResolver() const +{ + return fEntityResolver; +} + +inline XMLEntityResolver* SAX2XMLReaderImpl::getXMLEntityResolver() const +{ + return fXMLEntityResolver; +} + +inline ErrorHandler* SAX2XMLReaderImpl::getErrorHandler() const +{ + return fErrorHandler; +} + +inline PSVIHandler* SAX2XMLReaderImpl::getPSVIHandler() const +{ + return fPSVIHandler; +} + +inline LexicalHandler* SAX2XMLReaderImpl::getLexicalHandler() const +{ + return fLexicalHandler; +} + +inline DeclHandler* SAX2XMLReaderImpl::getDeclarationHandler() const +{ + return fDeclHandler; +} + +inline bool SAX2XMLReaderImpl::getExitOnFirstFatalError() const +{ + return fScanner->getExitOnFirstFatal(); +} + +inline bool SAX2XMLReaderImpl::getValidationConstraintFatal() const +{ + return fScanner->getValidationConstraintFatal(); +} + +inline Grammar* SAX2XMLReaderImpl::getRootGrammar() +{ + return fScanner->getRootGrammar(); +} + +inline const XMLCh* SAX2XMLReaderImpl::getURIText(unsigned int uriId) const +{ + return fScanner->getURIText(uriId); +} + +inline XMLFilePos SAX2XMLReaderImpl::getSrcOffset() const +{ + return fScanner->getSrcOffset(); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/parsers/SAXParser.cpp b/include/xercesc/parsers/SAXParser.cpp new file mode 100644 index 0000000..1441fc5 --- /dev/null +++ b/include/xercesc/parsers/SAXParser.cpp @@ -0,0 +1,1351 @@ +/* + * 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: SAXParser.cpp 882548 2009-11-20 13:44:14Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// SAXParser: Constructors and Destructor +// --------------------------------------------------------------------------- + + +typedef JanitorMemFunCall CleanupType; +typedef JanitorMemFunCall ResetInProgressType; + + +SAXParser::SAXParser( XMLValidator* const valToAdopt + , MemoryManager* const manager + , XMLGrammarPool* const gramPool): + + fParseInProgress(false) + , fElemDepth(0) + , fAdvDHCount(0) + , fAdvDHListSize(32) + , fDocHandler(0) + , fDTDHandler(0) + , fEntityResolver(0) + , fXMLEntityResolver(0) + , fErrorHandler(0) + , fPSVIHandler(0) + , fAdvDHList(0) + , fScanner(0) + , fGrammarResolver(0) + , fURIStringPool(0) + , fValidator(valToAdopt) + , fMemoryManager(manager) + , fGrammarPool(gramPool) + , fElemQNameBuf(1023, manager) +{ + CleanupType cleanup(this, &SAXParser::cleanUp); + + try + { + initialize(); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +SAXParser::~SAXParser() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// SAXParser: Initialize/CleanUp methods +// --------------------------------------------------------------------------- +void SAXParser::initialize() +{ + // Create grammar resolver and string pool to pass to scanner + fGrammarResolver = new (fMemoryManager) GrammarResolver(fGrammarPool, fMemoryManager); + fURIStringPool = fGrammarResolver->getStringPool(); + + // Create our scanner and tell it what validator to use + fScanner = XMLScannerResolver::getDefaultScanner(fValidator, fGrammarResolver, fMemoryManager); + fScanner->setURIStringPool(fURIStringPool); + + // Create the initial advanced handler list array and zero it out + fAdvDHList = (XMLDocumentHandler**) fMemoryManager->allocate + ( + fAdvDHListSize * sizeof(XMLDocumentHandler*) + );//new XMLDocumentHandler*[fAdvDHListSize]; + memset(fAdvDHList, 0, sizeof(void*) * fAdvDHListSize); +} + +void SAXParser::cleanUp() +{ + fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList; + delete fScanner; + delete fGrammarResolver; + // grammar pool must do this + //delete fURIStringPool; + + if (fValidator) + delete fValidator; +} + + +// --------------------------------------------------------------------------- +// SAXParser: Advanced document handler list maintenance methods +// --------------------------------------------------------------------------- +void SAXParser::installAdvDocHandler(XMLDocumentHandler* const toInstall) +{ + // See if we need to expand and do so now if needed + if (fAdvDHCount == fAdvDHListSize) + { + // Calc a new size and allocate the new temp buffer + const XMLSize_t newSize = (XMLSize_t)(fAdvDHListSize * 1.5); + XMLDocumentHandler** newList = (XMLDocumentHandler**) fMemoryManager->allocate + ( + newSize * sizeof(XMLDocumentHandler*) + );//new XMLDocumentHandler*[newSize]; + + // Copy over the old data to the new list and zero out the rest + memcpy(newList, fAdvDHList, sizeof(void*) * fAdvDHListSize); + memset + ( + &newList[fAdvDHListSize] + , 0 + , sizeof(void*) * (newSize - fAdvDHListSize) + ); + + // And now clean up the old array and store the new stuff + fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList; + fAdvDHList = newList; + fAdvDHListSize = newSize; + } + + // Add this new guy into the empty slot + fAdvDHList[fAdvDHCount++] = toInstall; + + // + // Install ourself as the document handler with the scanner. We might + // already be, but its not worth checking, just do it. + // + fScanner->setDocHandler(this); +} + + +bool SAXParser::removeAdvDocHandler(XMLDocumentHandler* const toRemove) +{ + // If our count is zero, can't be any installed + if (!fAdvDHCount) + return false; + + // + // Search the array until we find this handler. If we find a null entry + // first, we can stop there before the list is kept contiguous. + // + XMLSize_t index; + for (index = 0; index < fAdvDHCount; index++) + { + // + // We found it. We have to keep the list contiguous, so we have to + // copy down any used elements after this one. + // + if (fAdvDHList[index] == toRemove) + { + // + // Optimize if only one entry (pretty common). Otherwise, we + // have to copy them down to compact them. + // + if (fAdvDHCount > 1) + { + index++; + while (index < fAdvDHCount) + fAdvDHList[index - 1] = fAdvDHList[index]; + } + + // Bump down the count and zero out the last one + fAdvDHCount--; + fAdvDHList[fAdvDHCount] = 0; + + // + // If this leaves us with no advanced handlers and there is + // no SAX doc handler installed on us, then remove us from the + // scanner as the document handler. + // + if (!fAdvDHCount && !fDocHandler) + fScanner->setDocHandler(0); + + return true; + } + } + + // Never found it + return false; +} + + +// --------------------------------------------------------------------------- +// SAXParser: Getter methods +// --------------------------------------------------------------------------- +const XMLValidator& SAXParser::getValidator() const +{ + return *fScanner->getValidator(); +} + + +bool SAXParser::getDoNamespaces() const +{ + return fScanner->getDoNamespaces(); +} + +bool SAXParser::getGenerateSyntheticAnnotations() const +{ + return fScanner->getGenerateSyntheticAnnotations(); +} + +bool SAXParser::getValidateAnnotations() const +{ + return fScanner->getValidateAnnotations(); +} + +bool SAXParser::getExitOnFirstFatalError() const +{ + return fScanner->getExitOnFirstFatal(); +} + +bool SAXParser::getValidationConstraintFatal() const +{ + return fScanner->getValidationConstraintFatal(); +} + + +SAXParser::ValSchemes SAXParser::getValidationScheme() const +{ + const XMLScanner::ValSchemes scheme = fScanner->getValidationScheme(); + + if (scheme == XMLScanner::Val_Always) + return Val_Always; + else if (scheme == XMLScanner::Val_Never) + return Val_Never; + + return Val_Auto; +} + +bool SAXParser::getDoSchema() const +{ + return fScanner->getDoSchema(); +} + +bool SAXParser::getValidationSchemaFullChecking() const +{ + return fScanner->getValidationSchemaFullChecking(); +} + +bool SAXParser::getIdentityConstraintChecking() const +{ + return fScanner->getIdentityConstraintChecking(); +} + +int SAXParser::getErrorCount() const +{ + return fScanner->getErrorCount(); +} + +XMLCh* SAXParser::getExternalSchemaLocation() const +{ + return fScanner->getExternalSchemaLocation(); +} + +XMLCh* SAXParser::getExternalNoNamespaceSchemaLocation() const +{ + return fScanner->getExternalNoNamespaceSchemaLocation(); +} + +SecurityManager* SAXParser::getSecurityManager() const +{ + return fScanner->getSecurityManager(); +} + +XMLSize_t SAXParser::getLowWaterMark() const +{ + return fScanner->getLowWaterMark(); +} + +bool SAXParser::getLoadExternalDTD() const +{ + return fScanner->getLoadExternalDTD(); +} + +bool SAXParser::getLoadSchema() const +{ + return fScanner->getLoadSchema(); +} + +bool SAXParser::isCachingGrammarFromParse() const +{ + return fScanner->isCachingGrammarFromParse(); +} + +bool SAXParser::isUsingCachedGrammarInParse() const +{ + return fScanner->isUsingCachedGrammarInParse(); +} + +bool SAXParser::getCalculateSrcOfs() const +{ + return fScanner->getCalculateSrcOfs(); +} + +bool SAXParser::getStandardUriConformant() const +{ + return fScanner->getStandardUriConformant(); +} + +Grammar* SAXParser::getGrammar(const XMLCh* const nameSpaceKey) +{ + return fGrammarResolver->getGrammar(nameSpaceKey); +} + +Grammar* SAXParser::getRootGrammar() +{ + return fScanner->getRootGrammar(); +} + +const XMLCh* SAXParser::getURIText(unsigned int uriId) const +{ + return fScanner->getURIText(uriId); +} + +XMLFilePos SAXParser::getSrcOffset() const +{ + return fScanner->getSrcOffset(); +} + +bool SAXParser::getIgnoreCachedDTD() const +{ + return fScanner->getIgnoreCachedDTD(); +} + +bool SAXParser::getIgnoreAnnotations() const +{ + return fScanner->getIgnoreAnnotations(); +} + +bool SAXParser::getDisableDefaultEntityResolution() const +{ + return fScanner->getDisableDefaultEntityResolution(); +} + +bool SAXParser::getSkipDTDValidation() const +{ + return fScanner->getSkipDTDValidation(); +} + +bool SAXParser::getHandleMultipleImports() const +{ + return fScanner->getHandleMultipleImports(); +} + +// --------------------------------------------------------------------------- +// SAXParser: Setter methods +// --------------------------------------------------------------------------- +void SAXParser::setDoNamespaces(const bool newState) +{ + fScanner->setDoNamespaces(newState); +} + +void SAXParser::setGenerateSyntheticAnnotations(const bool newState) +{ + fScanner->setGenerateSyntheticAnnotations(newState); +} + +void SAXParser::setValidateAnnotations(const bool newState) +{ + fScanner->setValidateAnnotations(newState); +} + +void SAXParser::setExitOnFirstFatalError(const bool newState) +{ + fScanner->setExitOnFirstFatal(newState); +} + + +void SAXParser::setValidationConstraintFatal(const bool newState) +{ + fScanner->setValidationConstraintFatal(newState); +} + + +void SAXParser::setValidationScheme(const ValSchemes newScheme) +{ + if (newScheme == Val_Never) + fScanner->setValidationScheme(XMLScanner::Val_Never); + else if (newScheme == Val_Always) + fScanner->setValidationScheme(XMLScanner::Val_Always); + else + fScanner->setValidationScheme(XMLScanner::Val_Auto); +} + +void SAXParser::setDoSchema(const bool newState) +{ + fScanner->setDoSchema(newState); +} + +void SAXParser::setValidationSchemaFullChecking(const bool schemaFullChecking) +{ + fScanner->setValidationSchemaFullChecking(schemaFullChecking); +} + +void SAXParser::setIdentityConstraintChecking(const bool identityConstraintChecking) +{ + fScanner->setIdentityConstraintChecking(identityConstraintChecking); +} + +void SAXParser::setExternalSchemaLocation(const XMLCh* const schemaLocation) +{ + fScanner->setExternalSchemaLocation(schemaLocation); +} +void SAXParser::setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation) +{ + fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation); +} + +void SAXParser::setExternalSchemaLocation(const char* const schemaLocation) +{ + fScanner->setExternalSchemaLocation(schemaLocation); +} +void SAXParser::setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation) +{ + fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation); +} + +void SAXParser::setSecurityManager(SecurityManager* const securityManager) +{ + // since this could impact various components, don't permit it to change + // during a parse + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + fScanner->setSecurityManager(securityManager); +} + +void SAXParser::setLowWaterMark(XMLSize_t lwm) +{ + fScanner->setLowWaterMark(lwm); +} + +void SAXParser::setLoadExternalDTD(const bool newState) +{ + fScanner->setLoadExternalDTD(newState); +} + +void SAXParser::setLoadSchema(const bool newState) +{ + fScanner->setLoadSchema(newState); +} + +void SAXParser::cacheGrammarFromParse(const bool newState) +{ + fScanner->cacheGrammarFromParse(newState); + + if (newState) + fScanner->useCachedGrammarInParse(newState); +} + +void SAXParser::useCachedGrammarInParse(const bool newState) +{ + if (newState || !fScanner->isCachingGrammarFromParse()) + fScanner->useCachedGrammarInParse(newState); +} + +void SAXParser::setCalculateSrcOfs(const bool newState) +{ + fScanner->setCalculateSrcOfs(newState); +} + +void SAXParser::setStandardUriConformant(const bool newState) +{ + fScanner->setStandardUriConformant(newState); +} + +void SAXParser::useScanner(const XMLCh* const scannerName) +{ + XMLScanner* tempScanner = XMLScannerResolver::resolveScanner + ( + scannerName + , fValidator + , fGrammarResolver + , fMemoryManager + ); + + if (tempScanner) { + + tempScanner->setParseSettings(fScanner); + tempScanner->setURIStringPool(fURIStringPool); + delete fScanner; + fScanner = tempScanner; + } +} + +void SAXParser::setInputBufferSize(const XMLSize_t bufferSize) +{ + fScanner->setInputBufferSize(bufferSize); +} + +void SAXParser::setIgnoreCachedDTD(const bool newValue) +{ + fScanner->setIgnoredCachedDTD(newValue); +} + +void SAXParser::setIgnoreAnnotations(const bool newValue) +{ + fScanner->setIgnoreAnnotations(newValue); +} + +void SAXParser::setDisableDefaultEntityResolution(const bool newValue) +{ + fScanner->setDisableDefaultEntityResolution(newValue); +} + +void SAXParser::setSkipDTDValidation(const bool newValue) +{ + fScanner->setSkipDTDValidation(newValue); +} + +void SAXParser::setHandleMultipleImports(const bool newValue) +{ + fScanner->setHandleMultipleImports(newValue); +} + +// --------------------------------------------------------------------------- +// SAXParser: Overrides of the SAX Parser interface +// --------------------------------------------------------------------------- +void SAXParser::parse(const InputSource& source) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAXParser::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(source); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void SAXParser::parse(const XMLCh* const systemId) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAXParser::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(systemId); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void SAXParser::parse(const char* const systemId) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAXParser::resetInProgress); + + try + { + fParseInProgress = true; + fScanner->scanDocument(systemId); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } +} + +void SAXParser::setDocumentHandler(DocumentHandler* const handler) +{ + fDocHandler = handler; + if (fDocHandler) + { + // + // Make sure we are set as the document handler with the scanner. + // We may already be (if advanced handlers are installed), but its + // not worthing checking, just do it. + // + fScanner->setDocHandler(this); + } + else + { + // + // If we don't have any advanced handlers either, then deinstall us + // from the scanner because we don't need document events anymore. + // + if (!fAdvDHCount) + fScanner->setDocHandler(0); + } +} + + +void SAXParser::setDTDHandler(DTDHandler* const handler) +{ + fDTDHandler = handler; + if (fDTDHandler) + fScanner->setDocTypeHandler(this); + else + fScanner->setDocTypeHandler(0); +} + + +void SAXParser::setErrorHandler(ErrorHandler* const handler) +{ + // + // Store the handler. Then either install or deinstall us as the + // error reporter on the scanner. + // + fErrorHandler = handler; + if (fErrorHandler) { + fScanner->setErrorReporter(this); + fScanner->setErrorHandler(fErrorHandler); + } + else { + fScanner->setErrorReporter(0); + fScanner->setErrorHandler(0); + } +} + + +void SAXParser::setPSVIHandler(PSVIHandler* const handler) +{ + fPSVIHandler = handler; + if (fPSVIHandler) { + fScanner->setPSVIHandler(fPSVIHandler); + } + else { + fScanner->setPSVIHandler(0); + } +} + +void SAXParser::setEntityResolver(EntityResolver* const resolver) +{ + fEntityResolver = resolver; + if (fEntityResolver) { + fScanner->setEntityHandler(this); + fXMLEntityResolver = 0; + } + else { + fScanner->setEntityHandler(0); + } +} + +void SAXParser::setXMLEntityResolver(XMLEntityResolver* const resolver) +{ + fXMLEntityResolver = resolver; + if (fXMLEntityResolver) { + fScanner->setEntityHandler(this); + fEntityResolver = 0; + } + else { + fScanner->setEntityHandler(0); + } +} + +// --------------------------------------------------------------------------- +// SAXParser: Progressive parse methods +// --------------------------------------------------------------------------- +bool SAXParser::parseFirst( const XMLCh* const systemId + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(systemId, toFill); +} + +bool SAXParser::parseFirst( const char* const systemId + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(systemId, toFill); +} + +bool SAXParser::parseFirst( const InputSource& source + , XMLPScanToken& toFill) +{ + // + // Avoid multiple entrance. We cannot enter here while a regular parse + // is in progress. + // + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + return fScanner->scanFirst(source, toFill); +} + +bool SAXParser::parseNext(XMLPScanToken& token) +{ + return fScanner->scanNext(token); +} + +void SAXParser::parseReset(XMLPScanToken& token) +{ + // Reset the scanner + fScanner->scanReset(token); +} + + +// --------------------------------------------------------------------------- +// SAXParser: Overrides of the XMLDocumentHandler interface +// --------------------------------------------------------------------------- +void SAXParser::docCharacters( const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + // Suppress the chars before the root element. + if (fElemDepth) + { + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->characters(chars, length); + } + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->docCharacters(chars, length, cdataSection); +} + + +void SAXParser::docComment(const XMLCh* const commentText) +{ + // + // SAX has no way to report this. But, if there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->docComment(commentText); +} + + +void SAXParser::XMLDecl( const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncodingStr + ) +{ + // + // SAX has no way to report this. But, if there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->XMLDecl( versionStr, + encodingStr, + standaloneStr, + actualEncodingStr ); +} + + +void SAXParser::docPI( const XMLCh* const target + , const XMLCh* const data) +{ + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->processingInstruction(target, data); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->docPI(target, data); +} + + +void SAXParser::endDocument() +{ + if (fDocHandler) + fDocHandler->endDocument(); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->endDocument(); +} + + +void SAXParser::endElement( const XMLElementDecl& elemDecl + , const unsigned int uriId + , const bool isRoot + , const XMLCh* const elemPrefix) +{ + // Just map to the SAX document handler + if (fDocHandler) { + if (fScanner->getDoNamespaces()) { + + if (elemPrefix && *elemPrefix) { + + fElemQNameBuf.set(elemPrefix); + fElemQNameBuf.append(chColon); + fElemQNameBuf.append(elemDecl.getBaseName()); + fDocHandler->endElement(fElemQNameBuf.getRawBuffer()); + } + else { + fDocHandler->endElement(elemDecl.getBaseName()); + } + } + else + fDocHandler->endElement(elemDecl.getFullName()); + + } + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->endElement(elemDecl, uriId, isRoot, elemPrefix); + + // + // Dump the element depth down again. Don't let it underflow in case + // of malformed XML. + // + if (fElemDepth) + fElemDepth--; +} + + +void SAXParser::endEntityReference(const XMLEntityDecl& entityDecl) +{ + // + // SAX has no way to report this event. But, if there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->endEntityReference(entityDecl); +} + + +void SAXParser::ignorableWhitespace(const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + // Do not report the whitespace before the root element. + if (!fElemDepth) + return; + + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->ignorableWhitespace(chars, length); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->ignorableWhitespace(chars, length, cdataSection); +} + + +void SAXParser::resetDocument() +{ + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->resetDocument(); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->resetDocument(); + + // Make sure our element depth flag gets set back to zero + fElemDepth = 0; +} + + +void SAXParser::startDocument() +{ + // Just map to the SAX document handler + if (fDocHandler) + fDocHandler->setDocumentLocator(fScanner->getLocator()); + if(fDocHandler) + fDocHandler->startDocument(); + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->startDocument(); +} + + +void SAXParser:: +startElement( const XMLElementDecl& elemDecl + , const unsigned int elemURLId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot) +{ + // Bump the element depth counter if not empty + if (!isEmpty) + fElemDepth++; + + if (fDocHandler) + { + fAttrList.setVector(&attrList, attrCount); + if (fScanner->getDoNamespaces()) { + + if (elemPrefix && *elemPrefix) { + + fElemQNameBuf.set(elemPrefix); + fElemQNameBuf.append(chColon); + fElemQNameBuf.append(elemDecl.getBaseName()); + fDocHandler->startElement(fElemQNameBuf.getRawBuffer(), fAttrList); + + // If its empty, send the end tag event now + if (isEmpty && fDocHandler) + fDocHandler->endElement(fElemQNameBuf.getRawBuffer()); + } + else { + + fDocHandler->startElement(elemDecl.getBaseName(), fAttrList); + + // If its empty, send the end tag event now + if (isEmpty && fDocHandler) + fDocHandler->endElement(elemDecl.getBaseName()); + } + } + else { + fDocHandler->startElement(elemDecl.getFullName(), fAttrList); + + // If its empty, send the end tag event now + if (isEmpty && fDocHandler) + fDocHandler->endElement(elemDecl.getFullName()); + } + } + + // + // If there are any installed advanced handlers, then lets call them + // with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + { + fAdvDHList[index]->startElement + ( + elemDecl + , elemURLId + , elemPrefix + , attrList + , attrCount + , isEmpty + , isRoot + ); + } +} + + +void SAXParser::startEntityReference(const XMLEntityDecl& entityDecl) +{ + // + // SAX has no way to report this. But, If there are any installed + // advanced handlers, then lets call them with this info. + // + for (XMLSize_t index = 0; index < fAdvDHCount; index++) + fAdvDHList[index]->startEntityReference(entityDecl); +} + + + +// --------------------------------------------------------------------------- +// SAXParser: Overrides of the DocTypeHandler interface +// --------------------------------------------------------------------------- +void SAXParser::attDef( const DTDElementDecl& + , const DTDAttDef& + , const bool) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::doctypeComment(const XMLCh* const) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::doctypeDecl(const DTDElementDecl& + , const XMLCh* const + , const XMLCh* const + , const bool + , const bool) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::doctypePI( const XMLCh* const + , const XMLCh* const) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::doctypeWhitespace( const XMLCh* const + , const XMLSize_t) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::elementDecl(const DTDElementDecl&, const bool) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::endAttList(const DTDElementDecl&) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::endIntSubset() +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::endExtSubset() +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::entityDecl( const DTDEntityDecl& entityDecl + , const bool + , const bool isIgnored) +{ + // + // If we have a DTD handler, and this entity is not ignored, and + // its an unparsed entity, then send this one. + // + if (fDTDHandler && !isIgnored) + { + if (entityDecl.isUnparsed()) + { + fDTDHandler->unparsedEntityDecl + ( + entityDecl.getName() + , entityDecl.getPublicId() + , entityDecl.getSystemId() + , entityDecl.getNotationName() + ); + } + } +} + + +void SAXParser::resetDocType() +{ + // Just map to the DTD handler + if (fDTDHandler) + fDTDHandler->resetDocType(); +} + + +void SAXParser::notationDecl( const XMLNotationDecl& notDecl + , const bool isIgnored) +{ + if (fDTDHandler && !isIgnored) + { + fDTDHandler->notationDecl + ( + notDecl.getName() + , notDecl.getPublicId() + , notDecl.getSystemId() + ); + } +} + + +void SAXParser::startAttList(const DTDElementDecl&) +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::startIntSubset() +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::startExtSubset() +{ + // Unused by SAX DTDHandler interface at this time +} + + +void SAXParser::TextDecl( const XMLCh* const + , const XMLCh* const) +{ + // Unused by SAX DTDHandler interface at this time +} + + +// --------------------------------------------------------------------------- +// SAXParser: Overrides of the XMLErrorReporter interface +// --------------------------------------------------------------------------- +void SAXParser::resetErrors() +{ + if (fErrorHandler) + fErrorHandler->resetErrors(); +} + + +void SAXParser::error( const unsigned int + , const XMLCh* const + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum) +{ + SAXParseException toThrow = SAXParseException + ( + errorText + , publicId + , systemId + , lineNum + , colNum + , fMemoryManager + ); + + if (!fErrorHandler) + { + if (errType == XMLErrorReporter::ErrType_Fatal) + throw toThrow; + else + return; + } + + if (errType == XMLErrorReporter::ErrType_Warning) + fErrorHandler->warning(toThrow); + else if (errType == XMLErrorReporter::ErrType_Fatal) + fErrorHandler->fatalError(toThrow); + else + fErrorHandler->error(toThrow); +} + + + +// --------------------------------------------------------------------------- +// SAXParser: Handlers for the XMLEntityHandler interface +// --------------------------------------------------------------------------- +void SAXParser::endInputSource(const InputSource&) +{ +} + +bool SAXParser::expandSystemId(const XMLCh* const, XMLBuffer&) +{ + return false; +} + + +void SAXParser::resetEntities() +{ + // Nothing to do for this one +} + +InputSource* +SAXParser::resolveEntity( XMLResourceIdentifier* resourceIdentifier ) +{ + // Just map to the SAX entity resolver handler + if (fEntityResolver) + return fEntityResolver->resolveEntity(resourceIdentifier->getPublicId(), + resourceIdentifier->getSystemId()); + if (fXMLEntityResolver) + return fXMLEntityResolver->resolveEntity(resourceIdentifier); + return 0; +} + + +void SAXParser::startInputSource(const InputSource&) +{ + // Nothing to do for this one +} + + +// --------------------------------------------------------------------------- +// SAXParser: Grammar preparsing methods +// --------------------------------------------------------------------------- +Grammar* SAXParser::loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAXParser::resetInProgress); + + Grammar* grammar = 0; + try + { + fParseInProgress = true; + grammar = fScanner->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } + + return grammar; +} + +Grammar* SAXParser::loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAXParser::resetInProgress); + + Grammar* grammar = 0; + try + { + fParseInProgress = true; + grammar = fScanner->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } + + return grammar; +} + +Grammar* SAXParser::loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (fParseInProgress) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetInProgressType resetInProgress(this, &SAXParser::resetInProgress); + + Grammar* grammar = 0; + try + { + fParseInProgress = true; + grammar = fScanner->loadGrammar(source, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetInProgress.release(); + + throw; + } + + return grammar; +} + +void SAXParser::resetInProgress() +{ + fParseInProgress = false; +} + +void SAXParser::resetCachedGrammarPool() +{ + fGrammarResolver->resetCachedGrammar(); + fScanner->resetCachedGrammar(); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/parsers/SAXParser.hpp b/include/xercesc/parsers/SAXParser.hpp new file mode 100644 index 0000000..683ab6f --- /dev/null +++ b/include/xercesc/parsers/SAXParser.hpp @@ -0,0 +1,2204 @@ +/* + * 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: SAXParser.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAXPARSER_HPP) +#define XERCESC_INCLUDE_GUARD_SAXPARSER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + + +class DocumentHandler; +class EntityResolver; +class XMLPScanToken; +class XMLScanner; +class XMLValidator; +class GrammarResolver; +class XMLGrammarPool; +class XMLEntityResolver; +class XMLResourceIdentifier; +class PSVIHandler; + +/** + * This class implements the SAX 'Parser' interface and should be + * used by applications wishing to parse the XML files using SAX. + * It allows the client program to install SAX handlers for event + * callbacks. + * + *

It can be used to instantiate a validating or non-validating + * parser, by setting a member flag.

+ * + * @deprecated This interface has been replaced by the SAX2 + * interface, which includes Namespace support. + * See SAX2XMLReader for more information. + * + * Note - XMLDocumentHandler calls, when used with SAXParser, will not provide correct namespace information. This is becaue the SAX parser does not support namespace aware processing. + * + * + */ + +class PARSERS_EXPORT SAXParser : + + public XMemory + , public Parser + , public XMLDocumentHandler + , public XMLErrorReporter + , public XMLEntityHandler + , public DocTypeHandler +{ +public : + // ----------------------------------------------------------------------- + // Class types + // ----------------------------------------------------------------------- + /** ValScheme enum used in setValidationScheme + * Val_Never: Do not report validation errors. + * Val_Always: The parser will always report validation errors. + * Val_Auto: The parser will report validation errors only if a grammar is specified. + * + * @see #setValidationScheme + */ + + enum ValSchemes + { + Val_Never + , Val_Always + , Val_Auto + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** Constructor with an instance of validator class to use for + * validation. + * @param valToAdopt Pointer to the validator instance to use. The + * parser is responsible for freeing the memory. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + * @param gramPool The collection of cached grammars. + */ + SAXParser + ( + XMLValidator* const valToAdopt = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ); + + /** + * Destructor + */ + ~SAXParser(); + //@} + + + // ----------------------------------------------------------------------- + // Getter Methods + // ----------------------------------------------------------------------- + /** @name Getter methods */ + //@{ + /** + * This method returns the installed document handler. Suitable + * for 'lvalue' usages. + * + * @return The pointer to the installed document handler object. + */ + DocumentHandler* getDocumentHandler(); + + /** + * This method returns the installed document handler. Suitable + * only for 'rvalue' usages. + * + * @return A const pointer to the installed document handler object. + */ + const DocumentHandler* getDocumentHandler() const; + + /** + * This method returns the installed entity resolver. Suitable + * for 'lvalue' usages. + * + * @return The pointer to the installed entity resolver object. + */ + EntityResolver* getEntityResolver(); + + /** + * This method returns the installed entity resolver. Suitable + * for 'rvalue' usages. + * + * @return A const pointer to the installed entity resolver object. + */ + const EntityResolver* getEntityResolver() const; + + /** + * This method returns the installed entity resolver. Suitable + * for 'lvalue' usages. + * + * @return The pointer to the installed entity resolver object. + */ + XMLEntityResolver* getXMLEntityResolver(); + + /** + * This method returns the installed entity resolver. Suitable + * for 'rvalue' usages. + * + * @return A const pointer to the installed entity resolver object. + */ + const XMLEntityResolver* getXMLEntityResolver() const; + + /** + * This method returns the installed error handler. Suitable + * for 'lvalue' usages. + * + * @return The pointer to the installed error handler object. + */ + ErrorHandler* getErrorHandler(); + + /** + * This method returns the installed error handler. Suitable + * for 'rvalue' usages. + * + * @return A const pointer to the installed error handler object. + */ + const ErrorHandler* getErrorHandler() const; + + /** + * This method returns the installed PSVI handler. Suitable + * for 'lvalue' usages. + * + * @return The pointer to the installed PSVI handler object. + */ + PSVIHandler* getPSVIHandler(); + + /** + * This method returns the installed PSVI handler. Suitable + * for 'rvalue' usages. + * + * @return A const pointer to the installed PSVI handler object. + */ + const PSVIHandler* getPSVIHandler() const; + + /** + * This method returns a reference to the parser's installed + * validator. + * + * @return A const reference to the installed validator object. + */ + const XMLValidator& getValidator() const; + + /** + * This method returns an enumerated value that indicates the current + * validation scheme set on this parser. + * + * @return The ValSchemes value current set on this parser. + * @see #setValidationScheme + */ + ValSchemes getValidationScheme() const; + + /** Get the 'do schema' flag + * + * This method returns the state of the parser's schema processing + * flag. + * + * @return true, if the parser is currently configured to + * understand schema, false otherwise. + * + * @see #setDoSchema + */ + bool getDoSchema() const; + + /** Get the 'full schema constraint checking' flag + * + * This method returns the state of the parser's full schema constraint + * checking flag. + * + * @return true, if the parser is currently configured to + * have full schema constraint checking, false otherwise. + * + * @see #setValidationSchemaFullChecking + */ + bool getValidationSchemaFullChecking() const; + + /** Get the 'identity constraint checking' flag + * + * This method returns the state of the parser's identity constraint + * checking flag. + * + * @return true, if the parser is currently configured to + * have identity constraint checking, false otherwise. + * + * @see #setIdentityConstraintChecking + */ + bool getIdentityConstraintChecking() const; + + /** Get error count from the last parse operation. + * + * This method returns the error count from the last parse + * operation. Note that this count is actually stored in the + * scanner, so this method simply returns what the + * scanner reports. + * + * @return number of errors encountered during the latest + * parse operation. + */ + int getErrorCount() const; + + /** + * This method returns the state of the parser's namespace + * handling capability. + * + * @return true, if the parser is currently configured to + * understand namespaces, false otherwise. + * + * @see #setDoNamespaces + */ + bool getDoNamespaces() const; + + /** + * This method returns the state of the parser's + * exit-on-First-Fatal-Error flag. + * + * @return true, if the parser is currently configured to + * exit on the first fatal error, false otherwise. + * + * @see #setExitOnFirstFatalError + */ + bool getExitOnFirstFatalError() const; + + /** + * This method returns the state of the parser's + * validation-constraint-fatal flag. + * + * @return true, if the parser is currently configured to + * set validation constraint errors as fatal, false + * otherwise. + * + * @see #setValidationConstraintFatal + */ + bool getValidationConstraintFatal() const; + + /** Get the set of Namespace/SchemaLocation that is specified externally. + * + * This method returns the list of Namespace/SchemaLocation that was + * specified using setExternalSchemaLocation. + * + * The parser owns the returned string, and the memory allocated for + * the returned string will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else. + * + * @return a pointer to the list of Namespace/SchemaLocation that was + * specified externally. The pointer spans the same life-time as + * the parser. A null pointer is returned if nothing + * was specified externally. + * + * @see #setExternalSchemaLocation(const XMLCh* const) + */ + XMLCh* getExternalSchemaLocation() const; + + /** Get the noNamespace SchemaLocation that is specified externally. + * + * This method returns the no target namespace XML Schema Location + * that was specified using setExternalNoNamespaceSchemaLocation. + * + * The parser owns the returned string, and the memory allocated for + * the returned string will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else. + * + * @return a pointer to the no target namespace Schema Location that was + * specified externally. The pointer spans the same life-time as + * the parser. A null pointer is returned if nothing + * was specified externally. + * + * @see #setExternalNoNamespaceSchemaLocation(const XMLCh* const) + */ + XMLCh* getExternalNoNamespaceSchemaLocation() const; + + /** Get the SecurityManager instance attached to this parser. + * + * This method returns the security manager + * that was specified using setSecurityManager. + * + * The SecurityManager instance must have been specified by the application; + * this should not be deleted until after the parser has been deleted (or + * a new SecurityManager instance has been supplied to the parser). + * + * @return a pointer to the SecurityManager instance + * specified externally. A null pointer is returned if nothing + * was specified externally. + * + * @see #setSecurityManager(SecurityManager* const) + */ + SecurityManager* getSecurityManager() const; + + /** Get the raw buffer low water mark for this parser. + * + * If the number of available bytes in the raw buffer is less than + * the low water mark the parser will attempt to read more data before + * continuing parsing. By default the value for this parameter is 100 + * bytes. You may want to set this parameter to 0 if you would like + * the parser to parse the available data immediately without + * potentially blocking while waiting for more date. + * + * @return current low water mark + * + * @see #setSecurityManager + */ + XMLSize_t getLowWaterMark() const; + + /** Get the 'Loading External DTD' flag + * + * This method returns the state of the parser's loading external DTD + * flag. + * + * @return false, if the parser is currently configured to + * ignore external DTD completely, true otherwise. + * + * @see #setLoadExternalDTD + * @see #getValidationScheme + */ + bool getLoadExternalDTD() const; + + /** Get the 'Loading Schema' flag + * + * This method returns the state of the parser's loading schema + * flag. + * + * @return true, if the parser is currently configured to + * automatically load schemas that are not in the + * grammar pool, false otherwise. + * + * @see #setLoadSchema + */ + bool getLoadSchema() const; + + /** Get the 'Grammar caching' flag + * + * This method returns the state of the parser's grammar caching when + * parsing an XML document. + * + * @return true, if the parser is currently configured to + * cache grammars, false otherwise. + * + * @see #cacheGrammarFromParse + */ + bool isCachingGrammarFromParse() const; + + /** Get the 'Use cached grammar' flag + * + * This method returns the state of the parser's use of cached grammar + * when parsing an XML document. + * + * @return true, if the parser is currently configured to + * use cached grammars, false otherwise. + * + * @see #useCachedGrammarInParse + */ + bool isUsingCachedGrammarInParse() const; + + /** + * Get the 'calculate src offset flag' + * + * This method returns the state of the parser's src offset calculation + * when parsing an XML document. + * + * @return true, if the parser is currently configured to + * calculate src offsets, false otherwise. + * + * @see #setCalculateSrcOfs + */ + bool getCalculateSrcOfs() const; + + /** + * Get the 'force standard uri flag' + * + * This method returns the state if the parser forces standard uri + * + * @return true, if the parser is currently configured to + * force standard uri, i.e. malformed uri will be rejected. + * + * @see #setStandardUriConformant + */ + bool getStandardUriConformant() const; + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + Grammar* getGrammar(const XMLCh* const nameSpaceKey); + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + Grammar* getRootGrammar(); + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + const XMLCh* getURIText(unsigned int uriId) const; + + /** + * Returns the current src offset within the input source. + * To be used only while parsing is in progress. + * + * @return offset within the input source + */ + XMLFilePos getSrcOffset() const; + + /** Get the 'generate synthetic annotations' flag + * + * @return true, if the parser is currently configured to + * generate synthetic annotations, false otherwise. + * A synthetic XSAnnotation is created when a schema + * component has non-schema attributes but has no + * child annotations so that the non-schema attributes + * can be recovered under PSVI. + * + * @see #setGenerateSyntheticAnnotations + */ + bool getGenerateSyntheticAnnotations() const; + + /** Get the 'validate annotations' flag + * + * @return true, if the parser is currently configured to + * validate annotations, false otherwise. + * + * @see #setValidateAnnotations + */ + bool getValidateAnnotations() const; + + /** Get the 'ignore cached DTD grammar' flag + * + * @return true, if the parser is currently configured to + * ignore cached DTD, false otherwise. + * + * @see #setIgnoreCachedDTD + */ + bool getIgnoreCachedDTD() const; + + /** Get the 'ignore annotations' flag + * + * @return true, if the parser is currently configured to + * ignore annotations, false otherwise. + * + * @see #setIgnoreAnnotations + */ + bool getIgnoreAnnotations() const; + + /** Get the 'disable default entity resolution' flag + * + * @return true, if the parser is currently configured to + * not perform default entity resolution, false otherwise. + * + * @see #setDisableDefaultEntityResolution + */ + bool getDisableDefaultEntityResolution() const; + + /** Get the 'skip DTD validation' flag + * + * @return true, if the parser is currently configured to + * skip DTD validation, false otherwise. + * + * @see #setSkipDTDValidation + */ + bool getSkipDTDValidation() const; + + /** Get the 'handle multiple schema imports' flag + * + * @return true, if the parser is currently configured to + * import multiple schemas with the same namespace, false otherwise. + * + * @see #setHandleMultipleImports + */ + bool getHandleMultipleImports() const; + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + /** set the 'generate synthetic annotations' flag + * + * @param newValue The value for specifying whether Synthetic Annotations + * should be generated or not. + * A synthetic XSAnnotation is created when a schema + * component has non-schema attributes but has no + * child annotations. + * + * @see #getGenerateSyntheticAnnotations + */ + void setGenerateSyntheticAnnotations(const bool newValue); + + /** set the 'validate annotations' flag + * + * @param newValue The value for specifying whether annotations + * should be validate or not. + * + * @see #getValidateAnnotations + */ + void setValidateAnnotations(const bool newValue); + + /** + * This method allows users to enable or disable the parser's + * namespace processing. When set to true, parser starts enforcing + * all the constraints / rules specified by the NameSpace + * specification. + * + *

The parser's default state is: false.

+ * + * @param newState The value specifying whether NameSpace rules should + * be enforced or not. + * + * @see #getDoNamespaces + */ + void setDoNamespaces(const bool newState); + + /** + * This method allows users to set the validation scheme to be used + * by this parser. The value is one of the ValSchemes enumerated values + * defined by this class: + * + *
Val_Never - turn off validation + *
Val_Always - turn on validation + *
Val_Auto - turn on validation if any internal/external + * DTD subset have been seen + * + *

The parser's default state is: Val_Never.

+ * + * @param newScheme The new validation scheme to use. + * + * @see #getValidationScheme + */ + void setValidationScheme(const ValSchemes newScheme); + + /** Set the 'schema support' flag + * + * This method allows users to enable or disable the parser's + * schema processing. When set to false, parser will not process + * any schema found. + * + * The parser's default state is: false. + * + * Note: If set to true, namespace processing must also be turned on. + * + * @param newState The value specifying whether schema support should + * be enforced or not. + * + * @see #getDoSchema + */ + void setDoSchema(const bool newState); + + /** + * This method allows the user to turn full Schema constraint checking on/off. + * Only takes effect if Schema validation is enabled. + * If turned off, partial constraint checking is done. + * + * Full schema constraint checking includes those checking that may + * be time-consuming or memory intensive. Currently, particle unique + * attribution constraint checking and particle derivation restriction checking + * are controlled by this option. + * + * The parser's default state is: false. + * + * @param schemaFullChecking True to turn on full schema constraint checking. + * + * @see #getValidationSchemaFullChecking + */ + void setValidationSchemaFullChecking(const bool schemaFullChecking); + + /** + * This method allows the user to turn identity constraint checking on/off. + * Only takes effect if Schema validation is enabled. + * If turned off, identity constraint checking is not done. + * + * The parser's default state is: true. + * + * @param identityConstraintChecking True to turn on identity constraint checking. + * + * @see #getIdentityConstraintChecking + */ + void setIdentityConstraintChecking(const bool identityConstraintChecking); + + /** + * This method allows users to set the parser's behaviour when it + * encounters the first fatal error. If set to true, the parser + * will exit at the first fatal error. If false, then it will + * report the error and continue processing. + * + *

The default value is 'true' and the parser exits on the + * first fatal error.

+ * + * @param newState The value specifying whether the parser should + * continue or exit when it encounters the first + * fatal error. + * + * @see #getExitOnFirstFatalError + */ + void setExitOnFirstFatalError(const bool newState); + + /** + * This method allows users to set the parser's behaviour when it + * encounters a validation constraint error. If set to true, and the + * the parser will treat validation error as fatal and will exit depends on the + * state of "getExitOnFirstFatalError". If false, then it will + * report the error and continue processing. + * + * Note: setting this true does not mean the validation error will be printed with + * the word "Fatal Error". It is still printed as "Error", but the parser + * will exit if "setExitOnFirstFatalError" is set to true. + * + *

The default value is 'false'.

+ * + * @param newState If true, the parser will exit if "setExitOnFirstFatalError" + * is set to true. + * + * @see #getValidationConstraintFatal + * @see #setExitOnFirstFatalError + */ + void setValidationConstraintFatal(const bool newState); + + /** + * This method allows the user to specify a list of schemas to use. + * If the targetNamespace of a schema specified using this method matches + * the targetNamespace of a schema occurring in the instance document in + * the schemaLocation attribute, or if the targetNamespace matches the + * namespace attribute of the "import" element, the schema specified by the + * user using this method will be used (i.e., the schemaLocation attribute + * in the instance document or on the "import" element will be effectively ignored). + * + * If this method is called more than once, only the last one takes effect. + * + * The syntax is the same as for schemaLocation attributes in instance + * documents: e.g, "http://www.example.com file_name.xsd". The user can + * specify more than one XML Schema in the list. + * + * @param schemaLocation the list of schemas to use + * + * @see #getExternalSchemaLocation + */ + + void setExternalSchemaLocation(const XMLCh* const schemaLocation); + + /** + * This method is same as setExternalSchemaLocation(const XMLCh* const). + * It takes native char string as parameter + * + * @param schemaLocation the list of schemas to use + * + * @see #setExternalSchemaLocation(const XMLCh* const) + */ + void setExternalSchemaLocation(const char* const schemaLocation); + + /** + * This method allows the user to specify the no target namespace XML + * Schema Location externally. If specified, the instance document's + * noNamespaceSchemaLocation attribute will be effectively ignored. + * + * If this method is called more than once, only the last one takes effect. + * + * The syntax is the same as for the noNamespaceSchemaLocation attribute + * that may occur in an instance document: e.g."file_name.xsd". + * + * @param noNamespaceSchemaLocation the XML Schema Location with no target namespace + * + * @see #getExternalNoNamespaceSchemaLocation + */ + void setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation); + + /** + * This method is same as setExternalNoNamespaceSchemaLocation(const XMLCh* const). + * It takes native char string as parameter + * + * @param noNamespaceSchemaLocation the XML Schema Location with no target namespace + * + * @see #setExternalNoNamespaceSchemaLocation(const XMLCh* const) + */ + void setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation); + + /** + * This allows an application to set a SecurityManager on + * the parser; this object stores information that various + * components use to limit their consumption of system + * resources while processing documents. + * + * If this method is called more than once, only the last one takes effect. + * It may not be reset during a parse. + * + * + * @param securityManager the SecurityManager instance to + * be used by this parser + * + * @see #getSecurityManager + */ + void setSecurityManager(SecurityManager* const securityManager); + + /** Set the raw buffer low water mark for this parser. + * + * If the number of available bytes in the raw buffer is less than + * the low water mark the parser will attempt to read more data before + * continuing parsing. By default the value for this parameter is 100 + * bytes. You may want to set this parameter to 0 if you would like + * the parser to parse the available data immediately without + * potentially blocking while waiting for more date. + * + * @param lwm new low water mark + * + * @see #getSecurityManager + */ + void setLowWaterMark(XMLSize_t lwm); + + /** Set the 'Loading External DTD' flag + * + * This method allows users to enable or disable the loading of external DTD. + * When set to false, the parser will ignore any external DTD completely + * if the validationScheme is set to Val_Never. + * + * The parser's default state is: true. + * + * This flag is ignored if the validationScheme is set to Val_Always or Val_Auto. + * + * @param newState The value specifying whether external DTD should + * be loaded or not. + * + * @see #getLoadExternalDTD + * @see #setValidationScheme + */ + void setLoadExternalDTD(const bool newState); + + /** Set the 'Loading Schema' flag + * + * This method allows users to enable or disable the loading of schemas. + * When set to false, the parser not attempt to load schemas beyond + * querying the grammar pool for them. + * + * The parser's default state is: true. + * + * @param newState The value specifying whether schemas should + * be loaded if they're not found in the grammar + * pool. + * + * @see #getLoadSchema + * @see #setDoSchema + */ + void setLoadSchema(const bool newState); + + /** Set the 'Grammar caching' flag + * + * This method allows users to enable or disable caching of grammar when + * parsing XML documents. When set to true, the parser will cache the + * resulting grammar for use in subsequent parses. + * + * If the flag is set to true, the 'Use cached grammar' flag will also be + * set to true. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether we should cache grammars + * or not. + * + * @see #isCachingGrammarFromParse + * @see #useCachedGrammarInParse + */ + void cacheGrammarFromParse(const bool newState); + + /** Set the 'Use cached grammar' flag + * + * This method allows users to enable or disable the use of cached + * grammars. When set to true, the parser will use the cached grammar, + * instead of building the grammar from scratch, to validate XML + * documents. + * + * If the 'Grammar caching' flag is set to true, this method ignores the + * value passed in. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether we should use the cached + * grammar or not. + * + * @see #isUsingCachedGrammarInParse + * @see #cacheGrammarFromParse + */ + void useCachedGrammarInParse(const bool newState); + + /** Enable/disable src offset calculation + * + * This method allows users to enable/disable src offset calculation. + * Disabling the calculation will improve performance. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether we should enable or + * disable src offset calculation + * + * @see #getCalculateSrcOfs + */ + void setCalculateSrcOfs(const bool newState); + + /** Force standard uri + * + * This method allows users to tell the parser to force standard uri conformance. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether the parser should reject malformed URI. + * + * @see #getStandardUriConformant + */ + void setStandardUriConformant(const bool newState); + + /** Set the scanner to use when scanning the XML document + * + * This method allows users to set the scanner to use + * when scanning a given XML document. + * + * @param scannerName The name of the desired scanner + */ + void useScanner(const XMLCh* const scannerName); + + /** Set maximum input buffer size + * + * This method allows users to limit the size of buffers used in parsing + * XML character data. The effect of setting this size is to limit the + * size of a ContentHandler::characters() call. + * + * The parser's default input buffer size is 1 megabyte. + * + * @param bufferSize The maximum input buffer size + */ + void setInputBufferSize(const XMLSize_t bufferSize); + + /** Set the 'ignore cached DTD grammar' flag + * + * This method gives users the option to ignore a cached DTD grammar, when + * an XML document contains both an internal and external DTD, and the use + * cached grammar from parse option is enabled. Currently, we do not allow + * using cached DTD grammar when an internal subset is present in the + * document. This option will only affect the behavior of the parser when + * an internal and external DTD both exist in a document (i.e. no effect + * if document has no internal subset). + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setIgnoreCachedDTD(const bool newValue); + + /** Set the 'ignore annotation' flag + * + * This method gives users the option to not generate XSAnnotations + * when "traversing" a schema. + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setIgnoreAnnotations(const bool newValue); + + /** Set the 'disable default entity resolution' flag + * + * This method gives users the option to not perform default entity + * resolution. If the user's resolveEntity method returns NULL the + * parser will try to resolve the entity on its own. When this option + * is set to true, the parser will not attempt to resolve the entity + * when the resolveEntity method returns NULL. + * + * The parser's default state is false + * + * @param newValue The state to set + * + * @see #EntityResolver + */ + void setDisableDefaultEntityResolution(const bool newValue); + + /** Set the 'skip DTD validation' flag + * + * This method gives users the option to skip DTD validation only when + * schema validation is on (i.e. when performing validation, we will + * ignore the DTD, except for entities, when schema validation is enabled). + * + * NOTE: This option is ignored if schema validation is disabled. + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setSkipDTDValidation(const bool newValue); + + /** Set the 'handle multiple schema imports' flag + * + * This method gives users the ability to import multiple schemas that + * have the same namespace. + * + * NOTE: This option is ignored if schema validation is disabled. + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setHandleMultipleImports(const bool newValue); + //@} + + + // ----------------------------------------------------------------------- + // Advanced document handler list maintenance methods + // ----------------------------------------------------------------------- + + /** @name Advanced document handler list maintenance methods */ + //@{ + /** + * This method installs the specified 'advanced' document callback + * handler, thereby allowing the user to customize the processing, + * if they choose to do so. Any number of advanced callback handlers + * maybe installed. + * + *

The methods in the advanced callback interface represent + * Xerces-C extensions. There is no specification for this interface.

+ * + * Note - XMLDocumentHandler calls, when used with SAXParser, will not provide correct namespace information. This is becaue the SAX parser does not support namespace aware processing. + * + * @param toInstall A pointer to the users advanced callback handler. + * + * @see #removeAdvDocHandler + */ + void installAdvDocHandler(XMLDocumentHandler* const toInstall); + + /** + * This method removes the 'advanced' document handler callback from + * the underlying parser scanner. If no handler is installed, advanced + * callbacks are not invoked by the scanner. + * @param toRemove A pointer to the advanced callback handler which + * should be removed. + * + * Note - XMLDocumentHandler calls, when used with SAXParser, will not provide correct namespace information. This is becaue the SAX parser does not support namespace aware processing. + * + * @see #installAdvDocHandler + */ + bool removeAdvDocHandler(XMLDocumentHandler* const toRemove); + //@} + + + // ----------------------------------------------------------------------- + // Progressive scan methods + // ----------------------------------------------------------------------- + + /** @name Progressive scan methods */ + //@{ + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a Unicode string representing the path + * to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could parse the + * prolog (which means the token will not be valid.) + * + * @see #parseNext + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + bool parseFirst + ( + const XMLCh* const systemId + , XMLPScanToken& toFill + ); + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a regular native string representing + * the path to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(InputSource&,...) + */ + bool parseFirst + ( + const char* const systemId + , XMLPScanToken& toFill + ); + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + */ + bool parseFirst + ( + const InputSource& source + , XMLPScanToken& toFill + ); + + /** Continue a progressive parse operation + * + * This method is used to continue with progressive parsing of + * XML files started by a call to 'parseFirst' method. + * + * It parses the XML file and stops as soon as it comes across + * a XML token (as defined in the XML specification). Relevant + * callback handlers are invoked as required by the SAX + * specification. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the next XML token. + * It indicates the user can go ahead with parsing the rest + * of the file. It returns 'false' to indicate that the parser + * could not find next token as per the XML specification + * production rule. + * + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + bool parseNext(XMLPScanToken& token); + + /** Reset the parser after a progressive parse + * + * If a progressive parse loop exits before the end of the document + * is reached, the parser has no way of knowing this. So it will leave + * open any files or sockets or memory buffers that were in use at + * the time that the parse loop exited. + * + * The next parse operation will cause these open files and such to + * be closed, but the next parse operation might occur at some unknown + * future point. To avoid this problem, you should reset the parser if + * you exit the loop early. + * + * If you exited because of an error, then this cleanup will be done + * for you. Its only when you exit the file prematurely of your own + * accord, because you've found what you wanted in the file most + * likely. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + */ + void parseReset(XMLPScanToken& token); + + //@} + + // ----------------------------------------------------------------------- + // Grammar preparsing interface + // ----------------------------------------------------------------------- + + /** @name Implementation of Grammar preparsing interface's. */ + //@{ + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the SAX InputSource parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param source A const reference to the SAX InputSource object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see InputSource#InputSource + */ + Grammar* loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * This method allows the user to reset the pool of cached grammars. + */ + void resetCachedGrammarPool(); + + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the SAX Parser interface + // ----------------------------------------------------------------------- + + /** @name Implementation of SAX 1.0 Parser interface's. */ + //@{ + /** + * This method invokes the parsing process on the XML file specified + * by the InputSource parameter. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * + * @see Parser#parse(InputSource) + */ + virtual void parse(const InputSource& source); + + /** + * This method invokes the parsing process on the XML file specified by + * the Unicode string parameter 'systemId'. + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML file to be parsed. + * + * @see Parser#parse(XMLCh*) + */ + virtual void parse(const XMLCh* const systemId); + + /** + * This method invokes the parsing process on the XML file specified by + * the native char* string parameter 'systemId'. + * + * @param systemId A const char pointer to a native string which + * contains the path to the XML file to be parsed. + */ + virtual void parse(const char* const systemId); + + /** + * This method installs the user specified SAX Document Handler + * callback function on parser. + * + * @param handler A pointer to the document handler to be called + * when the parser comes across 'document' events + * as per the SAX specification. + * + * @see Parser#parse(char*) + */ + virtual void setDocumentHandler(DocumentHandler* const handler); + + /** + * This method installs the user specified DTD handler on the parser. + * + * @param handler A pointer to the DTD handler to be called + * when the parser comes across 'DTD' events + * as per the SAX specification. + * + * @see Parser#setDTDHandler + */ + virtual void setDTDHandler(DTDHandler* const handler); + + /** + * This method installs the user specified error handler on + * the parser. + * + * @param handler A pointer to the error handler to be called + * when the parser comes across 'error' events + * as per the SAX specification. + * + * @see Parser#setErrorHandler + */ + virtual void setErrorHandler(ErrorHandler* const handler); + + /** + * This method installs the user specified PSVI handler on + * the parser. + * + * @param handler A pointer to the PSVI handler to be called + * when the parser comes across 'PSVI' events + * as per the schema specification. + * + * @see Parser#setPSVIHandler + */ + virtual void setPSVIHandler(PSVIHandler* const handler); + + /** + * This method installs the user specified entity resolver on the + * parser. It allows applications to trap and redirect calls to + * external entities. + * + * Any previously set entity resolver is merely dropped, since the parser + * does not own them. If both setEntityResolver and setXMLEntityResolver + * are called, then the last one is used. + * + * @param resolver A pointer to the entity resolver to be called + * when the parser comes across references to + * entities in the XML file. + * + * @see Parser#setEntityResolver + */ + virtual void setEntityResolver(EntityResolver* const resolver); + + /** + * This method installs the user specified entity resolver on the + * parser. It allows applications to trap and redirect calls to + * external entities. + * + * Any previously set entity resolver is merely dropped, since the parser + * does not own them. If both setEntityResolver and setXMLEntityResolver + * are called, then the last one is used. + * + * @param resolver A pointer to the entity resolver to be called + * when the parser comes across references to + * entities in the XML file. + * + * @see Parser#setXMLEntityResolver + */ + virtual void setXMLEntityResolver(XMLEntityResolver* const resolver); + + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLDocumentHandler interface + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLDocumentHandler Interface. */ + //@{ + /** + * This method is used to report all the characters scanned + * by the parser. The driver will invoke the 'characters' + * method of the user installed SAX Document Handler. + * + *

If any advanced callback handlers are installed, the + * corresponding 'docCharacters' method will also be invoked.

+ * + * @param chars A const pointer to a Unicode string representing the + * character data. + * @param length The length of the Unicode string returned in 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + * @see DocumentHandler#characters + */ + virtual void docCharacters + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** + * This method is used to report any comments scanned by the parser. + * This method is a no-op unless, unless an advanced callback handler + * is installed, in which case the corresponding 'docComment' method + * is invoked. + * + * @param comment A const pointer to a null terminated Unicode + * string representing the comment text. + */ + virtual void docComment + ( + const XMLCh* const comment + ); + + /** + * This method is used to report any PI scanned by the parser. + * + *

Any PI's occurring before any 'content' are not reported + * to any SAX handler as per the specification. However, all + * PI's within content are reported via the SAX Document Handler's + * 'processingInstruction' method. + * + *

If any advanced callback handlers are installed, the + * corresponding 'docPI' method will be invoked.

+ * + * @param target A const pointer to a Unicode string representing the + * target of the PI declaration. + * @param data A const pointer to a Unicode string representing the + * data of the PI declaration. See the PI production rule + * in the XML specification for details. + * + * @see DocumentHandler#processingInstruction + */ + virtual void docPI + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * This method is used to indicate the end of root element + * was just scanned by the parser. Corresponding 'endDocument' + * method of the user installed SAX Document Handler will also + * be invoked. + * + *

In addition, if any advanced callback handlers are installed, + * the corresponding 'endDocument' method is invoked.

+ * + * @see DocumentHandler#endDocument + */ + virtual void endDocument(); + + /** + * This method is used to indicate the end tag of an element. + * The driver will invoke the corresponding 'endElement' method of + * the SAX Document Handler interface. + * + *

If any advanced callback handlers are installed, the + * corresponding 'endElement' method is also invoked.

+ * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param isRoot A flag indicating whether this element was the + * root element. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + * @see DocumentHandler#endElement + */ + virtual void endElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const bool isRoot + , const XMLCh* const elemPrefix + ); + + /** + * This method is used to indicate that an end of an entity reference + * was just scanned. + * + *

If any advanced callback handlers are installed, the + * corresponding 'endEntityReference' method is invoked.

+ * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void endEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** + * This method is used to report all the whitespace characters, + * which are determined to be 'ignorable'. This distinction + * between characters is only made, if validation is enabled. + * Corresponding 'ignorableWhitespace' method of the user installed + * SAX Document Handler interface is called. + * + *

Any whitespace before content is not reported to the SAX + * Document Handler method, as per the SAX specification. + * However, if any advanced callback handlers are installed, the + * corresponding 'ignorableWhitespace' method is invoked.

+ * + * @param chars A const pointer to a Unicode string representing the + * ignorable whitespace character data. + * @param length The length of the Unicode string 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + * @see DocumentHandler#ignorableWhitespace + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** + * This method allows the user installed Document Handler and + * any advanced callback handlers to 'reset' themselves. + */ + virtual void resetDocument(); + + /** + * This method is used to report the start of the parsing process. + * The corresponding user installed SAX Document Handler's method + * 'startDocument' is invoked. + * + *

If any advanced callback handlers are installed, then the + * corresponding 'startDocument' method is also called.

+ * + * @see DocumentHandler#startDocument + */ + virtual void startDocument(); + + /** + * This method is used to report the start of an element. It is + * called at the end of the element, by which time all attributes + * specified are also parsed. The corresponding user installed + * SAX Document Handler's method 'startElement' is invoked. + * + *

If any advanced callback handlers are installed, then the + * corresponding 'startElement' method is also called.

+ * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + * @param attrList A const reference to the object containing the + * list of attributes just scanned for this element. + * @param attrCount A count of number of attributes in the list + * specified by the parameter 'attrList'. + * @param isEmpty A flag indicating whether this is an empty element + * or not. + * @param isRoot A flag indicating whether this element was the + * root element. + * @see DocumentHandler#startElement + */ + virtual void startElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot + ); + + /** + * This method is used to indicate the start of an entity reference. + * + *

If any advanced callback handlers are installed, the + * corresponding 'endEntityReference' method is invoked.

+ * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void startEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** + * This method is used to report the XML decl scanned by the parser. + * Refer to the XML specification to see the meaning of parameters. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param versionStr A const pointer to a Unicode string representing + * version string value. + * @param encodingStr A const pointer to a Unicode string representing + * the encoding string value. + * @param standaloneStr A const pointer to a Unicode string + * representing the standalone string value. + * @param actualEncodingStr A const pointer to a Unicode string + * representing the actual encoding string + * value. + */ + virtual void XMLDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + , const XMLCh* const standaloneStr + , const XMLCh* const actualEncodingStr + ); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLErrorReporter interface + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLErrorReporter Interface. */ + //@{ + /** + * This method is used to report back errors found while parsing the + * XML file. The driver will call the corresponding user installed + * SAX Error Handler methods: 'fatal', 'error', 'warning' depending + * on the severity of the error. This classification is defined by + * the XML specification. + * + * @param errCode An integer code for the error. + * @param msgDomain A const pointer to an Unicode string representing + * the message domain to use. + * @param errType An enumeration classifying the severity of the error. + * @param errorText A const pointer to an Unicode string representing + * the text of the error message. + * @param systemId A const pointer to an Unicode string representing + * the system id of the XML file where this error + * was discovered. + * @param publicId A const pointer to an Unicode string representing + * the public id of the XML file where this error + * was discovered. + * @param lineNum The line number where the error occurred. + * @param colNum The column number where the error occurred. + * @see ErrorHandler + */ + virtual void error + ( + const unsigned int errCode + , const XMLCh* const msgDomain + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ); + + /** + * This method allows the user installed Error Handler + * callback to 'reset' itself. + * + * This method is a no-op for this SAX driver + * implementation. + * + */ + virtual void resetErrors(); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLEntityHandler interface + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLEntityHandler Interface. */ + //@{ + /** + * This method is used to indicate the end of parsing of an external + * entity file. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the XML file being parsed. + * @see InputSource + */ + virtual void endInputSource(const InputSource& inputSource); + + /** + * This method allows an installed XMLEntityHandler to further + * process any system id's of external entities encountered in + * the XML file being parsed, such as redirection etc. + * + * This method always returns 'false' + * for this SAX driver implementation. + * + * @param systemId A const pointer to an Unicode string representing + * the system id scanned by the parser. + * @param toFill A pointer to a buffer in which the application + * processed system id is stored. + * @return 'true', if any processing is done, 'false' otherwise. + */ + virtual bool expandSystemId + ( + const XMLCh* const systemId + , XMLBuffer& toFill + ); + + /** + * This method allows the installed XMLEntityHandler to reset + * itself. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void resetEntities(); + + /** Resolve a public/system id + * + * This method allows a user installed entity handler to further + * process any pointers to external entities. The applications can + * implement 'redirection' via this callback. + * + * @param resourceIdentifier An object containing the type of + * resource to be resolved and the associated data members + * corresponding to this type. + * @return The value returned by the user installed resolveEntity + * method or NULL otherwise to indicate no processing was done. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @see XMLEntityHandler + * @see XMLEntityResolver + */ + virtual InputSource* resolveEntity + ( + XMLResourceIdentifier* resourceIdentifier + ); + + /** + * This method is used to indicate the start of parsing an + * external entity file. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the external entity + * being parsed. + */ + virtual void startInputSource(const InputSource& inputSource); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the Deprecated DocTypeHandler Interface + // ----------------------------------------------------------------------- + /** @name Implementation of the deprecated DocTypeHandler Interface */ + //@{ + /** + * This method is used to report an attribute definition. + * + * This method is a no-op for this SAX + * driver implementation. + * + * @param elemDecl A const reference to the object containing information + * about the element whose attribute definition was just + * parsed. + * @param attDef A const reference to the object containing information + * attribute definition. + * @param ignore The flag indicating whether this attribute definition + * was ignored by the parser or not. + */ + virtual void attDef + ( + const DTDElementDecl& elemDecl + , const DTDAttDef& attDef + , const bool ignore + ); + + /** + * This method is used to report a comment occurring within the DTD. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param comment A const pointer to a Unicode string representing the + * text of the comment just parsed. + */ + virtual void doctypeComment + ( + const XMLCh* const comment + ); + + /** + * This method is used to report the DOCTYPE declaration. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param elemDecl A const reference to the object containing information + * about the root element definition declaration of the + * XML document being parsed. + * @param publicId A const pointer to a Unicode string representing the + * public id of the DTD file. + * @param systemId A const pointer to a Unicode string representing the + * system id of the DTD file. + * @param hasIntSubset A flag indicating if this XML file contains any + * internal subset. + * @param hasExtSubset A flag indicating if this XML file contains any + * external subset. Default is false. + */ + virtual void doctypeDecl + ( + const DTDElementDecl& elemDecl + , const XMLCh* const publicId + , const XMLCh* const systemId + , const bool hasIntSubset + , const bool hasExtSubset = false + ); + + /** + * This method is used to report any PI declarations + * occurring inside the DTD definition block. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param target A const pointer to a Unicode string representing the + * target of the PI declaration. + * @param data A const pointer to a Unicode string representing the + * data of the PI declaration. See the PI production rule + * in the XML specification for details. + */ + virtual void doctypePI + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * This method is used to report any whitespaces + * occurring inside the DTD definition block. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param chars A const pointer to a Unicode string representing the + * whitespace characters. + * @param length The length of the whitespace Unicode string. + */ + virtual void doctypeWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * This method is used to report an element declarations + * successfully scanned by the parser. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param decl A const reference to the object containing element + * declaration information. + * @param isIgnored The flag indicating whether this definition was + * ignored by the parser or not. + */ + virtual void elementDecl + ( + const DTDElementDecl& decl + , const bool isIgnored + ); + + /** + * This method is used to report the end of an attribute + * list declaration for an element. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param elemDecl A const reference to the object containing element + * declaration information. + */ + virtual void endAttList + ( + const DTDElementDecl& elemDecl + ); + + /** + * This method is used to report the end of the internal subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void endIntSubset(); + + /** + * This method is used to report the end of the external subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void endExtSubset(); + + /** + * This method is used to report any entity declarations. + * For unparsed entities, this driver will invoke the + * SAX DTDHandler::unparsedEntityDecl callback. + * + * @param entityDecl A const reference to the object containing + * the entity declaration information. + * @param isPEDecl The flag indicating whether this was a + * parameter entity declaration or not. + * @param isIgnored The flag indicating whether this definition + * was ignored by the parser or not. + * + * @see DTDHandler#unparsedEntityDecl + */ + virtual void entityDecl + ( + const DTDEntityDecl& entityDecl + , const bool isPEDecl + , const bool isIgnored + ); + + /** + * This method allows the user installed DTD handler to + * reset itself. + */ + virtual void resetDocType(); + + /** + * This method is used to report any notation declarations. + * If there is a user installed DTDHandler, then the driver will + * invoke the SAX DTDHandler::notationDecl callback. + * + * @param notDecl A const reference to the object containing the notation + * declaration information. + * @param isIgnored The flag indicating whether this definition was ignored + * by the parser or not. + * + * @see DTDHandler#notationDecl + */ + virtual void notationDecl + ( + const XMLNotationDecl& notDecl + , const bool isIgnored + ); + + /** + * This method is used to indicate the start of an element's attribute + * list declaration. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param elemDecl A const reference to the object containing element + * declaration information. + */ + virtual void startAttList + ( + const DTDElementDecl& elemDecl + ); + + /** + * This method is used indicate the start of the internal subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void startIntSubset(); + + /** + * This method is used indicate the start of the external subset. + * + * This method is a no-op for this SAX driver + * implementation. + */ + virtual void startExtSubset(); + + /** + * This method is used to report the TextDecl. Refer to the XML + * specification for the syntax of a TextDecl. + * + * This method is a no-op for this SAX driver + * implementation. + * + * @param versionStr A const pointer to a Unicode string representing + * the version number of the 'version' clause. + * @param encodingStr A const pointer to a Unicode string representing + * the encoding name of the 'encoding' clause. + */ + virtual void TextDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + ); + //@} + +protected : + // ----------------------------------------------------------------------- + // Protected Methods + // ----------------------------------------------------------------------- + /** + * This method returns a reference to the underlying scanner object. + * It allows read only access to data maintained in the scanner. + * + * @return A const reference to the underlying scanner object. + */ + const XMLScanner& getScanner() const; + + /** Get the Grammar resolver + * + * This provides derived classes with access to the grammar resolver. + */ + GrammarResolver* getGrammarResolver() const; + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SAXParser(const SAXParser&); + SAXParser& operator=(const SAXParser&); + + // ----------------------------------------------------------------------- + // Initialize/Cleanup methods + // ----------------------------------------------------------------------- + void initialize(); + void cleanUp(); + void resetInProgress(); + + // ----------------------------------------------------------------------- + // Private data members + // + // fAttrList + // A temporary implementation of the basic SAX attribute list + // interface. We use this one over and over on each startElement + // event to allow SAX-like access to the element attributes. + // + // fDocHandler + // The installed SAX doc handler, if any. Null if none. + // + // fDTDHandler + // The installed SAX DTD handler, if any. Null if none. + // + // fElemDepth + // This is used to track the element nesting depth, so that we can + // know when we are inside content. This is so we can ignore char + // data outside of content. + // + // fEntityResolver + // The installed SAX entity handler, if any. Null if none. + // + // fErrorHandler + // The installed SAX error handler, if any. Null if none. + // + // fPSVIHandler + // The installed PSVI handler, if any. Null if none. + // + // fAdvDHCount + // fAdvDHList + // fAdvDHListSize + // This is an array of pointers to XMLDocumentHandlers, which is + // how we see installed advanced document handlers. There will + // usually not be very many at all, so a simple array is used + // instead of a collection, for performance. It will grow if needed, + // but that is unlikely. + // + // The count is how many handlers are currently installed. The size + // is how big the array itself is (for expansion purposes.) When + // count == size, is time to expand. + // + // fParseInProgress + // This flag is set once a parse starts. It is used to prevent + // multiple entrance or reentrance of the parser. + // + // fScanner + // The scanner being used by this parser. It is created internally + // during construction. + // + // fGrammarPool + // The grammar pool passed from external application (through derivatives). + // which could be 0, not owned. + // + // ----------------------------------------------------------------------- + bool fParseInProgress; + XMLSize_t fElemDepth; + XMLSize_t fAdvDHCount; + XMLSize_t fAdvDHListSize; + VecAttrListImpl fAttrList; + DocumentHandler* fDocHandler; + DTDHandler* fDTDHandler; + EntityResolver* fEntityResolver; + XMLEntityResolver* fXMLEntityResolver; + ErrorHandler* fErrorHandler; + PSVIHandler* fPSVIHandler; + XMLDocumentHandler** fAdvDHList; + XMLScanner* fScanner; + GrammarResolver* fGrammarResolver; + XMLStringPool* fURIStringPool; + XMLValidator* fValidator; + MemoryManager* fMemoryManager; + XMLGrammarPool* fGrammarPool; + XMLBuffer fElemQNameBuf; +}; + + +// --------------------------------------------------------------------------- +// SAXParser: Getter methods +// --------------------------------------------------------------------------- +inline DocumentHandler* SAXParser::getDocumentHandler() +{ + return fDocHandler; +} + +inline const DocumentHandler* SAXParser::getDocumentHandler() const +{ + return fDocHandler; +} + +inline EntityResolver* SAXParser::getEntityResolver() +{ + return fEntityResolver; +} + +inline XMLEntityResolver* SAXParser::getXMLEntityResolver() +{ + return fXMLEntityResolver; +} + +inline const XMLEntityResolver* SAXParser::getXMLEntityResolver() const +{ + return fXMLEntityResolver; +} + +inline const EntityResolver* SAXParser::getEntityResolver() const +{ + return fEntityResolver; +} + +inline ErrorHandler* SAXParser::getErrorHandler() +{ + return fErrorHandler; +} + +inline const ErrorHandler* SAXParser::getErrorHandler() const +{ + return fErrorHandler; +} + +inline PSVIHandler* SAXParser::getPSVIHandler() +{ + return fPSVIHandler; +} + +inline const PSVIHandler* SAXParser::getPSVIHandler() const +{ + return fPSVIHandler; +} + +inline const XMLScanner& SAXParser::getScanner() const +{ + return *fScanner; +} + +inline GrammarResolver* SAXParser::getGrammarResolver() const +{ + return fGrammarResolver; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/parsers/XercesDOMParser.cpp b/include/xercesc/parsers/XercesDOMParser.cpp new file mode 100644 index 0000000..b60678e --- /dev/null +++ b/include/xercesc/parsers/XercesDOMParser.cpp @@ -0,0 +1,349 @@ +/* + * 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. + */ + +/** +* This file contains code to build the DOM tree. It registers a document +* handler with the scanner. In these handler methods, appropriate DOM nodes +* are created and added to the DOM tree. +* +* $Id: XercesDOMParser.cpp 882548 2009-11-20 13:44:14Z borisk $ +* +*/ + + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + + +// --------------------------------------------------------------------------- +// XercesDOMParser: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesDOMParser::XercesDOMParser( XMLValidator* const valToAdopt + , MemoryManager* const manager + , XMLGrammarPool* const gramPool): + +AbstractDOMParser(valToAdopt, manager, gramPool) +, fEntityResolver(0) +, fXMLEntityResolver(0) +, fErrorHandler(0) +{ +} + + +XercesDOMParser::~XercesDOMParser() +{ +} + + +// --------------------------------------------------------------------------- +// XercesDOMParser: Getter methods +// --------------------------------------------------------------------------- +bool XercesDOMParser::isCachingGrammarFromParse() const +{ + return getScanner()->isCachingGrammarFromParse(); +} + +bool XercesDOMParser::isUsingCachedGrammarInParse() const +{ + return getScanner()->isUsingCachedGrammarInParse(); +} + +Grammar* XercesDOMParser::getGrammar(const XMLCh* const nameSpaceKey) +{ + return getGrammarResolver()->getGrammar(nameSpaceKey); +} + +Grammar* XercesDOMParser::getRootGrammar() +{ + return getScanner()->getRootGrammar(); +} + +const XMLCh* XercesDOMParser::getURIText(unsigned int uriId) const +{ + return getScanner()->getURIText(uriId); +} + +XMLFilePos XercesDOMParser::getSrcOffset() const +{ + return getScanner()->getSrcOffset(); +} + +bool XercesDOMParser::getIgnoreCachedDTD() const +{ + return getScanner()->getIgnoreCachedDTD(); +} + +// --------------------------------------------------------------------------- +// XercesDOMParser: Setter methods +// --------------------------------------------------------------------------- +void XercesDOMParser::setErrorHandler(ErrorHandler* const handler) +{ + fErrorHandler = handler; + XMLScanner* scanner = getScanner(); + if (fErrorHandler) { + scanner->setErrorReporter(this); + scanner->setErrorHandler(fErrorHandler); + } + else { + scanner->setErrorReporter(0); + scanner->setErrorHandler(0); + } +} + +void XercesDOMParser::setEntityResolver(EntityResolver* const handler) +{ + fEntityResolver = handler; + if (fEntityResolver) { + getScanner()->setEntityHandler(this); + fXMLEntityResolver = 0; + } + else { + getScanner()->setEntityHandler(0); + } +} + +void XercesDOMParser::setXMLEntityResolver(XMLEntityResolver* const handler) +{ + fXMLEntityResolver = handler; + if (fXMLEntityResolver) { + getScanner()->setEntityHandler(this); + fEntityResolver = 0; + } + else { + getScanner()->setEntityHandler(0); + } +} + +void XercesDOMParser::cacheGrammarFromParse(const bool newState) +{ + getScanner()->cacheGrammarFromParse(newState); + + if (newState) + getScanner()->useCachedGrammarInParse(newState); +} + +void XercesDOMParser::useCachedGrammarInParse(const bool newState) +{ + if (newState || !getScanner()->isCachingGrammarFromParse()) + getScanner()->useCachedGrammarInParse(newState); +} + +void XercesDOMParser::setIgnoreCachedDTD(const bool newValue) +{ + getScanner()->setIgnoredCachedDTD(newValue); +} + +// --------------------------------------------------------------------------- +// XercesDOMParser: Utilities +// --------------------------------------------------------------------------- +void XercesDOMParser::resetDocumentPool() +{ + resetPool(); +} + + +// --------------------------------------------------------------------------- +// XercesDOMParser: Implementation of the XMLErrorReporter interface +// --------------------------------------------------------------------------- +void XercesDOMParser::error( const unsigned int + , const XMLCh* const + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum) +{ + SAXParseException toThrow = SAXParseException + ( + errorText + , publicId + , systemId + , lineNum + , colNum + , getMemoryManager() + ); + + // + // If there is an error handler registered, call it, otherwise ignore + // all but the fatal errors. + // + if (!fErrorHandler) + { + if (errType == XMLErrorReporter::ErrType_Fatal) + throw toThrow; + return; + } + + if (errType == XMLErrorReporter::ErrType_Warning) + fErrorHandler->warning(toThrow); + else if (errType >= XMLErrorReporter::ErrType_Fatal) + fErrorHandler->fatalError(toThrow); + else + fErrorHandler->error(toThrow); +} + +void XercesDOMParser::resetErrors() +{ +} + + +// --------------------------------------------------------------------------- +// XercesDOMParser: Implementation of XMLEntityHandler interface +// --------------------------------------------------------------------------- +InputSource* +XercesDOMParser::resolveEntity(XMLResourceIdentifier* resourceIdentifier) +{ + // + // Just map it to the SAX entity resolver. If there is not one installed, + // return a null pointer to cause the default resolution. + // + if (fEntityResolver) + return fEntityResolver->resolveEntity(resourceIdentifier->getPublicId(), + resourceIdentifier->getSystemId()); + if (fXMLEntityResolver) + return fXMLEntityResolver->resolveEntity(resourceIdentifier); + + return 0; +} + +typedef JanitorMemFunCall ResetParseType; + +// --------------------------------------------------------------------------- +// XercesDOMParser: Grammar preparsing methods +// --------------------------------------------------------------------------- +Grammar* XercesDOMParser::loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (getParseInProgress()) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetParseType resetParse(this, &XercesDOMParser::resetParse); + + Grammar* grammar = 0; + + try + { + setParseInProgress(true); + if (grammarType == Grammar::DTDGrammarType) + getScanner()->setDocTypeHandler(0); + grammar = getScanner()->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetParse.release(); + + throw; + } + + return grammar; +} + +Grammar* XercesDOMParser::loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (getParseInProgress()) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetParseType resetParse(this, &XercesDOMParser::resetParse); + + Grammar* grammar = 0; + + try + { + setParseInProgress(true); + if (grammarType == Grammar::DTDGrammarType) + getScanner()->setDocTypeHandler(0); + grammar = getScanner()->loadGrammar(systemId, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetParse.release(); + + throw; + } + + return grammar; +} + +Grammar* XercesDOMParser::loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache) +{ + // Avoid multiple entrance + if (getParseInProgress()) + ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); + + ResetParseType resetParse(this, &XercesDOMParser::resetParse); + + Grammar* grammar = 0; + + try + { + setParseInProgress(true); + if (grammarType == Grammar::DTDGrammarType) + getScanner()->setDocTypeHandler(0); + grammar = getScanner()->loadGrammar(source, grammarType, toCache); + } + catch(const OutOfMemoryException&) + { + resetParse.release(); + + throw; + } + + return grammar; +} + +void XercesDOMParser::resetParse() +{ + if (getScanner()->getDocTypeHandler() == 0) + { + getScanner()->setDocTypeHandler(this); + } + + setParseInProgress(false); +} + +void XercesDOMParser::resetCachedGrammarPool() +{ + getGrammarResolver()->resetCachedGrammar(); + getScanner()->resetCachedGrammar(); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/parsers/XercesDOMParser.hpp b/include/xercesc/parsers/XercesDOMParser.hpp new file mode 100644 index 0000000..de8d139 --- /dev/null +++ b/include/xercesc/parsers/XercesDOMParser.hpp @@ -0,0 +1,696 @@ +/* + * 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: XercesDOMParser.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XERCESDOMPARSER_HPP) +#define XERCESC_INCLUDE_GUARD_XERCESDOMPARSER_HPP + + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +class EntityResolver; +class ErrorHandler; +class XMLEntityResolver; +class XMLResourceIdentifier; + + /** + * This class implements the Document Object Model (DOM) interface. + * It should be used by applications which choose to parse and + * process the XML document using the DOM api's. This implementation + * also allows the applications to install an error and an entity + * handler (useful extensions to the DOM specification). + * + *

It can be used to instantiate a validating or non-validating + * parser, by setting a member flag.

+ */ +class PARSERS_EXPORT XercesDOMParser : public AbstractDOMParser +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors and Destructor */ + //@{ + /** Construct a XercesDOMParser, with an optional validator + * + * Constructor with an instance of validator class to use for + * validation. If you don't provide a validator, a default one will + * be created for you in the scanner. + * + * @param gramPool Pointer to the grammar pool instance from + * external application. + * The parser does NOT own it. + * + * @param valToAdopt Pointer to the validator instance to use. The + * parser is responsible for freeing the memory. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + XercesDOMParser + ( + XMLValidator* const valToAdopt = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ); + + /** + * Destructor + */ + virtual ~XercesDOMParser(); + + //@} + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + + /** @name Getter methods */ + //@{ + + /** Get a pointer to the error handler + * + * This method returns the installed error handler. If no handler + * has been installed, then it will be a zero pointer. + * + * @return The pointer to the installed error handler object. + */ + ErrorHandler* getErrorHandler(); + + /** Get a const pointer to the error handler + * + * This method returns the installed error handler. If no handler + * has been installed, then it will be a zero pointer. + * + * @return A const pointer to the installed error handler object. + */ + const ErrorHandler* getErrorHandler() const; + + /** Get a pointer to the entity resolver + * + * This method returns the installed entity resolver. If no resolver + * has been installed, then it will be a zero pointer. + * + * @return The pointer to the installed entity resolver object. + */ + EntityResolver* getEntityResolver(); + + /** Get a const pointer to the entity resolver + * + * This method returns the installed entity resolver. If no resolver + * has been installed, then it will be a zero pointer. + * + * @return A const pointer to the installed entity resolver object. + */ + const EntityResolver* getEntityResolver() const; + + /** + * Get a pointer to the entity resolver + * + * This method returns the installed entity resolver. If no resolver + * has been installed, then it will be a zero pointer. + * + * @return The pointer to the installed entity resolver object. + */ + XMLEntityResolver* getXMLEntityResolver(); + + /** + * Get a const pointer to the entity resolver + * + * This method returns the installed entity resolver. If no resolver + * has been installed, then it will be a zero pointer. + * + * @return A const pointer to the installed entity resolver object. + */ + const XMLEntityResolver* getXMLEntityResolver() const; + + /** Get the 'Grammar caching' flag + * + * This method returns the state of the parser's grammar caching when + * parsing an XML document. + * + * @return true, if the parser is currently configured to + * cache grammars, false otherwise. + * + * @see #cacheGrammarFromParse + */ + bool isCachingGrammarFromParse() const; + + /** Get the 'Use cached grammar' flag + * + * This method returns the state of the parser's use of cached grammar + * when parsing an XML document. + * + * @return true, if the parser is currently configured to + * use cached grammars, false otherwise. + * + * @see #useCachedGrammarInParse + */ + bool isUsingCachedGrammarInParse() const; + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + Grammar* getGrammar(const XMLCh* const nameSpaceKey); + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + Grammar* getRootGrammar(); + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + const XMLCh* getURIText(unsigned int uriId) const; + + /** + * Returns the current src offset within the input source. + * To be used only while parsing is in progress. + * + * @return offset within the input source + */ + XMLFilePos getSrcOffset() const; + + /** Get the 'ignore cached DTD grammar' flag + * + * @return true, if the parser is currently configured to + * ignore cached DTD, false otherwise. + * + * @see #setIgnoreCachedDTD + */ + bool getIgnoreCachedDTD() const; + + //@} + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + /** @name Setter methods */ + //@{ + + /** Set the error handler + * + * This method allows applications to install their own error handler + * to trap error and warning messages. + * + * Any previously set handler is merely dropped, since the parser + * does not own them. + * + * @param handler A const pointer to the user supplied error + * handler. + * + * @see #getErrorHandler + */ + void setErrorHandler(ErrorHandler* const handler); + + /** Set the entity resolver + * + * This method allows applications to install their own entity + * resolver. By installing an entity resolver, the applications + * can trap and potentially redirect references to external + * entities. + * + * Any previously set entity resolver is merely dropped, since the parser + * does not own them. If both setEntityResolver and setXMLEntityResolver + * are called, then the last one is used. + * + * @param handler A const pointer to the user supplied entity + * resolver. + * + * @see #getEntityResolver + */ + void setEntityResolver(EntityResolver* const handler); + + /** + * Set the entity resolver + * + * This method allows applications to install their own entity + * resolver. By installing an entity resolver, the applications + * can trap and potentially redirect references to external + * entities. + * + * Any previously set entity resolver is merely dropped, since the parser + * does not own them. If both setEntityResolver and setXMLEntityResolver + * are called, then the last one set is used. + * + * @param handler A const pointer to the user supplied entity + * resolver. + * + * @see #getXMLEntityResolver + */ + void setXMLEntityResolver(XMLEntityResolver* const handler); + + /** Set the 'Grammar caching' flag + * + * This method allows users to enable or disable caching of grammar when + * parsing XML documents. When set to true, the parser will cache the + * resulting grammar for use in subsequent parses. + * + * If the flag is set to true, the 'Use cached grammar' flag will also be + * set to true. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether we should cache grammars + * or not. + * + * @see #isCachingGrammarFromParse + * @see #useCachedGrammarInParse + */ + void cacheGrammarFromParse(const bool newState); + + /** Set the 'Use cached grammar' flag + * + * This method allows users to enable or disable the use of cached + * grammars. When set to true, the parser will use the cached grammar, + * instead of building the grammar from scratch, to validate XML + * documents. + * + * If the 'Grammar caching' flag is set to true, this method ignore the + * value passed in. + * + * The parser's default state is: false. + * + * @param newState The value specifying whether we should use the cached + * grammar or not. + * + * @see #isUsingCachedGrammarInParse + * @see #cacheGrammarFromParse + */ + void useCachedGrammarInParse(const bool newState); + + /** Set the 'ignore cached DTD grammar' flag + * + * This method gives users the option to ignore a cached DTD grammar, when + * an XML document contains both an internal and external DTD, and the use + * cached grammar from parse option is enabled. Currently, we do not allow + * using cached DTD grammar when an internal subset is present in the + * document. This option will only affect the behavior of the parser when + * an internal and external DTD both exist in a document (i.e. no effect + * if document has no internal subset). + * + * The parser's default state is false + * + * @param newValue The state to set + */ + void setIgnoreCachedDTD(const bool newValue); + + //@} + + // ----------------------------------------------------------------------- + // Utility methods + // ----------------------------------------------------------------------- + + /** @name Utility methods */ + //@{ + /** Reset the documents vector pool and release all the associated memory + * back to the system. + * + * When parsing a document using a DOM parser, all memory allocated + * for a DOM tree is associated to the DOM document. + * + * If you do multiple parse using the same DOM parser instance, then + * multiple DOM documents will be generated and saved in a vector pool. + * All these documents (and thus all the allocated memory) + * won't be deleted until the parser instance is destroyed. + * + * If you don't need these DOM documents anymore and don't want to + * destroy the DOM parser instance at this moment, then you can call this method + * to reset the document vector pool and release all the allocated memory + * back to the system. + * + * It is an error to call this method if you are in the middle of a + * parse (e.g. in the mid of a progressive parse). + * + * @exception IOException An exception from the parser if this function + * is called when a parse is in progress. + * + */ + void resetDocumentPool(); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the XMLErrorReporter interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLErrorReporter interface. */ + //@{ + + /** Handle errors reported from the parser + * + * This method is used to report back errors found while parsing the + * XML file. This method is also borrowed from the SAX specification. + * It calls the corresponding user installed Error Handler method: + * 'fatal', 'error', 'warning' depending on the severity of the error. + * This classification is defined by the XML specification. + * + * @param errCode An integer code for the error. + * @param msgDomain A const pointer to an Unicode string representing + * the message domain to use. + * @param errType An enumeration classifying the severity of the error. + * @param errorText A const pointer to an Unicode string representing + * the text of the error message. + * @param systemId A const pointer to an Unicode string representing + * the system id of the XML file where this error + * was discovered. + * @param publicId A const pointer to an Unicode string representing + * the public id of the XML file where this error + * was discovered. + * @param lineNum The line number where the error occurred. + * @param colNum The column number where the error occurred. + * @see ErrorHandler + */ + virtual void error + ( + const unsigned int errCode + , const XMLCh* const msgDomain + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ); + + /** Reset any error data before a new parse + * + * This method allows the user installed Error Handler callback to + * 'reset' itself. + * + * This method is a no-op for this DOM + * implementation. + */ + virtual void resetErrors(); + //@} + + + // ----------------------------------------------------------------------- + // Implementation of the XMLEntityHandler interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLEntityHandler interface. */ + //@{ + + /** Handle an end of input source event + * + * This method is used to indicate the end of parsing of an external + * entity file. + * + * This method is a no-op for this DOM + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the XML file being parsed. + * @see InputSource + */ + virtual void endInputSource(const InputSource& inputSource); + + /** Expand a system id + * + * This method allows an installed XMLEntityHandler to further + * process any system id's of external entities encountered in + * the XML file being parsed, such as redirection etc. + * + * This method always returns 'false' + * for this DOM implementation. + * + * @param systemId A const pointer to an Unicode string representing + * the system id scanned by the parser. + * @param toFill A pointer to a buffer in which the application + * processed system id is stored. + * @return 'true', if any processing is done, 'false' otherwise. + */ + virtual bool expandSystemId + ( + const XMLCh* const systemId + , XMLBuffer& toFill + ); + + /** Reset any entity handler information + * + * This method allows the installed XMLEntityHandler to reset + * itself. + * + * This method is a no-op for this DOM + * implementation. + */ + virtual void resetEntities(); + + /** Resolve a public/system id + * + * This method allows a user installed entity handler to further + * process any pointers to external entities. The applications can + * implement 'redirection' via this callback. + * + * @param resourceIdentifier An object containing the type of + * resource to be resolved and the associated data members + * corresponding to this type. + * @return The value returned by the user installed resolveEntity + * method or NULL otherwise to indicate no processing was done. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @see XMLEntityHandler + * @see XMLEntityResolver + */ + virtual InputSource* resolveEntity + ( + XMLResourceIdentifier* resourceIdentifier + ); + + /** Handle a 'start input source' event + * + * This method is used to indicate the start of parsing an external + * entity file. + * + * This method is a no-op for this DOM parse + * implementation. + * + * @param inputSource A const reference to the InputSource object + * which points to the external entity + * being parsed. + */ + virtual void startInputSource(const InputSource& inputSource); + + //@} + + // ----------------------------------------------------------------------- + // Grammar preparsing interface + // ----------------------------------------------------------------------- + + /** @name Implementation of Grammar preparsing interface's. */ + //@{ + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the SAX InputSource parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param source A const reference to the SAX InputSource object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see InputSource#InputSource + */ + Grammar* loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false); + + /** + * This method allows the user to reset the pool of cached grammars. + */ + void resetCachedGrammarPool(); + + //@} + + +private : + // ----------------------------------------------------------------------- + // Initialize/Cleanup methods + // ----------------------------------------------------------------------- + void resetParse(); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XercesDOMParser(const XercesDOMParser&); + XercesDOMParser& operator=(const XercesDOMParser&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fEntityResolver + // The installed SAX entity resolver, if any. Null if none. + // + // fErrorHandler + // The installed SAX error handler, if any. Null if none. + //----------------------------------------------------------------------- + EntityResolver* fEntityResolver; + XMLEntityResolver* fXMLEntityResolver; + ErrorHandler* fErrorHandler; +}; + + + +// --------------------------------------------------------------------------- +// XercesDOMParser: Handlers for the XMLEntityHandler interface +// --------------------------------------------------------------------------- +inline void XercesDOMParser::endInputSource(const InputSource&) +{ + // The DOM entity resolver doesn't handle this +} + +inline bool XercesDOMParser::expandSystemId(const XMLCh* const, XMLBuffer&) +{ + // The DOM entity resolver doesn't handle this + return false; +} + +inline void XercesDOMParser::resetEntities() +{ + // Nothing to do on this one +} + +inline void XercesDOMParser::startInputSource(const InputSource&) +{ + // The DOM entity resolver doesn't handle this +} + + +// --------------------------------------------------------------------------- +// XercesDOMParser: Getter methods +// --------------------------------------------------------------------------- +inline ErrorHandler* XercesDOMParser::getErrorHandler() +{ + return fErrorHandler; +} + +inline const ErrorHandler* XercesDOMParser::getErrorHandler() const +{ + return fErrorHandler; +} + +inline EntityResolver* XercesDOMParser::getEntityResolver() +{ + return fEntityResolver; +} + +inline const EntityResolver* XercesDOMParser::getEntityResolver() const +{ + return fEntityResolver; +} + +inline XMLEntityResolver* XercesDOMParser::getXMLEntityResolver() +{ + return fXMLEntityResolver; +} + +inline const XMLEntityResolver* XercesDOMParser::getXMLEntityResolver() const +{ + return fXMLEntityResolver; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/AttributeList.hpp b/include/xercesc/sax/AttributeList.hpp new file mode 100644 index 0000000..acd8a71 --- /dev/null +++ b/include/xercesc/sax/AttributeList.hpp @@ -0,0 +1,229 @@ +/* + * 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: AttributeList.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ATTRIBUTELIST_HPP) +#define XERCESC_INCLUDE_GUARD_ATTRIBUTELIST_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Interface for an element's attribute specifications. + * + * The SAX parser implements this interface and passes an instance + * to the SAX application as the second argument of each startElement + * event. + * + * The instance provided will return valid results only during the + * scope of the startElement invocation (to save it for future + * use, the application must make a copy: the AttributeListImpl + * helper class provides a convenient constructor for doing so). + * + * An AttributeList includes only attributes that have been + * specified or defaulted: \#IMPLIED attributes will not be included. + * + * There are two ways for the SAX application to obtain information + * from the AttributeList. First, it can iterate through the entire + * list: + * + * + * public void startElement (String name, AttributeList atts) {
+ *  for (XMLSize_t i = 0; i < atts.getLength(); i++) {
+ *   String name = atts.getName(i);
+ *   String type = atts.getType(i);
+ *   String value = atts.getValue(i);
+ *   [...]
+ *  }
+ * } + *
+ * + * (Note that the result of getLength() will be zero if there + * are no attributes.) + * + * As an alternative, the application can request the value or + * type of specific attributes: + * + * + * public void startElement (String name, AttributeList atts) {
+ *  String identifier = atts.getValue("id");
+ *  String label = atts.getValue("label");
+ *  [...]
+ * } + *
+ * + * The AttributeListImpl helper class provides a convenience + * implementation for use by parser or application writers. + * + * @see DocumentHandler#startElement + * @see AttributeListImpl#AttributeListImpl + */ + +class SAX_EXPORT AttributeList +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + AttributeList() + { + } + + /** Destructor */ + virtual ~AttributeList() + { + } + //@} + + /** @name The virtual attribute list interface */ + //@{ + /** + * Return the number of attributes in this list. + * + * The SAX parser may provide attributes in any + * arbitrary order, regardless of the order in which they were + * declared or specified. The number of attributes may be + * zero. + * + * @return The number of attributes in the list. + */ + virtual XMLSize_t getLength() const = 0; + + /** + * Return the name of an attribute in this list (by position). + * + * The names must be unique: the SAX parser shall not include the + * same attribute twice. Attributes without values (those declared + * \#IMPLIED without a value specified in the start tag) will be + * omitted from the list. + * + * If the attribute name has a namespace prefix, the prefix + * will still be attached. + * + * @param index The index of the attribute in the list (starting at 0). + * @return The name of the indexed attribute, or null + * if the index is out of range. + * @see #getLength + */ + virtual const XMLCh* getName(const XMLSize_t index) const = 0; + + /** + * Return the type of an attribute in the list (by position). + * + * The attribute type is one of the strings "CDATA", "ID", + * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", + * or "NOTATION" (always in upper case). + * + * If the parser has not read a declaration for the attribute, + * or if the parser does not report attribute types, then it must + * return the value "CDATA" as stated in the XML 1.0 Recommendation + * (clause 3.3.3, "Attribute-Value Normalization"). + * + * For an enumerated attribute that is not a notation, the + * parser will report the type as "NMTOKEN". + * + * @param index The index of the attribute in the list (starting at 0). + * @return The attribute type as a string, or + * null if the index is out of range. + * @see #getLength + * @see #getType + */ + virtual const XMLCh* getType(const XMLSize_t index) const = 0; + + /** + * Return the value of an attribute in the list (by position). + * + * If the attribute value is a list of tokens (IDREFS, + * ENTITIES, or NMTOKENS), the tokens will be concatenated + * into a single string separated by whitespace. + * + * @param index The index of the attribute in the list (starting at 0). + * @return The attribute value as a string, or + * null if the index is out of range. + * @see #getLength + * @see #getValue + */ + virtual const XMLCh* getValue(const XMLSize_t index) const = 0; + + /** + * Return the type of an attribute in the list (by name). + * + * The return value is the same as the return value for + * getType(XMLSize_t). + * + * If the attribute name has a namespace prefix in the document, + * the application must include the prefix here. + * + * @param name The name of the attribute. + * @return The attribute type as a string, or null if no + * such attribute exists. + * @see #getType + */ + virtual const XMLCh* getType(const XMLCh* const name) const = 0; + + /** + * Return the value of an attribute in the list (by name). + * + * The return value is the same as the return value for + * getValue(XMLSize_t). + * + * If the attribute name has a namespace prefix in the document, + * the application must include the prefix here. + * + * @param name The name of the attribute in the list. + * @return The attribute value as a string, or null if + * no such attribute exists. + * @see #getValue + */ + virtual const XMLCh* getValue(const XMLCh* const name) const = 0; + + /** + * Return the value of an attribute in the list (by name). + * + * The return value is the same as the return value for + * getValue(XMLSize_t). + * + * If the attribute name has a namespace prefix in the document, + * the application must include the prefix here. + * + * @param name The name of the attribute in the list. + * @return The attribute value as a string, or null if + * no such attribute exists. + * @see #getValue + */ + virtual const XMLCh* getValue(const char* const name) const = 0; + //@} + +private : + /* Constructors and operators */ + /* Copy constructor */ + AttributeList(const AttributeList&); + /* Assignment operator */ + AttributeList& operator=(const AttributeList&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/DTDHandler.hpp b/include/xercesc/sax/DTDHandler.hpp new file mode 100644 index 0000000..19793ad --- /dev/null +++ b/include/xercesc/sax/DTDHandler.hpp @@ -0,0 +1,159 @@ +/* + * 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: DTDHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DTDHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DTDHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Receive notification of basic DTD-related events. + * + *

If a SAX application needs information about notations and + * unparsed entities, then the application implements this + * interface and registers an instance with the SAX parser using + * the parser's setDTDHandler method. The parser uses the + * instance to report notation and unparsed entity declarations to + * the application.

+ * + *

The SAX parser may report these events in any order, regardless + * of the order in which the notations and unparsed entities were + * declared; however, all DTD events must be reported after the + * document handler's startDocument event, and before the first + * startElement event.

+ * + *

It is up to the application to store the information for + * future use (perhaps in a hash table or object tree). + * If the application encounters attributes of type "NOTATION", + * "ENTITY", or "ENTITIES", it can use the information that it + * obtained through this interface to find the entity and/or + * notation corresponding with the attribute value.

+ * + *

The HandlerBase class provides a default implementation + * of this interface, which simply ignores the events.

+ * + * @see Parser#setDTDHandler + * @see HandlerBase#HandlerBase + */ + +class SAX_EXPORT DTDHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default Constructor */ + DTDHandler() + { + } + + /** Destructor */ + virtual ~DTDHandler() + { + } + + //@} + + /** @name The DTD handler interface */ + //@{ + /** + * Receive notification of a notation declaration event. + * + *

It is up to the application to record the notation for later + * reference, if necessary.

+ * + *

If a system identifier is present, and it is a URL, the SAX + * parser must resolve it fully before passing it to the + * application.

+ * + * @param name The notation name. + * @param publicId The notation's public identifier, or null if + * none was given. + * @param systemId The notation's system identifier, or null if + * none was given. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #unparsedEntityDecl + * @see AttributeList#AttributeList + */ + virtual void notationDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ) = 0; + + /** + * Receive notification of an unparsed entity declaration event. + * + *

Note that the notation name corresponds to a notation + * reported by the notationDecl() event. It is up to the + * application to record the entity for later reference, if + * necessary.

+ * + *

If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @param name The unparsed entity's name. + * @param publicId The entity's public identifier, or null if none + * was given. + * @param systemId The entity's system identifier (it must always + * have one). + * @param notationName The name of the associated notation. + * @see #notationDecl + * @see AttributeList#AttributeList + */ + virtual void unparsedEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLCh* const notationName + ) = 0; + + /** + * Reset the DocType object on its reuse + * + *

This method helps in reseting the DTD object implementation + * defaults each time the DTD is begun.

+ * + */ + virtual void resetDocType() = 0; + + //@} + +private : + /* Unimplemented constructors and operators */ + + /* Copy constructor */ + DTDHandler(const DTDHandler&); + + /* Assignment operator */ + DTDHandler& operator=(const DTDHandler&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/DocumentHandler.hpp b/include/xercesc/sax/DocumentHandler.hpp new file mode 100644 index 0000000..e190709 --- /dev/null +++ b/include/xercesc/sax/DocumentHandler.hpp @@ -0,0 +1,283 @@ +/* + * 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: DocumentHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOCUMENTHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DOCUMENTHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class AttributeList; +class Locator; + +/** + * Receive notification of general document events. + * + *

This is the main interface that most SAX applications + * implement: if the application needs to be informed of basic parsing + * events, it implements this interface and registers an instance with + * the SAX parser using the setDocumentHandler method. The parser + * uses the instance to report basic document-related events like + * the start and end of elements and character data.

+ * + *

The order of events in this interface is very important, and + * mirrors the order of information in the document itself. For + * example, all of an element's content (character data, processing + * instructions, and/or subelements) will appear, in order, between + * the startElement event and the corresponding endElement event.

+ * + *

Application writers who do not want to implement the entire + * interface while can derive a class from HandlerBase, which implements + * the default functionality; parser writers can instantiate + * HandlerBase to obtain a default handler. The application can find + * the location of any document event using the Locator interface + * supplied by the Parser through the setDocumentLocator method.

+ * + * @see Parser#setDocumentHandler + * @see Locator#Locator + * @see HandlerBase#HandlerBase + */ + +class SAX_EXPORT DocumentHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + DocumentHandler() + { + } + + /** Destructor */ + virtual ~DocumentHandler() + { + } + //@} + + /** @name The virtual document handler interface */ + + //@{ + /** + * Receive notification of character data. + * + *

The Parser will call this method to report each chunk of + * character data. SAX parsers may return all contiguous character + * data in a single chunk, or they may split it into several + * chunks; however, all of the characters in any single event + * must come from the same external entity, so that the Locator + * provides useful information.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + *

Note that some parsers will report whitespace using the + * ignorableWhitespace() method rather than this one (validating + * parsers must do so).

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #ignorableWhitespace + * @see Locator#Locator + */ + virtual void characters + ( + const XMLCh* const chars + , const XMLSize_t length + ) = 0; + + /** + * Receive notification of the end of a document. + * + *

The SAX parser will invoke this method only once, and it will + * be the last method invoked during the parse. The parser shall + * not invoke this method until it has either abandoned parsing + * (because of an unrecoverable error) or reached the end of + * input.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endDocument () = 0; + + /** + * Receive notification of the end of an element. + * + *

The SAX parser will invoke this method at the end of every + * element in the XML document; there will be a corresponding + * startElement() event for every endElement() event (even when the + * element is empty).

+ * + *

If the element name has a namespace prefix, the prefix will + * still be attached to the name.

+ * + * @param name The element type name + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endElement(const XMLCh* const name) = 0; + + /** + * Receive notification of ignorable whitespace in element content. + * + *

Validating Parsers must use this method to report each chunk + * of ignorable whitespace (see the W3C XML 1.0 recommendation, + * section 2.10): non-validating parsers may also use this method + * if they are capable of parsing and using content models.

+ * + *

SAX parsers may return all contiguous whitespace in a single + * chunk, or they may split it into several chunks; however, all of + * the characters in any single event must come from the same + * external entity, so that the Locator provides useful + * information.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #characters + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ) = 0; + + /** + * Receive notification of a processing instruction. + * + *

The Parser will invoke this method once for each processing + * instruction found: note that processing instructions may occur + * before or after the main document element.

+ * + *

A SAX parser should never report an XML declaration (XML 1.0, + * section 2.8) or a text declaration (XML 1.0, section 4.3.1) + * using this method.

+ * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none was supplied. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void processingInstruction + ( + const XMLCh* const target + , const XMLCh* const data + ) = 0; + + /** + * Reset the Document object on its reuse + * + *

This method helps in reseting the document implementation + * defaults each time the document is begun.

+ * + */ + virtual void resetDocument() = 0; + + /** + * Receive an object for locating the origin of SAX document events. + * + * SAX parsers are strongly encouraged (though not absolutely + * required) to supply a locator: if it does so, it must supply + * the locator to the application by invoking this method before + * invoking any of the other methods in the DocumentHandler + * interface. + * + * The locator allows the application to determine the end + * position of any document-related event, even if the parser is + * not reporting an error. Typically, the application will + * use this information for reporting its own errors (such as + * character content that does not match an application's + * business rules). The information returned by the locator + * is probably not sufficient for use with a search engine. + * + * Note that the locator will return correct information only + * during the invocation of the events in this interface. The + * application should not attempt to use it at any other time. + * + * @param locator An object that can return the location of + * any SAX document event. The object is only + * 'on loan' to the client code and they are not + * to attempt to delete or modify it in any way! + * + * @see Locator#Locator + */ + virtual void setDocumentLocator(const Locator* const locator) = 0; + + /** + * Receive notification of the beginning of a document. + * + *

The SAX parser will invoke this method only once, before any + * other methods in this interface or in DTDHandler (except for + * setDocumentLocator).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startDocument() = 0; + + /** + * Receive notification of the beginning of an element. + * + *

The Parser will invoke this method at the beginning of every + * element in the XML document; there will be a corresponding + * endElement() event for every startElement() event (even when the + * element is empty). All of the element's content will be + * reported, in order, before the corresponding endElement() + * event.

+ * + *

If the element name has a namespace prefix, the prefix will + * still be attached. Note that the attribute list provided will + * contain only attributes with explicit values (specified or + * defaulted): \#IMPLIED attributes will be omitted.

+ * + * @param name The element type name. + * @param attrs The attributes attached to the element, if any. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #endElement + * @see AttributeList#AttributeList + */ + virtual void startElement + ( + const XMLCh* const name + , AttributeList& attrs + ) = 0; + + //@} + +private : + /* Unimplemented Constructors and operators */ + /* Copy constructor */ + DocumentHandler(const DocumentHandler&); + /** Assignment operator */ + DocumentHandler& operator=(const DocumentHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/Dummy.cpp b/include/xercesc/sax/Dummy.cpp new file mode 100644 index 0000000..7da384f --- /dev/null +++ b/include/xercesc/sax/Dummy.cpp @@ -0,0 +1,36 @@ +/* + * 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: Dummy.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/sax/EntityResolver.hpp b/include/xercesc/sax/EntityResolver.hpp new file mode 100644 index 0000000..017ea08 --- /dev/null +++ b/include/xercesc/sax/EntityResolver.hpp @@ -0,0 +1,165 @@ +/* + * 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: EntityResolver.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ENTITYRESOLVER_HPP) +#define XERCESC_INCLUDE_GUARD_ENTITYRESOLVER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class InputSource; + +/** + * Basic interface for resolving entities. + * + *

If a SAX application needs to implement customized handling + * for external entities, it must implement this interface and + * register an instance with the SAX parser using the parser's + * setEntityResolver method.

+ * + *

The parser will then allow the application to intercept any + * external entities (including the external DTD subset and external + * parameter entities, if any) before including them.

+ * + *

Many SAX applications will not need to implement this interface, + * but it will be especially useful for applications that build + * XML documents from databases or other specialised input sources, + * or for applications that use URI types other than URLs.

+ * + *

The following resolver would provide the application + * with a special character stream for the entity with the system + * identifier "http://www.myhost.com/today":

+ * + * + *\#include
+ *\#include
+ *
+ *class MyResolver : public EntityResolver {
+ * public:
  + * InputSource resolveEntity (const XMLCh* const publicId, const XMLCh* const systemId);
   + *
+ * ...
   + * };
  + *
+ * MyResolver::resolveEntity {
+ *  if (XMLString::compareString(systemId, "http://www.myhost.com/today")) {
+ *   MyReader* reader = new MyReader();
+ *   return new InputSource(reader);
+ *  } else {
+ *   return null;
+ *  }
+ * }
+ *
+ *
+ * + *

The application can also use this interface to redirect system + * identifiers to local URIs or to look up replacements in a catalog + * (possibly by using the public identifier).

+ * + *

The HandlerBase class implements the default behaviour for + * this interface, which is simply always to return null (to request + * that the parser use the default system identifier).

+ * + * @see Parser#setEntityResolver + * @see InputSource#InputSource + * @see HandlerBase#HandlerBase + */ +class SAX_EXPORT EntityResolver +{ +public: + /** @name Constructors and Destructor */ + //@{ + + /** Default Constructor */ + EntityResolver() + { + } + + /** Destructor */ + virtual ~EntityResolver() + { + } + + //@} + + /** @name The EntityResolver interface */ + //@{ + + /** + * Allow the application to resolve external entities. + * + *

The Parser will call this method before opening any external + * entity except the top-level document entity (including the + * external DTD subset, external entities referenced within the + * DTD, and external entities referenced within the document + * element): the application may request that the parser resolve + * the entity itself, that it use an alternative URI, or that it + * use an entirely different input source.

+ * + *

Application writers can use this method to redirect external + * system identifiers to secure and/or local URIs, to look up + * public identifiers in a catalogue, or to read an entity from a + * database or other input source (including, for example, a dialog + * box).

+ * + *

If the system identifier is a URL, the SAX parser must + * resolve it fully before reporting it to the application.

+ * + * @param publicId The public identifier of the external entity + * being referenced, or null if none was supplied. + * @param systemId The system identifier of the external entity + * being referenced. + * @return An InputSource object describing the new input source, + * or null to request that the parser open a regular + * URI connection to the system identifier. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception IOException An IO exception, + * possibly the result of creating a new InputStream + * or Reader for the InputSource. + * @see InputSource#InputSource + */ + virtual InputSource* resolveEntity + ( + const XMLCh* const publicId + , const XMLCh* const systemId + ) = 0; + + //@} + +private : + /* Unimplemented constructors and operators */ + + + /* Copy constructor */ + EntityResolver(const EntityResolver&); + + /* Assignment operator */ + EntityResolver& operator=(const EntityResolver&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/ErrorHandler.hpp b/include/xercesc/sax/ErrorHandler.hpp new file mode 100644 index 0000000..73b1b90 --- /dev/null +++ b/include/xercesc/sax/ErrorHandler.hpp @@ -0,0 +1,168 @@ +/* + * 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: ErrorHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ERRORHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_ERRORHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class SAXParseException; + + +/** + * Basic interface for SAX error handlers. + * + *

If a SAX application needs to implement customized error + * handling, it must implement this interface and then register an + * instance with the SAX parser using the parser's setErrorHandler + * method. The parser will then report all errors and warnings + * through this interface.

+ * + *

The parser shall use this interface instead of throwing an + * exception: it is up to the application whether to throw an + * exception for different types of errors and warnings. Note, + * however, that there is no requirement that the parser continue to + * provide useful information after a call to fatalError (in other + * words, a SAX driver class could catch an exception and report a + * fatalError).

+ * + *

The HandlerBase class provides a default implementation of this + * interface, ignoring warnings and recoverable errors and throwing a + * SAXParseException for fatal errors. An application may extend + * that class rather than implementing the complete interface + * itself.

+ * + * @see Parser#setErrorHandler + * @see SAXParseException#SAXParseException + * @see HandlerBase#HandlerBase + */ + +class SAX_EXPORT ErrorHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + ErrorHandler() + { + } + + /** Destructor */ + virtual ~ErrorHandler() + { + } + //@} + + /** @name The error handler interface */ + //@{ + /** + * Receive notification of a warning. + * + *

SAX parsers will use this method to report conditions that + * are not errors or fatal errors as defined by the XML 1.0 + * recommendation. The default behaviour is to take no action.

+ * + *

The SAX parser must continue to provide normal parsing events + * after invoking this method: it should still be possible for the + * application to process the document through to the end.

+ * + * @param exc The warning information encapsulated in a + * SAX parse exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see SAXParseException#SAXParseException + */ + virtual void warning(const SAXParseException& exc) = 0; + + /** + * Receive notification of a recoverable error. + * + *

This corresponds to the definition of "error" in section 1.2 + * of the W3C XML 1.0 Recommendation. For example, a validating + * parser would use this callback to report the violation of a + * validity constraint. The default behaviour is to take no + * action.

+ * + *

The SAX parser must continue to provide normal parsing events + * after invoking this method: it should still be possible for the + * application to process the document through to the end. If the + * application cannot do so, then the parser should report a fatal + * error even if the XML 1.0 recommendation does not require it to + * do so.

+ * + * @param exc The error information encapsulated in a + * SAX parse exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see SAXParseException#SAXParseException + */ + virtual void error(const SAXParseException& exc) = 0; + + /** + * Receive notification of a non-recoverable error. + * + *

This corresponds to the definition of "fatal error" in + * section 1.2 of the W3C XML 1.0 Recommendation. For example, a + * parser would use this callback to report the violation of a + * well-formedness constraint.

+ * + *

The application must assume that the document is unusable + * after the parser has invoked this method, and should continue + * (if at all) only for the sake of collecting addition error + * messages: in fact, SAX parsers are free to stop reporting any + * other events once this method has been invoked.

+ * + * @param exc The error information encapsulated in a + * SAX parse exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see SAXParseException#SAXParseException + */ + virtual void fatalError(const SAXParseException& exc) = 0; + + /** + * Reset the Error handler object on its reuse + * + *

This method helps in reseting the Error handler object + * implementation defaults each time the Error handler is begun.

+ * + */ + virtual void resetErrors() = 0; + + + //@} + +private : + /* Unimplemented constructors and operators */ + + /* Copy constructor */ + ErrorHandler(const ErrorHandler&); + + /* Assignment operator */ + ErrorHandler& operator=(const ErrorHandler&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/HandlerBase.hpp b/include/xercesc/sax/HandlerBase.hpp new file mode 100644 index 0000000..1dca8d1 --- /dev/null +++ b/include/xercesc/sax/HandlerBase.hpp @@ -0,0 +1,466 @@ +/* + * 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: HandlerBase.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_HANDLERBASE_HPP) +#define XERCESC_INCLUDE_GUARD_HANDLERBASE_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class Locator; +class AttributeList; + +/** + * Default base class for handlers. + * + *

This class implements the default behaviour for four SAX + * interfaces: EntityResolver, DTDHandler, DocumentHandler, + * and ErrorHandler.

+ * + *

Application writers can extend this class when they need to + * implement only part of an interface; parser writers can + * instantiate this class to provide default handlers when the + * application has not supplied its own.

+ * + *

Note that the use of this class is optional.

+ * + * @see EntityResolver#EntityResolver + * @see DTDHandler#DTDHandler + * @see DocumentHandler#DocumentHandler + * @see ErrorHandler#ErrorHandler + */ + +class SAX_EXPORT HandlerBase : + + public EntityResolver, public DTDHandler, public DocumentHandler + , public ErrorHandler +{ +public: + /** @name Default handlers for the DocumentHandler interface */ + //@{ + /** + * Receive notification of character data inside an element. + * + *

By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of character data + * (such as adding the data to a node or buffer, or printing it to + * a file).

+ * + * @param chars The characters. + * @param length The number of characters to use from the + * character array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#characters + */ + virtual void characters + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of the end of the document. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as finalising a tree or closing an output + * file).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#endDocument + */ + virtual void endDocument(); + + /** + * Receive notification of the end of an element. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each element (such as finalising a tree node or writing + * output to a file).

+ * + * @param name The element type name. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#endElement + */ + virtual void endElement(const XMLCh* const name); + + /** + * Receive notification of ignorable whitespace in element content. + * + *

By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of ignorable + * whitespace (such as adding data to a node or buffer, or printing + * it to a file).

+ * + * @param chars The whitespace characters. + * @param length The number of characters to use from the + * character array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#ignorableWhitespace + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of a processing instruction. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions for each + * processing instruction, such as setting status variables or + * invoking other methods.

+ * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none is supplied. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#processingInstruction + */ + virtual void processingInstruction + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * Reset the Document object on its reuse + * + * @see DocumentHandler#resetDocument + */ + virtual void resetDocument(); + //@} + + /** @name Default implementation of DocumentHandler interface */ + + //@{ + /** + * Receive a Locator object for document events. + * + *

By default, do nothing. Application writers may override this + * method in a subclass if they wish to store the locator for use + * with other document events.

+ * + * @param locator A locator for all SAX document events. + * @see DocumentHandler#setDocumentLocator + * @see Locator + */ + virtual void setDocumentLocator(const Locator* const locator); + + /** + * Receive notification of the beginning of the document. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as allocating the root node of a tree or + * creating an output file).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#startDocument + */ + virtual void startDocument(); + + /** + * Receive notification of the start of an element. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each element (such as allocating a new tree node or writing + * output to a file).

+ * + * @param name The element type name. + * @param attributes The specified or defaulted attributes. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#startElement + */ + virtual void startElement + ( + const XMLCh* const name + , AttributeList& attributes + ); + + //@} + + /** @name Default implementation of the EntityResolver interface. */ + + //@{ + /** + * Resolve an external entity. + * + *

Always return null, so that the parser will use the system + * identifier provided in the XML document. This method implements + * the SAX default behaviour: application writers can override it + * in a subclass to do special translations such as catalog lookups + * or URI redirection.

+ * + * @param publicId The public identifier, or null if none is + * available. + * @param systemId The system identifier provided in the XML + * document. + * @return The new input source, or null to require the + * default behaviour. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see EntityResolver#resolveEntity + */ + virtual InputSource* resolveEntity + ( + const XMLCh* const publicId + , const XMLCh* const systemId + ); + + //@} + + /** @name Default implementation of the ErrorHandler interface */ + //@{ + /** + * Receive notification of a recoverable parser error. + * + *

The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each error, such as inserting the message in a log file or + * printing it to the console.

+ * + * @param exc The warning information encoded as an exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see ErrorHandler#warning + * @see SAXParseException#SAXParseException + */ + virtual void error(const SAXParseException& exc); + + /** + * Report a fatal XML parsing error. + * + *

The default implementation throws a SAXParseException. + * Application writers may override this method in a subclass if + * they need to take specific actions for each fatal error (such as + * collecting all of the errors into a single report): in any case, + * the application must stop all regular processing when this + * method is invoked, since the document is no longer reliable, and + * the parser may no longer report parsing events.

+ * + * @param exc The error information encoded as an exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see ErrorHandler#fatalError + * @see SAXParseException#SAXParseException + */ + virtual void fatalError(const SAXParseException& exc); + + /** + * Receive notification of a parser warning. + * + *

The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each warning, such as inserting the message in a log file or + * printing it to the console.

+ * + * @param exc The warning information encoded as an exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see ErrorHandler#warning + * @see SAXParseException#SAXParseException + */ + virtual void warning(const SAXParseException& exc); + + /** + * Reset the Error handler object on its reuse + * + * @see ErrorHandler#resetErrors + */ + virtual void resetErrors(); + + //@} + + + /** @name Default implementation of DTDHandler interface. */ + //@{ + + /** + * Receive notification of a notation declaration. + * + *

By default, do nothing. Application writers may override this + * method in a subclass if they wish to keep track of the notations + * declared in a document.

+ * + * @param name The notation name. + * @param publicId The notation public identifier, or null if not + * available. + * @param systemId The notation system identifier. + * @see DTDHandler#notationDecl + */ + virtual void notationDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ); + + /** + * Reset the DTD object on its reuse + * + * @see DTDHandler#resetDocType + */ + virtual void resetDocType(); + + /** + * Receive notification of an unparsed entity declaration. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to keep track of the unparsed entities + * declared in a document.

+ * + * @param name The entity name. + * @param publicId The entity public identifier, or null if not + * available. + * @param systemId The entity system identifier. + * @param notationName The name of the associated notation. + * @see DTDHandler#unparsedEntityDecl + */ + virtual void unparsedEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLCh* const notationName + ); + //@} + + HandlerBase() {}; + virtual ~HandlerBase() {}; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + HandlerBase(const HandlerBase&); + HandlerBase& operator=(const HandlerBase&); +}; + + +// --------------------------------------------------------------------------- +// HandlerBase: Inline default implementations +// --------------------------------------------------------------------------- +inline void HandlerBase::characters(const XMLCh* const + , const XMLSize_t) +{ +} + +inline void HandlerBase::endDocument() +{ +} + +inline void HandlerBase::endElement(const XMLCh* const) +{ +} + +inline void HandlerBase::error(const SAXParseException&) +{ +} + +inline void HandlerBase::fatalError(const SAXParseException& exc) +{ + throw exc; +} + +inline void +HandlerBase::ignorableWhitespace( const XMLCh* const + , const XMLSize_t) +{ +} + +inline void HandlerBase::notationDecl( const XMLCh* const + , const XMLCh* const + , const XMLCh* const) +{ +} + +inline void +HandlerBase::processingInstruction( const XMLCh* const + , const XMLCh* const) +{ +} + +inline void HandlerBase::resetErrors() +{ +} + +inline void HandlerBase::resetDocument() +{ +} + +inline void HandlerBase::resetDocType() +{ +} + +inline InputSource* +HandlerBase::resolveEntity( const XMLCh* const + , const XMLCh* const) +{ + return 0; +} + +inline void +HandlerBase::unparsedEntityDecl(const XMLCh* const + , const XMLCh* const + , const XMLCh* const + , const XMLCh* const) +{ +} + +inline void HandlerBase::setDocumentLocator(const Locator* const) +{ +} + +inline void HandlerBase::startDocument() +{ +} + +inline void +HandlerBase::startElement( const XMLCh* const + , AttributeList&) +{ +} + +inline void HandlerBase::warning(const SAXParseException&) +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/InputSource.cpp b/include/xercesc/sax/InputSource.cpp new file mode 100644 index 0000000..2fc922b --- /dev/null +++ b/include/xercesc/sax/InputSource.cpp @@ -0,0 +1,133 @@ +/* + * 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: InputSource.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// InputSource: Destructor +// --------------------------------------------------------------------------- +InputSource::~InputSource() +{ + fMemoryManager->deallocate(fEncoding); + fMemoryManager->deallocate(fPublicId); + fMemoryManager->deallocate(fSystemId); +} + + +// --------------------------------------------------------------------------- +// InputSource: Setter methods +// --------------------------------------------------------------------------- +void InputSource::setEncoding(const XMLCh* const encodingStr) +{ + fMemoryManager->deallocate(fEncoding); + fEncoding = XMLString::replicate(encodingStr, fMemoryManager); +} + + +void InputSource::setPublicId(const XMLCh* const publicId) +{ + fMemoryManager->deallocate(fPublicId); + fPublicId = XMLString::replicate(publicId, fMemoryManager); +} + + +void InputSource::setSystemId(const XMLCh* const systemId) +{ + fMemoryManager->deallocate(fSystemId); + fSystemId = XMLString::replicate(systemId, fMemoryManager); +} + + + +// --------------------------------------------------------------------------- +// InputSource: Hidden Constructors +// --------------------------------------------------------------------------- +InputSource::InputSource(MemoryManager* const manager) : + + fMemoryManager(manager) + , fEncoding(0) + , fPublicId(0) + , fSystemId(0) + , fFatalErrorIfNotFound(true) +{ +} + +InputSource::InputSource(const XMLCh* const systemId, + MemoryManager* const manager) : + + fMemoryManager(manager) + , fEncoding(0) + , fPublicId(0) + , fSystemId(0) + , fFatalErrorIfNotFound(true) +{ + fSystemId = XMLString::replicate(systemId, fMemoryManager); +} + +InputSource::InputSource(const XMLCh* const systemId + , const XMLCh* const publicId + , MemoryManager* const manager) : + + fMemoryManager(manager) + , fEncoding(0) + , fPublicId(0) + , fSystemId(0) + , fFatalErrorIfNotFound(true) +{ + fPublicId = XMLString::replicate(publicId, fMemoryManager); + fSystemId = XMLString::replicate(systemId, fMemoryManager); +} + +InputSource::InputSource(const char* const systemId, + MemoryManager* const manager) : + + fMemoryManager(manager) + , fEncoding(0) + , fPublicId(0) + , fSystemId(0) + , fFatalErrorIfNotFound(true) +{ + fSystemId = XMLString::transcode(systemId, fMemoryManager); +} + +InputSource::InputSource(const char* const systemId + , const char* const publicId + , MemoryManager* const manager) : + + fMemoryManager(manager) + , fEncoding(0) + , fPublicId(0) + , fSystemId(0) + , fFatalErrorIfNotFound(true) +{ + fPublicId = XMLString::transcode(publicId, fMemoryManager); + fSystemId = XMLString::transcode(systemId, fMemoryManager); +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/sax/InputSource.hpp b/include/xercesc/sax/InputSource.hpp new file mode 100644 index 0000000..8fa3d2c --- /dev/null +++ b/include/xercesc/sax/InputSource.hpp @@ -0,0 +1,337 @@ +/* + * 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: InputSource.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_INPUTSOURCE_HPP) +#define XERCESC_INCLUDE_GUARD_INPUTSOURCE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class BinInputStream; + + +/** + * A single input source for an XML entity. + * + *

This class encapsulates information about an input source in a + * single object, which may include a public identifier or a system + * identifier

+ * + *

There are two places that the application will deliver this input + * source to the parser: as the argument to the Parser::parse method, or as + * the return value of the EntityResolver::resolveEntity method.

+ * + *

InputSource is never used directly, but is the base class for a number + * of derived classes for particular types of input sources. Derivatives are + * provided (in the framework/ directory) for URL input sources, memory buffer + * input sources, and so on.

+ * + *

When it is time to parse the input described by an input source, it + * will be asked to create a binary stream for that source. That stream will + * be used to input the data of the source. The derived class provides the + * implementation of the makeStream() method, and provides a type of stream + * of the correct type for the input source it represents. + * + *

An InputSource object belongs to the application: the parser never + * modifies them in any way. They are always passed by const reference so + * the parser will make a copy of any input sources that it must keep + * around beyond the call.

+ * + * @see Parser#parse + * @see EntityResolver#resolveEntity + */ +class SAX_EXPORT InputSource : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // All constructors are hidden, just the destructor is available + // ----------------------------------------------------------------------- + /** @name Destructor */ + //@{ + /** + * Destructor + * + */ + virtual ~InputSource(); + //@} + + + // ----------------------------------------------------------------------- + /** @name Virtual input source interface */ + //@{ + /** + * Makes the byte stream for this input source. + * + *

The derived class must create and return a binary input stream of an + * appropriate type for its kind of data source. The returned stream must + * be dynamically allocated and becomes the parser's property. + *

+ * + * @see BinInputStream + */ + virtual BinInputStream* makeStream() const = 0; + + //@} + + + // ----------------------------------------------------------------------- + /** @name Getter methods */ + //@{ + /** + * An input source can be set to force the parser to assume a particular + * encoding for the data that input source represents, via the setEncoding() + * method. This method returns name of the encoding that is to be forced. + * If the encoding has never been forced, it returns a null pointer. + * + * @return The forced encoding, or null if none was supplied. + * @see #setEncoding + */ + virtual const XMLCh* getEncoding() const; + + + /** + * Get the public identifier for this input source. + * + * @return The public identifier, or null if none was supplied. + * @see #setPublicId + */ + virtual const XMLCh* getPublicId() const; + + + /** + * Get the system identifier for this input source. + * + *

If the system ID is a URL, it will be fully resolved.

+ * + * @return The system identifier. + * @see #setSystemId + */ + virtual const XMLCh* getSystemId() const; + + /** + * Get the flag that indicates if the parser should issue fatal error if this input source + * is not found. + * + * @return True if the parser should issue fatal error if this input source is not found. + * False if the parser issue warning message instead. + * @see #setIssueFatalErrorIfNotFound + */ + virtual bool getIssueFatalErrorIfNotFound() const; + + MemoryManager* getMemoryManager() const; + + //@} + + + // ----------------------------------------------------------------------- + /** @name Setter methods */ + //@{ + + /** + * Set the encoding which will be required for use with the XML text read + * via a stream opened by this input source. + * + *

This is usually not set, allowing the encoding to be sensed in the + * usual XML way. However, in some cases, the encoding in the file is known + * to be incorrect because of intermediate transcoding, for instance + * encapsulation within a MIME document. + * + * @param encodingStr The name of the encoding to force. + */ + virtual void setEncoding(const XMLCh* const encodingStr); + + + /** + * Set the public identifier for this input source. + * + *

The public identifier is always optional: if the application writer + * includes one, it will be provided as part of the location information.

+ * + * @param publicId The public identifier as a string. + * @see Locator#getPublicId + * @see SAXParseException#getPublicId + * @see #getPublicId + */ + virtual void setPublicId(const XMLCh* const publicId); + + /** + * Set the system identifier for this input source. + * + *

Set the system identifier for this input source. + * + *

The system id is always required. The public id may be used to map + * to another system id, but the system id must always be present as a fall + * back. + * + *

If the system ID is a URL, it must be fully resolved.

+ * + * @param systemId The system identifier as a string. + * @see #getSystemId + * @see Locator#getSystemId + * @see SAXParseException#getSystemId + */ + virtual void setSystemId(const XMLCh* const systemId); + + /** + * Indicates if the parser should issue fatal error if this input source + * is not found. If set to false, the parser issue warning message instead. + * + * @param flag True if the parser should issue fatal error if this input source is not found. + * If set to false, the parser issue warning message instead. (Default: true) + * + * @see #getIssueFatalErrorIfNotFound + */ + virtual void setIssueFatalErrorIfNotFound(const bool flag); + + //@} + + +protected : + // ----------------------------------------------------------------------- + // Hidden constructors + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + InputSource(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** Constructor with a system identifier as XMLCh type. + * @param systemId The system identifier (URI). + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + InputSource(const XMLCh* const systemId, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** Constructor with a system and public identifiers + * @param systemId The system identifier (URI). + * @param publicId The public identifier as in the entity definition. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + InputSource + ( + const XMLCh* const systemId + , const XMLCh* const publicId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** Constructor witha system identifier as string + * @param systemId The system identifier (URI). + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + InputSource(const char* const systemId, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** Constructor witha system and public identifiers. Both as string + * @param systemId The system identifier (URI). + * @param publicId The public identifier as in the entity definition. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + InputSource + ( + const char* const systemId + , const char* const publicId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + + + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + InputSource(const InputSource&); + InputSource& operator=(const InputSource&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fEncoding + // This is the encoding to use. Usually this is null, which means + // to use the information found in the file itself. But, if set, + // this encoding will be used without question. + // + // fPublicId + // This is the optional public id for the input source. It can be + // null if none is desired. + // + // fSystemId + // This is the system id for the input source. This is what is + // actually used to open the source. + // + // fFatalErrorIfNotFound + // ----------------------------------------------------------------------- + MemoryManager* const fMemoryManager; + XMLCh* fEncoding; + XMLCh* fPublicId; + XMLCh* fSystemId; + bool fFatalErrorIfNotFound; +}; + + +// --------------------------------------------------------------------------- +// InputSource: Getter methods +// --------------------------------------------------------------------------- +inline const XMLCh* InputSource::getEncoding() const +{ + return fEncoding; +} + +inline const XMLCh* InputSource::getPublicId() const +{ + return fPublicId; +} + +inline const XMLCh* InputSource::getSystemId() const +{ + return fSystemId; +} + +inline bool InputSource::getIssueFatalErrorIfNotFound() const +{ + return fFatalErrorIfNotFound; +} + +inline MemoryManager* InputSource::getMemoryManager() const +{ + return fMemoryManager; +} + +// --------------------------------------------------------------------------- +// InputSource: Setter methods +// --------------------------------------------------------------------------- +inline void InputSource::setIssueFatalErrorIfNotFound(const bool flag) +{ + fFatalErrorIfNotFound = flag; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/Locator.hpp b/include/xercesc/sax/Locator.hpp new file mode 100644 index 0000000..1a451d7 --- /dev/null +++ b/include/xercesc/sax/Locator.hpp @@ -0,0 +1,125 @@ +/* + * 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: Locator.hpp 672273 2008-06-27 13:57:00Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_LOCATOR_HPP) +#define XERCESC_INCLUDE_GUARD_LOCATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Interface for associating a SAX event with a document location. + * + *

If a SAX parser provides location information to the SAX + * application, it does so by implementing this interface and then + * passing an instance to the application using the document + * handler's setDocumentLocator method. The application can use the + * object to obtain the location of any other document handler event + * in the XML source document.

+ * + *

Note that the results returned by the object will be valid only + * during the scope of each document handler method: the application + * will receive unpredictable results if it attempts to use the + * locator at any other time.

+ * + *

SAX parsers are not required to supply a locator, but they are + * very strong encouraged to do so. If the parser supplies a + * locator, it must do so before reporting any other document events. + * If no locator has been set by the time the application receives + * the startDocument event, the application should assume that a + * locator is not available.

+ * + * @see DocumentHandler#setDocumentLocator + */ + +class SAX_EXPORT Locator +{ +public: + + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + Locator() + { + } + + /** Destructor */ + virtual ~Locator() + { + } + + //@} + + /** @name The locator interface */ + //@{ + /** + * Return the public identifier for the current document event. + *

This will be the public identifier + * @return A string containing the public identifier, or + * null if none is available. + * @see #getSystemId + */ + virtual const XMLCh* getPublicId() const = 0; + + /** + * Return the system identifier for the current document event. + * + *

If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.

+ * + * @return A string containing the system identifier, or null + * if none is available. + * @see #getPublicId + */ + virtual const XMLCh* getSystemId() const = 0; + + /** + * Return the line number where the current document event ends. + * Note that this is the line position of the first character + * after the text associated with the document event. + * @return The line number, or 0 if none is available. + * @see #getColumnNumber + */ + virtual XMLFileLoc getLineNumber() const = 0; + + /** + * Return the column number where the current document event ends. + * Note that this is the column number of the first + * character after the text associated with the document + * event. The first column in a line is position 1. + * @return The column number, or 0 if none is available. + * @see #getLineNumber + */ + virtual XMLFileLoc getColumnNumber() const = 0; + //@} + +private : + /* Copy constructor */ + Locator(const Locator&); + + /* Assignment operator */ + Locator& operator=(const Locator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/Parser.hpp b/include/xercesc/sax/Parser.hpp new file mode 100644 index 0000000..f5aa6ff --- /dev/null +++ b/include/xercesc/sax/Parser.hpp @@ -0,0 +1,245 @@ +/* + * 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: Parser.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PARSER_HPP) +#define XERCESC_INCLUDE_GUARD_PARSER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DTDHandler; +class EntityResolver; +class DocumentHandler; +class ErrorHandler; +class InputSource; + +/** + * Basic interface for SAX (Simple API for XML) parsers. + * + * All SAX parsers must implement this basic interface: it allows + * applications to register handlers for different types of events + * and to initiate a parse from a URI, or a character stream. + * + * All SAX parsers must also implement a zero-argument constructor + * (though other constructors are also allowed). + * + * SAX parsers are reusable but not re-entrant: the application + * may reuse a parser object (possibly with a different input source) + * once the first parse has completed successfully, but it may not + * invoke the parse() methods recursively within a parse. + * + * @see EntityResolver#EntityResolver + * @see DTDHandler#DTDHandler + * @see DocumentHandler#DocumentHandler + * @see ErrorHandler#ErrorHandler + * @see HandlerBase#HandlerBase + * @see InputSource#InputSource + */ + +#include + +class SAX_EXPORT Parser +{ +public: + /** @name Constructors and Destructor */ + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + //@{ + /** The default constructor */ + Parser() + { + } + /** The destructor */ + virtual ~Parser() + { + } + //@} + + //----------------------------------------------------------------------- + // The parser interface + //----------------------------------------------------------------------- + /** @name The parser interfaces */ + //@{ + /** + * Allow an application to register a custom entity resolver. + * + * If the application does not register an entity resolver, the + * SAX parser will resolve system identifiers and open connections + * to entities itself (this is the default behaviour implemented in + * HandlerBase). + * + * Applications may register a new or different entity resolver + * in the middle of a parse, and the SAX parser must begin using + * the new resolver immediately. + * + * @param resolver The object for resolving entities. + * @see EntityResolver#EntityResolver + * @see HandlerBase#HandlerBase + */ + virtual void setEntityResolver(EntityResolver* const resolver) = 0; + + /** + * Allow an application to register a DTD event handler. + * + * If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored (this + * is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the middle + * of a parse, and the SAX parser must begin using the new handler + * immediately. + * + * @param handler The DTD handler. + * @see DTDHandler#DTDHandler + * @see HandlerBase#HandlerBase + */ + virtual void setDTDHandler(DTDHandler* const handler) = 0; + + /** + * Allow an application to register a document event handler. + * + * If the application does not register a document handler, all + * document events reported by the SAX parser will be silently + * ignored (this is the default behaviour implemented by + * HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The document handler. + * @see DocumentHandler#DocumentHandler + * @see HandlerBase#HandlerBase + */ + virtual void setDocumentHandler(DocumentHandler* const handler) = 0; + + /** + * Allow an application to register an error event handler. + * + * If the application does not register an error event handler, + * all error events reported by the SAX parser will be silently + * ignored, except for fatalError, which will throw a SAXException + * (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see ErrorHandler#ErrorHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setErrorHandler(ErrorHandler* const handler) = 0; + + /** + * Parse an XML document. + * + * The application can use this method to instruct the SAX parser + * to begin parsing an XML document from any valid input + * source (a character stream, a byte stream, or a URI). + * + * Applications may not invoke this method while a parse is in + * progress (they should create a new Parser instead for each + * additional XML document). Once a parse is complete, an + * application may reuse the same Parser object, possibly with a + * different input source. + * + * @param source The input source for the top-level of the + * XML document. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see InputSource#InputSource + * @see #setEntityResolver + * @see #setDTDHandler + * @see #setDocumentHandler + * @see #setErrorHandler + */ + virtual void parse + ( + const InputSource& source + ) = 0; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(const InputSource&) + */ + virtual void parse + ( + const XMLCh* const systemId + ) = 0; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(const InputSource&) + */ + virtual void parse + ( + const char* const systemId + ) = 0; + //@} + + +private : + /* The copy constructor, you cannot call this directly */ + Parser(const Parser&); + + /* The assignment operator, you cannot call this directly */ + Parser& operator=(const Parser&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/SAXException.cpp b/include/xercesc/sax/SAXException.cpp new file mode 100644 index 0000000..4d86d19 --- /dev/null +++ b/include/xercesc/sax/SAXException.cpp @@ -0,0 +1,74 @@ +/* + * 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: SAXException.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +#include "SAXException.hpp" + +XERCES_CPP_NAMESPACE_BEGIN + + +// SAXNotSupportedException Constructors +SAXNotSupportedException::SAXNotSupportedException(MemoryManager* const manager) + : SAXException(manager) +{ +} + +SAXNotSupportedException::SAXNotSupportedException(const XMLCh* const msg, + MemoryManager* const manager) + : SAXException(msg, manager) +{ +} + +SAXNotSupportedException::SAXNotSupportedException(const char* const msg, + MemoryManager* const manager) + : SAXException(msg, manager) +{ +} + +SAXNotSupportedException::SAXNotSupportedException(const SAXException& toCopy) + : SAXException(toCopy) +{ +} + +// SAXNotRecognizedException Constructors +SAXNotRecognizedException::SAXNotRecognizedException(MemoryManager* const manager) + : SAXException(manager) +{ +} + +SAXNotRecognizedException::SAXNotRecognizedException(const XMLCh* const msg, + MemoryManager* const manager) + : SAXException(msg, manager) +{ +} + +SAXNotRecognizedException::SAXNotRecognizedException(const char* const msg, + MemoryManager* const manager) + : SAXException(msg, manager) +{ +} + +SAXNotRecognizedException::SAXNotRecognizedException(const SAXException& toCopy) + : SAXException(toCopy) +{ +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/sax/SAXException.hpp b/include/xercesc/sax/SAXException.hpp new file mode 100644 index 0000000..53fa43d --- /dev/null +++ b/include/xercesc/sax/SAXException.hpp @@ -0,0 +1,230 @@ +/* + * 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: SAXException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAXEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_SAXEXCEPTION_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * Encapsulate a general SAX error or warning. + * + *

This class can contain basic error or warning information from + * either the XML SAX parser or the application: a parser writer or + * application writer can subclass it to provide additional + * functionality. SAX handlers may throw this exception or + * any exception subclassed from it.

+ * + *

If the application needs to pass through other types of + * exceptions, it must wrap those exceptions in a SAXException + * or an exception derived from a SAXException.

+ * + *

If the parser or application needs to include information + * about a specific location in an XML document, it should use the + * SAXParseException subclass.

+ * + * @see SAXParseException#SAXParseException + */ +class SAX_EXPORT SAXException : public XMemory +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXException(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) : + + fMsg(XMLString::replicate(XMLUni::fgZeroLenString, manager)) + , fMemoryManager(manager) + { + } + + /** + * Create a new SAXException. + * + * @param msg The error or warning message. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXException(const XMLCh* const msg, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) : + + fMsg(XMLString::replicate(msg, manager)) + , fMemoryManager(manager) + { + } + + /** + * Create a new SAXException. + * + * @param msg The error or warning message. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXException(const char* const msg, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) : + + fMsg(XMLString::transcode(msg, manager)) + , fMemoryManager(manager) + { + } + + /** + * Copy constructor + * + * @param toCopy The exception to be copy constructed + */ + SAXException(const SAXException& toCopy) : + XMemory(toCopy) + , fMsg(XMLString::replicate(toCopy.fMsg, toCopy.fMemoryManager)) + , fMemoryManager(toCopy.fMemoryManager) + { + } + + /** Destructor */ + virtual ~SAXException() + { + fMemoryManager->deallocate(fMsg);//delete [] fMsg; + } + + //@} + + + /** @name Public Operators */ + //@{ + /** + * Assignment operator + * + * @param toCopy The object to be copied + */ + SAXException& operator=(const SAXException& toCopy) + { + if (this == &toCopy) + return *this; + + fMemoryManager->deallocate(fMsg);//delete [] fMsg; + fMsg = XMLString::replicate(toCopy.fMsg, toCopy.fMemoryManager); + fMemoryManager = toCopy.fMemoryManager; + return *this; + } + //@} + + /** @name Getter Methods */ + //@{ + /** + * Get the contents of the message + * + */ + virtual const XMLCh* getMessage() const + { + return fMsg; + } + //@} + + +protected : + // ----------------------------------------------------------------------- + // Protected data members + // + // fMsg + // This is the text of the error that is being thrown. + // ----------------------------------------------------------------------- + XMLCh* fMsg; + MemoryManager* fMemoryManager; +}; + +class SAX_EXPORT SAXNotSupportedException : public SAXException +{ + +public: + SAXNotSupportedException(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Create a new SAXException. + * + * @param msg The error or warning message. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXNotSupportedException(const XMLCh* const msg, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Create a new SAXException. + * + * @param msg The error or warning message. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXNotSupportedException(const char* const msg, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Copy constructor + * + * @param toCopy The exception to be copy constructed + */ + SAXNotSupportedException(const SAXException& toCopy); +}; + +class SAX_EXPORT SAXNotRecognizedException : public SAXException +{ +public: + SAXNotRecognizedException(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Create a new SAXException. + * + * @param msg The error or warning message. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXNotRecognizedException(const XMLCh* const msg, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Create a new SAXException. + * + * @param msg The error or warning message. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + */ + SAXNotRecognizedException(const char* const msg, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /** + * Copy constructor + * + * @param toCopy The exception to be copy constructed + */ + SAXNotRecognizedException(const SAXException& toCopy); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax/SAXParseException.cpp b/include/xercesc/sax/SAXParseException.cpp new file mode 100644 index 0000000..4e042ca --- /dev/null +++ b/include/xercesc/sax/SAXParseException.cpp @@ -0,0 +1,125 @@ +/* + * 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: SAXParseException.cpp 672273 2008-06-27 13:57:00Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SAXParseException: Constructors and Destructor +// --------------------------------------------------------------------------- +SAXParseException::SAXParseException(const XMLCh* const message + , const Locator& locator + , MemoryManager* const manager) : + SAXException(message, manager) + , fColumnNumber(locator.getColumnNumber()) + , fLineNumber(locator.getLineNumber()) + , fPublicId(XMLString::replicate(locator.getPublicId(), manager)) + , fSystemId(XMLString::replicate(locator.getSystemId(), manager)) +{ +} + +SAXParseException::SAXParseException(const XMLCh* const message + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLFileLoc lineNumber + , const XMLFileLoc columnNumber + , MemoryManager* const manager) : + SAXException(message, manager) + , fColumnNumber(columnNumber) + , fLineNumber(lineNumber) + , fPublicId(XMLString::replicate(publicId, manager)) + , fSystemId(XMLString::replicate(systemId, manager)) +{ +} + +SAXParseException::SAXParseException(const SAXParseException& toCopy) : + + SAXException(toCopy) + , fColumnNumber(toCopy.fColumnNumber) + , fLineNumber(toCopy.fLineNumber) + , fPublicId(0) + , fSystemId(0) +{ + fPublicId = XMLString::replicate(toCopy.fPublicId, toCopy.fMemoryManager); + fSystemId = XMLString::replicate(toCopy.fSystemId, toCopy.fMemoryManager); +} + +SAXParseException::~SAXParseException() +{ + fMemoryManager->deallocate(fPublicId);//XMLString::release(&fPublicId); + fMemoryManager->deallocate(fSystemId);//XMLString::release(&fSystemId); +} + + +// --------------------------------------------------------------------------- +// SAXParseException: Public operators +// --------------------------------------------------------------------------- +SAXParseException& +SAXParseException::operator=(const SAXParseException& toAssign) +{ + if (this == &toAssign) + return *this; + + fMemoryManager->deallocate(fPublicId);//XMLString::release(&fPublicId); + fMemoryManager->deallocate(fSystemId);//XMLString::release(&fSystemId); + + this->SAXException::operator =(toAssign); + fColumnNumber = toAssign.fColumnNumber; + fLineNumber = toAssign.fLineNumber; + + fPublicId = XMLString::replicate(toAssign.fPublicId, fMemoryManager); + fSystemId = XMLString::replicate(toAssign.fSystemId, fMemoryManager); + + return *this; +} + + +// --------------------------------------------------------------------------- +// SAXParseException: Getter methods +// --------------------------------------------------------------------------- +const XMLCh* SAXParseException::getPublicId() const +{ + return fPublicId; +} + +const XMLCh* SAXParseException::getSystemId() const +{ + return fSystemId; +} + +XMLFileLoc SAXParseException::getLineNumber() const +{ + return fLineNumber; +} + +XMLFileLoc SAXParseException::getColumnNumber() const +{ + return fColumnNumber; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/sax/SAXParseException.hpp b/include/xercesc/sax/SAXParseException.hpp new file mode 100644 index 0000000..3117efa --- /dev/null +++ b/include/xercesc/sax/SAXParseException.hpp @@ -0,0 +1,185 @@ +/* + * 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: SAXParseException.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAXPARSEEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_SAXPARSEEXCEPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class Locator; + +/** + * Encapsulate an XML parse error or warning. + * + *

This exception will include information for locating the error + * in the original XML document. Note that although the application + * will receive a SAXParseException as the argument to the handlers + * in the ErrorHandler interface, the application is not actually + * required to throw the exception; instead, it can simply read the + * information in it and take a different action.

+ * + *

Since this exception is a subclass of SAXException, it + * inherits the ability to wrap another exception.

+ * + * @see SAXException#SAXException + * @see Locator#Locator + * @see ErrorHandler#ErrorHandler + */ +class SAX_EXPORT SAXParseException : public SAXException +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** + * Create a new SAXParseException from a message and a Locator. + * + *

This constructor is especially useful when an application is + * creating its own exception from within a DocumentHandler + * callback.

+ * + * @param message The error or warning message. + * @param locator The locator object for the error or warning. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + * @see Locator#Locator + * @see Parser#setLocale + */ + SAXParseException(const XMLCh* const message, const Locator& locator, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + + /** + * Create a new SAXParseException. + * + *

This constructor is most useful for parser writers.

+ * + *

If the system identifier is a URL, the parser must resolve it + * fully before creating the exception.

+ * + * @param message The error or warning message. + * @param publicId The public identifier of the entity that generated + * the error or warning. + * @param systemId The system identifier of the entity that generated + * the error or warning. + * @param lineNumber The line number of the end of the text that + * caused the error or warning. + * @param columnNumber The column number of the end of the text that + * caused the error or warning. + * @param manager Pointer to the memory manager to be used to + * allocate objects. + * @see Parser#setLocale + */ + SAXParseException + ( + const XMLCh* const message + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLFileLoc lineNumber + , const XMLFileLoc columnNumber + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Copy constructor + * + * @param toCopy The object to be copied + */ + SAXParseException(const SAXParseException& toCopy); + + /** + * Destructor + */ + ~SAXParseException(); + + //@} + + /** @name Assignment operator */ + //@{ + /** + * Assignment operator + * + * @param toAssign The object to be copied through assignment + * + */ + SAXParseException& operator=(const SAXParseException& toAssign); + //@} + + /** @name Getter methods */ + //@{ + /** + * The column number of the end of the text where the exception occurred. + * + *

The first column in a line is position 1.

+ * + * @return An integer representing the column number, or 0 + * if none is available. + * @see Locator#getColumnNumber + */ + XMLFileLoc getColumnNumber() const; + /** + * The line number of the end of the text where the exception occurred. + * + * @return An integer representing the line number, or 0 + * if none is available. + * @see Locator#getLineNumber + */ + XMLFileLoc getLineNumber() const; + /** + * Get the public identifier of the entity where the exception occurred. + * + * @return A string containing the public identifier, or null + * if none is available. + * @see Locator#getPublicId + */ + const XMLCh* getPublicId() const; + /** + * Get the system identifier of the entity where the exception occurred. + * + *

If the system identifier is a URL, it will be resolved + * fully.

+ * + * @return A string containing the system identifier, or null + * if none is available. + * @see Locator#getSystemId + */ + const XMLCh* getSystemId() const; + //@} + +private: + /* Data Members */ + + /* The column in the source text where the error occured. */ + XMLFileLoc fColumnNumber; + /* The line in the source text where the error occured. */ + XMLFileLoc fLineNumber; + /* The public id of the file where the error occured. */ + XMLCh* fPublicId; + /* The system id of the file where the error occured. */ + XMLCh* fSystemId; + + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/Attributes.hpp b/include/xercesc/sax2/Attributes.hpp new file mode 100644 index 0000000..49c7048 --- /dev/null +++ b/include/xercesc/sax2/Attributes.hpp @@ -0,0 +1,313 @@ +/* + * 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: Attributes.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ATTRIBUTES_HPP) +#define XERCESC_INCLUDE_GUARD_ATTRIBUTES_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Interface for an element's attribute specifications. + * + * The SAX2 parser implements this interface and passes an instance + * to the SAX2 application as the last argument of each startElement + * event. + * + * The instance provided will return valid results only during the + * scope of the startElement invocation (to save it for future + * use, the application must make a copy: the AttributesImpl + * helper class provides a convenient constructor for doing so). + * + * An Attributes includes only attributes that have been + * specified or defaulted: \#IMPLIED attributes will not be included. + * + * There are two ways for the SAX application to obtain information + * from the Attributes. First, it can iterate through the entire + * list: + * + * + * public void startElement (String uri, String localpart, String qName, Attributes atts) {
+ *  for (XMLSize_t i = 0; i < atts.getLength(); i++) {
+ *   String Qname = atts.getQName(i);
+ *   String URI = atts.getURI(i)
+ *   String local = atts.GetLocalName(i)
+ *   String type = atts.getType(i);
+ *   String value = atts.getValue(i);
+ *   [...]
+ *  }
+ * } + *
+ * + * (Note that the result of getLength() will be zero if there + * are no attributes.) + * + * As an alternative, the application can request the value or + * type of specific attributes: + * + * + * public void startElement (String uri, String localpart, String qName, Attributes atts) {
+ *  String identifier = atts.getValue("id");
+ *  String label = atts.getValue("label");
+ *  [...]
+ * } + *
+ * + * The AttributesImpl helper class provides a convenience + * implementation for use by parser or application writers. + * + * @see Sax2DocumentHandler#startElement + * @see AttributesImpl#AttributesImpl + */ + +class SAX2_EXPORT Attributes +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + Attributes() + { + } + + /** Destructor */ + virtual ~Attributes() + { + } + //@} + + /** @name The virtual attribute list interface */ + //@{ + /** + * Return the number of attributes in this list. + * + * The SAX parser may provide attributes in any + * arbitrary order, regardless of the order in which they were + * declared or specified. The number of attributes may be + * zero. + * + * @return The number of attributes in the list. + */ + virtual XMLSize_t getLength() const = 0; + + /** + * Return the namespace URI of an attribute in this list (by position). + * + * The QNames must be unique: the SAX parser shall not include the + * same attribute twice. Attributes without values (those declared + * \#IMPLIED without a value specified in the start tag) will be + * omitted from the list. + * + * @param index The index of the attribute in the list (starting at 0). + * @return The URI of the indexed attribute, or null + * if the index is out of range. + * @see #getLength + */ + virtual const XMLCh* getURI(const XMLSize_t index) const = 0; + + /** + * Return the local name of an attribute in this list (by position). + * + * The QNames must be unique: the SAX parser shall not include the + * same attribute twice. Attributes without values (those declared + * \#IMPLIED without a value specified in the start tag) will be + * omitted from the list. + * + * @param index The index of the attribute in the list (starting at 0). + * @return The local name of the indexed attribute, or null + * if the index is out of range. + * @see #getLength + */ + virtual const XMLCh* getLocalName(const XMLSize_t index) const = 0; + + /** + * Return the qName of an attribute in this list (by position). + * + * The QNames must be unique: the SAX parser shall not include the + * same attribute twice. Attributes without values (those declared + * \#IMPLIED without a value specified in the start tag) will be + * omitted from the list. + * + * @param index The index of the attribute in the list (starting at 0). + * @return The qName of the indexed attribute, or null + * if the index is out of range. + * @see #getLength + */ + virtual const XMLCh* getQName(const XMLSize_t index) const = 0; + + /** + * Return the type of an attribute in the list (by position). + * + * The attribute type is one of the strings "CDATA", "ID", + * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", + * or "NOTATION" (always in upper case). + * + * If the parser has not read a declaration for the attribute, + * or if the parser does not report attribute types, then it must + * return the value "CDATA" as stated in the XML 1.0 Recommendation + * (clause 3.3.3, "Attribute-Value Normalization"). + * + * For an enumerated attribute that is not a notation, the + * parser will report the type as "NMTOKEN". + * + * @param index The index of the attribute in the list (starting at 0). + * @return The attribute type as a string, or + * null if the index is out of range. + * @see #getLength + * @see #getType + */ + virtual const XMLCh* getType(const XMLSize_t index) const = 0; + + /** + * Return the value of an attribute in the list (by position). + * + * If the attribute value is a list of tokens (IDREFS, + * ENTITIES, or NMTOKENS), the tokens will be concatenated + * into a single string separated by whitespace. + * + * @param index The index of the attribute in the list (starting at 0). + * @return The attribute value as a string, or + * null if the index is out of range. + * @see #getLength + * @see #getValue + */ + virtual const XMLCh* getValue(const XMLSize_t index) const = 0; + + //////////////////////////////////////////////////////////////////// + // Name-based query. + //////////////////////////////////////////////////////////////////// + + /** + * Look up the index of an attribute by Namespace name. Non-standard + * extension. + * + * @param uri The Namespace URI, or the empty string if + * the name has no Namespace URI. + * @param localPart The attribute's local name. + * @param index Reference to the variable where the index will be stored. + * @return true if the attribute is found and false otherwise. + */ + virtual bool getIndex(const XMLCh* const uri, + const XMLCh* const localPart, + XMLSize_t& index) const = 0 ; + + /** + * Look up the index of an attribute by Namespace name. + * + * @param uri The Namespace URI, or the empty string if + * the name has no Namespace URI. + * @param localPart The attribute's local name. + * @return The index of the attribute, or -1 if it does not + * appear in the list. + */ + virtual int getIndex(const XMLCh* const uri, + const XMLCh* const localPart ) const = 0 ; + + /** + * Look up the index of an attribute by XML 1.0 qualified name. + * Non-standard extension. + * + * @param qName The qualified (prefixed) name. + * @param index Reference to the variable where the index will be stored. + * @return true if the attribute is found and false otherwise. + */ + virtual bool getIndex(const XMLCh* const qName, + XMLSize_t& index) const = 0 ; + + /** + * Look up the index of an attribute by XML 1.0 qualified name. + * + * @param qName The qualified (prefixed) name. + * @return The index of the attribute, or -1 if it does not + * appear in the list. + */ + virtual int getIndex(const XMLCh* const qName ) const = 0 ; + + /** + * Look up an attribute's type by Namespace name. + * + *

See #getType for a description of the possible types.

+ * + * @param uri The Namespace URI, or the empty String if the + * name has no Namespace URI. + * @param localPart The local name of the attribute. + * @return The attribute type as a string, or null if the + * attribute is not in the list or if Namespace + * processing is not being performed. + */ + virtual const XMLCh* getType(const XMLCh* const uri, + const XMLCh* const localPart ) const = 0 ; + + /** + * Look up an attribute's type by XML 1.0 qualified name. + * + *

See #getType for a description of the possible types.

+ * + * @param qName The XML 1.0 qualified name. + * @return The attribute type as a string, or null if the + * attribute is not in the list or if qualified names + * are not available. + */ + virtual const XMLCh* getType(const XMLCh* const qName) const = 0; + + /** + * Look up an attribute's value by Namespace name. + * + *

See #getValue for a description of the possible values.

+ * + * @param uri The Namespace URI, or the empty String if the + * name has no Namespace URI. + * @param localPart The local name of the attribute. + * @return The attribute value as a string, or null if the + * attribute is not in the list. + */ + virtual const XMLCh* getValue(const XMLCh* const uri, const XMLCh* const localPart ) const = 0 ; + + /** + * Look up an attribute's value by XML 1.0 qualified name. + * + *

See #getValue for a description of the possible values.

+ * + * @param qName The XML 1.0 qualified name. + * @return The attribute value as a string, or null if the + * attribute is not in the list or if qualified names + * are not available. + */ + virtual const XMLCh* getValue(const XMLCh* const qName) const = 0; + + //@} + +private : + /* Constructors and operators */ + /* Copy constructor */ + Attributes(const Attributes&); + /* Assignment operator */ + Attributes& operator=(const Attributes&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/ContentHandler.hpp b/include/xercesc/sax2/ContentHandler.hpp new file mode 100644 index 0000000..bb9ab69 --- /dev/null +++ b/include/xercesc/sax2/ContentHandler.hpp @@ -0,0 +1,340 @@ +/* + * 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: ContentHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_CONTENTHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_CONTENTHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class Attributes; +class Locator; + +/** + * Receive notification of general document events. + * + *

This is the main interface that most SAX2 applications + * implement: if the application needs to be informed of basic parsing + * events, it implements this interface and registers an instance with + * the SAX2 parser using the setDocumentHandler method. The parser + * uses the instance to report basic document-related events like + * the start and end of elements and character data.

+ * + *

The order of events in this interface is very important, and + * mirrors the order of information in the document itself. For + * example, all of an element's content (character data, processing + * instructions, and/or subelements) will appear, in order, between + * the startElement event and the corresponding endElement event.

+ * + *

Application writers who do not want to implement the entire + * interface while can derive a class from Sax2HandlerBase, which implements + * the default functionality; parser writers can instantiate + * Sax2HandlerBase to obtain a default handler. The application can find + * the location of any document event using the Locator interface + * supplied by the Parser through the setDocumentLocator method.

+ * + * @see Parser#setDocumentHandler + * @see Locator#Locator + * @see Sax2HandlerBase#Sax2HandlerBase + */ + +class SAX2_EXPORT ContentHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + ContentHandler() + { + } + + /** Destructor */ + virtual ~ContentHandler() + { + } + //@} + + /** @name The virtual document handler interface */ + + //@{ + /** + * Receive notification of character data. + * + *

The Parser will call this method to report each chunk of + * character data. SAX parsers may return all contiguous character + * data in a single chunk, or they may split it into several + * chunks; however, all of the characters in any single event + * must come from the same external entity, so that the Locator + * provides useful information.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + *

Note that some parsers will report whitespace using the + * ignorableWhitespace() method rather than this one (validating + * parsers must do so).

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #ignorableWhitespace + * @see Locator#Locator + */ + virtual void characters + ( + const XMLCh* const chars + , const XMLSize_t length + ) = 0; + + /** + * Receive notification of the end of a document. + * + *

The SAX parser will invoke this method only once, and it will + * be the last method invoked during the parse. The parser shall + * not invoke this method until it has either abandoned parsing + * (because of an unrecoverable error) or reached the end of + * input.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endDocument () = 0; + + /** + * Receive notification of the end of an element. + * + *

The SAX parser will invoke this method at the end of every + * element in the XML document; there will be a corresponding + * startElement() event for every endElement() event (even when the + * element is empty).

+ * + * @param uri The URI of the associated namespace for this element + * @param localname The local part of the element name + * @param qname The QName of this element + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endElement + ( + const XMLCh* const uri, + const XMLCh* const localname, + const XMLCh* const qname + ) = 0; + + /** + * Receive notification of ignorable whitespace in element content. + * + *

Validating Parsers must use this method to report each chunk + * of ignorable whitespace (see the W3C XML 1.0 recommendation, + * section 2.10): non-validating parsers may also use this method + * if they are capable of parsing and using content models.

+ * + *

SAX parsers may return all contiguous whitespace in a single + * chunk, or they may split it into several chunks; however, all of + * the characters in any single event must come from the same + * external entity, so that the Locator provides useful + * information.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #characters + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ) = 0; + + /** + * Receive notification of a processing instruction. + * + *

The Parser will invoke this method once for each processing + * instruction found: note that processing instructions may occur + * before or after the main document element.

+ * + *

A SAX parser should never report an XML declaration (XML 1.0, + * section 2.8) or a text declaration (XML 1.0, section 4.3.1) + * using this method.

+ * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none was supplied. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void processingInstruction + ( + const XMLCh* const target + , const XMLCh* const data + ) = 0; + + /** + * Receive an object for locating the origin of SAX document events. + * + * SAX parsers are strongly encouraged (though not absolutely + * required) to supply a locator: if it does so, it must supply + * the locator to the application by invoking this method before + * invoking any of the other methods in the DocumentHandler + * interface. + * + * The locator allows the application to determine the end + * position of any document-related event, even if the parser is + * not reporting an error. Typically, the application will + * use this information for reporting its own errors (such as + * character content that does not match an application's + * business rules). The information returned by the locator + * is probably not sufficient for use with a search engine. + * + * Note that the locator will return correct information only + * during the invocation of the events in this interface. The + * application should not attempt to use it at any other time. + * + * @param locator An object that can return the location of + * any SAX document event. The object is only + * 'on loan' to the client code and they are not + * to attempt to delete or modify it in any way! + * + * @see Locator#Locator + */ + virtual void setDocumentLocator(const Locator* const locator) = 0; + + /** + * Receive notification of the beginning of a document. + * + *

The SAX parser will invoke this method only once, before any + * other methods in this interface or in DTDHandler (except for + * setDocumentLocator).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startDocument() = 0; + + /** + * Receive notification of the beginning of an element. + * + *

The Parser will invoke this method at the beginning of every + * element in the XML document; there will be a corresponding + * endElement() event for every startElement() event (even when the + * element is empty). All of the element's content will be + * reported, in order, before the corresponding endElement() + * event.

+ * + *

Note that the attribute list provided will + * contain only attributes with explicit values (specified or + * defaulted): \#IMPLIED attributes will be omitted.

+ * + * @param uri The URI of the associated namespace for this element + * @param localname The local part of the element name + * @param qname The QName of this element + * @param attrs The attributes attached to the element, if any. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #endElement + * @see Attributes#Attributes + */ + virtual void startElement + ( + const XMLCh* const uri, + const XMLCh* const localname, + const XMLCh* const qname, + const Attributes& attrs + ) = 0; + + /** + * Receive notification of the start of an namespace prefix mapping. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each namespace prefix mapping.

+ * + * @param prefix The namespace prefix used + * @param uri The namespace URI used. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startPrefixMapping + ( + const XMLCh* const prefix, + const XMLCh* const uri + ) = 0 ; + + /** + * Receive notification of the end of an namespace prefix mapping. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each namespace prefix mapping.

+ * + * @param prefix The namespace prefix used + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endPrefixMapping + ( + const XMLCh* const prefix + ) = 0 ; + + /** + * Receive notification of a skipped entity + * + *

The parser will invoke this method once for each entity + * skipped. All processors may skip external entities, + * depending on the values of the features:
+ * http://xml.org/sax/features/external-general-entities
+ * http://xml.org/sax/features/external-parameter-entities

+ * + *

Note: Xerces (specifically) never skips any entities, regardless + * of the above features. This function is never called in the + * Xerces implementation of SAX2.

+ * + *

Introduced with SAX2

+ * + * @param name The name of the skipped entity. If it is a parameter entity, + * the name will begin with %, and if it is the external DTD subset, + * it will be the string [dtd]. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void skippedEntity + ( + const XMLCh* const name + ) = 0 ; + + //@} +private : + /* Unimplemented Constructors and operators */ + /* Copy constructor */ + ContentHandler(const ContentHandler&); + /** Assignment operator */ + ContentHandler& operator=(const ContentHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/DeclHandler.hpp b/include/xercesc/sax2/DeclHandler.hpp new file mode 100644 index 0000000..8127c00 --- /dev/null +++ b/include/xercesc/sax2/DeclHandler.hpp @@ -0,0 +1,163 @@ +/* + * 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: DeclHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DECLHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DECLHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Receive notification of DTD declaration events. + * + *

This is an optional extension handler for SAX2 to provide more + * complete information about DTD declarations in an XML document. + * XML readers are not required to recognize this handler, and it is not + * part of core-only SAX2 distributions.

+ * + *

Note that data-related DTD declarations (unparsed entities and + * notations) are already reported through the DTDHandler interface.

+ * + *

If you are using the declaration handler together with a lexical + * handler, all of the events will occur between the startDTD and the endDTD + * events.

+ * + * @see SAX2XMLReader#setLexicalHandler + * @see SAX2XMLReader#setDeclarationHandler + */ + +class SAX2_EXPORT DeclHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + DeclHandler() + { + } + + /** Destructor */ + virtual ~DeclHandler() + { + } + //@} + + /** @name The virtual declaration handler interface */ + + //@{ + /** + * Report an element type declaration. + * + *

The content model will consist of the string "EMPTY", the string + * "ANY", or a parenthesised group, optionally followed by an occurrence + * indicator. The model will be normalized so that all parameter entities + * are fully resolved and all whitespace is removed,and will include the + * enclosing parentheses. Other normalization (such as removing redundant + * parentheses or simplifying occurrence indicators) is at the discretion + * of the parser.

+ * + * @param name The element type name. + * @param model The content model as a normalized string. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void elementDecl + ( + const XMLCh* const name + , const XMLCh* const model + ) = 0; + + /** + * Report an attribute type declaration. + * + *

The Parser will call this method to report each occurrence of + * a comment in the XML document.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @param eName The name of the associated element. + * @param aName The name of the attribute. + * @param type A string representing the attribute type. + * @param mode A string representing the attribute defaulting mode ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if none of these applies. + * @param value A string representing the attribute's default value, or null if there is none. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void attributeDecl + ( + const XMLCh* const eName + , const XMLCh* const aName + , const XMLCh* const type + , const XMLCh* const mode + , const XMLCh* const value + ) = 0; + + /** + * Report an internal entity declaration. + * + *

Only the effective (first) declaration for each entity will be + * reported. All parameter entities in the value will be expanded, but + * general entities will not.

+ * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param value The replacement text of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void internalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const value + ) = 0; + + /** + * Report a parsed external entity declaration. + * + *

Only the effective (first) declaration for each entity will + * be reported.

+ * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param publicId The The declared public identifier of the entity, or null if none was declared. + * @param systemId The declared system identifier of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void externalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ) = 0; + + //@} +private : + /* Unimplemented Constructors and operators */ + /* Copy constructor */ + DeclHandler(const DeclHandler&); + /** Assignment operator */ + DeclHandler& operator=(const DeclHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/DefaultHandler.hpp b/include/xercesc/sax2/DefaultHandler.hpp new file mode 100644 index 0000000..307de74 --- /dev/null +++ b/include/xercesc/sax2/DefaultHandler.hpp @@ -0,0 +1,806 @@ +/* + * 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: DefaultHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DEFAULTHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DEFAULTHANDLER_HPP + +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class Locator; +class Attributes; + +/** + * Default base class for SAX2 handlers. + * + *

This class implements the default behaviour for SAX2 + * interfaces: EntityResolver, DTDHandler, ContentHandler, + * ErrorHandler, LexicalHandler, and DeclHandler.

+ * + *

Application writers can extend this class when they need to + * implement only part of an interface; parser writers can + * instantiate this class to provide default handlers when the + * application has not supplied its own.

+ * + *

Note that the use of this class is optional.

+ * + * @see EntityResolver#EntityResolver + * @see DTDHandler#DTDHandler + * @see ContentHandler#ContentHandler + * @see ErrorHandler#ErrorHandler + * @see LexicalHandler#LexicalHandler + * @see DeclHandler#DeclHandler + */ + +class SAX2_EXPORT DefaultHandler : + + public EntityResolver, + public DTDHandler, + public ContentHandler, + public ErrorHandler, + public LexicalHandler, + public DeclHandler +{ +public: + /** @name Default handlers for the DocumentHandler interface */ + //@{ + /** + * Receive notification of character data inside an element. + * + *

By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of character data + * (such as adding the data to a node or buffer, or printing it to + * a file).

+ * + * @param chars The characters. + * @param length The number of characters to use from the + * character array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#characters + */ + virtual void characters + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of the end of the document. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as finalising a tree or closing an output + * file).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#endDocument + */ + virtual void endDocument(); + + /** + * Receive notification of the end of an element. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each element (such as finalising a tree node or writing + * output to a file).

+ * + * @param uri The URI of the associated namespace for this element + * @param localname The local part of the element name + * @param qname The QName of this element + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#endElement + */ + virtual void endElement + ( + const XMLCh* const uri, + const XMLCh* const localname, + const XMLCh* const qname + ); + + /** + * Receive notification of ignorable whitespace in element content. + * + *

By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of ignorable + * whitespace (such as adding data to a node or buffer, or printing + * it to a file).

+ * + * @param chars The whitespace characters. + * @param length The number of characters to use from the + * character array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#ignorableWhitespace + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of a processing instruction. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions for each + * processing instruction, such as setting status variables or + * invoking other methods.

+ * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none is supplied. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#processingInstruction + */ + virtual void processingInstruction + ( + const XMLCh* const target + , const XMLCh* const data + ); + + /** + * Reset the Document object on its reuse + * + * @see DocumentHandler#resetDocument + */ + virtual void resetDocument(); + //@} + + /** @name Default implementation of DocumentHandler interface */ + + //@{ + /** + * Receive a Locator object for document events. + * + *

By default, do nothing. Application writers may override this + * method in a subclass if they wish to store the locator for use + * with other document events.

+ * + * @param locator A locator for all SAX document events. + * @see DocumentHandler#setDocumentLocator + * @see Locator + */ + virtual void setDocumentLocator(const Locator* const locator); + + /** + * Receive notification of the beginning of the document. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as allocating the root node of a tree or + * creating an output file).

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#startDocument + */ + virtual void startDocument(); + + /** + * Receive notification of the start of an element. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each element (such as allocating a new tree node or writing + * output to a file).

+ * + * @param uri The URI of the associated namespace for this element + * @param localname the local part of the element name + * @param qname the QName of this element + * @param attrs The specified or defaulted attributes. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#startElement + */ + virtual void startElement + ( + const XMLCh* const uri, + const XMLCh* const localname, + const XMLCh* const qname + , const Attributes& attrs + ); + + /** + * Receive notification of the start of an namespace prefix mapping. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each namespace prefix mapping.

+ * + * @param prefix The namespace prefix used + * @param uri The namespace URI used. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#startPrefixMapping + */ + virtual void startPrefixMapping + ( + const XMLCh* const prefix, + const XMLCh* const uri + ) ; + + /** + * Receive notification of the end of an namespace prefix mapping. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each namespace prefix mapping.

+ * + * @param prefix The namespace prefix used + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see DocumentHandler#endPrefixMapping + */ + virtual void endPrefixMapping + ( + const XMLCh* const prefix + ) ; + + /** + * Receive notification of a skipped entity + * + *

The parser will invoke this method once for each entity + * skipped. All processors may skip external entities, + * depending on the values of the features:
+ * http://xml.org/sax/features/external-general-entities
+ * http://xml.org/sax/features/external-parameter-entities

+ * + *

Introduced with SAX2

+ * + * @param name The name of the skipped entity. If it is a parameter entity, + * the name will begin with %, and if it is the external DTD subset, + * it will be the string [dtd]. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void skippedEntity + ( + const XMLCh* const name + ) ; + + //@} + + /** @name Default implementation of the EntityResolver interface. */ + + //@{ + /** + * Resolve an external entity. + * + *

Always return null, so that the parser will use the system + * identifier provided in the XML document. This method implements + * the SAX default behaviour: application writers can override it + * in a subclass to do special translations such as catalog lookups + * or URI redirection.

+ * + * @param publicId The public identifier, or null if none is + * available. + * @param systemId The system identifier provided in the XML + * document. + * @return The new input source, or null to require the + * default behaviour. + * The returned InputSource is owned by the parser which is + * responsible to clean up the memory. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see EntityResolver#resolveEntity + */ + virtual InputSource* resolveEntity + ( + const XMLCh* const publicId + , const XMLCh* const systemId + ); + + //@} + + /** @name Default implementation of the ErrorHandler interface */ + //@{ + /** + * Receive notification of a recoverable parser error. + * + *

The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each error, such as inserting the message in a log file or + * printing it to the console.

+ * + * @param exc The warning information encoded as an exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see ErrorHandler#warning + * @see SAXParseException#SAXParseException + */ + virtual void error(const SAXParseException& exc); + + /** + * Report a fatal XML parsing error. + * + *

The default implementation throws a SAXParseException. + * Application writers may override this method in a subclass if + * they need to take specific actions for each fatal error (such as + * collecting all of the errors into a single report): in any case, + * the application must stop all regular processing when this + * method is invoked, since the document is no longer reliable, and + * the parser may no longer report parsing events.

+ * + * @param exc The error information encoded as an exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see ErrorHandler#fatalError + * @see SAXParseException#SAXParseException + */ + virtual void fatalError(const SAXParseException& exc); + + /** + * Receive notification of a parser warning. + * + *

The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each warning, such as inserting the message in a log file or + * printing it to the console.

+ * + * @param exc The warning information encoded as an exception. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @see ErrorHandler#warning + * @see SAXParseException#SAXParseException + */ + virtual void warning(const SAXParseException& exc); + + /** + * Reset the Error handler object on its reuse + * + * @see ErrorHandler#resetErrors + */ + virtual void resetErrors(); + + //@} + + + /** @name Default implementation of DTDHandler interface. */ + //@{ + + /** + * Receive notification of a notation declaration. + * + *

By default, do nothing. Application writers may override this + * method in a subclass if they wish to keep track of the notations + * declared in a document.

+ * + * @param name The notation name. + * @param publicId The notation public identifier, or null if not + * available. + * @param systemId The notation system identifier. + * @see DTDHandler#notationDecl + */ + virtual void notationDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ); + + /** + * Reset the DTD object on its reuse + * + * @see DTDHandler#resetDocType + */ + virtual void resetDocType(); + + /** + * Receive notification of an unparsed entity declaration. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to keep track of the unparsed entities + * declared in a document.

+ * + * @param name The entity name. + * @param publicId The entity public identifier, or null if not + * available. + * @param systemId The entity system identifier. + * @param notationName The name of the associated notation. + * @see DTDHandler#unparsedEntityDecl + */ + virtual void unparsedEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + , const XMLCh* const notationName + ); + //@} + + + /** @name Default implementation of LexicalHandler interface. */ + + //@{ + /** + * Receive notification of comments. + * + *

The Parser will call this method to report each occurrence of + * a comment in the XML document.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void comment + ( + const XMLCh* const chars + , const XMLSize_t length + ); + + /** + * Receive notification of the end of a CDATA section. + * + *

The SAX parser will invoke this method at the end of + * each CDATA parsed.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endCDATA (); + + /** + * Receive notification of the end of the DTD declarations. + * + *

The SAX parser will invoke this method at the end of the + * DTD

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endDTD (); + + /** + * Receive notification of the end of an entity. + * + *

The SAX parser will invoke this method at the end of an + * entity

+ * + * @param name The name of the entity that is ending. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endEntity (const XMLCh* const name); + + /** + * Receive notification of the start of a CDATA section. + * + *

The SAX parser will invoke this method at the start of + * each CDATA parsed.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startCDATA (); + + /** + * Receive notification of the start of the DTD declarations. + * + *

The SAX parser will invoke this method at the start of the + * DTD

+ * + * @param name The document type name. + * @param publicId The declared public identifier for the external DTD subset, or null if none was declared. + * @param systemId The declared system identifier for the external DTD subset, or null if none was declared. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startDTD + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ); + + /** + * Receive notification of the start of an entity. + * + *

The SAX parser will invoke this method at the start of an + * entity

+ * + * @param name The name of the entity that is starting. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startEntity (const XMLCh* const name); + + //@} + + /** @name Default implementation of DeclHandler interface. */ + + //@{ + + /** + * Report an element type declaration. + * + *

The content model will consist of the string "EMPTY", the string + * "ANY", or a parenthesised group, optionally followed by an occurrence + * indicator. The model will be normalized so that all parameter entities + * are fully resolved and all whitespace is removed,and will include the + * enclosing parentheses. Other normalization (such as removing redundant + * parentheses or simplifying occurrence indicators) is at the discretion + * of the parser.

+ * + * @param name The element type name. + * @param model The content model as a normalized string. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void elementDecl + ( + const XMLCh* const name + , const XMLCh* const model + ); + + /** + * Report an attribute type declaration. + * + *

Only the effective (first) declaration for an attribute will + * be reported.

+ * + * @param eName The name of the associated element. + * @param aName The name of the attribute. + * @param type A string representing the attribute type. + * @param mode A string representing the attribute defaulting mode ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if none of these applies. + * @param value A string representing the attribute's default value, or null if there is none. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void attributeDecl + ( + const XMLCh* const eName + , const XMLCh* const aName + , const XMLCh* const type + , const XMLCh* const mode + , const XMLCh* const value + ); + + /** + * Report an internal entity declaration. + * + *

Only the effective (first) declaration for each entity will be + * reported. All parameter entities in the value will be expanded, but + * general entities will not.

+ * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param value The replacement text of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void internalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const value + ); + + /** + * Report a parsed external entity declaration. + * + *

Only the effective (first) declaration for each entity will + * be reported.

+ * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param publicId The The declared public identifier of the entity, or null if none was declared. + * @param systemId The declared system identifier of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void externalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ); + + //@} + + DefaultHandler() {}; + virtual ~DefaultHandler() {}; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DefaultHandler(const DefaultHandler&); + DefaultHandler& operator=(const DefaultHandler&); +}; + + +// --------------------------------------------------------------------------- +// HandlerBase: Inline default implementations +// --------------------------------------------------------------------------- +inline void DefaultHandler::characters(const XMLCh* const + ,const XMLSize_t) +{ +} + +inline void DefaultHandler::endDocument() +{ +} + +inline void DefaultHandler::endElement(const XMLCh* const + , const XMLCh* const + , const XMLCh* const) +{ +} + +inline void DefaultHandler::error(const SAXParseException&) +{ +} + +inline void DefaultHandler::fatalError(const SAXParseException& exc) +{ + throw exc; +} + +inline void +DefaultHandler::ignorableWhitespace( const XMLCh* const + , const XMLSize_t) +{ +} + +inline void DefaultHandler::notationDecl( const XMLCh* const + , const XMLCh* const + , const XMLCh* const) +{ +} + +inline void +DefaultHandler::processingInstruction( const XMLCh* const + , const XMLCh* const) +{ +} + +inline void DefaultHandler::resetErrors() +{ +} + +inline void DefaultHandler::resetDocument() +{ +} + +inline void DefaultHandler::resetDocType() +{ +} + +inline InputSource* +DefaultHandler::resolveEntity( const XMLCh* const + , const XMLCh* const) +{ + return 0; +} + +inline void +DefaultHandler::unparsedEntityDecl(const XMLCh* const + , const XMLCh* const + , const XMLCh* const + , const XMLCh* const) +{ +} + +inline void DefaultHandler::setDocumentLocator(const Locator* const) +{ +} + +inline void DefaultHandler::startDocument() +{ +} + +inline void +DefaultHandler::startElement( const XMLCh* const + , const XMLCh* const + , const XMLCh* const + , const Attributes& +) +{ +} + +inline void DefaultHandler::warning(const SAXParseException&) +{ +} + +inline void DefaultHandler::startPrefixMapping ( const XMLCh* const + ,const XMLCh* const) +{ +} + +inline void DefaultHandler::endPrefixMapping ( const XMLCh* const) +{ +} + +inline void DefaultHandler::skippedEntity ( const XMLCh* const) +{ +} + +inline void DefaultHandler::comment( const XMLCh* const + , const XMLSize_t) +{ +} + +inline void DefaultHandler::endCDATA () +{ +} + +inline void DefaultHandler::endDTD () +{ +} + +inline void DefaultHandler::endEntity (const XMLCh* const) +{ +} + +inline void DefaultHandler::startCDATA () +{ +} + +inline void DefaultHandler::startDTD( const XMLCh* const + , const XMLCh* const + , const XMLCh* const) +{ +} + +inline void DefaultHandler::startEntity (const XMLCh* const) +{ +} + +inline void DefaultHandler::attributeDecl(const XMLCh* const, + const XMLCh* const, + const XMLCh* const, + const XMLCh* const, + const XMLCh* const) +{ +} + +inline void DefaultHandler::elementDecl(const XMLCh* const, + const XMLCh* const) +{ +} + +inline void DefaultHandler::externalEntityDecl(const XMLCh* const, + const XMLCh* const, + const XMLCh* const) +{ +} + +inline void DefaultHandler::internalEntityDecl(const XMLCh* const, + const XMLCh* const) +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif // ! DEFAULTHANDLER_HPP diff --git a/include/xercesc/sax2/LexicalHandler.hpp b/include/xercesc/sax2/LexicalHandler.hpp new file mode 100644 index 0000000..96603e7 --- /dev/null +++ b/include/xercesc/sax2/LexicalHandler.hpp @@ -0,0 +1,172 @@ +/* + * 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: LexicalHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_LEXICALHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_LEXICALHANDLER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Receive notification of lexical events. + * + *

This is an extension handler for that provides lexical information + * about an XML document. It does not provide information about document + * content. For those events, an application must register an instance of + * a ContentHandler.

+ * + *

The order of events in this interface is very important, and + * mirrors the order of information in the document itself. For + * example, startDTD() and endDTD() events will occur before the + * first element in the document.

+ * + * @see SAX2XMLReader#setLexicalHandler + * @see SAX2XMLReader#setContentHandler + */ + +class SAX2_EXPORT LexicalHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + LexicalHandler() + { + } + + /** Destructor */ + virtual ~LexicalHandler() + { + } + //@} + + /** @name The virtual document handler interface */ + + //@{ + /** + * Receive notification of comments. + * + *

The Parser will call this method to report each occurrence of + * a comment in the XML document.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @param chars The characters from the XML document. + * @param length The number of characters to read from the array. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void comment + ( + const XMLCh* const chars + , const XMLSize_t length + ) = 0; + + /** + * Receive notification of the end of a CDATA section. + * + *

The SAX parser will invoke this method at the end of + * each CDATA parsed.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endCDATA () = 0; + + /** + * Receive notification of the end of the DTD declarations. + * + *

The SAX parser will invoke this method at the end of the + * DTD

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endDTD () = 0; + + /** + * Receive notification of the end of an entity. + * + *

The SAX parser will invoke this method at the end of an + * entity

+ * + * @param name The name of the entity that is ending. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void endEntity (const XMLCh* const name) = 0; + + /** + * Receive notification of the start of a CDATA section. + * + *

The SAX parser will invoke this method at the start of + * each CDATA parsed.

+ * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startCDATA () = 0; + + /** + * Receive notification of the start of the DTD declarations. + * + *

The SAX parser will invoke this method at the start of the + * DTD

+ * + * @param name The document type name. + * @param publicId The declared public identifier for the external DTD subset, or null if none was declared. + * @param systemId The declared system identifier for the external DTD subset, or null if none was declared. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startDTD + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ) = 0; + + /** + * Receive notification of the start of an entity. + * + *

The SAX parser will invoke this method at the start of an + * entity

+ * + * @param name The name of the entity that is starting. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void startEntity (const XMLCh* const name) = 0; + + //@} +private : + /* Unimplemented Constructors and operators */ + /* Copy constructor */ + LexicalHandler(const LexicalHandler&); + /** Assignment operator */ + LexicalHandler& operator=(const LexicalHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/SAX2XMLFilter.hpp b/include/xercesc/sax2/SAX2XMLFilter.hpp new file mode 100644 index 0000000..166d544 --- /dev/null +++ b/include/xercesc/sax2/SAX2XMLFilter.hpp @@ -0,0 +1,82 @@ +/* + * 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: SAX2XMLFilter.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAX2XMLFILTER_HPP) +#define XERCESC_INCLUDE_GUARD_SAX2XMLFILTER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class SAX2_EXPORT SAX2XMLFilter : public SAX2XMLReader +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** The default constructor */ + SAX2XMLFilter() + { + } + /** The destructor */ + virtual ~SAX2XMLFilter() + { + } + //@} + + //----------------------------------------------------------------------- + // The XMLFilter interface + //----------------------------------------------------------------------- + /** @name Implementation of SAX 2.0 XMLFilter interface's. */ + //@{ + + /** + * This method returns the parent XMLReader object. + * + * @return A pointer to the parent XMLReader object. + */ + virtual SAX2XMLReader* getParent() const = 0 ; + + /** + * Sets the parent XMLReader object; parse requests will be forwarded to this + * object, and callback notifications coming from it will be postprocessed + * + * @param parent The new XMLReader parent. + * @see SAX2XMLReader#SAX2XMLReader + */ + virtual void setParent(SAX2XMLReader* parent) = 0; + + //@} + +private : + /* The copy constructor, you cannot call this directly */ + SAX2XMLFilter(const SAX2XMLFilter&); + + /* The assignment operator, you cannot call this directly */ + SAX2XMLFilter& operator=(const SAX2XMLFilter&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/SAX2XMLReader.hpp b/include/xercesc/sax2/SAX2XMLReader.hpp new file mode 100644 index 0000000..7004640 --- /dev/null +++ b/include/xercesc/sax2/SAX2XMLReader.hpp @@ -0,0 +1,896 @@ +/* + * 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: SAX2XMLReader.hpp 984018 2010-08-10 14:12:43Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SAX2XMLREADER_HPP) +#define XERCESC_INCLUDE_GUARD_SAX2XMLREADER_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class ContentHandler ; +class DTDHandler; +class EntityResolver; +class ErrorHandler; +class InputSource; +class LexicalHandler; +class DeclHandler; +class XMLDocumentHandler; + +class SAX2_EXPORT SAX2XMLReader +{ +public: + // ----------------------------------------------------------------------- + // Class types + // ----------------------------------------------------------------------- + /** @name Public constants */ + //@{ + + /** ValScheme enum used in setValidationScheme + * Val_Never: Do not report validation errors. + * Val_Always: The parser will always report validation errors. + * Val_Auto: The parser will report validation errors only if a grammar is specified. + * + * The schemes map to these feature values: + * Val_Never: + * parser->setFeature(XMLUni::fgSAX2CoreValidation, false); + * + * Val_Always: + * parser->setFeature(XMLUni::fgSAX2CoreValidation, true); + * parser->setFeature(XMLUni::fgXercesDynamic, false); + * + * Val_Auto: + * parser->setFeature(XMLUni::fgSAX2CoreValidation, true); + * parser->setFeature(XMLUni::fgXercesDynamic, true); + * + * @see #setFeature + */ + enum ValSchemes + { + Val_Never + , Val_Always + , Val_Auto + }; + //@} + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + /** The default constructor */ + SAX2XMLReader() + { + } + /** The destructor */ + virtual ~SAX2XMLReader() + { + } + //@} + + //----------------------------------------------------------------------- + // The XMLReader interface + //----------------------------------------------------------------------- + /** @name Implementation of SAX 2.0 XMLReader interface's. */ + //@{ + + /** + * This method returns the installed content handler. + * + * @return A pointer to the installed content handler object. + */ + virtual ContentHandler* getContentHandler() const = 0 ; + + /** + * This method returns the installed DTD handler. + * + * @return A pointer to the installed DTD handler object. + */ + virtual DTDHandler* getDTDHandler() const = 0; + + /** + * This method returns the installed entity resolver. + * + * @return A pointer to the installed entity resolver object. + */ + virtual EntityResolver* getEntityResolver() const = 0 ; + + /** + * This method returns the installed error handler. + * + * @return A pointer to the installed error handler object. + */ + virtual ErrorHandler* getErrorHandler() const = 0 ; + + /** + * Query the current state of any feature in a SAX2 XMLReader. + * + * @param name The unique identifier (URI) of the feature being set. + * @return The current state of the feature. + * @exception SAXNotRecognizedException If the requested feature is not known. + */ + virtual bool getFeature(const XMLCh* const name) const = 0; + + /** + * Query the current value of a property in a SAX2 XMLReader. + * + * The parser owns the returned pointer. The memory allocated for + * the returned pointer will be destroyed when the parser is deleted. + * + * To ensure accessibility of the returned information after the parser + * is deleted, callers need to copy and store the returned information + * somewhere else; otherwise you may get unexpected result. Since the returned + * pointer is a generic void pointer, see the SAX2 Programming Guide to learn + * exactly what type of property value each property returns for replication. + * + * @param name The unique identifier (URI) of the property being set. + * @return The current value of the property. The pointer spans the same + * life-time as the parser. A null pointer is returned if nothing + * was specified externally. + * @exception SAXNotRecognizedException If the requested property is not known. + */ + virtual void* getProperty(const XMLCh* const name) const = 0 ; + + /** + * Allow an application to register a document event handler. + * + * If the application does not register a document handler, all + * document events reported by the SAX parser will be silently + * ignored (this is the default behaviour implemented by + * HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The document handler. + * @see ContentHandler#ContentHandler + * @see HandlerBase#HandlerBase + */ + virtual void setContentHandler(ContentHandler* const handler) = 0; + + /** + * Allow an application to register a DTD event handler. + * + * If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored (this + * is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the middle + * of a parse, and the SAX parser must begin using the new handler + * immediately. + * + * @param handler The DTD handler. + * @see DTDHandler#DTDHandler + * @see HandlerBase#HandlerBase + */ + virtual void setDTDHandler(DTDHandler* const handler) = 0; + + /** + * Allow an application to register a custom entity resolver. + * + * If the application does not register an entity resolver, the + * SAX parser will resolve system identifiers and open connections + * to entities itself (this is the default behaviour implemented in + * DefaultHandler). + * + * Applications may register a new or different entity resolver + * in the middle of a parse, and the SAX parser must begin using + * the new resolver immediately. + * + * @param resolver The object for resolving entities. + * @see EntityResolver#EntityResolver + * @see DefaultHandler#DefaultHandler + */ + virtual void setEntityResolver(EntityResolver* const resolver) = 0; + + /** + * Allow an application to register an error event handler. + * + * If the application does not register an error event handler, + * all error events reported by the SAX parser will be silently + * ignored, except for fatalError, which will throw a SAXException + * (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see ErrorHandler#ErrorHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setErrorHandler(ErrorHandler* const handler) = 0; + + /** + * Set the state of any feature in a SAX2 XMLReader. + * Supported features in SAX2 for xerces-c are: + *
(See the SAX2 Programming Guide for detail description). + * + *
http://xml.org/sax/features/validation (default: true) + *
http://xml.org/sax/features/namespaces (default: true) + *
http://xml.org/sax/features/namespace-prefixes (default: false) + *
http://apache.org/xml/features/validation/dynamic (default: false) + *
http://apache.org/xml/features/validation/reuse-grammar (default: false) + *
http://apache.org/xml/features/validation/schema (default: true) + *
http://apache.org/xml/features/validation/schema-full-checking (default: false) + *
http://apache.org/xml/features/validating/load-schema (default: true) + *
http://apache.org/xml/features/nonvalidating/load-external-dtd (default: true) + *
http://apache.org/xml/features/continue-after-fatal-error (default: false) + *
http://apache.org/xml/features/validation-error-as-fatal (default: false) + * + * @param name The unique identifier (URI) of the feature. + * @param value The requested state of the feature (true or false). + * @exception SAXNotRecognizedException If the requested feature is not known. + * @exception SAXNotSupportedException Feature modification is not supported during parse + * + */ + virtual void setFeature(const XMLCh* const name, const bool value) = 0; + + /** + * Set the value of any property in a SAX2 XMLReader. + * Supported properties in SAX2 for xerces-c are: + *
(See the SAX2 Programming Guide for detail description). + * + *
http://apache.org/xml/properties/schema/external-schemaLocation + *
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation + *
http://apache.org/xml/properties/security-manager + *
http://apache.org/xml/properties/low-water-mark + *
http://apache.org/xml/properties/scannerName + * + * It takes a void pointer as the property value. Application is required to initialize this void + * pointer to a correct type. See the SAX2 Programming Guide + * to learn exactly what type of property value each property expects for processing. + * Passing a void pointer that was initialized with a wrong type will lead to unexpected result. + * If the same property is set more than once, the last one takes effect. + * + * @param name The unique identifier (URI) of the property being set. + * @param value The requested value for the property. See + * the SAX2 Programming Guide to learn + * exactly what type of property value each property expects for processing. + * Passing a void pointer that was initialized with a wrong type will lead + * to unexpected result. + * @exception SAXNotRecognizedException If the requested property is not known. + * @exception SAXNotSupportedException Property modification is not supported during parse + */ + virtual void setProperty(const XMLCh* const name, void* value) = 0 ; + + /** + * Parse an XML document. + * + * The application can use this method to instruct the SAX parser + * to begin parsing an XML document from any valid input + * source (a character stream, a byte stream, or a URI). + * + * Applications may not invoke this method while a parse is in + * progress (they should create a new Parser instead for each + * additional XML document). Once a parse is complete, an + * application may reuse the same Parser object, possibly with a + * different input source. + * + * @param source The input source for the top-level of the + * XML document. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see InputSource#InputSource + * @see #setEntityResolver + * @see #setDTDHandler + * @see #setContentHandler + * @see #setErrorHandler + */ + virtual void parse + ( + const InputSource& source + ) = 0; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(const InputSource&) + */ + virtual void parse + ( + const XMLCh* const systemId + ) = 0; + + /** + * Parse an XML document from a system identifier (URI). + * + * This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact equivalent + * of the following: + * + * parse(new URLInputSource(systemId)); + * + * If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser. + * + * @param systemId The system identifier (URI). + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @see #parse(const InputSource&) + */ + virtual void parse + ( + const char* const systemId + ) = 0; + + //@} + + // ----------------------------------------------------------------------- + // SAX 2.0-ext + // ----------------------------------------------------------------------- + /** @name SAX 2.0-ext */ + //@{ + /** + * This method returns the installed declaration handler. + * + * @return A pointer to the installed declaration handler object. + */ + virtual DeclHandler* getDeclarationHandler() const = 0 ; + + /** + * This method returns the installed lexical handler. + * + * @return A pointer to the installed lexical handler object. + */ + virtual LexicalHandler* getLexicalHandler() const = 0 ; + + /** + * Allow an application to register a declaration event handler. + * + * If the application does not register a declaration handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by DefaultHandler). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The DTD declaration handler. + * @see DeclHandler#DeclHandler + * @see SAXException#SAXException + * @see DefaultHandler#DefaultHandler + */ + virtual void setDeclarationHandler(DeclHandler* const handler) = 0; + + /** + * Allow an application to register a lexical event handler. + * + * If the application does not register a lexical handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by HandlerBase). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The error handler. + * @see LexicalHandler#LexicalHandler + * @see SAXException#SAXException + * @see HandlerBase#HandlerBase + */ + virtual void setLexicalHandler(LexicalHandler* const handler) = 0; + + //@} + + // ----------------------------------------------------------------------- + // Getter Methods + // ----------------------------------------------------------------------- + /** @name Getter Methods (Xerces-C specific) */ + //@{ + /** + * This method is used to get the current validator. + * + * SAX2XMLReader assumes responsibility for the validator. It will be + * deleted when the XMLReader is destroyed. + * + * @return A pointer to the validator. An application should not deleted + * the object returned. + * + */ + virtual XMLValidator* getValidator() const = 0; + + /** Get error count from the last parse operation. + * + * This method returns the error count from the last parse + * operation. Note that this count is actually stored in the + * scanner, so this method simply returns what the + * scanner reports. + * + * @return number of errors encountered during the latest + * parse operation. + */ + virtual XMLSize_t getErrorCount() const = 0 ; + + /** + * This method returns the state of the parser's + * exit-on-First-Fatal-Error flag. + * + *

Or you can query the feature "http://apache.org/xml/features/continue-after-fatal-error" + * which indicates the opposite state.

+ * + * @return true, if the parser is currently configured to + * exit on the first fatal error, false otherwise. + * + * @see #setExitOnFirstFatalError + * @see #getFeature + */ + virtual bool getExitOnFirstFatalError() const = 0; + + /** + * This method returns the state of the parser's + * validation-constraint-fatal flag. + * + *

Or you can query the feature "http://apache.org/xml/features/validation-error-as-fatal" + * which means the same thing. + * + * @return true, if the parser is currently configured to + * set validation constraint errors as fatal, false + * otherwise. + * + * @see #setValidationConstraintFatal + * @see #getFeature + */ + virtual bool getValidationConstraintFatal() const = 0; + + /** + * Retrieve the grammar that is associated with the specified namespace key + * + * @param nameSpaceKey Namespace key + * @return Grammar associated with the Namespace key. + */ + virtual Grammar* getGrammar(const XMLCh* const nameSpaceKey) = 0; + + /** + * Retrieve the grammar where the root element is declared. + * + * @return Grammar where root element declared + */ + virtual Grammar* getRootGrammar() = 0; + + /** + * Returns the string corresponding to a URI id from the URI string pool. + * + * @param uriId id of the string in the URI string pool. + * @return URI string corresponding to the URI id. + */ + virtual const XMLCh* getURIText(unsigned int uriId) const = 0; + + /** + * Returns the current src offset within the input source. + * To be used only while parsing is in progress. + * + * @return offset within the input source + */ + virtual XMLFilePos getSrcOffset() const = 0; + + //@} + + // ----------------------------------------------------------------------- + // Setter Methods + // ----------------------------------------------------------------------- + /** @name Setter Methods (Xerces-C specific) */ + //@{ + /** + * This method is used to set a validator. + * + * SAX2XMLReader assumes responsibility for the validator. It will be + * deleted when the XMLReader is destroyed. + * + * @param valueToAdopt A pointer to the validator that the reader should use. + * + */ + virtual void setValidator(XMLValidator* valueToAdopt) = 0; + + /** + * This method allows users to set the parser's behaviour when it + * encounters the first fatal error. If set to true, the parser + * will exit at the first fatal error. If false, then it will + * report the error and continue processing. + * + *

The default value is 'true' and the parser exits on the + * first fatal error.

+ * + *

Or you can set the feature "http://apache.org/xml/features/continue-after-fatal-error" + * which has the opposite behaviour.

+ * + *

If both the feature above and this function are used, the latter takes effect.

+ * + * @param newState The value specifying whether the parser should + * continue or exit when it encounters the first + * fatal error. + * + * @see #getExitOnFirstFatalError + * @see #setFeature + */ + virtual void setExitOnFirstFatalError(const bool newState) = 0; + + /** + * This method allows users to set the parser's behaviour when it + * encounters a validation constraint error. If set to true, and the + * the parser will treat validation error as fatal and will exit depends on the + * state of "getExitOnFirstFatalError". If false, then it will + * report the error and continue processing. + * + * Note: setting this true does not mean the validation error will be printed with + * the word "Fatal Error". It is still printed as "Error", but the parser + * will exit if "setExitOnFirstFatalError" is set to true. + * + *

The default value is 'false'.

+ * + *

Or you can set the feature "http://apache.org/xml/features/validation-error-as-fatal" + * which means the same thing.

+ * + *

If both the feature above and this function are used, the latter takes effect.

+ * + * @param newState If true, the parser will exit if "setExitOnFirstFatalError" + * is set to true. + * + * @see #getValidationConstraintFatal + * @see #setExitOnFirstFatalError + * @see #setFeature + */ + virtual void setValidationConstraintFatal(const bool newState) = 0; + //@} + + + // ----------------------------------------------------------------------- + // Progressive scan methods + // ----------------------------------------------------------------------- + + /** @name Progressive scan methods */ + //@{ + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a Unicode string representing the path + * to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could parse the + * prolog (which means the token will not be valid.) + * + * @see #parseNext + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseFirst + ( + const XMLCh* const systemId + , XMLPScanToken& toFill + ) = 0; + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param systemId A pointer to a regular native string representing + * the path to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseFirst + ( + const char* const systemId + , XMLPScanToken& toFill + ) = 0; + + /** Begin a progressive parse operation + * + * This method is used to start a progressive parse on a XML file. + * To continue parsing, subsequent calls must be to the parseNext + * method. + * + * It scans through the prolog and returns a token to be used on + * subsequent scanNext() calls. If the return value is true, then the + * token is legal and ready for further use. If it returns false, then + * the scan of the prolog failed and the token is not going to work on + * subsequent scanNext() calls. + * + * @param source A const reference to the InputSource object which + * points to the XML file to be parsed. + * @param toFill A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the prolog. It indicates the + * user can go ahead with parsing the rest of the file. It + * returns 'false' to indicate that the parser could not parse + * the prolog. + * + * @see #parseNext + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + */ + virtual bool parseFirst + ( + const InputSource& source + , XMLPScanToken& toFill + ) = 0; + + /** Continue a progressive parse operation + * + * This method is used to continue with progressive parsing of + * XML files started by a call to 'parseFirst' method. + * + * It parses the XML file and stops as soon as it comes across + * a XML token (as defined in the XML specification). Relevant + * callback handlers are invoked as required by the SAX + * specification. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + * + * @return 'true', if successful in parsing the next XML token. + * It indicates the user can go ahead with parsing the rest + * of the file. It returns 'false' to indicate that the parser + * could not find next token as per the XML specification + * production rule. + * + * @see #parseFirst(XMLCh*,...) + * @see #parseFirst(char*,...) + * @see #parseFirst(InputSource&,...) + */ + virtual bool parseNext(XMLPScanToken& token) = 0; + + /** Reset the parser after a progressive parse + * + * If a progressive parse loop exits before the end of the document + * is reached, the parser has no way of knowing this. So it will leave + * open any files or sockets or memory buffers that were in use at + * the time that the parse loop exited. + * + * The next parse operation will cause these open files and such to + * be closed, but the next parse operation might occur at some unknown + * future point. To avoid this problem, you should reset the parser if + * you exit the loop early. + * + * If you exited because of an error, then this cleanup will be done + * for you. Its only when you exit the file prematurely of your own + * accord, because you've found what you wanted in the file most + * likely. + * + * @param token A token maintaing state information to maintain + * internal consistency between invocation of 'parseNext' + * calls. + */ + virtual void parseReset(XMLPScanToken& token) = 0; + + //@} + + // ----------------------------------------------------------------------- + // Grammar preparsing interface + // ----------------------------------------------------------------------- + + /** @name Grammar preparsing interface's. */ + //@{ + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via an input source + * object. + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the SAX InputSource parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param source A const reference to the SAX InputSource object which + * points to the schema grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + * + * @see InputSource#InputSource + */ + virtual Grammar* loadGrammar(const InputSource& source, + const Grammar::GrammarType grammarType, + const bool toCache = false) = 0; + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const XMLCh pointer to the Unicode string which + * contains the path to the XML grammar file to be + * preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const XMLCh* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false) = 0; + + /** + * Preparse schema grammar (XML Schema, DTD, etc.) via a file path or URL + * + * This method invokes the preparsing process on a schema grammar XML + * file specified by the file path parameter. If the 'toCache' flag + * is enabled, the parser will cache the grammars for re-use. If a grammar + * key is found in the pool, no caching of any grammar will take place. + * + * + * @param systemId A const char pointer to a native string which contains + * the path to the XML grammar file to be preparsed. + * @param grammarType The grammar type (Schema or DTD). + * @param toCache If true, we cache the preparsed grammar, + * otherwise, no caching. Default is false. + * @return The preparsed schema grammar object (SchemaGrammar or + * DTDGrammar). That grammar object is owned by the parser. + * + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception XMLException An exception from the parser or client + * handler code. + * @exception DOMException A DOM exception as per DOM spec. + */ + virtual Grammar* loadGrammar(const char* const systemId, + const Grammar::GrammarType grammarType, + const bool toCache = false) = 0; + + /** + * Clear the cached grammar pool + */ + virtual void resetCachedGrammarPool() = 0; + + /** Set maximum input buffer size + * + * This method allows users to limit the size of buffers used in parsing + * XML character data. The effect of setting this size is to limit the + * size of a ContentHandler::characters() call. + * + * The parser's default input buffer size is 1 megabyte. + * + * @param bufferSize The maximum input buffer size + */ + virtual void setInputBufferSize(const XMLSize_t bufferSize); + + //@} + + + // ----------------------------------------------------------------------- + // Advanced document handler list maintenance methods + // ----------------------------------------------------------------------- + + /** @name Advanced document handler list maintenance methods */ + //@{ + /** + * This method installs the specified 'advanced' document callback + * handler, thereby allowing the user to customize the processing, + * if they choose to do so. Any number of advanced callback handlers + * maybe installed. + * + *

The methods in the advanced callback interface represent + * Xerces-C extensions. There is no specification for this interface.

+ * + * @param toInstall A pointer to the users advanced callback handler. + * + * @see #removeAdvDocHandler + */ + virtual void installAdvDocHandler(XMLDocumentHandler* const toInstall) = 0; + + /** + * This method removes the 'advanced' document handler callback from + * the underlying parser scanner. If no handler is installed, advanced + * callbacks are not invoked by the scanner. + * @param toRemove A pointer to the advanced callback handler which + * should be removed. + * + * @see #installAdvDocHandler + */ + virtual bool removeAdvDocHandler(XMLDocumentHandler* const toRemove) = 0; + //@} + +private : + /* The copy constructor, you cannot call this directly */ + SAX2XMLReader(const SAX2XMLReader&); + + /* The assignment operator, you cannot call this directly */ + SAX2XMLReader& operator=(const SAX2XMLReader&); + +}; + +inline void SAX2XMLReader::setInputBufferSize(const XMLSize_t /*bufferSize*/) +{ +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/XMLReaderFactory.hpp b/include/xercesc/sax2/XMLReaderFactory.hpp new file mode 100644 index 0000000..a674625 --- /dev/null +++ b/include/xercesc/sax2/XMLReaderFactory.hpp @@ -0,0 +1,71 @@ +/* + * 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: XMLReaderFactory.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLREADERFACTORY_HPP) +#define XERCESC_INCLUDE_GUARD_XMLREADERFACTORY_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class MemoryManager; +class XMLGrammarPool; + +/** + * Creates a SAX2 parser (SAX2XMLReader). + * + *

Note: The parser object returned by XMLReaderFactory is owned by the + * calling users, and it's the responsibility of the users to delete that + * parser object, once they no longer need it.

+ * + * @see SAX2XMLReader#SAX2XMLReader + */ +class SAX2_EXPORT XMLReaderFactory +{ +protected: // really should be private, but that causes compiler warnings. + XMLReaderFactory() ; + ~XMLReaderFactory() ; + +public: + static SAX2XMLReader * createXMLReader( MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ) ; + static SAX2XMLReader * createXMLReader(const XMLCh* className) ; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLReaderFactory(const XMLReaderFactory&); + XMLReaderFactory& operator=(const XMLReaderFactory&); +}; + +inline SAX2XMLReader * XMLReaderFactory::createXMLReader(const XMLCh *) +{ + throw SAXNotSupportedException(); + // unimplemented + return 0; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/sax2/sax2Dummy.cpp b/include/xercesc/sax2/sax2Dummy.cpp new file mode 100644 index 0000000..bf7f8e4 --- /dev/null +++ b/include/xercesc/sax2/sax2Dummy.cpp @@ -0,0 +1,30 @@ +/* + * 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: sax2Dummy.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/ArrayIndexOutOfBoundsException.hpp b/include/xercesc/util/ArrayIndexOutOfBoundsException.hpp new file mode 100644 index 0000000..5d9aa67 --- /dev/null +++ b/include/xercesc/util/ArrayIndexOutOfBoundsException.hpp @@ -0,0 +1,33 @@ +/* + * 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: ArrayIndexOutOfBoundsException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ARRAYINDEXOUTOFBOUNDSEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_ARRAYINDEXOUTOFBOUNDSEXCEPTION_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(ArrayIndexOutOfBoundsException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/Base64.cpp b/include/xercesc/util/Base64.cpp new file mode 100644 index 0000000..fbd5837 --- /dev/null +++ b/include/xercesc/util/Base64.cpp @@ -0,0 +1,636 @@ +/* + * 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. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// constants +// --------------------------------------------------------------------------- +static const int BASELENGTH = 255; +static const int FOURBYTE = 4; + +// --------------------------------------------------------------------------- +// class data member +// --------------------------------------------------------------------------- + +// the base64 alphabet according to definition in RFC 2045 +const XMLByte Base64::base64Alphabet[] = { + chLatin_A, chLatin_B, chLatin_C, chLatin_D, chLatin_E, + chLatin_F, chLatin_G, chLatin_H, chLatin_I, chLatin_J, + chLatin_K, chLatin_L, chLatin_M, chLatin_N, chLatin_O, + chLatin_P, chLatin_Q, chLatin_R, chLatin_S, chLatin_T, + chLatin_U, chLatin_V, chLatin_W, chLatin_X, chLatin_Y, chLatin_Z, + chLatin_a, chLatin_b, chLatin_c, chLatin_d, chLatin_e, + chLatin_f, chLatin_g, chLatin_h, chLatin_i, chLatin_j, + chLatin_k, chLatin_l, chLatin_m, chLatin_n, chLatin_o, + chLatin_p, chLatin_q, chLatin_r, chLatin_s, chLatin_t, + chLatin_u, chLatin_v, chLatin_w, chLatin_x, chLatin_y, chLatin_z, + chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, + chDigit_5, chDigit_6, chDigit_7, chDigit_8, chDigit_9, + chPlus, chForwardSlash, chNull +}; + +// This is an inverse table for base64 decoding. So, if +// base64Alphabet[17] = 'R', then base64Inverse['R'] = 17. +// +// For characters not in base64Alphabet then +// base64Inverse[ch] = 0xFF. +const XMLByte Base64::base64Inverse[BASELENGTH] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +const XMLByte Base64::base64Padding = chEqual; + +/*** + * + * Memory Management Issue: + * + * . For memory allocated for result returned to caller (external memory), + * the plugged memory manager is used if it is provided, otherwise global + * new used to retain the pre-memory-manager behaviour. + * + * . For memory allocated for temperary buffer (internal memory), + * XMLPlatformUtils::fgMemoryManager is used. + * + */ + +static void* getExternalMemory( MemoryManager* const allocator + , XMLSize_t const sizeToAllocate) +{ + return allocator ? allocator->allocate(sizeToAllocate) + : ::operator new(sizeToAllocate); +} + +/*** + * internal memory is deallocated by janitorArray + */ +static void returnExternalMemory( MemoryManager* const allocator + , void* buffer) +{ + allocator ? allocator->deallocate(buffer) + : ::operator delete(buffer); +} + +/** + * E2-9 + * + * Canonical-base64Binary ::= (B64line* B64lastline)? + * + * B64line ::= B64x15 B64x15 B64x15 B64x15 B64x15 B64 #xA + * 76 Base64 characters followed by newline + * + * B64x15 ::= B64 B64 B64 B64 B64 + * B64 B64 B64 B64 B64 + * B64 B64 B64 B64 B64 + * + * B64lastline ::= B64x4? B64x4? B64x4? B64x4? + * B64x4? B64x4? B64x4? B64x4? + * B64x4? B64x4? B64x4? B64x4? + * B64x4? B64x4? B64x4? B64x4? + * B64x4? B64x4? + * (B64x4 | (B64 B64 B16 '=') | (B64 B04 '==')) + * #xA + * + * B64x4 ::= B64 B64 B64 B64 + * B04 ::= [AQgw] + * B16 ::= [AEIMQUYcgkosw048] +*/ + +// number of quadruplets per one line ( must be >1 and <19 ) +const unsigned int Base64::quadsPerLine = 15; + +XMLByte* Base64::encode(const XMLByte* const inputData + , const XMLSize_t inputLength + , XMLSize_t* outputLength + , MemoryManager* const memMgr) +{ + if (!inputData || !outputLength) + return 0; + + int quadrupletCount = ( (int)inputLength + 2 ) / 3; + if (quadrupletCount == 0) + return 0; + + // number of rows in encoded stream ( including the last one ) + int lineCount = ( quadrupletCount + quadsPerLine-1 ) / quadsPerLine; + + // + // convert the triplet(s) to quadruplet(s) + // + XMLByte b1, b2, b3, b4; // base64 binary codes ( 0..63 ) + + XMLSize_t inputIndex = 0; + XMLSize_t outputIndex = 0; + XMLByte *encodedData = (XMLByte*) getExternalMemory(memMgr, (quadrupletCount*FOURBYTE+lineCount+1) * sizeof(XMLByte)); + + // + // Process all quadruplet(s) except the last + // + int quad = 1; + for (; quad <= quadrupletCount-1; quad++ ) + { + // read triplet from the input stream + split1stOctet( inputData[ inputIndex++ ], b1, b2 ); + split2ndOctet( inputData[ inputIndex++ ], b2, b3 ); + split3rdOctet( inputData[ inputIndex++ ], b3, b4 ); + + // write quadruplet to the output stream + encodedData[ outputIndex++ ] = base64Alphabet[ b1 ]; + encodedData[ outputIndex++ ] = base64Alphabet[ b2 ]; + encodedData[ outputIndex++ ] = base64Alphabet[ b3 ]; + encodedData[ outputIndex++ ] = base64Alphabet[ b4 ]; + + if (( quad % quadsPerLine ) == 0 ) + encodedData[ outputIndex++ ] = chLF; + } + + // + // process the last Quadruplet + // + // first octet is present always, process it + split1stOctet( inputData[ inputIndex++ ], b1, b2 ); + encodedData[ outputIndex++ ] = base64Alphabet[ b1 ]; + + if( inputIndex < inputLength ) + { + // second octet is present, process it + split2ndOctet( inputData[ inputIndex++ ], b2, b3 ); + encodedData[ outputIndex++ ] = base64Alphabet[ b2 ]; + + if( inputIndex < inputLength ) + { + // third octet present, process it + // no PAD e.g. 3cQl + split3rdOctet( inputData[ inputIndex++ ], b3, b4 ); + encodedData[ outputIndex++ ] = base64Alphabet[ b3 ]; + encodedData[ outputIndex++ ] = base64Alphabet[ b4 ]; + } + else + { + // third octet not present + // one PAD e.g. 3cQ= + encodedData[ outputIndex++ ] = base64Alphabet[ b3 ]; + encodedData[ outputIndex++ ] = base64Padding; + } + } + else + { + // second octet not present + // two PADs e.g. 3c== + encodedData[ outputIndex++ ] = base64Alphabet[ b2 ]; + encodedData[ outputIndex++ ] = base64Padding; + encodedData[ outputIndex++ ] = base64Padding; + } + + // write out end of the last line + encodedData[ outputIndex++ ] = chLF; + // write out end of string + encodedData[ outputIndex ] = 0; + + *outputLength = outputIndex; + + return encodedData; +} + +// +// delete the buffer allocated by decode() if +// decoding is successfully done. +// +// In previous version, we use XMLString::strLen(decodedData) +// to get the length, this will fail for test case containing +// consequtive "A", such "AAFF", or "ab56AA56". Instead of +// returning 3/6, we have 0 and 3, indicating that "AA", after +// decoded, is interpreted as by the strLen(). +// +// Since decode() has track of length of the decoded data, we +// will get this length from decode(), instead of strLen(). +// +int Base64::getDataLength(const XMLCh* const inputData + , MemoryManager* const manager + , Conformance conform ) + +{ + XMLSize_t retLen = 0; + XMLByte* decodedData = decodeToXMLByte(inputData, &retLen, manager, conform); + + if ( !decodedData ) + return -1; + else + { + returnExternalMemory(manager, decodedData); + return (int)retLen; + } +} + +XMLByte* Base64::decode(const XMLByte* const inputData + , XMLSize_t* decodedLength + , MemoryManager* const memMgr + , Conformance conform ) +{ + XMLByte* canRepInByte = 0; + XMLByte* retStr = decode( + inputData + , decodedLength + , canRepInByte + , memMgr + , conform); + + /*** + * Release the canRepData + */ + if (retStr) + returnExternalMemory(memMgr, canRepInByte); + + return retStr; +} + + +XMLByte* Base64::decodeToXMLByte(const XMLCh* const inputData + , XMLSize_t* decodedLen + , MemoryManager* const memMgr + , Conformance conform ) +{ + if (!inputData || !*inputData) + return 0; + + /*** + * Move input data to a XMLByte buffer + */ + XMLSize_t srcLen = XMLString::stringLen(inputData); + XMLByte *dataInByte = (XMLByte*) getExternalMemory(memMgr, (srcLen+1) * sizeof(XMLByte)); + ArrayJanitor janFill(dataInByte, memMgr ? memMgr : XMLPlatformUtils::fgMemoryManager); + + for (XMLSize_t i = 0; i < srcLen; i++) + dataInByte[i] = (XMLByte)inputData[i]; + + dataInByte[srcLen] = 0; + + /*** + * Forward to the actual decoding method to do the decoding + */ + *decodedLen = 0; + return decode(dataInByte, decodedLen, memMgr, conform); +} + +/*** +* E2-54 +* +* Canonical-base64Binary ::= (B64 B64 B64 B64)*((B64 B64 B16 '=')|(B64 B04 '=='))? +* B04 ::= [AQgw] +* B16 ::= [AEIMQUYcgkosw048] +* B64 ::= [A-Za-z0-9+/] +* +***/ +XMLCh* Base64::getCanonicalRepresentation(const XMLCh* const inputData + , MemoryManager* const memMgr + , Conformance conform) + +{ + if (!inputData || !*inputData) + return 0; + + /*** + * Move input data to a XMLByte buffer + */ + XMLSize_t srcLen = XMLString::stringLen(inputData); + XMLByte *dataInByte = (XMLByte*) getExternalMemory(memMgr, (srcLen+1) * sizeof(XMLByte)); + ArrayJanitor janFill(dataInByte, memMgr ? memMgr : XMLPlatformUtils::fgMemoryManager); + + for (XMLSize_t i = 0; i < srcLen; i++) + dataInByte[i] = (XMLByte)inputData[i]; + + dataInByte[srcLen] = 0; + + /*** + * Forward to the actual decoding method to do the decoding + */ + XMLSize_t decodedLength = 0; + XMLByte* canRepInByte = 0; + XMLByte* retStr = decode( + dataInByte + , &decodedLength + , canRepInByte + , memMgr + , conform); + + if (!retStr) + return 0; + + /*** + * Move canonical representation to a XMLCh buffer to return + */ + XMLSize_t canRepLen = XMLString::stringLen((char*)canRepInByte); + XMLCh *canRepData = (XMLCh*) getExternalMemory(memMgr, (canRepLen + 1) * sizeof(XMLCh)); + + for (XMLSize_t j = 0; j < canRepLen; j++) + canRepData[j] = (XMLCh)canRepInByte[j]; + + canRepData[canRepLen] = 0; + + /*** + * Release the memory allocated in the actual decoding method + */ + returnExternalMemory(memMgr, retStr); + returnExternalMemory(memMgr, canRepInByte); + + return canRepData; +} +// ----------------------------------------------------------------------- +// Helper methods +// ----------------------------------------------------------------------- + +// +// return 0(null) if invalid data found. +// return the buffer containning decoded data otherwise +// the caller is responsible for the de-allocation of the +// buffer returned. +// +// temporary data, rawInputData, is ALWAYS released by this function. +// + +/*** + * E2-9 + * + * Base64Binary ::= S? B64quartet* B64final? + * + * B64quartet ::= B64 S? B64 S? B64 S? B64 S? + * + * B64final ::= B64 S? B04 S? '=' S? '=' S? + * | B64 S? B64 S? B16 S? '=' S? + * + * B04 ::= [AQgw] + * B16 ::= [AEIMQUYcgkosw048] + * B64 ::= [A-Za-z0-9+/] + * + * + * E2-54 + * + * Base64Binary ::= ((B64S B64S B64S B64S)* + * ((B64S B64S B64S B64) | + * (B64S B64S B16S '=') | + * (B64S B04S '=' #x20? '=')))? + * + * B64S ::= B64 #x20? + * B16S ::= B16 #x20? + * B04S ::= B04 #x20? + * + * + * Note that this grammar requires the number of non-whitespace characters + * in the lexical form to be a multiple of four, and for equals signs to + * appear only at the end of the lexical form; strings which do not meet these + * constraints are not legal lexical forms of base64Binary because they + * cannot successfully be decoded by base64 decoders. + * + * Note: + * The above definition of the lexical space is more restrictive than that given + * in [RFC 2045] as regards whitespace -- this is not an issue in practice. Any + * string compatible with the RFC can occur in an element or attribute validated + * by this type, because the whiteSpace facet of this type is fixed to collapse, + * which means that all leading and trailing whitespace will be stripped, and all + * internal whitespace collapsed to single space characters, before the above grammar + * is enforced. + * +*/ + +XMLByte* Base64::decode ( const XMLByte* const inputData + , XMLSize_t* decodedLength + , XMLByte*& canRepData + , MemoryManager* const memMgr + , Conformance conform + ) +{ + if ((!inputData) || (!*inputData)) + return 0; + + // + // remove all XML whitespaces from the base64Data + // + XMLSize_t inputLength = XMLString::stringLen( (const char*)inputData ); + XMLByte* rawInputData = (XMLByte*) getExternalMemory(memMgr, (inputLength+1) * sizeof(XMLByte)); + ArrayJanitor jan(rawInputData, memMgr ? memMgr : XMLPlatformUtils::fgMemoryManager); + + XMLSize_t inputIndex = 0; + XMLSize_t rawInputLength = 0; + bool inWhiteSpace = false; + + switch (conform) + { + case Conf_RFC2045: + while ( inputIndex < inputLength ) + { + if (!XMLChar1_0::isWhitespace(inputData[inputIndex])) + { + rawInputData[ rawInputLength++ ] = inputData[ inputIndex ]; + } + // RFC2045 does not explicitly forbid more than ONE whitespace + // before, in between, or after base64 octects. + // Besides, S? allows more than ONE whitespace as specified in the production + // [3] S ::= (#x20 | #x9 | #xD | #xA)+ + // therefore we do not detect multiple ws + + inputIndex++; + } + + break; + case Conf_Schema: + // no leading #x20 + if (chSpace == inputData[inputIndex]) + return 0; + + while ( inputIndex < inputLength ) + { + if (chSpace != inputData[inputIndex]) + { + rawInputData[ rawInputLength++ ] = inputData[ inputIndex ]; + inWhiteSpace = false; + } + else + { + if (inWhiteSpace) + return 0; // more than 1 #x20 encountered + else + inWhiteSpace = true; + } + + inputIndex++; + } + + // no trailing #x20 + if (inWhiteSpace) + return 0; + + break; + + default: + break; + } + + //now rawInputData contains canonical representation + //if the data is valid Base64 + rawInputData[ rawInputLength ] = 0; + + // the length of raw data should be divisible by four + if (( rawInputLength % FOURBYTE ) != 0 ) + return 0; + + int quadrupletCount = (int)rawInputLength / FOURBYTE; + if ( quadrupletCount == 0 ) + return 0; + + // + // convert the quadruplet(s) to triplet(s) + // + XMLByte d1, d2, d3, d4; // base64 characters + XMLByte b1, b2, b3, b4; // base64 binary codes ( 0..64 ) + + XMLSize_t rawInputIndex = 0; + XMLSize_t outputIndex = 0; + XMLByte *decodedData = (XMLByte*) getExternalMemory(memMgr, (quadrupletCount*3+1) * sizeof(XMLByte)); + + // + // Process all quadruplet(s) except the last + // + int quad = 1; + for (; quad <= quadrupletCount-1; quad++ ) + { + // read quadruplet from the input stream + if (!isData( (d1 = rawInputData[ rawInputIndex++ ]) ) || + !isData( (d2 = rawInputData[ rawInputIndex++ ]) ) || + !isData( (d3 = rawInputData[ rawInputIndex++ ]) ) || + !isData( (d4 = rawInputData[ rawInputIndex++ ]) )) + { + // if found "no data" just return NULL + returnExternalMemory(memMgr, decodedData); + return 0; + } + + b1 = base64Inverse[ d1 ]; + b2 = base64Inverse[ d2 ]; + b3 = base64Inverse[ d3 ]; + b4 = base64Inverse[ d4 ]; + + // write triplet to the output stream + decodedData[ outputIndex++ ] = set1stOctet(b1, b2); + decodedData[ outputIndex++ ] = set2ndOctet(b2, b3); + decodedData[ outputIndex++ ] = set3rdOctet(b3, b4); + } + + // + // process the last Quadruplet + // + // first two octets are present always, process them + if (!isData( (d1 = rawInputData[ rawInputIndex++ ]) ) || + !isData( (d2 = rawInputData[ rawInputIndex++ ]) )) + { + // if found "no data" just return NULL + returnExternalMemory(memMgr, decodedData); + return 0; + } + + b1 = base64Inverse[ d1 ]; + b2 = base64Inverse[ d2 ]; + + // try to process last two octets + d3 = rawInputData[ rawInputIndex++ ]; + d4 = rawInputData[ rawInputIndex++ ]; + + if (!isData( d3 ) || !isData( d4 )) + { + // check if last two are PAD characters + if (isPad( d3 ) && isPad( d4 )) + { + // two PAD e.g. 3c== + if ((b2 & 0xf) != 0) // last 4 bits should be zero + { + returnExternalMemory(memMgr, decodedData); + return 0; + } + + decodedData[ outputIndex++ ] = set1stOctet(b1, b2); + } + else if (!isPad( d3 ) && isPad( d4 )) + { + // one PAD e.g. 3cQ= + b3 = base64Inverse[ d3 ]; + if (( b3 & 0x3 ) != 0 ) // last 2 bits should be zero + { + returnExternalMemory(memMgr, decodedData); + return 0; + } + + decodedData[ outputIndex++ ] = set1stOctet( b1, b2 ); + decodedData[ outputIndex++ ] = set2ndOctet( b2, b3 ); + } + else + { + // an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data + returnExternalMemory(memMgr, decodedData); + return 0; + } + } + else + { + // no PAD e.g 3cQl + b3 = base64Inverse[ d3 ]; + b4 = base64Inverse[ d4 ]; + decodedData[ outputIndex++ ] = set1stOctet( b1, b2 ); + decodedData[ outputIndex++ ] = set2ndOctet( b2, b3 ); + decodedData[ outputIndex++ ] = set3rdOctet( b3, b4 ); + } + + // write out the end of string + decodedData[ outputIndex ] = 0; + *decodedLength = outputIndex; + + //allow the caller to have access to the canonical representation + jan.release(); + canRepData = rawInputData; + + return decodedData; +} + +bool Base64::isData(const XMLByte& octet) +{ + return (base64Inverse[octet]!=(XMLByte)-1); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/Base64.hpp b/include/xercesc/util/Base64.hpp new file mode 100644 index 0000000..134bc88 --- /dev/null +++ b/include/xercesc/util/Base64.hpp @@ -0,0 +1,266 @@ +/* + * 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: Base64.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BASE64_HPP) +#define XERCESC_INCLUDE_GUARD_BASE64_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This class provides encode/decode for RFC 2045 Base64 as +// defined by RFC 2045, N. Freed and N. Borenstein. +// RFC 2045: Multipurpose Internet Mail Extensions (MIME) +// Part One: Format of Internet Message Bodies. Reference +// 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt +// This class is used by XML Schema binary format validation +// +// +class XMLUTIL_EXPORT Base64 +{ +public : + + enum Conformance + { + Conf_RFC2045 + , Conf_Schema + }; + + //@{ + + /** + * Encodes octets into Base64 data + * + * NOTE: The returned buffer is dynamically allocated and is the + * responsibility of the caller to delete it when not longer needed. + * Use the memory manager to release the returned buffer or + * operator delete() if none was provided. + * + * @param inputData Binary data in XMLByte stream. + * @param inputLength Length of the XMLByte stream. + * @param outputLength Length of the encoded Base64 byte stream. + * @param memMgr client provided memory manager + * @return Encoded Base64 data in XMLByte stream, + * or NULL if input data can not be encoded. + */ + static XMLByte* encode(const XMLByte* const inputData + , const XMLSize_t inputLength + , XMLSize_t* outputLength + , MemoryManager* const memMgr = 0); + + /** + * Decodes Base64 data into octets + * + * NOTE: The returned buffer is dynamically allocated and is the + * responsibility of the caller to delete it when not longer needed. + * Use the memory manager to release the returned buffer or + * operator delete() if none was provided. + * + * @param inputData Base64 data in XMLByte stream. + * @param decodedLength Length of decoded XMLByte stream. + * @param memMgr client provided memory manager + * @param conform conformance specified: if the input data conforms to the + * RFC 2045 it is allowed to have any number of whitespace + * characters inside; if it conforms to the XMLSchema specs, + * it is allowed to have at most one whitespace character + * between the quartets + * @return Decoded binary data in XMLByte stream, + * or NULL if input data can not be decoded. + */ + static XMLByte* decode( + const XMLByte* const inputData + , XMLSize_t* decodedLength + , MemoryManager* const memMgr = 0 + , Conformance conform = Conf_RFC2045 + ); + + /** + * Decodes Base64 data into octets + * + * NOTE: The returned buffer is dynamically allocated and is the + * responsibility of the caller to delete it when not longer needed. + * Use the memory manager to release the returned buffer or + * operator delete() if none was provided. + * + * @param inputData Base64 data in XMLCh stream. + * @param decodedLength Length of decoded XMLByte stream. + * @param memMgr client provided memory manager + * @param conform conformance specified: if the input data conforms to the + * RFC 2045 it is allowed to have any number of whitespace + * characters inside; if it conforms to the XMLSchema specs, + * it is allowed to have at most one whitespace character + * between the quartets + * @return Decoded binary data in XMLByte stream, + * or NULL if input data can not be decoded. + */ + static XMLByte* decodeToXMLByte( + const XMLCh* const inputData + , XMLSize_t* decodedLength + , MemoryManager* const memMgr = 0 + , Conformance conform = Conf_RFC2045 + ); + /** + * Get data length + * + * Returns length of decoded data given an array + * containing encoded data. + * + * @param inputData Base64 data in XMLCh stream. + * @param memMgr client provided memory manager + * @param conform conformance specified + * @return Length of decoded data, + * or -1 if input data can not be decoded. + */ + static int getDataLength( + const XMLCh* const inputData + , MemoryManager* const memMgr = 0 + , Conformance conform = Conf_RFC2045 + ); + + //@} + + /** + * get canonical representation + * + * Caller is responsible for the proper deallocation + * of the string returned. + * + * @param inputData A string containing the Base64 + * @param memMgr client provided memory manager + * @param conform conformance specified + * + * return: the canonical representation of the Base64 + * if it is a valid Base64 + * 0 otherwise + */ + + static XMLCh* getCanonicalRepresentation + ( + const XMLCh* const inputData + , MemoryManager* const memMgr = 0 + , Conformance conform = Conf_RFC2045 + ); + +private : + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + + static XMLByte* decode( + const XMLByte* const inputData + , XMLSize_t* outputLength + , XMLByte*& canRepData + , MemoryManager* const memMgr = 0 + , Conformance conform = Conf_RFC2045 + ); + + static bool isData(const XMLByte& octet); + static bool isPad(const XMLByte& octet); + + static XMLByte set1stOctet(const XMLByte&, const XMLByte&); + static XMLByte set2ndOctet(const XMLByte&, const XMLByte&); + static XMLByte set3rdOctet(const XMLByte&, const XMLByte&); + + static void split1stOctet(const XMLByte&, XMLByte&, XMLByte&); + static void split2ndOctet(const XMLByte&, XMLByte&, XMLByte&); + static void split3rdOctet(const XMLByte&, XMLByte&, XMLByte&); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Base64(); + Base64(const Base64&); + + // ----------------------------------------------------------------------- + // Private data members + // + // base64Alphabet + // The Base64 alphabet (see RFC 2045). + // + // base64Padding + // Padding character (see RFC 2045). + // + // base64Inverse + // Table used in decoding base64. + // + // isInitialized + // Set once base64Inverse is initialized. + // + // quadsPerLine + // Number of quadruplets per one line. The encoded output + // stream must be represented in lines of no more + // than 19 quadruplets each. + // + // ----------------------------------------------------------------------- + + static const XMLByte base64Alphabet[]; + static const XMLByte base64Padding; + + static const XMLByte base64Inverse[]; + + static const unsigned int quadsPerLine; +}; + +// ----------------------------------------------------------------------- +// Helper methods +// ----------------------------------------------------------------------- +inline bool Base64::isPad(const XMLByte& octet) +{ + return ( octet == base64Padding ); +} + +inline XMLByte Base64::set1stOctet(const XMLByte& b1, const XMLByte& b2) +{ + return (( b1 << 2 ) | ( b2 >> 4 )); +} + +inline XMLByte Base64::set2ndOctet(const XMLByte& b2, const XMLByte& b3) +{ + return (( b2 << 4 ) | ( b3 >> 2 )); +} + +inline XMLByte Base64::set3rdOctet(const XMLByte& b3, const XMLByte& b4) +{ + return (( b3 << 6 ) | b4 ); +} + +inline void Base64::split1stOctet(const XMLByte& ch, XMLByte& b1, XMLByte& b2) { + b1 = ch >> 2; + b2 = ( ch & 0x3 ) << 4; +} + +inline void Base64::split2ndOctet(const XMLByte& ch, XMLByte& b2, XMLByte& b3) { + b2 |= ch >> 4; // combine with previous value + b3 = ( ch & 0xf ) << 2; +} + +inline void Base64::split3rdOctet(const XMLByte& ch, XMLByte& b3, XMLByte& b4) { + b3 |= ch >> 6; // combine with previous value + b4 = ( ch & 0x3f ); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/BaseRefVectorOf.c b/include/xercesc/util/BaseRefVectorOf.c new file mode 100644 index 0000000..31e03bf --- /dev/null +++ b/include/xercesc/util/BaseRefVectorOf.c @@ -0,0 +1,344 @@ +/* + * 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. + */ +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// BaseRefVectorOf: Constructors and Destructor +// --------------------------------------------------------------------------- +template +BaseRefVectorOf::BaseRefVectorOf( const XMLSize_t maxElems + , const bool adoptElems + , MemoryManager* const manager) : + + fAdoptedElems(adoptElems) + , fCurCount(0) + , fMaxCount(maxElems) + , fElemList(0) + , fMemoryManager(manager) +{ + // Allocate and initialize the array + fElemList = (TElem**) fMemoryManager->allocate(maxElems * sizeof(TElem*));//new TElem*[maxElems]; + for (XMLSize_t index = 0; index < maxElems; index++) + fElemList[index] = 0; +} + + +//implemented so code will link +template BaseRefVectorOf::~BaseRefVectorOf() +{ +} + + +// --------------------------------------------------------------------------- +// BaseRefVectorOf: Element management +// --------------------------------------------------------------------------- +template void BaseRefVectorOf::addElement(TElem* const toAdd) +{ + ensureExtraCapacity(1); + fElemList[fCurCount] = toAdd; + fCurCount++; +} + + +template void +BaseRefVectorOf::setElementAt(TElem* const toSet, const XMLSize_t setAt) +{ + if (setAt >= fCurCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager); + + if (fAdoptedElems) + delete fElemList[setAt]; + fElemList[setAt] = toSet; +} + +template void BaseRefVectorOf:: +insertElementAt(TElem* const toInsert, const XMLSize_t insertAt) +{ + if (insertAt == fCurCount) + { + addElement(toInsert); + return; + } + + if (insertAt > fCurCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager); + + ensureExtraCapacity(1); + + // Make room for the newbie + for (XMLSize_t index = fCurCount; index > insertAt; index--) + fElemList[index] = fElemList[index-1]; + + // And stick it in and bump the count + fElemList[insertAt] = toInsert; + fCurCount++; +} + +template TElem* BaseRefVectorOf:: +orphanElementAt(const XMLSize_t orphanAt) +{ + if (orphanAt >= fCurCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager); + + // Get the element we are going to orphan + TElem* retVal = fElemList[orphanAt]; + + // Optimize if its the last element + if (orphanAt == fCurCount-1) + { + fElemList[orphanAt] = 0; + fCurCount--; + return retVal; + } + + // Copy down every element above orphan point + for (XMLSize_t index = orphanAt; index < fCurCount-1; index++) + fElemList[index] = fElemList[index+1]; + + // Keep unused elements zero for sanity's sake + fElemList[fCurCount-1] = 0; + + // And bump down count + fCurCount--; + + return retVal; +} + +template void BaseRefVectorOf::removeAllElements() +{ + for (XMLSize_t index = 0; index < fCurCount; index++) + { + if (fAdoptedElems) + delete fElemList[index]; + + // Keep unused elements zero for sanity's sake + fElemList[index] = 0; + } + fCurCount = 0; +} + +template void BaseRefVectorOf:: +removeElementAt(const XMLSize_t removeAt) +{ + if (removeAt >= fCurCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager); + + if (fAdoptedElems) + delete fElemList[removeAt]; + + // Optimize if its the last element + if (removeAt == fCurCount-1) + { + fElemList[removeAt] = 0; + fCurCount--; + return; + } + + // Copy down every element above remove point + for (XMLSize_t index = removeAt; index < fCurCount-1; index++) + fElemList[index] = fElemList[index+1]; + + // Keep unused elements zero for sanity's sake + fElemList[fCurCount-1] = 0; + + // And bump down count + fCurCount--; +} + +template void BaseRefVectorOf::removeLastElement() +{ + if (!fCurCount) + return; + fCurCount--; + + if (fAdoptedElems) + delete fElemList[fCurCount]; +} + +template +bool BaseRefVectorOf::containsElement(const TElem* const toCheck) { + + for (XMLSize_t i = 0; i < fCurCount; i++) { + if (fElemList[i] == toCheck) { + return true; + } + } + + return false; +} + +// +// cleanup(): +// similar to destructor +// called to cleanup the memory, in case destructor cannot be called +// +template void BaseRefVectorOf::cleanup() +{ + if (fAdoptedElems) + { + for (XMLSize_t index = 0; index < fCurCount; index++) + delete fElemList[index]; + } + fMemoryManager->deallocate(fElemList);//delete [] fElemList; +} + +// +// reinitialize(): +// similar to constructor +// called to re-construct the fElemList from scratch again +// +template void BaseRefVectorOf::reinitialize() +{ + // reinitialize the array + if (fElemList) + cleanup(); + + fElemList = (TElem**) fMemoryManager->allocate(fMaxCount * sizeof(TElem*));//new TElem*[fMaxCount]; + for (XMLSize_t index = 0; index < fMaxCount; index++) + fElemList[index] = 0; + +} + +template +MemoryManager* BaseRefVectorOf::getMemoryManager() const +{ + return fMemoryManager; +} + + +// --------------------------------------------------------------------------- +// BaseRefVectorOf: Getter methods +// --------------------------------------------------------------------------- +template XMLSize_t BaseRefVectorOf::curCapacity() const +{ + return fMaxCount; +} + +template const TElem* BaseRefVectorOf:: +elementAt(const XMLSize_t getAt) const +{ + if (getAt >= fCurCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager); + return fElemList[getAt]; +} + +template TElem* +BaseRefVectorOf::elementAt(const XMLSize_t getAt) +{ + if (getAt >= fCurCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Vector_BadIndex, fMemoryManager); + return fElemList[getAt]; +} + +template XMLSize_t BaseRefVectorOf::size() const +{ + return fCurCount; +} + + +// --------------------------------------------------------------------------- +// BaseRefVectorOf: Miscellaneous +// --------------------------------------------------------------------------- +template void BaseRefVectorOf:: +ensureExtraCapacity(const XMLSize_t length) +{ + XMLSize_t newMax = fCurCount + length; + + if (newMax <= fMaxCount) + return; + + // Choose how much bigger based on the current size. + // This will grow half as much again. + if (newMax < fMaxCount + fMaxCount/2) + newMax = fMaxCount + fMaxCount/2; + + // Allocate the new array and copy over the existing stuff + TElem** newList = (TElem**) fMemoryManager->allocate + ( + newMax * sizeof(TElem*) + );//new TElem*[newMax]; + XMLSize_t index = 0; + for (; index < fCurCount; index++) + newList[index] = fElemList[index]; + + // Zero out the rest of them + for (; index < newMax; index++) + newList[index] = 0; + + // Clean up the old array and update our members + fMemoryManager->deallocate(fElemList);//delete [] fElemList; + fElemList = newList; + fMaxCount = newMax; +} + + + +// --------------------------------------------------------------------------- +// AbstractBaseRefVectorEnumerator: Constructors and Destructor +// --------------------------------------------------------------------------- +template BaseRefVectorEnumerator:: +BaseRefVectorEnumerator( BaseRefVectorOf* const toEnum + , const bool adopt) : + fAdopted(adopt) + , fCurIndex(0) + , fToEnum(toEnum) +{ +} + +template BaseRefVectorEnumerator::~BaseRefVectorEnumerator() +{ + if (fAdopted) + delete fToEnum; +} + +template BaseRefVectorEnumerator:: +BaseRefVectorEnumerator(const BaseRefVectorEnumerator& toCopy) : + XMLEnumerator(toCopy) + , XMemory(toCopy) + , fAdopted(toCopy.fAdopted) + , fCurIndex(toCopy.fCurIndex) + , fToEnum(toCopy.fToEnum) +{ +} +// --------------------------------------------------------------------------- +// RefBaseRefVectorEnumerator: Enum interface +// --------------------------------------------------------------------------- +template bool BaseRefVectorEnumerator::hasMoreElements() const +{ + if (fCurIndex >= fToEnum->size()) + return false; + return true; +} + +template TElem& BaseRefVectorEnumerator::nextElement() +{ + return *(fToEnum->elementAt(fCurIndex++)); +} + +template void BaseRefVectorEnumerator::Reset() +{ + fCurIndex = 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/BaseRefVectorOf.hpp b/include/xercesc/util/BaseRefVectorOf.hpp new file mode 100644 index 0000000..f519e2e --- /dev/null +++ b/include/xercesc/util/BaseRefVectorOf.hpp @@ -0,0 +1,158 @@ +/* + * 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: BaseRefVectorOf.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ABSTRACTVECTOROF_HPP) +#define XERCESC_INCLUDE_GUARD_ABSTRACTVECTOROF_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Abstract base class for the xerces internal representation of Vector. + * + * The destructor is abstract, forcing each of RefVectorOf and + * RefArrayVectorOf to implement their own appropriate one. + * + */ +template class BaseRefVectorOf : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + BaseRefVectorOf + ( + const XMLSize_t maxElems + , const bool adoptElems = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~BaseRefVectorOf(); + + + // ----------------------------------------------------------------------- + // Element management + // ----------------------------------------------------------------------- + void addElement(TElem* const toAdd); + virtual void setElementAt(TElem* const toSet, const XMLSize_t setAt); + void insertElementAt(TElem* const toInsert, const XMLSize_t insertAt); + TElem* orphanElementAt(const XMLSize_t orphanAt); + virtual void removeAllElements(); + virtual void removeElementAt(const XMLSize_t removeAt); + virtual void removeLastElement(); + bool containsElement(const TElem* const toCheck); + virtual void cleanup(); + void reinitialize(); + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLSize_t curCapacity() const; + const TElem* elementAt(const XMLSize_t getAt) const; + TElem* elementAt(const XMLSize_t getAt); + XMLSize_t size() const; + MemoryManager* getMemoryManager() const; + + + // ----------------------------------------------------------------------- + // Miscellaneous + // ----------------------------------------------------------------------- + void ensureExtraCapacity(const XMLSize_t length); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + BaseRefVectorOf(const BaseRefVectorOf& copy); + BaseRefVectorOf& operator=(const BaseRefVectorOf& copy); + +protected: + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + bool fAdoptedElems; + XMLSize_t fCurCount; + XMLSize_t fMaxCount; + TElem** fElemList; + MemoryManager* fMemoryManager; +}; + + +// +// An enumerator for a vector. It derives from the basic enumerator +// class, so that value vectors can be generically enumerated. +// +template class BaseRefVectorEnumerator : public XMLEnumerator, public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + BaseRefVectorEnumerator + ( + BaseRefVectorOf* const toEnum + , const bool adopt = false + ); + virtual ~BaseRefVectorEnumerator(); + + BaseRefVectorEnumerator(const BaseRefVectorEnumerator& copy); + // ----------------------------------------------------------------------- + // Enum interface + // ----------------------------------------------------------------------- + bool hasMoreElements() const; + TElem& nextElement(); + void Reset(); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + BaseRefVectorEnumerator& operator=(const BaseRefVectorEnumerator& copy); + // ----------------------------------------------------------------------- + // Data Members + // + // fAdopted + // Indicates whether we have adopted the passed vector. If so then + // we delete the vector when we are destroyed. + // + // fCurIndex + // This is the current index into the vector. + // + // fToEnum + // The reference vector being enumerated. + // ----------------------------------------------------------------------- + bool fAdopted; + XMLSize_t fCurIndex; + BaseRefVectorOf* fToEnum; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/BinFileInputStream.cpp b/include/xercesc/util/BinFileInputStream.cpp new file mode 100644 index 0000000..48dea6b --- /dev/null +++ b/include/xercesc/util/BinFileInputStream.cpp @@ -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: BinFileInputStream.cpp 1662880 2015-02-28 01:55:31Z scantor $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// BinFileInputStream: Constructors and Destructor +// --------------------------------------------------------------------------- +BinFileInputStream::BinFileInputStream(const XMLCh* const fileName + , MemoryManager* const manager) : + + fSource(XMLPlatformUtils::openFile(fileName, manager)) + , fMemoryManager(manager) +{ +} + +BinFileInputStream::BinFileInputStream(const char* const fileName, + MemoryManager* const manager) : + + fSource(XMLPlatformUtils::openFile(fileName, manager)) + , fMemoryManager(manager) +{ +} + +BinFileInputStream::BinFileInputStream(const FileHandle toAdopt + , MemoryManager* const manager) : + + fSource(toAdopt) + , fMemoryManager(manager) +{ +} + +BinFileInputStream::~BinFileInputStream() +{ + if (getIsOpen()) + { + try + { + XMLPlatformUtils::closeFile(fSource, fMemoryManager); + } + catch (...) + { + // There is nothing we can do about it here. + } + } +} + + +// --------------------------------------------------------------------------- +// BinFileInputStream: Getter methods +// --------------------------------------------------------------------------- +XMLFilePos BinFileInputStream::getSize() const +{ + return XMLPlatformUtils::fileSize(fSource, fMemoryManager); +} + + +// --------------------------------------------------------------------------- +// BinFileInputStream: Stream management methods +// --------------------------------------------------------------------------- +void BinFileInputStream::reset() +{ + XMLPlatformUtils::resetFile(fSource, fMemoryManager); +} + + +// --------------------------------------------------------------------------- +// BinFileInputStream: Implementation of the input stream interface +// --------------------------------------------------------------------------- +XMLFilePos BinFileInputStream::curPos() const +{ + return XMLPlatformUtils::curFilePos(fSource, fMemoryManager); +} + +XMLSize_t +BinFileInputStream::readBytes( XMLByte* const toFill + , const XMLSize_t maxToRead) +{ + // + // Read up to the maximum bytes requested. We return the number + // actually read. + // + return XMLPlatformUtils::readFileBuffer(fSource, maxToRead, toFill, fMemoryManager); +} + +const XMLCh* BinFileInputStream::getContentType() const +{ + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/BinFileInputStream.hpp b/include/xercesc/util/BinFileInputStream.hpp new file mode 100644 index 0000000..1303a4b --- /dev/null +++ b/include/xercesc/util/BinFileInputStream.hpp @@ -0,0 +1,107 @@ +/* + * 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: BinFileInputStream.hpp 670359 2008-06-22 13:43:45Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BINFILEINPUTSTREAM_HPP) +#define XERCESC_INCLUDE_GUARD_BINFILEINPUTSTREAM_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BinFileInputStream : public BinInputStream +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + BinFileInputStream + ( + const XMLCh* const fileName + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + BinFileInputStream + ( + const char* const fileName + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + BinFileInputStream + ( + const FileHandle toUse + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~BinFileInputStream(); + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getIsOpen() const; + XMLFilePos getSize() const; + void reset(); + + + // ----------------------------------------------------------------------- + // Implementation of the input stream interface + // ----------------------------------------------------------------------- + virtual XMLFilePos curPos() const; + + virtual XMLSize_t readBytes + ( + XMLByte* const toFill + , const XMLSize_t maxToRead + ); + + virtual const XMLCh* getContentType() const; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + BinFileInputStream(const BinFileInputStream&); + BinFileInputStream& operator=(const BinFileInputStream&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fSource + // The source file that we represent. The FileHandle type is defined + // per platform. + // ----------------------------------------------------------------------- + FileHandle fSource; + MemoryManager* const fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// BinFileInputStream: Getter methods +// --------------------------------------------------------------------------- +inline bool BinFileInputStream::getIsOpen() const +{ + return (fSource != (FileHandle) XERCES_Invalid_File_Handle); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/BinInputStream.cpp b/include/xercesc/util/BinInputStream.cpp new file mode 100644 index 0000000..2475f9c --- /dev/null +++ b/include/xercesc/util/BinInputStream.cpp @@ -0,0 +1,45 @@ +/* + * 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: BinInputStream.cpp 670359 2008-06-22 13:43:45Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// BinInputStream: Virtual destructor! +// --------------------------------------------------------------------------- +BinInputStream::~BinInputStream() +{ +} + + +// --------------------------------------------------------------------------- +// BinInputStream: Hidden Constructors +// --------------------------------------------------------------------------- +BinInputStream::BinInputStream() +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/BinInputStream.hpp b/include/xercesc/util/BinInputStream.hpp new file mode 100644 index 0000000..ad9360b --- /dev/null +++ b/include/xercesc/util/BinInputStream.hpp @@ -0,0 +1,87 @@ +/* + * 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: BinInputStream.hpp 670359 2008-06-22 13:43:45Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BININPUTSTREAM_HPP) +#define XERCESC_INCLUDE_GUARD_BININPUTSTREAM_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BinInputStream : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Virtual destructor for derived classes + // ----------------------------------------------------------------------- + virtual ~BinInputStream(); + + + // ----------------------------------------------------------------------- + // The virtual input stream interface + // ----------------------------------------------------------------------- + virtual XMLFilePos curPos() const = 0; + + virtual XMLSize_t readBytes + ( + XMLByte* const toFill + , const XMLSize_t maxToRead + ) = 0; + + /** + * Return the "out-of-band" content type for the data supplied by this + * input stream in the form of the media-type production (mime type + * with optional parameters such as encoding) as defined by the HTTP 1.1 + * specification. If no such content type is provided for the data, 0 is + * returned. This function is expected to return the correct value at + * any time after the construction of the stream. + * + * An example of the stream that may return non-0 from this function is + * an HTTP stream with the value returned taken from the "Content-Type" + * HTTP header. Note also that if the encoding of the data is known + * to the application by some other means then the setEncoding function + * in the InputSource object should be used instead. The getContentType + * function should only be used to return information that is intrinsic + * to the stream. + * + * @return The content type, or 0 if one is not available. + */ + virtual const XMLCh* getContentType() const = 0; + + +protected : + // ----------------------------------------------------------------------- + // Hidden Constructors + // ----------------------------------------------------------------------- + BinInputStream(); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented Constructors + // ----------------------------------------------------------------------- + BinInputStream(const BinInputStream&); + BinInputStream& operator=(const BinInputStream&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/BinMemInputStream.cpp b/include/xercesc/util/BinMemInputStream.cpp new file mode 100644 index 0000000..baef93f --- /dev/null +++ b/include/xercesc/util/BinMemInputStream.cpp @@ -0,0 +1,98 @@ +/* + * 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: BinMemInputStream.cpp 670359 2008-06-22 13:43:45Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// BinMemInputStream: Constructors and Destructor +// --------------------------------------------------------------------------- +BinMemInputStream::BinMemInputStream( const XMLByte* const initData + , const XMLSize_t capacity + , const BufOpts bufOpt + , MemoryManager* const manager) : + fBuffer(0) + , fBufOpt(bufOpt) + , fCapacity(capacity) + , fCurIndex(0) + , fMemoryManager(manager) +{ + // According to the buffer option, do the right thing + if (fBufOpt == BufOpt_Copy) + { + XMLByte* tmpBuf = (XMLByte*) fMemoryManager->allocate + ( + fCapacity * sizeof(XMLByte) + );//new XMLByte[fCapacity]; + memcpy(tmpBuf, initData, capacity); + fBuffer = tmpBuf; + } + else + { + fBuffer = initData; + } +} + +BinMemInputStream::~BinMemInputStream() +{ + // + // If we adopted or copied the buffer, then clean it up. We have to + // cast off the const'ness in that case in order to delete it. + // + if ((fBufOpt == BufOpt_Adopt) || (fBufOpt == BufOpt_Copy)) + fMemoryManager->deallocate((XMLByte*)fBuffer);//delete [] (XMLByte*)fBuffer; +} + + +// --------------------------------------------------------------------------- +// MemBinInputStream: Implementation of the input stream interface +// --------------------------------------------------------------------------- +XMLSize_t BinMemInputStream::readBytes( XMLByte* const toFill + , const XMLSize_t maxToRead) +{ + // + // Figure out how much we can really read. Its the smaller of the + // amount available and the amount asked for. + // + const XMLSize_t available = (fCapacity - fCurIndex); + if (!available) + return 0; + + const XMLSize_t actualToRead = available < maxToRead ? available : maxToRead; + + memcpy(toFill, &fBuffer[fCurIndex], actualToRead); + fCurIndex += actualToRead; + return actualToRead; +} + +const XMLCh* BinMemInputStream::getContentType() const +{ + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/BinMemInputStream.hpp b/include/xercesc/util/BinMemInputStream.hpp new file mode 100644 index 0000000..abb65b8 --- /dev/null +++ b/include/xercesc/util/BinMemInputStream.hpp @@ -0,0 +1,134 @@ +/* + * 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: BinMemInputStream.hpp 670359 2008-06-22 13:43:45Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BINMEMINPUTSTREAM_HPP) +#define XERCESC_INCLUDE_GUARD_BINMEMINPUTSTREAM_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BinMemInputStream : public BinInputStream +{ +public : + // ----------------------------------------------------------------------- + // Class specific types + // ----------------------------------------------------------------------- + enum BufOpts + { + BufOpt_Adopt + , BufOpt_Copy + , BufOpt_Reference + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + BinMemInputStream + ( + const XMLByte* const initData + , const XMLSize_t capacity + , const BufOpts bufOpt = BufOpt_Copy + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~BinMemInputStream(); + + + // ----------------------------------------------------------------------- + // Stream management methods + // ----------------------------------------------------------------------- + void reset(); + + + // ----------------------------------------------------------------------- + // Implementation of the input stream interface + // ----------------------------------------------------------------------- + virtual XMLFilePos curPos() const; + + virtual XMLSize_t readBytes + ( + XMLByte* const toFill + , const XMLSize_t maxToRead + ); + + virtual const XMLCh* getContentType() const; + + inline XMLSize_t getSize() const; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + BinMemInputStream(const BinMemInputStream&); + BinMemInputStream& operator=(const BinMemInputStream&); + // ----------------------------------------------------------------------- + // Private data members + // + // fBuffer + // The buffer of bytes that we are streaming. + // + // fBufOpt + // Indicates the ownership status of the buffer. The caller can have + // us adopt it (we delete it), reference it, or just make our own + // copy of it. + // + // fCapacity + // The size of the buffer being streamed. + // + // fCurIndex + // The current index where the next byte will be read from. When it + // hits fCapacity, we are done. + // ----------------------------------------------------------------------- + const XMLByte* fBuffer; + BufOpts fBufOpt; + XMLSize_t fCapacity; + XMLSize_t fCurIndex; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// BinMemInputStream: Stream management methods +// --------------------------------------------------------------------------- +inline void BinMemInputStream::reset() +{ + fCurIndex = 0; +} + + +// --------------------------------------------------------------------------- +// BinMemInputStream: Implementation of the input stream interface +// --------------------------------------------------------------------------- +inline XMLFilePos BinMemInputStream::curPos() const +{ + return fCurIndex; +} + +inline XMLSize_t BinMemInputStream::getSize() const +{ + return fCapacity; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/BitOps.hpp b/include/xercesc/util/BitOps.hpp new file mode 100644 index 0000000..fe54511 --- /dev/null +++ b/include/xercesc/util/BitOps.hpp @@ -0,0 +1,67 @@ +/* + * 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: BitOps.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BITOPS_HPP) +#define XERCESC_INCLUDE_GUARD_BITOPS_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BitOps +{ +public: + // ----------------------------------------------------------------------- + // Public static methods + // ----------------------------------------------------------------------- + static inline XMLCh swapBytes(const XMLUInt16 toSwap) + { + //The mask is required to overcome a compiler error on solaris + return XMLCh(((toSwap >> 8) | (toSwap << 8)) & 0xFFFF); + } + + static inline unsigned int swapBytes(const XMLUInt32 toSwap) + { + return + ( + (toSwap >> 24) + | (toSwap << 24) + | ((toSwap & 0xFF00) << 8) + | ((toSwap & 0xFF0000) >> 8) + ); + } + + + +protected : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators. (These ought to be private, + // but that produces spurious compiler warnings + // on some platforms.) + // ----------------------------------------------------------------------- + BitOps(); + BitOps(const BitOps&); + BitOps& operator=(const BitOps&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/BitSet.cpp b/include/xercesc/util/BitSet.cpp new file mode 100644 index 0000000..ec14bdc --- /dev/null +++ b/include/xercesc/util/BitSet.cpp @@ -0,0 +1,270 @@ +/* + * 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: BitSet.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local const data +// +// kBitsPerUnit +// The number of bits in each of our allocation units, which is a 32 +// bit value in this case. +// +// kGrowBy +// The minimum allocation units to grow the buffer by. +// --------------------------------------------------------------------------- +const XMLSize_t kBitsPerUnit = 32; +const XMLSize_t kGrowBy = 1; + + + +// --------------------------------------------------------------------------- +// BitSet: Constructors and Destructor +// --------------------------------------------------------------------------- +BitSet::BitSet( const XMLSize_t size + , MemoryManager* const manager) : + + fMemoryManager(manager) + , fBits(0) + , fUnitLen(0) +{ + ensureCapacity(size); +} + +BitSet::BitSet(const BitSet& toCopy) : + XMemory(toCopy) + , fMemoryManager(toCopy.fMemoryManager) + , fBits(0) + , fUnitLen(toCopy.fUnitLen) +{ + fBits = (unsigned long*) fMemoryManager->allocate + ( + fUnitLen * sizeof(unsigned long) + ); //new unsigned long[fUnitLen]; + for (XMLSize_t i = 0; i < fUnitLen; i++) + fBits[i] = toCopy.fBits[i]; +} + +BitSet::~BitSet() +{ + fMemoryManager->deallocate(fBits); //delete [] fBits; +} + + +// --------------------------------------------------------------------------- +// BitSet: Equality methods +// --------------------------------------------------------------------------- +bool BitSet::equals(const BitSet& other) const +{ + if (this == &other) + return true; + + if (fUnitLen != other.fUnitLen) + return false; + + for (XMLSize_t i = 0; i < fUnitLen; i++) + { + if (fBits[i] != other.fBits[i]) + return false; + } + return true; +} + + +// --------------------------------------------------------------------------- +// BitSet: Getter methods +// --------------------------------------------------------------------------- +bool BitSet::get(const XMLSize_t index) const +{ + const XMLSize_t unitOfBit = (index / kBitsPerUnit); + const XMLSize_t bitWithinUnit = index % kBitsPerUnit; + + // + // If the index is beyond our size, don't actually expand. Just return + // false, which is what the state would be if we did expand it. + // + bool retVal = false; + if (unitOfBit <= fUnitLen) + { + if (fBits[unitOfBit] & (1 << bitWithinUnit)) + retVal = true; + } + return retVal; +} + + +XMLSize_t BitSet::size() const +{ + return fUnitLen * kBitsPerUnit; +} + + + +// --------------------------------------------------------------------------- +// BitSet: Setter methods +// --------------------------------------------------------------------------- +bool BitSet::allAreCleared() const +{ + for (XMLSize_t index = 0; index < fUnitLen; index++) + { + if (fBits[index]) + return false; + } + return true; +} + +bool BitSet::allAreSet() const +{ + for (XMLSize_t index = 0; index < fUnitLen; index++) + { + if (fBits[index] != 0xFFFFFFFF) + return false; + } + return true; +} + +void BitSet::clearAll() +{ + // Just zero out all the units + for (XMLSize_t index = 0; index < fUnitLen; index++) + fBits[index] = 0; +} + +void BitSet::clear(const XMLSize_t index) +{ + ensureCapacity(index+1); + + const XMLSize_t unitOfBit = (index / kBitsPerUnit); + const XMLSize_t bitWithinUnit = index % kBitsPerUnit; + + fBits[unitOfBit] &= ~(1UL << bitWithinUnit); +} + + +void BitSet::set(const XMLSize_t index) +{ + ensureCapacity(index+1); + + const XMLSize_t unitOfBit = (index / kBitsPerUnit); + const XMLSize_t bitWithinUnit = index % kBitsPerUnit; + + fBits[unitOfBit] |= (1UL << bitWithinUnit); +} + + + +// --------------------------------------------------------------------------- +// BitSet: Bitwise logical methods +// --------------------------------------------------------------------------- +void BitSet::andWith(const BitSet& other) +{ + if (fUnitLen < other.fUnitLen) + ensureCapacity(other.fUnitLen * kBitsPerUnit); + + for (XMLSize_t index = 0; index < other.fUnitLen; index++) + fBits[index] &= other.fBits[index]; +} + + +void BitSet::orWith(const BitSet& other) +{ + if (fUnitLen < other.fUnitLen) + ensureCapacity(other.fUnitLen * kBitsPerUnit); + + for (XMLSize_t index = 0; index < other.fUnitLen; index++) + fBits[index] |= other.fBits[index]; +} + + +void BitSet::xorWith(const BitSet& other) +{ + if (fUnitLen < other.fUnitLen) + ensureCapacity(other.fUnitLen * kBitsPerUnit); + + for (XMLSize_t index = 0; index < other.fUnitLen; index++) + fBits[index] ^= other.fBits[index]; +} + + + +// --------------------------------------------------------------------------- +// BitSet: Miscellaneous methods +// --------------------------------------------------------------------------- +XMLSize_t BitSet::hash(const XMLSize_t hashModulus) const +{ + const unsigned char* pBytes = (const unsigned char*)fBits; + const XMLSize_t len = fUnitLen * sizeof(unsigned long); + + XMLSize_t hashVal = 0; + for (XMLSize_t index = 0; index < len; index++) + { + hashVal <<= 1; + hashVal ^= *pBytes; + } + return hashVal % hashModulus; +} + + + +// --------------------------------------------------------------------------- +// BitSet: Private methods +// --------------------------------------------------------------------------- +void BitSet::ensureCapacity(const XMLSize_t size) +{ + // If we have enough space, do nothing + if(fUnitLen * kBitsPerUnit >= size) + return; + + // Calculate the units required to hold the passed bit count. + XMLSize_t unitsNeeded = size / kBitsPerUnit; + if (size % kBitsPerUnit) + unitsNeeded++; + + // Regrow the unit length by at least the expansion unit + if (unitsNeeded < (fUnitLen + kGrowBy)) + unitsNeeded = fUnitLen + kGrowBy; + + // Allocate the array, copy the old stuff, and zero the new stuff + unsigned long* newBits = (unsigned long*) fMemoryManager->allocate + ( + unitsNeeded * sizeof(unsigned long) + ); //new unsigned long[unitsNeeded]; + + XMLSize_t index; + for (index = 0; index < fUnitLen; index++) + newBits[index] = fBits[index]; + + for (; index < unitsNeeded; index++) + newBits[index] = 0; + + fMemoryManager->deallocate(fBits); //delete [] fBits; + fBits = newBits; + fUnitLen = unitsNeeded; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/BitSet.hpp b/include/xercesc/util/BitSet.hpp new file mode 100644 index 0000000..1410865 --- /dev/null +++ b/include/xercesc/util/BitSet.hpp @@ -0,0 +1,107 @@ +/* + * 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: BitSet.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BITSET_HPP) +#define XERCESC_INCLUDE_GUARD_BITSET_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT BitSet : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + BitSet( const XMLSize_t size + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + BitSet(const BitSet& toCopy); + ~BitSet(); + + + // ----------------------------------------------------------------------- + // Equality methods + // ----------------------------------------------------------------------- + bool equals(const BitSet& other) const; + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool allAreCleared() const; + bool allAreSet() const; + XMLSize_t size() const; + bool get(const XMLSize_t index) const; + + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void clear(const XMLSize_t index); + void clearAll(); + void set(const XMLSize_t index); + + + // ----------------------------------------------------------------------- + // Bitwise logical operations + // ----------------------------------------------------------------------- + void andWith(const BitSet& other); + void orWith(const BitSet& other); + void xorWith(const BitSet& other); + + + // ----------------------------------------------------------------------- + // Miscellaneous + // ----------------------------------------------------------------------- + XMLSize_t hash(const XMLSize_t hashModulus) const; + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors + // ----------------------------------------------------------------------- + BitSet(); + BitSet& operator=(const BitSet&); + // ----------------------------------------------------------------------- + // Private methods + // ----------------------------------------------------------------------- + void ensureCapacity(const XMLSize_t bits); + + + // ----------------------------------------------------------------------- + // Data members + // + // fBits + // The array of unsigned longs used to store the bits. + // + // fUnitLen + // The length of the storage array, in storage units not bits. + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + unsigned long* fBits; + XMLSize_t fUnitLen; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/CountedPointer.c b/include/xercesc/util/CountedPointer.c new file mode 100644 index 0000000..d03ab8f --- /dev/null +++ b/include/xercesc/util/CountedPointer.c @@ -0,0 +1,107 @@ +/* + * 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: CountedPointer.c 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// CountedPointerTo: Constructors and Destructor +// --------------------------------------------------------------------------- +template CountedPointerTo:: +CountedPointerTo(const CountedPointerTo& toCopy) : + + fPtr(toCopy.fPtr) +{ + if (fPtr) + fPtr->addRef(); +} + +template CountedPointerTo::CountedPointerTo(T* p) : + + fPtr(p) +{ + if (fPtr) + fPtr->addRef(); +} + +template CountedPointerTo::~CountedPointerTo() +{ + if (fPtr) + fPtr->removeRef(); +} + + +// --------------------------------------------------------------------------- +// CountedPointerTo: Operators +// --------------------------------------------------------------------------- +template CountedPointerTo& +CountedPointerTo::operator=(const CountedPointerTo& other) +{ + if (this == &other) + return *this; + + if (other.fPtr) + other.fPtr->addRef(); + + if (fPtr) + fPtr->removeRef(); + + fPtr = other.fPtr; + return *this; +} + +template CountedPointerTo::operator T*() +{ + return fPtr; +} + +template const T* CountedPointerTo::operator->() const +{ + return fPtr; +} + +template T* CountedPointerTo::operator->() +{ + return fPtr; +} + +template const T& CountedPointerTo::operator*() const +{ + if (!fPtr) + ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, 0); + return *fPtr; +} + +template T& CountedPointerTo::operator*() +{ + if (!fPtr) + ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, 0); + return *fPtr; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/CountedPointer.hpp b/include/xercesc/util/CountedPointer.hpp new file mode 100644 index 0000000..3bcdf6c --- /dev/null +++ b/include/xercesc/util/CountedPointer.hpp @@ -0,0 +1,69 @@ +/* + * 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: CountedPointer.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_COUNTEDPOINTERTO_HPP) +#define XERCESC_INCLUDE_GUARD_COUNTEDPOINTERTO_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +template class CountedPointerTo : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + CountedPointerTo(const CountedPointerTo& toCopy); + CountedPointerTo(T* p = 0); + ~CountedPointerTo(); + + + // ----------------------------------------------------------------------- + // Operators + // ----------------------------------------------------------------------- + CountedPointerTo& operator=(const CountedPointerTo& other); + operator T*(); + const T* operator->() const; + T* operator->(); + const T& operator*() const; + T& operator*(); + + +private: + // ----------------------------------------------------------------------- + // Data members + // + // fPtr + // The pointer that we are counting. The T type must implement the + // addRef() and removeRef() APIs but it doesn't have to derive from + // any particular type. + // ----------------------------------------------------------------------- + T* fPtr; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/DefaultPanicHandler.cpp b/include/xercesc/util/DefaultPanicHandler.cpp new file mode 100644 index 0000000..bf305fe --- /dev/null +++ b/include/xercesc/util/DefaultPanicHandler.cpp @@ -0,0 +1,40 @@ +/* + * 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: DefaultPanicHandler.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +void DefaultPanicHandler::panic(const PanicHandler::PanicReasons reason) +{ + fprintf(stderr, "%s\n", PanicHandler::getPanicReasonString(reason)); + exit(-1); +} + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/util/DefaultPanicHandler.hpp b/include/xercesc/util/DefaultPanicHandler.hpp new file mode 100644 index 0000000..ef19440 --- /dev/null +++ b/include/xercesc/util/DefaultPanicHandler.hpp @@ -0,0 +1,80 @@ +/* + * 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: DefaultPanicHandler.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DEFAULT_PANICHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DEFAULT_PANICHANDLER_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * Receive notification of panic. + * + *

This is Xerces' default implementation of the PanicHanlder + * interface, which will be instantiated and used in the + * absence of an application's panic handler. + *

+ */ + +class XMLUTIL_EXPORT DefaultPanicHandler : public XMemory, public PanicHandler +{ +public: + + /** @name hidden Constructors */ + //@{ + /** Default constructor */ + DefaultPanicHandler(){}; + + /** Destructor */ + virtual ~DefaultPanicHandler(){}; + //@} + + /** @name Implement virtual panic handler interface */ + //@{ + /** + * Receive notification of panic + * + *

Upon invocation, a corresponding error message will be output + * to the stderr, and program exit. + *

+ * + * @param reason The reason of panic + * + */ + virtual void panic(const PanicHandler::PanicReasons reason); + //@} + +private: + + /* Unimplemented Constructors and operators */ + /* Copy constructor */ + DefaultPanicHandler(const PanicHandler&); + + /** Assignment operator */ + DefaultPanicHandler& operator=(const DefaultPanicHandler&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/EmptyStackException.hpp b/include/xercesc/util/EmptyStackException.hpp new file mode 100644 index 0000000..a043f0f --- /dev/null +++ b/include/xercesc/util/EmptyStackException.hpp @@ -0,0 +1,34 @@ +/* + * 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: EmptyStackException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_EMPTYSTACKEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_EMPTYSTACKEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(EmptyStackException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/EncodingValidator.cpp b/include/xercesc/util/EncodingValidator.cpp new file mode 100644 index 0000000..c04f4e1 --- /dev/null +++ b/include/xercesc/util/EncodingValidator.cpp @@ -0,0 +1,96 @@ +/* + * 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: EncodingValidator.cpp 635560 2008-03-10 14:10:09Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +EncodingValidator* EncodingValidator::fInstance = 0; + +void XMLInitializer::initializeEncodingValidator() +{ + EncodingValidator::fInstance = new EncodingValidator(); +} + +void XMLInitializer::terminateEncodingValidator() +{ + delete EncodingValidator::fInstance; + EncodingValidator::fInstance = 0; +} + +// --------------------------------------------------------------------------- +// EncodingValidator: Constructors and Destructor +// --------------------------------------------------------------------------- +EncodingValidator::EncodingValidator() : + fEncodingRegistry(0) +{ + initializeRegistry(); +} + +EncodingValidator::~EncodingValidator() { + + delete fEncodingRegistry; + fEncodingRegistry = 0; +} + +// --------------------------------------------------------------------------- +// EncodingValidator: Validation methods +// --------------------------------------------------------------------------- +bool EncodingValidator::isValidEncoding(const XMLCh* const encName) { + + if (fEncodingRegistry->containsKey(encName)) + return true; + + return false; +} + + +// --------------------------------------------------------------------------- +// EncodingValidator: Initialization methods +// --------------------------------------------------------------------------- +void EncodingValidator::initializeRegistry() { + + fEncodingRegistry = new ValueHashTableOf(109); + + for (unsigned int i=0; i < gEncodingArraySize; i++) { + fEncodingRegistry->put((void*) gEncodingArray[i], true); + } +} + + +// --------------------------------------------------------------------------- +// EncodingValidator: Instance methods +// --------------------------------------------------------------------------- +EncodingValidator* EncodingValidator::instance() +{ + return fInstance; +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file EncodingValidator.cpp + */ diff --git a/include/xercesc/util/EncodingValidator.hpp b/include/xercesc/util/EncodingValidator.hpp new file mode 100644 index 0000000..4a7b49e --- /dev/null +++ b/include/xercesc/util/EncodingValidator.hpp @@ -0,0 +1,85 @@ +/* + * 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: EncodingValidator.hpp 635560 2008-03-10 14:10:09Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ENCODINGVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ENCODINGVALIDATOR_HPP + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/** + * A singleton class that checks whether an encoding name is a valid IANA + * encoding + */ + +class XMLUTIL_EXPORT EncodingValidator { + +public: + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + bool isValidEncoding(const XMLCh* const encName); + + // ----------------------------------------------------------------------- + // Instance methods + // ----------------------------------------------------------------------- + static EncodingValidator* instance(); + +private: + // ----------------------------------------------------------------------- + // Constructor and destructors + // ----------------------------------------------------------------------- + EncodingValidator(); + ~EncodingValidator(); + + // ----------------------------------------------------------------------- + // Private Helpers methods + // ----------------------------------------------------------------------- + /* + * Initializes the registry with a set of valid IANA encoding names + */ + void initializeRegistry(); + + // ----------------------------------------------------------------------- + // Private data members + // + // fEncodingRegistry + // Contains a set of IANA encoding names + // + // fInstance + // An EncodingValidator singleton instance + // ----------------------------------------------------------------------- + ValueHashTableOf* fEncodingRegistry; + static EncodingValidator* fInstance; + friend class XMLInitializer; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End file EncodingValidator.hpp + */ diff --git a/include/xercesc/util/FileManagers/PosixFileMgr.cpp b/include/xercesc/util/FileManagers/PosixFileMgr.cpp new file mode 100644 index 0000000..4c147e0 --- /dev/null +++ b/include/xercesc/util/FileManagers/PosixFileMgr.cpp @@ -0,0 +1,255 @@ +/* + * 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: PosixFileMgr.cpp 1662881 2015-02-28 02:00:45Z scantor $ + */ + +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#if HAVE_LIMITS_H +#include +#endif + +#include + +#include +#include +#include +#include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + + +PosixFileMgr::PosixFileMgr() +{ +} + + +PosixFileMgr::~PosixFileMgr() +{ +} + + +FileHandle +PosixFileMgr::fileOpen(const XMLCh* path, bool toWrite, MemoryManager* const manager) +{ + const char* tmpFileName = XMLString::transcode(path, manager); + ArrayJanitor janText((char*)tmpFileName, manager); + return fileOpen(tmpFileName, toWrite, manager); +} + + +FileHandle +PosixFileMgr::fileOpen(const char* path, bool toWrite, MemoryManager* const /*manager*/) +{ + const char* perms = (toWrite) ? "wb" : "rb"; + FileHandle result = (FileHandle)fopen(path , perms); + return result; +} + + +FileHandle +PosixFileMgr::openStdIn(MemoryManager* const /*manager*/) +{ + return (FileHandle)fdopen(dup(0), "rb"); +} + + +void +PosixFileMgr::fileClose(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + if (fclose((FILE*)f)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotCloseFile, manager); +} + + +void +PosixFileMgr::fileReset(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + // Seek to the start of the file + if (fseek((FILE*)f, 0, SEEK_SET)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotResetFile, manager); +} + + +XMLFilePos +PosixFileMgr::curPos(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + long curPos = ftell((FILE*)f); + + if (curPos == -1) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize, manager); + + return (XMLFilePos)curPos; +} + + +XMLFilePos +PosixFileMgr::fileSize(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + // Get the current position + long curPos = ftell((FILE*)f); + if (curPos == -1) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager); + + // Seek to the end and save that value for return + if (fseek((FILE*)f, 0, SEEK_END)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd, manager); + + long retVal = ftell((FILE*)f); + if (retVal == -1) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd, manager); + + // And put the pointer back + if (fseek((FILE*)f, curPos, SEEK_SET)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos, manager); + + return (XMLFilePos)retVal; +} + + +XMLSize_t +PosixFileMgr::fileRead(FileHandle f, XMLSize_t byteCount, XMLByte* buffer, MemoryManager* const manager) +{ + if (!f || !buffer) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + XMLSize_t bytesRead = 0; + if (byteCount > 0) + { + bytesRead = fread((void*)buffer, 1, byteCount, (FILE*)f); + + if (ferror((FILE*)f)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile, manager); + } + + return bytesRead; +} + + +void +PosixFileMgr::fileWrite(FileHandle f, XMLSize_t byteCount, const XMLByte* buffer, MemoryManager* const manager) +{ + if (!f || !buffer) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + while (byteCount > 0) + { + XMLSize_t bytesWritten = fwrite(buffer, sizeof(XMLByte), byteCount, (FILE*)f); + + if (ferror((FILE*)f)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile, manager); + + buffer += bytesWritten; + byteCount -= bytesWritten; + } +} + + +XMLCh* +PosixFileMgr::getFullPath(const XMLCh* const srcPath, MemoryManager* const manager) +{ + // + // NOTE: The path provided has always already been opened successfully, + // so we know that its not some pathological freaky path. It comes in + // in native format, and goes out as Unicode always + // + char* newSrc = XMLString::transcode(srcPath, manager); + ArrayJanitor janText(newSrc, manager); + +#if HAVE_PATH_MAX + // Use a local buffer that is big enough for the largest legal path + char absPath[PATH_MAX + 1]; + + // get the absolute path + if (!realpath(newSrc, absPath)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName, manager); + + XMLCh* ret = XMLString::transcode(absPath, manager); +#else + // get the absolute path + char *absPath = realpath(newSrc, NULL); + if(!absPath) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName, manager); + + XMLCh* ret = XMLString::transcode(absPath, manager); + free(absPath); +#endif + return ret; +} + + +XMLCh* +PosixFileMgr::getCurrentDirectory(MemoryManager* const manager) +{ +#if HAVE_PATH_MAX + char dirBuf[PATH_MAX + 2]; + char *curDir = getcwd(&dirBuf[0], PATH_MAX + 1); +#else + char *curDir = getcwd(NULL, 0); +#endif + + if (!curDir) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotGetBasePathName, manager); + + XMLCh* ret = XMLString::transcode(curDir, manager); +#if !HAVE_PATH_MAX + free(curDir); +#endif + return ret; +} + + +bool +PosixFileMgr::isRelative(const XMLCh* const toCheck, MemoryManager* const /*manager*/) +{ + // Check for pathological case of empty path + if (!toCheck || !toCheck[0]) + return false; + + // + // If it starts with a slash, then it cannot be relative. + // + return toCheck[0] != XMLCh('/'); +} + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/util/FileManagers/PosixFileMgr.hpp b/include/xercesc/util/FileManagers/PosixFileMgr.hpp new file mode 100644 index 0000000..1b32636 --- /dev/null +++ b/include/xercesc/util/FileManagers/PosixFileMgr.hpp @@ -0,0 +1,60 @@ +/* + * 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: PosixFileMgr.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_POSIXFILEMGR_HPP) +#define XERCESC_INCLUDE_GUARD_POSIXFILEMGR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// Concrete implementation of XMLFileMgr, implementing +// file access on posix compatible systems. +class PosixFileMgr : public XMLFileMgr +{ + public: + PosixFileMgr(); + virtual ~PosixFileMgr(); + + // File access + virtual FileHandle fileOpen(const XMLCh* path, bool toWrite, MemoryManager* const manager); + virtual FileHandle fileOpen(const char* path, bool toWrite, MemoryManager* const manager); + virtual FileHandle openStdIn(MemoryManager* const manager); + + virtual void fileClose(FileHandle f, MemoryManager* const manager); + virtual void fileReset(FileHandle f, MemoryManager* const manager); + + virtual XMLFilePos curPos(FileHandle f, MemoryManager* const manager); + virtual XMLFilePos fileSize(FileHandle f, MemoryManager* const manager); + + virtual XMLSize_t fileRead(FileHandle f, XMLSize_t byteCount, XMLByte* buffer, MemoryManager* const manager); + virtual void fileWrite(FileHandle f, XMLSize_t byteCount, const XMLByte* buffer, MemoryManager* const manager); + + // Ancillary path handling routines + virtual XMLCh* getFullPath(const XMLCh* const srcPath, MemoryManager* const manager); + virtual XMLCh* getCurrentDirectory(MemoryManager* const manager); + virtual bool isRelative(const XMLCh* const toCheck, MemoryManager* const manager); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/util/FileManagers/WindowsFileMgr.cpp b/include/xercesc/util/FileManagers/WindowsFileMgr.cpp new file mode 100644 index 0000000..e790a37 --- /dev/null +++ b/include/xercesc/util/FileManagers/WindowsFileMgr.cpp @@ -0,0 +1,431 @@ +/* + * 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: WindowsFileMgr.cpp 556533 2007-07-16 07:36:41Z amassari $ + */ + +#include + +#include +#include +#include +#include + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +static bool isBackSlash(XMLCh c) { + return c == chBackSlash || + c == chYenSign || + c == chWonSign; +} + +WindowsFileMgr::WindowsFileMgr() +{ + // Figure out if we are on NT and save that flag for later use + OSVERSIONINFO OSVer; + OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + ::GetVersionEx(&OSVer); + _onNT = (OSVer.dwPlatformId == VER_PLATFORM_WIN32_NT); +} + + +WindowsFileMgr::~WindowsFileMgr() +{ +} + + +FileHandle +WindowsFileMgr::fileOpen(const XMLCh* fileName, bool toWrite, MemoryManager* const manager) +{ + // Watch for obvious wierdness + if (!fileName) + return 0; + + // + // We have to play a little trick here. If its /x:..... + // style fully qualified path, we have to toss the leading / + // character. + // + const XMLCh* nameToOpen = fileName; + if (*fileName == chForwardSlash) + { + if (XMLString::stringLen(fileName) > 3) + { + if (*(fileName + 2) == chColon) + { + const XMLCh chDrive = *(fileName + 1); + if (((chDrive >= chLatin_A) && (chDrive <= chLatin_Z)) + || ((chDrive >= chLatin_a) && (chDrive <= chLatin_z))) + { + nameToOpen = fileName + 1; + } + } + + // Similarly for UNC paths + if ( *(fileName + 1) == *(fileName + 2) && + (*(fileName + 1) == chForwardSlash || + *(fileName + 1) == chBackSlash) ) + { + nameToOpen = fileName + 1; + } + } + } + + // Ok, this might look stupid but its a semi-expedient way to deal + // with a thorny problem. Shift-JIS and some other Asian encodings + // are fundamentally broken and map both the backslash and the Yen + // sign to the same code point. Transcoders have to pick one or the + // other to map '\' to Unicode and tend to choose the Yen sign. + // + // Unicode Yen or Won signs as directory separators will fail. + // + // So, we will check this path name for Yen or won signs and, if they are + // there, we'll replace them with slashes. + // + // A further twist: we replace Yen and Won with forward slashes rather + // than back slashes. Either form of slash will work as a directory + // separator. On Win 95 and 98, though, Unicode back-slashes may + // fail to transode back to 8-bit 0x5C with some Unicode converters + // to some of the problematic code pages. Forward slashes always + // transcode correctly back to 8 bit char * form. + // + XMLCh *tmpUName = 0; + + const XMLCh* srcPtr = nameToOpen; + while (*srcPtr) + { + if (*srcPtr == chYenSign || + *srcPtr == chWonSign) + break; + srcPtr++; + } + + // + // If we found a yen, then we have to create a temp file name. Else + // go with the file name as is and save the overhead. + // + if (*srcPtr) + { + tmpUName = XMLString::replicate(nameToOpen, manager); + + XMLCh* tmpPtr = tmpUName; + while (*tmpPtr) + { + if (*tmpPtr == chYenSign || + *tmpPtr == chWonSign) + *tmpPtr = chForwardSlash; + tmpPtr++; + } + nameToOpen = tmpUName; + } + FileHandle retVal = 0; + if (_onNT) + { + retVal = ::CreateFileW + ( + (LPCWSTR) nameToOpen + , toWrite?GENERIC_WRITE:GENERIC_READ + , FILE_SHARE_READ + , 0 + , toWrite?CREATE_ALWAYS:OPEN_EXISTING + , toWrite?FILE_ATTRIBUTE_NORMAL:FILE_FLAG_SEQUENTIAL_SCAN + , 0 + ); + } + else + { + // + // We are Win 95 / 98. Take the Unicode file name back to (char *) + // so that we can open it. + // + char* tmpName = XMLString::transcode(nameToOpen, manager); + retVal = ::CreateFileA + ( + tmpName + , toWrite?GENERIC_WRITE:GENERIC_READ + , FILE_SHARE_READ + , 0 + , toWrite?CREATE_ALWAYS:OPEN_EXISTING + , toWrite?FILE_ATTRIBUTE_NORMAL:FILE_FLAG_SEQUENTIAL_SCAN + , 0 + ); + manager->deallocate(tmpName);//delete [] tmpName; + } + + if (tmpUName) + manager->deallocate(tmpUName);//delete [] tmpUName; + + if (retVal == INVALID_HANDLE_VALUE) + return 0; + + return retVal; +} + + +FileHandle +WindowsFileMgr::fileOpen(const char* path, bool toWrite, MemoryManager* const manager) +{ + XMLCh* tmpFileName = XMLString::transcode(path, manager); + ArrayJanitor janText(tmpFileName, manager); + return fileOpen(tmpFileName, toWrite, manager); +} + + +FileHandle +WindowsFileMgr::openStdIn(MemoryManager* const manager) +{ + // + // Get the standard input handle. Duplicate it and return that copy + // since the outside world cannot tell the difference and will shut + // down this handle when its done with it. If we gave out the orignal, + // shutting it would prevent any further output. + // + HANDLE stdInOrg = ::GetStdHandle(STD_INPUT_HANDLE); + if (stdInOrg == INVALID_HANDLE_VALUE) { + XMLCh stdinStr[] = {chLatin_s, chLatin_t, chLatin_d, chLatin_i, chLatin_n, chNull}; + ThrowXMLwithMemMgr1(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile, stdinStr, manager); + } + + HANDLE retHandle; + if (!::DuplicateHandle + ( + ::GetCurrentProcess() + , stdInOrg + , ::GetCurrentProcess() + , &retHandle + , 0 + , FALSE + , DUPLICATE_SAME_ACCESS)) + { + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotDupHandle, manager); + } + return retHandle; +} + + +void +WindowsFileMgr::fileClose(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + if (!::CloseHandle(f)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile, manager); +} + + +void +WindowsFileMgr::fileReset(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + // Seek to the start of the file + if (::SetFilePointer(f, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile, manager); +} + + +XMLFilePos +WindowsFileMgr::curPos(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + // Get the current position + LONG high=0; + DWORD low = ::SetFilePointer(f, 0, &high, FILE_CURRENT); + if (low == INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager); + + return (((XMLFilePos)high) << 32) | low; +} + + +XMLFilePos +WindowsFileMgr::fileSize(FileHandle f, MemoryManager* const manager) +{ + if (!f) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + DWORD high=0; + DWORD low=::GetFileSize(f, &high); + if(low==INVALID_FILE_SIZE && GetLastError()!=NO_ERROR) + // TODO: find a better exception + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager); + + return (((XMLFilePos)high) << 32) | low; +} + + +XMLSize_t +WindowsFileMgr::fileRead(FileHandle f, XMLSize_t byteCount, XMLByte* buffer, MemoryManager* const manager) +{ + if (!f || !buffer) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + DWORD bytesRead = 0; + if (!::ReadFile(f, buffer, (DWORD)byteCount, &bytesRead, 0)) + { + // + // Check specially for a broken pipe error. If we get this, it just + // means no more data from the pipe, so return zero. + // + if (::GetLastError() != ERROR_BROKEN_PIPE) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile, manager); + } + return (unsigned int)bytesRead; +} + + +void +WindowsFileMgr::fileWrite(FileHandle f, XMLSize_t byteCount, const XMLByte* buffer, MemoryManager* const manager) +{ + if (!f || !buffer) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager); + + const XMLByte* tmpFlush = buffer; + + while (byteCount > 0) + { + DWORD bytesWritten = 0; + if (!::WriteFile(f, tmpFlush, (DWORD)byteCount, &bytesWritten, 0)) + ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile, manager); + + tmpFlush+=bytesWritten; + byteCount-=bytesWritten; + } +} + + +XMLCh* +WindowsFileMgr::getFullPath(const XMLCh* const srcPath, MemoryManager* const manager) +{ + // + // If we are on NT, then use wide character APIs, else use ASCII APIs. + // We have to do it manually since we are only built in ASCII mode from + // the standpoint of the APIs. + // + if (_onNT) + { + // Use a local buffer that is big enough for the largest legal path + const unsigned int bufSize = 1024; + XMLCh tmpPath[bufSize + 1]; + + XMLCh* namePart = 0; + if (!::GetFullPathNameW((LPCWSTR)srcPath, bufSize, (LPWSTR)tmpPath, (LPWSTR*)&namePart)) + return 0; + + // Return a copy of the path + return XMLString::replicate(tmpPath, manager); + } + else + { + // Transcode the incoming string + char* tmpSrcPath = XMLString::transcode(srcPath, manager); + ArrayJanitor janSrcPath(tmpSrcPath, manager); + + // Use a local buffer that is big enough for the largest legal path + const unsigned int bufSize = 511; + char tmpPath[511 + 1]; + + char* namePart = 0; + if (!::GetFullPathNameA(tmpSrcPath, bufSize, tmpPath, &namePart)) + return 0; + + // Return a transcoded copy of the path + return XMLString::transcode(tmpPath, manager); + } +} + + +XMLCh* +WindowsFileMgr::getCurrentDirectory(MemoryManager* const manager) +{ + // + // If we are on NT, then use wide character APIs, else use ASCII APIs. + // We have to do it manually since we are only built in ASCII mode from + // the standpoint of the APIs. + // + if (_onNT) + { + // Use a local buffer that is big enough for the largest legal path + const unsigned int bufSize = 1024; + XMLCh tmpPath[bufSize + 1]; + + if (!::GetCurrentDirectoryW(bufSize, (LPWSTR)tmpPath)) + return 0; + + // Return a copy of the path + return XMLString::replicate(tmpPath, manager); + } + else + { + // Use a local buffer that is big enough for the largest legal path + const unsigned int bufSize = 511; + char tmpPath[511 + 1]; + + if (!::GetCurrentDirectoryA(bufSize, tmpPath)) + return 0; + + // Return a transcoded copy of the path + return XMLString::transcode(tmpPath, manager); + } +} + + +bool +WindowsFileMgr::isRelative(const XMLCh* const toCheck, MemoryManager* const /*manager*/) +{ + // Check for pathological case of empty path + if (!toCheck || !toCheck[0]) + return false; + + // + // If its starts with a drive, then it cannot be relative. Note that + // we checked the drive not being empty above, so worst case its one + // char long and the check of the 1st char will fail because its really + // a null character. + // + if (toCheck[1] == chColon) + { + if (((toCheck[0] >= chLatin_A) && (toCheck[0] <= chLatin_Z)) + || ((toCheck[0] >= chLatin_a) && (toCheck[0] <= chLatin_z))) + { + return false; + } + } + + // + // If it starts with a double slash, then it cannot be relative since + // it's a remote file. + // + if (isBackSlash(toCheck[0])) + return false; + + // Else assume its a relative path + return true; +} + + +XERCES_CPP_NAMESPACE_END + diff --git a/include/xercesc/util/FileManagers/WindowsFileMgr.hpp b/include/xercesc/util/FileManagers/WindowsFileMgr.hpp new file mode 100644 index 0000000..38a01e2 --- /dev/null +++ b/include/xercesc/util/FileManagers/WindowsFileMgr.hpp @@ -0,0 +1,63 @@ +/* + * 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: WindowsFileMgr.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_WINDOWSFILEMGR_HPP) +#define XERCESC_INCLUDE_GUARD_WINDOWSFILEMGR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// Concrete implementation of XMLFileMgr, implementing +// file access on Windows systems. +class WindowsFileMgr : public XMLFileMgr +{ + public: + WindowsFileMgr(); + virtual ~WindowsFileMgr(); + + // File access + virtual FileHandle fileOpen(const XMLCh* path, bool toWrite, MemoryManager* const manager); + virtual FileHandle fileOpen(const char* path, bool toWrite, MemoryManager* const manager); + virtual FileHandle openStdIn(MemoryManager* const manager); + + virtual void fileClose(FileHandle f, MemoryManager* const manager); + virtual void fileReset(FileHandle f, MemoryManager* const manager); + + virtual XMLFilePos curPos(FileHandle f, MemoryManager* const manager); + virtual XMLFilePos fileSize(FileHandle f, MemoryManager* const manager); + + virtual XMLSize_t fileRead(FileHandle f, XMLSize_t byteCount, XMLByte* buffer, MemoryManager* const manager); + virtual void fileWrite(FileHandle f, XMLSize_t byteCount, const XMLByte* buffer, MemoryManager* const manager); + + // Ancillary path handling routines + virtual XMLCh* getFullPath(const XMLCh* const srcPath, MemoryManager* const manager); + virtual XMLCh* getCurrentDirectory(MemoryManager* const manager); + virtual bool isRelative(const XMLCh* const toCheck, MemoryManager* const manager); + + private: + bool _onNT; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + diff --git a/include/xercesc/util/FlagJanitor.c b/include/xercesc/util/FlagJanitor.c new file mode 100644 index 0000000..e5f0d4d --- /dev/null +++ b/include/xercesc/util/FlagJanitor.c @@ -0,0 +1,62 @@ +/* + * 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: FlagJanitor.c 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +template FlagJanitor::FlagJanitor(T* const valPtr, const T newVal) +: fValPtr(valPtr) +{ + // Store the pointer, save the org value, and store the new value + if (fValPtr) + { + fOldVal = *fValPtr; + *fValPtr = newVal; + } +} + +template FlagJanitor::~FlagJanitor() +{ + // Restore the old value + if (fValPtr) + *fValPtr = fOldVal; +} + + +// --------------------------------------------------------------------------- +// Value management methods +// --------------------------------------------------------------------------- +template void FlagJanitor::release() +{ + fValPtr = 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/FlagJanitor.hpp b/include/xercesc/util/FlagJanitor.hpp new file mode 100644 index 0000000..dba1b35 --- /dev/null +++ b/include/xercesc/util/FlagJanitor.hpp @@ -0,0 +1,73 @@ +/* + * 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: FlagJanitor.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_FLAGJANITOR_HPP) +#define XERCESC_INCLUDE_GUARD_FLAGJANITOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +template class FlagJanitor +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + FlagJanitor(T* const valPtr, const T newVal); + ~FlagJanitor(); + + + // ----------------------------------------------------------------------- + // Value management methods + // ----------------------------------------------------------------------- + void release(); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + FlagJanitor(); + FlagJanitor(const FlagJanitor&); + FlagJanitor& operator=(const FlagJanitor&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fOldVal + // The old value that was in the flag when we were constructed. + // + // fValPtr + // A pointer to the flag that we are to restore the value of + // ----------------------------------------------------------------------- + T fOldVal; + T* fValPtr; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/Hash2KeysSetOf.c b/include/xercesc/util/Hash2KeysSetOf.c new file mode 100644 index 0000000..50ac774 --- /dev/null +++ b/include/xercesc/util/Hash2KeysSetOf.c @@ -0,0 +1,591 @@ +/* + * 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: Hash2KeysSetOf.c 883368 2009-11-23 15:28:19Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Include +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Constructors and Destructor +// --------------------------------------------------------------------------- + +template +Hash2KeysSetOf::Hash2KeysSetOf( + const XMLSize_t modulus, + MemoryManager* const manager) + + : fMemoryManager(manager) + , fBucketList(0) + , fHashModulus(modulus) + , fCount(0) + , fAvailable(0) +{ + initialize(modulus); +} + +template +Hash2KeysSetOf::Hash2KeysSetOf( + const XMLSize_t modulus, + const THasher& hasher, + MemoryManager* const manager) + + : fMemoryManager(manager) + , fBucketList(0) + , fHashModulus(modulus) + , fCount(0) + , fAvailable(0) + , fHasher (hasher) +{ + initialize(modulus); +} + +template +void Hash2KeysSetOf::initialize(const XMLSize_t modulus) +{ + if (modulus == 0) + ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager); + + // Allocate the bucket list and zero them + fBucketList = (Hash2KeysSetBucketElem**) fMemoryManager->allocate + ( + fHashModulus * sizeof(Hash2KeysSetBucketElem*) + ); //new Hash2KeysSetBucketElem*[fHashModulus]; + memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus); +} + +template +Hash2KeysSetOf::~Hash2KeysSetOf() +{ + Hash2KeysSetBucketElem* nextElem; + if(!isEmpty()) + { + // Clean up the buckets first + for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) + { + // Get the bucket list head for this entry + Hash2KeysSetBucketElem* curElem = fBucketList[buckInd]; + while (curElem) + { + // Save the next element before we hose this one + nextElem = curElem->fNext; + fMemoryManager->deallocate(curElem); + curElem = nextElem; + } + + // Clean out this entry + fBucketList[buckInd] = 0; + } + } + // Then delete the list of available blocks + Hash2KeysSetBucketElem* curElem = fAvailable; + while (curElem) + { + // Save the next element before we hose this one + nextElem = curElem->fNext; + fMemoryManager->deallocate(curElem); + curElem = nextElem; + } + fAvailable = 0; + + // Then delete the bucket list & hasher + fMemoryManager->deallocate(fBucketList); //delete [] fBucketList; + fBucketList = 0; +} + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Element management +// --------------------------------------------------------------------------- +template +bool Hash2KeysSetOf::isEmpty() const +{ + return (fCount==0); +} + +template +bool Hash2KeysSetOf::containsKey(const void* const key1, const int key2) const +{ + XMLSize_t hashVal; + const Hash2KeysSetBucketElem* findIt = findBucketElem(key1, key2, hashVal); + return (findIt != 0); +} + +template +void Hash2KeysSetOf::removeKey(const void* const key1, const int key2) +{ + // Hash the key + XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // + // Search the given bucket for this key. Keep up with the previous + // element so we can patch around it. + // + Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + Hash2KeysSetBucketElem* lastElem = 0; + + while (curElem) + { + if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) + { + if (!lastElem) + { + // It was the first in the bucket + fBucketList[hashVal] = curElem->fNext; + } + else + { + // Patch around the current element + lastElem->fNext = curElem->fNext; + } + + // Move the current element to the list of available blocks + curElem->fNext=fAvailable; + fAvailable=curElem; + + fCount--; + return; + } + + // Move both pointers upwards + lastElem = curElem; + curElem = curElem->fNext; + } + + // We never found that key + ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager); +} + +template +void Hash2KeysSetOf:: +removeKey(const void* const key1) +{ + // Hash the key + XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // + // Search the given bucket for this key. Keep up with the previous + // element so we can patch around it. + // + Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + Hash2KeysSetBucketElem* lastElem = 0; + + while (curElem) + { + if(fHasher.equals(key1, curElem->fKey1)) + { + if (!lastElem) + { + // It was the first in the bucket + fBucketList[hashVal] = curElem->fNext; + } + else + { + // Patch around the current element + lastElem->fNext = curElem->fNext; + } + + Hash2KeysSetBucketElem* toBeDeleted=curElem; + curElem = curElem->fNext; + + // Move the current element to the list of available blocks + toBeDeleted->fNext=fAvailable; + fAvailable=toBeDeleted; + + fCount--; + } + else + { + // Move both pointers upwards + lastElem = curElem; + curElem = curElem->fNext; + } + } +} + +template +void Hash2KeysSetOf::removeAll() +{ + if(isEmpty()) + return; + + for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) + { + if(fBucketList[buckInd]!=0) + { + // Advance to the end of the chain, and connect it to the list of + // available blocks + Hash2KeysSetBucketElem* curElem = fBucketList[buckInd]; + while (curElem->fNext) + curElem = curElem->fNext; + curElem->fNext=fAvailable; + fAvailable=fBucketList[buckInd]; + fBucketList[buckInd] = 0; + } + } + fCount=0; +} + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Getters +// --------------------------------------------------------------------------- +template +MemoryManager* Hash2KeysSetOf::getMemoryManager() const +{ + return fMemoryManager; +} + +template +XMLSize_t Hash2KeysSetOf::getHashModulus() const +{ + return fHashModulus; +} + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Putters +// --------------------------------------------------------------------------- +template +void Hash2KeysSetOf::put(const void* key1, int key2) +{ + // Apply 4 load factor to find threshold. + XMLSize_t threshold = fHashModulus * 4; + + // If we've grown too big, expand the table and rehash. + if (fCount >= threshold) + rehash(); + + // First see if the key exists already + XMLSize_t hashVal; + Hash2KeysSetBucketElem* newBucket = findBucketElem(key1, key2, hashVal); + + // + // If so,then update its value. If not, then we need to add it to + // the right bucket + // + if (newBucket) + { + newBucket->fKey1 = key1; + newBucket->fKey2 = key2; + } + else + { + if(fAvailable==0) + newBucket = (Hash2KeysSetBucketElem*)fMemoryManager->allocate(sizeof(Hash2KeysSetBucketElem)); + else + { + newBucket = fAvailable; + fAvailable = fAvailable->fNext; + } + newBucket->fKey1 = key1; + newBucket->fKey2 = key2; + newBucket->fNext = fBucketList[hashVal]; + fBucketList[hashVal] = newBucket; + fCount++; + } +} + +template +bool Hash2KeysSetOf::putIfNotPresent(const void* key1, int key2) +{ + // First see if the key exists already + XMLSize_t hashVal; + Hash2KeysSetBucketElem* newBucket = findBucketElem(key1, key2, hashVal); + + // + // If so,then update its value. If not, then we need to add it to + // the right bucket + // + if (newBucket) + return false; + + // Apply 4 load factor to find threshold. + XMLSize_t threshold = fHashModulus * 4; + + // If we've grown too big, expand the table and rehash. + if (fCount >= threshold) + rehash(); + + if(fAvailable==0) + newBucket = (Hash2KeysSetBucketElem*)fMemoryManager->allocate(sizeof(Hash2KeysSetBucketElem)); + else + { + newBucket = fAvailable; + fAvailable = fAvailable->fNext; + } + newBucket->fKey1 = key1; + newBucket->fKey2 = key2; + newBucket->fNext = fBucketList[hashVal]; + fBucketList[hashVal] = newBucket; + fCount++; + return true; +} + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOf: Private methods +// --------------------------------------------------------------------------- +template +inline Hash2KeysSetBucketElem* Hash2KeysSetOf:: +findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) +{ + // Hash the key + hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // Search that bucket for the key + Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + while (curElem) + { + if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) + return curElem; + + curElem = curElem->fNext; + } + return 0; +} + +template +inline const Hash2KeysSetBucketElem* Hash2KeysSetOf:: +findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const +{ + // Hash the key + hashVal = fHasher.getHashVal(key1, fHashModulus); + assert(hashVal < fHashModulus); + + // Search that bucket for the key + const Hash2KeysSetBucketElem* curElem = fBucketList[hashVal]; + while (curElem) + { + if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) + return curElem; + + curElem = curElem->fNext; + } + return 0; +} + + +template +void Hash2KeysSetOf:: +rehash() +{ + const XMLSize_t newMod = (fHashModulus * 8)+1; + + Hash2KeysSetBucketElem** newBucketList = + (Hash2KeysSetBucketElem**) fMemoryManager->allocate + ( + newMod * sizeof(Hash2KeysSetBucketElem*) + );//new Hash2KeysSetBucketElem*[fHashModulus]; + + // Make sure the new bucket list is destroyed if an + // exception is thrown. + ArrayJanitor guard(newBucketList, fMemoryManager); + + memset(newBucketList, 0, newMod * sizeof(newBucketList[0])); + + // Rehash all existing entries. + for (XMLSize_t index = 0; index < fHashModulus; index++) + { + // Get the bucket list head for this entry + Hash2KeysSetBucketElem* curElem = fBucketList[index]; + while (curElem) + { + // Save the next element before we detach this one + Hash2KeysSetBucketElem* nextElem = curElem->fNext; + + const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey1, newMod); + assert(hashVal < newMod); + + Hash2KeysSetBucketElem* newHeadElem = newBucketList[hashVal]; + + // Insert at the start of this bucket's list. + curElem->fNext = newHeadElem; + newBucketList[hashVal] = curElem; + + curElem = nextElem; + } + } + + Hash2KeysSetBucketElem** const oldBucketList = fBucketList; + + // Everything is OK at this point, so update the + // member variables. + fBucketList = guard.release(); + fHashModulus = newMod; + + // Delete the old bucket list. + fMemoryManager->deallocate(oldBucketList);//delete[] oldBucketList; + +} + + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOfEnumerator: Constructors and Destructor +// --------------------------------------------------------------------------- +template +Hash2KeysSetOfEnumerator:: +Hash2KeysSetOfEnumerator(Hash2KeysSetOf* const toEnum + , const bool adopt + , MemoryManager* const manager) + : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum) + , fMemoryManager(manager) + , fLockPrimaryKey(0) +{ + if (!toEnum) + ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager); + + // + // Find the next available bucket element in the hash table. If it + // comes back zero, that just means the table is empty. + // + // Note that the -1 in the current hash tells it to start + // from the beginning. + // + findNext(); +} + +template +Hash2KeysSetOfEnumerator::~Hash2KeysSetOfEnumerator() +{ + if (fAdopted) + delete fToEnum; +} + + +// --------------------------------------------------------------------------- +// Hash2KeysSetOfEnumerator: Enum interface +// --------------------------------------------------------------------------- +template +bool Hash2KeysSetOfEnumerator::hasMoreElements() const +{ + // + // If our current has is at the max and there are no more elements + // in the current bucket, then no more elements. + // + if (!fCurElem && (fCurHash == fToEnum->fHashModulus)) + return false; + return true; +} + +template +void Hash2KeysSetOfEnumerator::nextElementKey(const void*& retKey1, int& retKey2) +{ + // Make sure we have an element to return + if (!hasMoreElements()) + ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager); + + // + // Save the current element, then move up to the next one for the + // next time around. + // + Hash2KeysSetBucketElem* saveElem = fCurElem; + findNext(); + + retKey1 = saveElem->fKey1; + retKey2 = saveElem->fKey2; + + return; +} + +template +void Hash2KeysSetOfEnumerator::Reset() +{ + if(fLockPrimaryKey) + fCurHash=fToEnum->fHasher.getHashVal(fLockPrimaryKey, fToEnum->fHashModulus); + else + fCurHash = (XMLSize_t)-1; + + fCurElem = 0; + findNext(); +} + + +template +void Hash2KeysSetOfEnumerator::setPrimaryKey(const void* key) +{ + fLockPrimaryKey=key; + Reset(); +} + +// --------------------------------------------------------------------------- +// Hash2KeysSetOfEnumerator: Private helper methods +// --------------------------------------------------------------------------- +template +void Hash2KeysSetOfEnumerator::findNext() +{ + // Code to execute if we have to return only values with the primary key + if(fLockPrimaryKey) + { + if(!fCurElem) + fCurElem = fToEnum->fBucketList[fCurHash]; + else + fCurElem = fCurElem->fNext; + while (fCurElem && (!fToEnum->fHasher.equals(fLockPrimaryKey, fCurElem->fKey1))) + fCurElem = fCurElem->fNext; + // if we didn't found it, make so hasMoreElements() returns false + if(!fCurElem) + fCurHash = fToEnum->fHashModulus; + return; + } + // + // If there is a current element, move to its next element. If this + // hits the end of the bucket, the next block will handle the rest. + // + if (fCurElem) + fCurElem = fCurElem->fNext; + + // + // If the current element is null, then we have to move up to the + // next hash value. If that is the hash modulus, then we cannot + // go further. + // + if (!fCurElem) + { + fCurHash++; + if (fCurHash == fToEnum->fHashModulus) + return; + + // Else find the next non-empty bucket + while (fToEnum->fBucketList[fCurHash]==0) + { + // Bump to the next hash value. If we max out return + fCurHash++; + if (fCurHash == fToEnum->fHashModulus) + return; + } + fCurElem = fToEnum->fBucketList[fCurHash]; + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/Hash2KeysSetOf.hpp b/include/xercesc/util/Hash2KeysSetOf.hpp new file mode 100644 index 0000000..e827d82 --- /dev/null +++ b/include/xercesc/util/Hash2KeysSetOf.hpp @@ -0,0 +1,223 @@ +/* + * 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: Hash2KeysSetOf.hpp 883368 2009-11-23 15:28:19Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_HASH2KEYSSETOF_HPP) +#define XERCESC_INCLUDE_GUARD_HASH2KEYSSETOF_HPP + + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// This hash table is similar to Hash2KeysSetOf with an additional integer as key2 + +// Forward declare the enumerator so it can be our friend. +// +template +class Hash2KeysSetOfEnumerator; + +// +// This should really be a nested class, but some of the compilers we +// have to support cannot deal with that! +// +struct Hash2KeysSetBucketElem +{ + Hash2KeysSetBucketElem* fNext; + const void* fKey1; + int fKey2; +}; + + +template +class Hash2KeysSetOf : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + Hash2KeysSetOf( + const XMLSize_t modulus, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + Hash2KeysSetOf( + const XMLSize_t modulus, + const THasher& hasher, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + ~Hash2KeysSetOf(); + + + // ----------------------------------------------------------------------- + // Element management + // ----------------------------------------------------------------------- + bool isEmpty() const; + bool containsKey(const void* const key1, const int key2) const; + void removeKey(const void* const key1, const int key2); + void removeKey(const void* const key1); + void removeAll(); + + // ----------------------------------------------------------------------- + // Getters + // ----------------------------------------------------------------------- + MemoryManager* getMemoryManager() const; + XMLSize_t getHashModulus() const; + + // ----------------------------------------------------------------------- + // Putters + // ----------------------------------------------------------------------- + void put(const void* key1, int key2); + bool putIfNotPresent(const void* key1, int key2); + +private : + // ----------------------------------------------------------------------- + // Declare our friends + // ----------------------------------------------------------------------- + friend class Hash2KeysSetOfEnumerator; + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Hash2KeysSetOf(const Hash2KeysSetOf&); + Hash2KeysSetOf& operator=(const Hash2KeysSetOf&); + + // ----------------------------------------------------------------------- + // Private methods + // ----------------------------------------------------------------------- + Hash2KeysSetBucketElem* findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal); + const Hash2KeysSetBucketElem* findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const; + void initialize(const XMLSize_t modulus); + void rehash(); + + + // ----------------------------------------------------------------------- + // Data members + // + // fBucketList + // This is the array that contains the heads of all of the list + // buckets, one for each possible hash value. + // + // fHashModulus + // The modulus used for this hash table, to hash the keys. This is + // also the number of elements in the bucket list. + // + // fCount + // The number of elements currently in the map + // + // fHash + // The hasher for the key1 data type. + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + Hash2KeysSetBucketElem** fBucketList; + XMLSize_t fHashModulus; + XMLSize_t fCount; + Hash2KeysSetBucketElem* fAvailable; + THasher fHasher; +}; + + + +// +// An enumerator for a value array. It derives from the basic enumerator +// class, so that value vectors can be generically enumerated. +// +template +class Hash2KeysSetOfEnumerator : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + Hash2KeysSetOfEnumerator(Hash2KeysSetOf* const toEnum + , const bool adopt = false + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual ~Hash2KeysSetOfEnumerator(); + + + // ----------------------------------------------------------------------- + // Enum interface + // ----------------------------------------------------------------------- + bool hasMoreElements() const; + void Reset(); + + // ----------------------------------------------------------------------- + // New interface + // ----------------------------------------------------------------------- + void nextElementKey(const void*&, int&); + void setPrimaryKey(const void* key); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Hash2KeysSetOfEnumerator(const Hash2KeysSetOfEnumerator&); + Hash2KeysSetOfEnumerator& operator=(const Hash2KeysSetOfEnumerator&); + + // ----------------------------------------------------------------------- + // Private methods + // ----------------------------------------------------------------------- + void findNext(); + + + // ----------------------------------------------------------------------- + // Data Members + // + // fAdopted + // Indicates whether we have adopted the passed vector. If so then + // we delete the vector when we are destroyed. + // + // fCurElem + // This is the current bucket bucket element that we are on. + // + // fCurHash + // The is the current hash buck that we are working on. Once we hit + // the end of the bucket that fCurElem is in, then we have to start + // working this one up to the next non-empty bucket. + // + // fToEnum + // The value array being enumerated. + // + // fLockPrimaryKey + // Indicates that we are requested to iterate over the secondary keys + // associated with the given primary key + // + // ----------------------------------------------------------------------- + bool fAdopted; + Hash2KeysSetBucketElem* fCurElem; + XMLSize_t fCurHash; + Hash2KeysSetOf* fToEnum; + MemoryManager* const fMemoryManager; + const void* fLockPrimaryKey; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/Hashers.hpp b/include/xercesc/util/Hashers.hpp new file mode 100644 index 0000000..dd2d704 --- /dev/null +++ b/include/xercesc/util/Hashers.hpp @@ -0,0 +1,95 @@ +/* + * 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: Hashers.hpp 679382 2008-07-24 12:09:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_HASHERS_HPP) +#define XERCESC_INCLUDE_GUARD_HASHERS_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// Common hashers. Only widely-used hashers should be placed here. +// + +/** + * Hasher for keys that are const XMLCh*. + */ +struct StringHasher +{ + /** + * Returns a hash value based on the key + * + * @param key the key to be hashed + * @param mod the modulus the hasher should use + */ + XMLSize_t getHashVal(const void* key, XMLSize_t mod) const + { + return XMLString::hash ((const XMLCh*)key, mod); + } + + /** + * Compares two keys and determines if they are semantically equal + * + * @param key1 the first key to be compared + * @param key2 the second key to be compared + * + * @return true if they are equal + */ + bool equals(const void *const key1, const void *const key2) const + { + return XMLString::equals ((const XMLCh*)key1, (const XMLCh*)key2); + } +}; + +/** + * Hasher for keys that are pointers. + */ +struct PtrHasher +{ + /** + * Returns a hash value based on the key + * + * @param key the key to be hashed + * @param mod the modulus the hasher should use + */ + XMLSize_t getHashVal(const void* key, XMLSize_t mod) const + { + return ((XMLSize_t)key) % mod; + } + + /** + * Compares two keys and determines if they are semantically equal + * + * @param key1 the first key to be compared + * @param key2 the second key to be compared + * + * @return true if they are equal + */ + bool equals(const void *const key1, const void *const key2) const + { + return key1 == key2; + } +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/HeaderDummy.cpp b/include/xercesc/util/HeaderDummy.cpp new file mode 100644 index 0000000..57a17f7 --- /dev/null +++ b/include/xercesc/util/HeaderDummy.cpp @@ -0,0 +1,40 @@ +/* + * 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: HeaderDummy.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/HexBin.cpp b/include/xercesc/util/HexBin.cpp new file mode 100644 index 0000000..28e3ab2 --- /dev/null +++ b/include/xercesc/util/HexBin.cpp @@ -0,0 +1,138 @@ +/* + * 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. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// constants +// --------------------------------------------------------------------------- +static const int BASELENGTH = 255; + +// --------------------------------------------------------------------------- +// class data member +// --------------------------------------------------------------------------- +const XMLByte HexBin::hexNumberTable[BASELENGTH] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + + +int HexBin::getDataLength(const XMLCh* const hexData) +{ + if (!isArrayByteHex(hexData)) + return -1; + + return (int)XMLString::stringLen(hexData)/2; +} + +bool HexBin::isArrayByteHex(const XMLCh* const hexData) +{ + if (( hexData == 0 ) || ( *hexData == 0 )) // zero length + return true; + + XMLSize_t strLen = XMLString::stringLen(hexData); + if ( strLen%2 != 0 ) + return false; + + for ( XMLSize_t i = 0; i < strLen; i++ ) + if( !isHex(hexData[i]) ) + return false; + + return true; +} + +XMLCh* HexBin::getCanonicalRepresentation(const XMLCh* const hexData + , MemoryManager* const manager) +{ + + if (getDataLength(hexData) == -1) + return 0; + + XMLCh* retStr = XMLString::replicate(hexData, manager); + XMLString::upperCaseASCII(retStr); + + return retStr; +} + +XMLByte* HexBin::decodeToXMLByte(const XMLCh* const hexData + , MemoryManager* const manager) +{ + if (( hexData == 0 ) || ( *hexData == 0 )) // zero length + return 0; + + XMLSize_t strLen = XMLString::stringLen(hexData); + if ( strLen%2 != 0 ) + return 0; + + //prepare the return string + int decodeLength = (int)strLen/2; + XMLByte *retVal = (XMLByte*) manager->allocate( (decodeLength + 1) * sizeof(XMLByte)); + ArrayJanitor janFill(retVal, manager); + + XMLByte temp1, temp2; + for( int i = 0; i= BASELENGTH ) + return false; + + return (hexNumberTable[octet] != (XMLByte) -1); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/HexBin.hpp b/include/xercesc/util/HexBin.hpp new file mode 100644 index 0000000..5a0328b --- /dev/null +++ b/include/xercesc/util/HexBin.hpp @@ -0,0 +1,128 @@ +/* + * 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: HexBin.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_HEXBIN_HPP) +#define XERCESC_INCLUDE_GUARD_HEXBIN_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLUTIL_EXPORT HexBin +{ +public : + //@{ + + /** + * return the length of hexData in terms of HexBinary. + * + * @param hexData A string containing the HexBinary + * + * return: -1 if it contains any invalid HexBinary + * the length of the HexNumber otherwise. + */ + + static int getDataLength(const XMLCh* const hexData); + + /** + * check an array of data against the Hex table. + * + * @param hexData A string containing the HexBinary + * + * return: false if it contains any invalid HexBinary + * true otherwise. + */ + + static bool isArrayByteHex(const XMLCh* const hexData); + + /** + * get canonical representation + * + * Caller is responsible for the proper deallocation + * of the string returned. + * + * @param hexData A string containing the HexBinary + * @param manager The MemoryManager to use to allocate the string + * + * return: the canonical representation of the HexBinary + * if it is a valid HexBinary, + * 0 otherwise + */ + + static XMLCh* getCanonicalRepresentation + ( + const XMLCh* const hexData + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Decodes HexBinary data into XMLByte + * + * NOTE: The returned buffer is dynamically allocated and is the + * responsibility of the caller to delete it when not longer needed. + * Use the memory manager to release the returned buffer. + * + * @param hexData HexBinary data in XMLCh stream. + * @param manager client provided memory manager + * @return Decoded binary data in XMLByte stream, + * or NULL if input data can not be decoded. + */ + static XMLByte* decodeToXMLByte( + const XMLCh* const hexData + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + + //@} + +private : + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + + static bool isHex(const XMLCh& octet); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + HexBin(); + HexBin(const HexBin&); + HexBin& operator=(const HexBin&); + + // ----------------------------------------------------------------------- + // Private data members + // + // isInitialized + // + // set once hexNumberTable is initialized. + // + // hexNumberTable + // + // arrany holding valid hexNumber character. + // + // ----------------------------------------------------------------------- + static const XMLByte hexNumberTable[]; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/IOException.hpp b/include/xercesc/util/IOException.hpp new file mode 100644 index 0000000..bc73fb0 --- /dev/null +++ b/include/xercesc/util/IOException.hpp @@ -0,0 +1,34 @@ +/* + * 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: IOException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IOEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_IOEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(IOException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/IllegalArgumentException.hpp b/include/xercesc/util/IllegalArgumentException.hpp new file mode 100644 index 0000000..52380d8 --- /dev/null +++ b/include/xercesc/util/IllegalArgumentException.hpp @@ -0,0 +1,34 @@ +/* + * 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: IllegalArgumentException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ILLEGALARGUMENTEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_ILLEGALARGUMENTEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(IllegalArgumentException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/InvalidCastException.hpp b/include/xercesc/util/InvalidCastException.hpp new file mode 100644 index 0000000..bfb040d --- /dev/null +++ b/include/xercesc/util/InvalidCastException.hpp @@ -0,0 +1,34 @@ +/* + * 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: InvalidCastException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_INVALIDCASTEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_INVALIDCASTEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(InvalidCastException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/Janitor.c b/include/xercesc/util/Janitor.c new file mode 100644 index 0000000..2786f99 --- /dev/null +++ b/include/xercesc/util/Janitor.c @@ -0,0 +1,248 @@ +/* + * 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: Janitor.c 669844 2008-06-20 10:11:44Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Janitor: Constructors and Destructor +// --------------------------------------------------------------------------- +template Janitor::Janitor(T* const toDelete) : + fData(toDelete) +{ +} + + +template Janitor::~Janitor() +{ + reset(); +} + + +// --------------------------------------------------------------------------- +// Janitor: Public, non-virtual methods +// --------------------------------------------------------------------------- +template void +Janitor::orphan() +{ + release(); +} + + +template T& +Janitor::operator*() const +{ + return *fData; +} + + +template T* +Janitor::operator->() const +{ + return fData; +} + + +template T* +Janitor::get() const +{ + return fData; +} + + +template T* +Janitor::release() +{ + T* p = fData; + fData = 0; + return p; +} + + +template void Janitor::reset(T* p) +{ + if (fData) + delete fData; + + fData = p; +} + +template bool Janitor::isDataNull() +{ + return (fData == 0); +} + + +// ----------------------------------------------------------------------- +// ArrayJanitor: Constructors and Destructor +// ----------------------------------------------------------------------- +template ArrayJanitor::ArrayJanitor(T* const toDelete) : + fData(toDelete) + , fMemoryManager(0) +{ +} + +template +ArrayJanitor::ArrayJanitor(T* const toDelete, + MemoryManager* const manager) : + fData(toDelete) + , fMemoryManager(manager) +{ +} + + +template ArrayJanitor::~ArrayJanitor() +{ + reset(); +} + + +// ----------------------------------------------------------------------- +// ArrayJanitor: Public, non-virtual methods +// ----------------------------------------------------------------------- +template void +ArrayJanitor::orphan() +{ + release(); +} + + +// Look, Ma! No hands! Don't call this with null data! +template T& +ArrayJanitor::operator[](int index) const +{ + // TODO: Add appropriate exception + return fData[index]; +} + + +template T* +ArrayJanitor::get() const +{ + return fData; +} + + +template T* +ArrayJanitor::release() +{ + T* p = fData; + fData = 0; + return p; +} + + +template void +ArrayJanitor::reset(T* p) +{ + if (fData) { + + if (fMemoryManager) + fMemoryManager->deallocate((void*)fData); + else + delete [] fData; + } + + fData = p; + fMemoryManager = 0; +} + +template void +ArrayJanitor::reset(T* p, MemoryManager* const manager) +{ + if (fData) { + + if (fMemoryManager) + fMemoryManager->deallocate((void*)fData); + else + delete [] fData; + } + + fData = p; + fMemoryManager = manager; +} + +// +// JanitorMemFunCall +// + +template +JanitorMemFunCall::JanitorMemFunCall( + T* object, + MFPT toCall) : + fObject(object), + fToCall(toCall) +{ +} + +template +JanitorMemFunCall::~JanitorMemFunCall() +{ + reset (); +} + +template +T& JanitorMemFunCall::operator*() const +{ + return *fObject; +} + + +template +T* JanitorMemFunCall::operator->() const +{ + return fObject; +} + + +template +T* JanitorMemFunCall::get() const +{ + return fObject; +} + + +template +T* JanitorMemFunCall::release() +{ + T* p = fObject; + fObject = 0; + return p; +} + +template +void JanitorMemFunCall::reset(T* p) +{ + if (fObject != 0 && fToCall != 0) + (fObject->*fToCall)(); + + fObject = p; +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/Janitor.hpp b/include/xercesc/util/Janitor.hpp new file mode 100644 index 0000000..18596bf --- /dev/null +++ b/include/xercesc/util/Janitor.hpp @@ -0,0 +1,166 @@ +/* + * 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: Janitor.hpp 669844 2008-06-20 10:11:44Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_JANITOR_HPP) +#define XERCESC_INCLUDE_GUARD_JANITOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +template class Janitor : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + Janitor(T* const toDelete); + ~Janitor(); + + // ----------------------------------------------------------------------- + // Public, non-virtual methods + // ----------------------------------------------------------------------- + void orphan(); + + // small amount of auto_ptr compatibility + T& operator*() const; + T* operator->() const; + T* get() const; + T* release(); + void reset(T* p = 0); + bool isDataNull(); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Janitor(); + Janitor(const Janitor&); + Janitor& operator=(const Janitor&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fData + // This is the pointer to the object or structure that must be + // destroyed when this object is destroyed. + // ----------------------------------------------------------------------- + T* fData; +}; + + + +template class ArrayJanitor : public XMemory +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + ArrayJanitor(T* const toDelete); + ArrayJanitor(T* const toDelete, MemoryManager* const manager); + ~ArrayJanitor(); + + + // ----------------------------------------------------------------------- + // Public, non-virtual methods + // ----------------------------------------------------------------------- + void orphan(); + + // small amount of auto_ptr compatibility + T& operator[](int index) const; + T* get() const; + T* release(); + void reset(T* p = 0); + void reset(T* p, MemoryManager* const manager); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ArrayJanitor(); + ArrayJanitor(const ArrayJanitor& copy); + ArrayJanitor& operator=(const ArrayJanitor& copy); + + // ----------------------------------------------------------------------- + // Private data members + // + // fData + // This is the pointer to the object or structure that must be + // destroyed when this object is destroyed. + // ----------------------------------------------------------------------- + T* fData; + MemoryManager* fMemoryManager; +}; + + + +template class JanitorMemFunCall +{ +public : + + typedef void (T::*MFPT) (); + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + JanitorMemFunCall( + T* object, + MFPT toCall); + + ~JanitorMemFunCall(); + + // small amount of auto_ptr compatibility + T& operator*() const; + T* operator->() const; + T* get() const; + T* release(); + void reset(T* p = 0); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + JanitorMemFunCall(); + JanitorMemFunCall(const JanitorMemFunCall&); + JanitorMemFunCall& operator=(const JanitorMemFunCall&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fObject + // This is the pointer to the object for which we will call the + // member function when this object is destroyed. + // ----------------------------------------------------------------------- + T* fObject; + MFPT fToCall; +}; + + + + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/KVStringPair.cpp b/include/xercesc/util/KVStringPair.cpp new file mode 100644 index 0000000..6456d01 --- /dev/null +++ b/include/xercesc/util/KVStringPair.cpp @@ -0,0 +1,126 @@ +/* + * 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: KVStringPair.cpp 554580 2007-07-09 09:09:51Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// KVStringPair: Constructors and Destructor +// --------------------------------------------------------------------------- +KVStringPair::KVStringPair(MemoryManager* const manager) +:fKeyAllocSize(0) +,fValueAllocSize(0) +,fKey(0) +,fValue(0) +,fMemoryManager(manager) +{ +} + +KVStringPair::KVStringPair(const XMLCh* const key, + const XMLCh* const value, + MemoryManager* const manager) +:fKeyAllocSize(0) +,fValueAllocSize(0) +,fKey(0) +,fValue(0) +,fMemoryManager(manager) +{ + set(key, value); +} + +KVStringPair::KVStringPair(const XMLCh* const key, + const XMLCh* const value, + const XMLSize_t valueLength, + MemoryManager* const manager) +:fKeyAllocSize(0) +,fValueAllocSize(0) +,fKey(0) +,fValue(0) +,fMemoryManager(manager) +{ + setKey(key); + setValue(value, valueLength); +} + +KVStringPair::KVStringPair(const XMLCh* const key, + const XMLSize_t keyLength, + const XMLCh* const value, + const XMLSize_t valueLength, + MemoryManager* const manager) +:fKeyAllocSize(0) +,fValueAllocSize(0) +,fKey(0) +,fValue(0) +,fMemoryManager(manager) +{ + setKey(key, keyLength); + setValue(value, valueLength); +} + +KVStringPair::KVStringPair(const KVStringPair& toCopy) +:XSerializable(toCopy) +,XMemory(toCopy) +,fKeyAllocSize(0) +,fValueAllocSize(0) +,fKey(0) +,fValue(0) +,fMemoryManager(toCopy.fMemoryManager) +{ + set(toCopy.fKey, toCopy.fValue); +} + +KVStringPair::~KVStringPair() +{ + fMemoryManager->deallocate(fKey); //delete [] fKey; + fMemoryManager->deallocate(fValue); //delete [] fValue; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(KVStringPair) + +void KVStringPair::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + + serEng.writeString(fKey, fKeyAllocSize, XSerializeEngine::toWriteBufferLen); + serEng.writeString(fValue, fValueAllocSize, XSerializeEngine::toWriteBufferLen); + } + else + { + XMLSize_t dataLen = 0; + serEng.readString(fKey, fKeyAllocSize, dataLen, XSerializeEngine::toReadBufferLen); + serEng.readString(fValue, fValueAllocSize, dataLen, XSerializeEngine::toReadBufferLen); + } + +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/KVStringPair.hpp b/include/xercesc/util/KVStringPair.hpp new file mode 100644 index 0000000..685b0cb --- /dev/null +++ b/include/xercesc/util/KVStringPair.hpp @@ -0,0 +1,223 @@ +/* + * 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: KVStringPair.hpp 554580 2007-07-09 09:09:51Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_KVSTRINGPAIR_HPP) +#define XERCESC_INCLUDE_GUARD_KVSTRINGPAIR_HPP + +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This class provides a commonly used data structure, which is that of +// a pair of strings which represent a 'key=value' type mapping. It works +// only in terms of XMLCh type raw strings. +// +class XMLUTIL_EXPORT KVStringPair : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + KVStringPair(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + KVStringPair + ( + const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + KVStringPair + ( + const XMLCh* const key + , const XMLCh* const value + , const XMLSize_t valueLength + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + KVStringPair + ( + const XMLCh* const key + , const XMLSize_t keyLength + , const XMLCh* const value + , const XMLSize_t valueLength + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + KVStringPair(const KVStringPair& toCopy); + ~KVStringPair(); + + + // ----------------------------------------------------------------------- + // Getters + // + // We support the + // ----------------------------------------------------------------------- + const XMLCh* getKey() const; + XMLCh* getKey(); + const XMLCh* getValue() const; + XMLCh* getValue(); + + + // ----------------------------------------------------------------------- + // Setters + // ----------------------------------------------------------------------- + void setKey(const XMLCh* const newKey); + void setValue(const XMLCh* const newValue); + void setKey + ( + const XMLCh* const newKey + , const XMLSize_t newKeyLength + ); + void setValue + ( + const XMLCh* const newValue + , const XMLSize_t newValueLength + ); + void set + ( + const XMLCh* const newKey + , const XMLCh* const newValue + ); + void set + ( + const XMLCh* const newKey + , const XMLSize_t newKeyLength + , const XMLCh* const newValue + , const XMLSize_t newValueLength + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(KVStringPair) + +private : + // unimplemented: + + KVStringPair& operator=(const KVStringPair&); + // ----------------------------------------------------------------------- + // Private data members + // + // fKey + // The string that represents the key field of this object. + // + // fKeyAllocSize + // The amount of memory allocated for fKey. + // + // fValue + // The string that represents the value of this pair object. + // + // fValueAllocSize + // The amount of memory allocated for fValue. + // + // ----------------------------------------------------------------------- + XMLSize_t fKeyAllocSize; + XMLSize_t fValueAllocSize; + XMLCh* fKey; + XMLCh* fValue; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// KVStringPair: Getters +// --------------------------------------------------------------------------- +inline const XMLCh* KVStringPair::getKey() const +{ + return fKey; +} + +inline XMLCh* KVStringPair::getKey() +{ + return fKey; +} + +inline const XMLCh* KVStringPair::getValue() const +{ + return fValue; +} + +inline XMLCh* KVStringPair::getValue() +{ + return fValue; +} + +// --------------------------------------------------------------------------- +// KVStringPair: Setters +// --------------------------------------------------------------------------- +inline void KVStringPair::setKey(const XMLCh* const newKey) +{ + setKey(newKey, XMLString::stringLen(newKey)); +} + +inline void KVStringPair::setValue(const XMLCh* const newValue) +{ + setValue(newValue, XMLString::stringLen(newValue)); +} + +inline void KVStringPair::setKey( const XMLCh* const newKey + , const XMLSize_t newKeyLength) +{ + if (newKeyLength >= fKeyAllocSize) + { + fMemoryManager->deallocate(fKey); //delete [] fKey; + fKey = 0; + fKeyAllocSize = newKeyLength + 1; + fKey = (XMLCh*) fMemoryManager->allocate(fKeyAllocSize * sizeof(XMLCh)); //new XMLCh[fKeyAllocSize]; + } + + memcpy(fKey, newKey, (newKeyLength+1) * sizeof(XMLCh)); // len+1 because of the 0 at the end +} + +inline void KVStringPair::setValue( const XMLCh* const newValue + , const XMLSize_t newValueLength) +{ + if (newValueLength >= fValueAllocSize) + { + fMemoryManager->deallocate(fValue); //delete [] fValue; + fValue = 0; + fValueAllocSize = newValueLength + 1; + fValue = (XMLCh*) fMemoryManager->allocate(fValueAllocSize * sizeof(XMLCh)); //new XMLCh[fValueAllocSize]; + } + + memcpy(fValue, newValue, (newValueLength+1) * sizeof(XMLCh)); // len+1 because of the 0 at the end +} + +inline void KVStringPair::set( const XMLCh* const newKey + , const XMLCh* const newValue) +{ + setKey(newKey, XMLString::stringLen(newKey)); + setValue(newValue, XMLString::stringLen(newValue)); +} + +inline void KVStringPair::set( const XMLCh* const newKey + , const XMLSize_t newKeyLength + , const XMLCh* const newValue + , const XMLSize_t newValueLength) +{ + setKey(newKey, newKeyLength); + setValue(newValue, newValueLength); +} + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/KeyRefPair.c b/include/xercesc/util/KeyRefPair.c new file mode 100644 index 0000000..52f1649 --- /dev/null +++ b/include/xercesc/util/KeyRefPair.c @@ -0,0 +1,113 @@ +/* + * 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: KeyRefPair.c 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Include +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// KeyRefPair: Constructors and Destructor +// --------------------------------------------------------------------------- +template KeyRefPair::KeyRefPair() +{ +} + +template KeyRefPair:: +KeyRefPair(TKey* key, TValue* value) : + + fKey(key) + , fValue(value) +{ +} + +template KeyRefPair:: +KeyRefPair(const KeyRefPair* toCopy) : + + fKey(toCopy->fKey) + , fValue(toCopy->fValue) +{ +} + +template KeyRefPair:: +KeyRefPair(const KeyRefPair& toCopy) : + + fKey(toCopy.fKey) + , fValue(toCopy.fValue) +{ +} + + +template KeyRefPair::~KeyRefPair() +{ +} + + +// --------------------------------------------------------------------------- +// KeyRefPair: Getters +// --------------------------------------------------------------------------- +template const TKey* +KeyRefPair::getKey() const +{ + return fKey; + +} + +template TKey* KeyRefPair::getKey() +{ + return fKey; +} + +template const TValue* +KeyRefPair::getValue() const +{ + return fValue; +} + +template TValue* KeyRefPair::getValue() +{ + return fValue; +} + + +// --------------------------------------------------------------------------- +// KeyRefPair: Setters +// --------------------------------------------------------------------------- +template TKey* +KeyRefPair::setKey(TKey* newKey) +{ + fKey = newKey; + return fKey; +} + +template TValue* +KeyRefPair::setValue(TValue* newValue) +{ + fValue = newValue; + return fValue; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/KeyRefPair.hpp b/include/xercesc/util/KeyRefPair.hpp new file mode 100644 index 0000000..ee04c70 --- /dev/null +++ b/include/xercesc/util/KeyRefPair.hpp @@ -0,0 +1,81 @@ +/* + * 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: KeyRefPair.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_KEYREFPAIR_HPP) +#define XERCESC_INCLUDE_GUARD_KEYREFPAIR_HPP + + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +template class KeyRefPair : public XMemory +{ + public : + // ------------------------------------------------------------------- + // Constructors and Destructor + // ------------------------------------------------------------------- + KeyRefPair(); + KeyRefPair(TKey* key, TValue* value); + KeyRefPair(const KeyRefPair* toCopy); + KeyRefPair(const KeyRefPair& toCopy); + ~KeyRefPair(); + + + // ------------------------------------------------------------------- + // Getters + // ------------------------------------------------------------------- + const TKey* getKey() const; + TKey* getKey(); + const TValue* getValue() const; + TValue* getValue(); + + + // ------------------------------------------------------------------- + // Setters + // ------------------------------------------------------------------- + TKey* setKey(TKey* newKey); + TValue* setValue(TValue* newValue); + + + private : + // unimplemented: + KeyRefPair& operator=(const KeyRefPair&); + // ------------------------------------------------------------------- + // Private data members + // + // fKey + // The object that represents the key of the pair + // + // fValue + // The object that represents the value of the pair + // ------------------------------------------------------------------- + TKey* fKey; + TValue* fValue; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/KeyValuePair.c b/include/xercesc/util/KeyValuePair.c new file mode 100644 index 0000000..11f9334 --- /dev/null +++ b/include/xercesc/util/KeyValuePair.c @@ -0,0 +1,104 @@ +/* + * 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: KeyValuePair.c 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Include +// --------------------------------------------------------------------------- +#if defined(XERCES_TMPLSINC) +#include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// KeyValuePair: Constructors and Destructor +// --------------------------------------------------------------------------- +template KeyValuePair::KeyValuePair() +{ +} + +template KeyValuePair:: +KeyValuePair(const TKey& key, const TValue& value) : + + fKey(key) + , fValue(value) +{ +} + +template KeyValuePair:: +KeyValuePair(const KeyValuePair& toCopy) : + + fKey(toCopy.fKey) + , fValue(toCopy.fValue) +{ +} + +template KeyValuePair::~KeyValuePair() +{ +} + + +// --------------------------------------------------------------------------- +// KeyValuePair: Getters +// --------------------------------------------------------------------------- +template const TKey& +KeyValuePair::getKey() const +{ + return fKey; + +} + +template TKey& KeyValuePair::getKey() +{ + return fKey; +} + +template const TValue& +KeyValuePair::getValue() const +{ + return fValue; +} + +template TValue& KeyValuePair::getValue() +{ + return fValue; +} + + +// --------------------------------------------------------------------------- +// KeyValuePair: Setters +// --------------------------------------------------------------------------- +template TKey& +KeyValuePair::setKey(const TKey& newKey) +{ + fKey = newKey; + return fKey; +} + +template TValue& +KeyValuePair::setValue(const TValue& newValue) +{ + fValue = newValue; + return fValue; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/KeyValuePair.hpp b/include/xercesc/util/KeyValuePair.hpp new file mode 100644 index 0000000..11e7833 --- /dev/null +++ b/include/xercesc/util/KeyValuePair.hpp @@ -0,0 +1,81 @@ +/* + * 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: KeyValuePair.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_KEYVALUEPAIR_HPP) +#define XERCESC_INCLUDE_GUARD_KEYVALUEPAIR_HPP + + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +template class KeyValuePair : public XMemory +{ + public : + // ------------------------------------------------------------------- + // Constructors and Destructor + // ------------------------------------------------------------------- + KeyValuePair(); + KeyValuePair(const TKey& key, const TValue& value); + KeyValuePair(const KeyValuePair& toCopy); + ~KeyValuePair(); + + + // ------------------------------------------------------------------- + // Getters + // ------------------------------------------------------------------- + const TKey& getKey() const; + TKey& getKey(); + const TValue& getValue() const; + TValue& getValue(); + + + // ------------------------------------------------------------------- + // Setters + // ------------------------------------------------------------------- + TKey& setKey(const TKey& newKey); + TValue& setValue(const TValue& newValue); + + + private : + // unimplemented: + KeyValuePair& operator=(const KeyValuePair&); + + // ------------------------------------------------------------------- + // Private data members + // + // fKey + // The object that represents the key of the pair + // + // fValue + // The object that represents the value of the pair + // ------------------------------------------------------------------- + TKey fKey; + TValue fValue; +}; + +XERCES_CPP_NAMESPACE_END + +#if !defined(XERCES_TMPLSINC) +#include +#endif + +#endif diff --git a/include/xercesc/util/LogicalPath.c b/include/xercesc/util/LogicalPath.c new file mode 100644 index 0000000..3c7ba9d --- /dev/null +++ b/include/xercesc/util/LogicalPath.c @@ -0,0 +1,275 @@ +/* + * 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: LogicalPath.c 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_WEAVEPATH_CPP) +#define XERCESC_INCLUDE_GUARD_WEAVEPATH_CPP + +/*** + * + * Previously, each PlatformUtils.cpp has its onw copy of the + * method weavePaths(), and almost of them implemented the same logic, + * with few platform specific difference, and unfortunately that + * implementation was wrong. + * + * The only platform specific issue is slash character. + * On all platforms other than Windows, chForwardSlash and chBackSlash + * are considered slash, while on Windows, two additional characters, + * chYenSign and chWonSign are slash as well. + * + * The idea is to maintain a SINGLE copy of this method rather than + * each PlatformUtils.cpp has its own copy, we introduce a new + * method, XMLPlatformUtils::isAnySlash(), to replace the direct checking + * code ( if ( c == chForwardSlash || c == chBackSlash). + * + * With this approach, we might have a performance hit since isAnySlash() + * is so frequently used in this implementation, so we intend to make it + * inline. Then we face a complier issue. + * + * There are two compilation units involved, one is PlatformUtils.cpp and + * the other PlatformUtils.cpp. When PlatformUtils.cp get compiled, + * the weavePath(), remove**Slash() have dependency upon isAnySlash() which + * is in PlatformUtils.cpp (and what is worse, it is inlined), so we have + * undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and + * Linux/gcc, while MSVC and HP/aCC are fine with this. + * + * That means we can not place these new methods in PlatformUtils.cpp with + * inlined XMLPlatformUtils::isAnySlash() in PlatformUtils.cpp. + * + * The solution to this is PlatformUtils.cpp will include this file so that + * we have only one copy of these methods while get compiled in PlatformUtils + * inlined isAnySlash(). + * + ***/ +XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const basePath + , const XMLCh* const relativePath + , MemoryManager* const manager) + +{ + // Create a buffer as large as both parts and empty it + XMLCh* tmpBuf = (XMLCh*) manager->allocate + ( + (XMLString::stringLen(basePath) + + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh) + );//new XMLCh[XMLString::stringLen(basePath) + XMLString::stringLen(relativePath) + 2]; + *tmpBuf = 0; + + // + // If we have no base path, then just take the relative path as is. + // + if ((!basePath) || (!*basePath)) + { + XMLString::copyString(tmpBuf, relativePath); + return tmpBuf; + } + + // + // Remove anything after the last slash + // + const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1); + while ((basePtr >= basePath) && ((isAnySlash(*basePtr) == false))) + { + basePtr--; + } + + // There is no relevant base path, so just take the relative part + if (basePtr < basePath) + { + XMLString::copyString(tmpBuf, relativePath); + return tmpBuf; + } + + // + // 1. concatenate the base and relative + // 2. remove all occurrences of "/./" + // 3. remove all occurrences of segment/../ where segment is not ../ + // + + XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1), manager); + tmpBuf[basePtr - basePath + 1] = 0; + XMLString::catString(tmpBuf, relativePath); + + removeDotSlash(tmpBuf, manager); + + removeDotDotSlash(tmpBuf, manager); + + return tmpBuf; + +} + +// +// Remove all occurrences of './' when it is part of '/./' +// +// Since it could be '.\' or other combination on windows ( eg, '.'+chYanSign) +// we can't make use of patterMatch(). +// +// +void XMLPlatformUtils::removeDotSlash(XMLCh* const path + , MemoryManager* const manager) +{ + if ((!path) || (!*path)) + return; + + XMLCh* srcPtr = XMLString::replicate(path, manager); + int srcLen = XMLString::stringLen(srcPtr); + ArrayJanitor janName(srcPtr, manager); + XMLCh* tarPtr = path; + + while (*srcPtr) + { + if ( 3 <= srcLen ) + { + if ( (isAnySlash(*srcPtr)) && + (chPeriod == *(srcPtr+1)) && + (isAnySlash(*(srcPtr+2))) ) + { + // "\.\x" seen + // skip the first two, and start from the 3rd, + // since "\x" could be another "\." + srcPtr+=2; + srcLen-=2; + } + else + { + *tarPtr++ = *srcPtr++; // eat the current char + srcLen--; + } + } + else if ( 1 == srcLen ) + { + *tarPtr++ = *srcPtr++; + } + else if ( 2 == srcLen) + { + *tarPtr++ = *srcPtr++; + *tarPtr++ = *srcPtr++; + } + + } + + *tarPtr = 0; + + return; +} + +// +// Remove all occurrences of '/segment/../' when segment is not '..' +// +// Cases with extra /../ is left to the underlying file system. +// +void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path + , MemoryManager* const manager) +{ + int pathLen = XMLString::stringLen(path); + XMLCh* tmp1 = (XMLCh*) manager->allocate + ( + (pathLen+1) * sizeof(XMLCh) + );//new XMLCh [pathLen+1]; + ArrayJanitor tmp1Name(tmp1, manager); + + XMLCh* tmp2 = (XMLCh*) manager->allocate + ( + (pathLen+1) * sizeof(XMLCh) + );//new XMLCh [pathLen+1]; + ArrayJanitor tmp2Name(tmp2, manager); + + // remove all "/../" where "" is a complete + // path segment not equal to ".." + int index = -1; + int segIndex = -1; + int offset = 1; + + while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1) + { + // Undo offset + index += offset; + + // Find start of within substring ending at found point. + XMLString::subString(tmp1, path, 0, index-1, manager); + segIndex = index - 1; + while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex]))) + { + segIndex--; + } + + // Ensure exists and != ".." + if (segIndex >= 0 && + (path[segIndex+1] != chPeriod || + path[segIndex+2] != chPeriod || + segIndex + 3 != index)) + { + + XMLString::subString(tmp1, path, 0, segIndex, manager); + XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path), manager); + + path[0] = 0; + XMLString::catString(path, tmp1); + XMLString::catString(path, tmp2); + + offset = (segIndex == 0 ? 1 : segIndex); + } + else + { + offset += 4; + } + + }// while + +} + +int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath) +{ + if ((!srcPath) || (!*srcPath)) + return -1; + + XMLCh* srcPtr = srcPath; + int srcLen = XMLString::stringLen(srcPath); + int retVal = -1; + + while (*srcPtr) + { + if ( 4 <= srcLen ) + { + if ( (isAnySlash(*srcPtr)) && + (chPeriod == *(srcPtr+1)) && + (chPeriod == *(srcPtr+2)) && + (isAnySlash(*(srcPtr+3))) ) + { + retVal = (srcPtr - srcPath); + break; + } + else + { + srcPtr++; + srcLen--; + } + } + else + { + break; + } + + } // while + + return retVal; + +} + +#endif diff --git a/include/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.cpp b/include/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.cpp new file mode 100644 index 0000000..1c0a87f --- /dev/null +++ b/include/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.cpp @@ -0,0 +1,312 @@ +/* + * 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: ICUMsgLoader.cpp 883612 2009-11-24 07:24:53Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include "ICUMsgLoader.hpp" +#include "unicode/putil.h" +#include "unicode/uloc.h" +#include "unicode/udata.h" + +#include "string.h" +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local static methods +// --------------------------------------------------------------------------- + +/* + * Resource Data Reference. + * + * The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol. + * The application (this *.cpp) references that symbol here, and will pass the data address to ICU, which + * will then be able to fetch resources from the data. + */ +#define ENTRY_POINT xercesc_messages_3_1_dat +#define BUNDLE_NAME "xercesc_messages_3_1" + +extern "C" void U_IMPORT *ENTRY_POINT; + +/* + * Tell ICU where our resource data is located in memory. The data lives in the xercesc_nessages dll, and we just + * pass the address of an exported symbol from that library to ICU. + */ +static bool setAppDataOK = false; + +static void setAppData() +{ + static bool setAppDataDone = false; + + if (setAppDataDone) + { + return; + } + else + { + setAppDataDone = true; + UErrorCode err = U_ZERO_ERROR; + udata_setAppData(BUNDLE_NAME, &ENTRY_POINT, &err); + if (U_SUCCESS(err)) + { + setAppDataOK = true; + } + } + +} + +// --------------------------------------------------------------------------- +// Public Constructors and Destructor +// --------------------------------------------------------------------------- +ICUMsgLoader::ICUMsgLoader(const XMLCh* const msgDomain) +:fLocaleBundle(0) +,fDomainBundle(0) +{ + /*** + Validate msgDomain + ***/ + if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain) && + !XMLString::equals(msgDomain, XMLUni::fgExceptDomain) && + !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain) && + !XMLString::equals(msgDomain, XMLUni::fgValidityDomain) ) + { + XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain); + } + + /*** + Resolve domainName + ***/ + int index = XMLString::lastIndexOf(msgDomain, chForwardSlash); + char* domainName = XMLString::transcode(&(msgDomain[index + 1]), XMLPlatformUtils::fgMemoryManager); + ArrayJanitor jan1(domainName, XMLPlatformUtils::fgMemoryManager); + + /*** + Location resolution priority + + 1. XMLMsgLoader::getNLSHome(), set by user through + XMLPlatformUtils::Initialize(), which provides user-specified + location where the message loader shall retrieve error messages. + + 2. environment var: XERCESC_NLS_HOME + + 3. path $XERCESCROOT/msg + ***/ + + char locationBuf[1024]; + memset(locationBuf, 0, sizeof locationBuf); + const char *nlsHome = XMLMsgLoader::getNLSHome(); + + if (nlsHome) + { + strcpy(locationBuf, nlsHome); + strcat(locationBuf, U_FILE_SEP_STRING); + } + else + { + nlsHome = getenv("XERCESC_NLS_HOME"); + if (nlsHome) + { + strcpy(locationBuf, nlsHome); + strcat(locationBuf, U_FILE_SEP_STRING); + } + else + { + nlsHome = getenv("XERCESCROOT"); + if (nlsHome) + { + strcpy(locationBuf, nlsHome); + strcat(locationBuf, U_FILE_SEP_STRING); + strcat(locationBuf, "msg"); + strcat(locationBuf, U_FILE_SEP_STRING); + } + else + { + /*** + leave it to ICU to decide where to search + for the error message. + ***/ + setAppData(); + } + } + } + + /*** + Open the locale-specific resource bundle + ***/ + strcat(locationBuf, BUNDLE_NAME); + UErrorCode err = U_ZERO_ERROR; + uloc_setDefault("root", &err); // in case user-specified locale unavailable + err = U_ZERO_ERROR; + fLocaleBundle = ures_open(locationBuf, XMLMsgLoader::getLocale(), &err); + if (!U_SUCCESS(err) || fLocaleBundle == NULL) + { + /*** + in case user specified location does not work + try the dll + ***/ + + if (strcmp(locationBuf, BUNDLE_NAME) !=0 ) + { + setAppData(); + err = U_ZERO_ERROR; + fLocaleBundle = ures_open(BUNDLE_NAME, XMLMsgLoader::getLocale(), &err); + if (!U_SUCCESS(err) || fLocaleBundle == NULL) + { + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); + } + } + else + { + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); + } + } + + /*** + Open the domain specific resource bundle within + the locale-specific resource bundle + ***/ + err = U_ZERO_ERROR; + fDomainBundle = ures_getByKey(fLocaleBundle, domainName, NULL, &err); + if (!U_SUCCESS(err) || fDomainBundle == NULL) + { + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); + } +} + +ICUMsgLoader::~ICUMsgLoader() +{ + ures_close(fDomainBundle); + ures_close(fLocaleBundle); +} + + +// --------------------------------------------------------------------------- +// Implementation of the virtual message loader API +// --------------------------------------------------------------------------- +bool ICUMsgLoader::loadMsg( const XMLMsgLoader::XMLMsgId msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars) +{ + UErrorCode err = U_ZERO_ERROR; + int32_t strLen = 0; + + // Assuming array format + const UChar *name = ures_getStringByIndex(fDomainBundle, (int32_t)msgToLoad-1, &strLen, &err); + + if (!U_SUCCESS(err) || (name == NULL)) + { + return false; + } + + int retStrLen = strLen > (int32_t)maxChars ? maxChars : strLen; + + if (sizeof(UChar)==sizeof(XMLCh)) + { + XMLString::moveChars(toFill, (XMLCh*)name, retStrLen); + toFill[retStrLen] = (XMLCh) 0; + } + else + { + XMLCh* retStr = toFill; + const UChar *srcPtr = name; + + while (retStrLen--) + *retStr++ = *srcPtr++; + + *retStr = 0; + } + + return true; +} + + +bool ICUMsgLoader::loadMsg( const XMLMsgLoader::XMLMsgId msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars + , const XMLCh* const repText1 + , const XMLCh* const repText2 + , const XMLCh* const repText3 + , const XMLCh* const repText4 + , MemoryManager* const manager ) +{ + // Call the other version to load up the message + if (!loadMsg(msgToLoad, toFill, maxChars)) + return false; + + // And do the token replacement + XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager); + return true; +} + + +bool ICUMsgLoader::loadMsg( const XMLMsgLoader::XMLMsgId msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars + , const char* const repText1 + , const char* const repText2 + , const char* const repText3 + , const char* const repText4 + , MemoryManager * const manager) +{ + // + // Transcode the provided parameters and call the other version, + // which will do the replacement work. + // + XMLCh* tmp1 = 0; + XMLCh* tmp2 = 0; + XMLCh* tmp3 = 0; + XMLCh* tmp4 = 0; + + bool bRet = false; + if (repText1) + tmp1 = XMLString::transcode(repText1, manager); + if (repText2) + tmp2 = XMLString::transcode(repText2, manager); + if (repText3) + tmp3 = XMLString::transcode(repText3, manager); + if (repText4) + tmp4 = XMLString::transcode(repText4, manager); + + bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager); + + if (tmp1) + manager->deallocate(tmp1);//delete [] tmp1; + if (tmp2) + manager->deallocate(tmp2);//delete [] tmp2; + if (tmp3) + manager->deallocate(tmp3);//delete [] tmp3; + if (tmp4) + manager->deallocate(tmp4);//delete [] tmp4; + + return bRet; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp b/include/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp new file mode 100644 index 0000000..75ead94 --- /dev/null +++ b/include/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp @@ -0,0 +1,107 @@ +/* + * 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: ICUMsgLoader.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ICUMSGLOADER_HPP) +#define XERCESC_INCLUDE_GUARD_ICUMSGLOADER_HPP + +#include +#include "unicode/ures.h" + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This is the ICU specific implementation of the XMLMsgLoader interface. +// This one uses ICU resource bundles to store its messages. +// +class XMLUTIL_EXPORT ICUMsgLoader : public XMLMsgLoader +{ +public : + // ----------------------------------------------------------------------- + // Public Constructors and Destructor + // ----------------------------------------------------------------------- + ICUMsgLoader(const XMLCh* const msgDomain); + ~ICUMsgLoader(); + + + // ----------------------------------------------------------------------- + // Implementation of the virtual message loader API + // ----------------------------------------------------------------------- + virtual bool loadMsg + ( + const XMLMsgLoader::XMLMsgId msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars + ); + + virtual bool loadMsg + ( + const XMLMsgLoader::XMLMsgId msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars + , const XMLCh* const repText1 + , const XMLCh* const repText2 = 0 + , const XMLCh* const repText3 = 0 + , const XMLCh* const repText4 = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual bool loadMsg + ( + const XMLMsgLoader::XMLMsgId msgToLoad + , XMLCh* const toFill + , const XMLSize_t maxChars + , const char* const repText1 + , const char* const repText2 = 0 + , const char* const repText3 = 0 + , const char* const repText4 = 0 + , MemoryManager * const manager = XMLPlatformUtils::fgMemoryManager + ); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ICUMsgLoader(); + ICUMsgLoader(const ICUMsgLoader&); + ICUMsgLoader& operator=(const ICUMsgLoader&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fLocaleBundle + // pointer to the required locale specific resource bundle, + // or to the default locale resource bundle in case the required + // locale specific resource bundle unavailable. + // + // fDomainBundle + // pointer to the domain specific resource bundle with in the + // required locale specific (or default locale) resource bundle. + // + // ----------------------------------------------------------------------- + UResourceBundle* fLocaleBundle; + UResourceBundle* fDomainBundle; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/util/MsgLoaders/ICU/resources/res-file-list.txt b/include/xercesc/util/MsgLoaders/ICU/resources/res-file-list.txt new file mode 100644 index 0000000..4199293 --- /dev/null +++ b/include/xercesc/util/MsgLoaders/ICU/resources/res-file-list.txt @@ -0,0 +1 @@ +root.res diff --git a/include/xercesc/util/MsgLoaders/ICU/resources/root.txt b/include/xercesc/util/MsgLoaders/ICU/resources/root.txt new file mode 100644 index 0000000..aebf012 --- /dev/null +++ b/include/xercesc/util/MsgLoaders/ICU/resources/root.txt @@ -0,0 +1,791 @@ +root { + + // an array + XMLErrors { + "W_ Start " , + "notation '{0}' has already been declared" , + "attribute '{0}' has already been declared for element '{1}'" , + "encoding '{0}' from XML declaration or manually set contradicts the auto-sensed encoding; ignoring" , + "element '{0}' is referenced in a content model but was never declared" , + "element '{0}' is referenced in an ATTLIST but was never declared" , + "{0}" , + "unable to include document '{0}'" , + "unable to open text file target '{0}'" , + "unable to include resource '{0}'" , + "W_ End " , + "E_ Start " , + "'{0}' is not allowed for the content of simpleType; only list, union, and restriction are allowed" , + "globally-defined complex type must have a name" , + "globally-declared attribute must have a name" , + "attribute declaration must have name or 'ref' attribute" , + "element declaration must have name or 'ref' attribute" , + "group declaration must have name or a 'ref' attribute" , + "attributeGroup declaration must have name or 'ref' attribute" , + "anonymous complexType in element '{0}' has name" , + "anonymous simpleType in element '{0}' has name" , + "content of element declaration must match (annotation?, (simpleType | complexType)?, (unique | key | keyref)*)" , + "invalid content in simple type '{0}'; only list, union, and restriction are allowed" , + "expected simpleType in list definition for type '{0}'" , + "list, union, or restriction content is invalid for type '{0}'" , + "invalid content in list definition for type '{0}'" , + "expected simpleType in restriction definition for type '{0}'" , + "facet '{0}' is already defined" , + "expected simpleType in union definition for type '{0}'" , + "content in simpleType definition is empty" , + "expected restriction or extension in simpleContent definition" , + "base attribute must be specified for restriction or extension definition" , + "expected restriction or extension in complexContent definition" , + "invalid content in 'schema' element" , + "invalid content for type '{0}'" , + "unknown simpleType '{0}'" , + "unknown complexType '{0}'" , + "prefix '{0}' can not be resolved to namespace URI" , + "referenced element '{0}' not found" , + "type '{0}:{1}' not found" , + "attribute '{0}' not found" , + "invalid element '{0}' in complex type definition" , + "base type '{0}' not found" , + "unable to create validator for '{0}'" , + "invalid element following simpleContent definition in complexType" , + "invalid element following complexContent definition in complexType" , + "attribute '{0}' cannot have both fixed and default values" , + "attribute '{0}' with default value must be optional" , + "attribute '{0}' declared more than once in the same scope" , + "attribute '{0}' cannot have both 'type' attribute and simpleType definition" , + "simpleType '{0}:{1}' for attribute '{2}' not found" , + "element '{0}' cannot have both fixed and default values" , + "invalid {0} name '{1}'" , + "element '{0}' cannot have both 'type' attribute and simpleType/complexType definition" , + "element '{0}' has fixed or default value and must have mixed simple or simple content model" , + "simpleType '{0}' that '{1}' extends has a value of the final attribute that does not permit extension" , + "type '{0}' specified as the base in simpleContent definition must not have complex content" , + "type '{0}' is a simple type and cannot be used in derivation by restriction in complexType definition" , + "invalid element following restriction or extension definition in simpleContent" , + "invalid element following restriction or extension definition in complexContent" , + "duplicate annotation in type '{0}'" , + "type '{0}' cannot be used in its own union, list, or restriction definition" , + "block value '{0}' is invalid" , + "final value '{0}' is invalid" , + "element '{0}' cannot be part of the substitution group headed by '{1}'" , + "element '{0}' has a type which does not derive from the type of the element at the head of the substitution group" , + "element '{0}' declared more than once in the same scope" , + "value '{0}' invalid for attribute '{1}'" , + "attribute '{0}' has both 'ref' attribute and inline simpleType definition or 'form' or 'type' attribute" , + "duplicate reference attribute '{0}:{1}' in complexType definition" , + "derivation by restriction is forbidden by either base type '{0}' or globally" , + "derivation by extension is forbidden by either base type '{0}' or globally" , + "base type specified in complexContent definition must be a complex type" , + "imported schema '{0}' has different target namespace '{1}'; expected '{2}'" , + "'schemaLocation' attribute must be specified in element '{0}'" , + "included schema '{0}' has different target namespace '{1}'" , + "at most one annotation is allowed" , + "content of attribute '{0}' must match (annotation?, simpleType?)" , + "attribute '{0}' must appear in global {1} declarations" , + "attribute '{0}' must appear in local {1} declarations" , + "attribute '{0}' cannot appear in global {1} declarations" , + "attribute '{0}' cannot appear in local {1} declarations" , + "minOccurs value '{0}' must not be greater than maxOccurs value '{1}'" , + "duplicate annotation in anyAttribute declaration" , + "global {0} declaration must have name" , + "circular definition in '{0}'" , + "global type '{0}:{1}' declared more than once or also declared as {2}" , + "global {0} '{1}' declared more than once" , + "invalid value '{0}' for whiteSpace facet; expected 'collapse'" , + "namespace of import declaration must be different from target namespace of importing schema" , + "importing schema must have target namespace if namespace in import declaration is not present" , + "element '{0}' cannot have value constraint '{1}' if its type is derived from ID" , + "element/attribute '{0}' is of NOTATION type" , + "element '{0}' has mixed content type and the content type's particle must be emptiable" , + "complexType definition has empty content but base type is not empty or does not have emptiable particle" , + "content types of base type '{0}' and derived type '{1}' must both be mixed or element-only" , + "derived content type is not a valid restriction of base content type" , + "derivation by extension or restriction is forbidden by either base type '{0}' or globally" , + "item type definition must have variety of atomic or union where all member types must be atomic" , + "group '{0}' must contain all, choice, or sequence compositor" , + "content of attributeGroup '{0}' must match (annotation?, ((attribute | attributeGroup)*, anyAttribute?))" , + "top-level compositor in a group must not have 'minOccurs' or 'maxOccurs' attribute" , + "{0} '{1}:{2}' not found" , + "group with the all compositor must only appear as content type of a complex type" , + "group with the all compositor constituting the content type of a complex type must have both minOccurs and maxOccurs equal 1" , + "element declaration in the all compositor must have minOccurs and maxOccurs equal 0 or 1" , + "attribute '{0}' is already defined in base" , + "intensional intersection of attribute wildcards must be expressible" , + "base type does not have any attributes" , + "attribute '{0}' has incompatible use value in the base" , + "type of attribute '{0}' must be derived by restriction from type of the corresponding attribute in the base" , + "attribute '{0}' does not have a fixed value or has a different fixed value from that of the base" , + "attribute '{0}' has invalid target namespace with respect to the base wildcard constraint or base has no wildcard" , + "attribute wildcard is present in the derived type but not in the base" , + "attribute wildcard in the derived type is not a valid subset of that in the base" , + "attribute '{0}' cannot have different use value in the derived type if the base attribute use value is 'prohibited'" , + "attribute wildcard in the derived type must be identical to or stricter than the one in the base" , + "unexpected '{0}' in the content of the all compositor; only elements are allowed" , + "redefined schema '{0}' has a different target namespace '{1}'" , + "simpleType in redefine must have a restriction definition" , + "simpleType base attribute in redefine must reference the original type with the same name" , + "complexType in redefine must have a restriction or extension definition" , + "complexType base attribute in redefine must reference the original type with the same name" , + "group '{0}' must have minOccurs and maxOccurs equal 1" , + "unable to find declaration in the schema being redefined corresponding to '{0}'" , + "group declaration in redefine may only contain one reference to itself" , + "attributeGroup declaration in redefine may only contain one reference to itself" , + "redefine declaration cannot contain '{0}'" , + "notation declaration '{0}:{1}' not found" , + "more than one identity constraint has name '{0}'" , + "identity constraint declaration must match (annotation?, selector, field+)" , + "key reference declaration '{0}' refers to unknown key '{1}'" , + "field cardinalities for keyref '{0}' and key '{1}' must match" , + "XPath expression is missing or empty" , + "fixed value in attribute reference is not set or differs from the fixed value of '{0}'" , + "attribute '{0}' is of ID type or type derived from ID and cannot have default/fixed value constraint" , + "attribute '{0}' is a subsequent attribute in this complex type with a type derived from ID" , + "attribute '{0}' is a subsequent attribute in this attribute group with a type derived from ID" , + "empty value illegal for 'targetNamespace' attribute; target namespace must be absent or contain non-empty value" , + "{0}" , + "'{0}' has already been included or redefined" , + "namespace '{0}' is referenced without import declaration" , + "all compositor that is part of a complex type definition must constitute the entire content of the definition" , + "annotation can only contain appinfo and documentation declarations" , + "invalid facet name '{0}'" , + "root element name of XML Schema document must be 'schema'" , + "circular substitution group in element '{0}'" , + "element '{0}' must be from the XML Schema namespace" , + "target namespace of attribute '{0}' cannot be http://www.w3.org/2001/XMLSchema-instance" , + "invalid namespace declaration" , + "namespace fix-up cannot be performed on DOM Level 1 node" , + "more than one anyAttribute declaration found in complex type declaration" , + "anyAttribute must not be followed by other declarations" , + "E_ End " , + "F_ Start " , + "parser has encountered more than '{0}' entity expansions in the document; this is the limit imposed by the application" , + "expected comment or CDATA section" , + "attribute name expected" , + "notation name expected" , + "illegal repetition of elements in mixed content model" , + "default attribute declaration expected" , + "equal sign expected" , + "element name expected" , + "comment must start with ' It will calls the appropriate handler with the comment +// text, if one is provided. A comment can be in either the document or +// the DTD, so the fInDocument flag is used to know which handler to send +// it to. +// +void DTDScanner::scanComment() +{ + enum States + { + InText + , OneDash + , TwoDashes + }; + + // Get a buffer for this + XMLBufBid bbComment(fBufMgr); + + // + // Get the comment text into a temp buffer. Be sure to use temp buffer + // two here, since its to be used for stuff that is potentially longer + // than just a name. + // + bool gotLeadingSurrogate = false; + States curState = InText; + while (true) + { + // Get the next character + const XMLCh nextCh = fReaderMgr->getNextChar(); + + // Watch for an end of file + if (!nextCh) + { + fScanner->emitError(XMLErrs::UnterminatedComment); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + // Check for correct surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + if (gotLeadingSurrogate) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + if (gotLeadingSurrogate) + { + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + } + // Its got to at least be a valid XML character + else if (!fReaderMgr->getCurrentReader()->isXMLChar(nextCh)) { + + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + + gotLeadingSurrogate = false; + } + + if (curState == InText) + { + // If its a dash, go to OneDash state. Otherwise take as text + if (nextCh == chDash) + curState = OneDash; + else + bbComment.append(nextCh); + } + else if (curState == OneDash) + { + // + // If its another dash, then we change to the two dashes states. + // Otherwise, we have to put in the deficit dash and the new + // character and go back to InText. + // + if (nextCh == chDash) + { + curState = TwoDashes; + } + else + { + bbComment.append(chDash); + bbComment.append(nextCh); + curState = InText; + } + } + else if (curState == TwoDashes) + { + // The next character must be the closing bracket + if (nextCh != chCloseAngle) + { + fScanner->emitError(XMLErrs::IllegalSequenceInComment); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + break; + } + } + + // If there is a doc type handler, then pass on the comment stuff + if (fDocTypeHandler) + fDocTypeHandler->doctypeComment(bbComment.getRawBuffer()); +} + + +bool DTDScanner::scanContentSpec(DTDElementDecl& toFill) +{ + // + // Check for for a couple of the predefined content type strings. If + // its not one of these, its got to be a parenthesized reg ex type + // expression. + // + if (fReaderMgr->skippedString(XMLUni::fgEmptyString)) + { + toFill.setModelType(DTDElementDecl::Empty); + return true; + } + + if (fReaderMgr->skippedString(XMLUni::fgAnyString)) + { + toFill.setModelType(DTDElementDecl::Any); + return true; + } + + // Its got to be a parenthesized regular expression + if (!fReaderMgr->skippedChar(chOpenParen)) + { + fScanner->emitError + ( + XMLErrs::ExpectedContentSpecExpr + , toFill.getFullName() + ); + return false; + } + + // Get the current reader id, so we can test for partial markup + const XMLSize_t curReader = fReaderMgr->getCurrentReaderNum(); + + // We could have a PE ref here, but don't require space + checkForPERef(false, true); + + // + // Now we look for a PCDATA string. If its PCDATA, then it must be a + // MIXED model. Otherwise, it must be a regular list of children in + // a regular expression perhaps. + // + bool status; + if (fReaderMgr->skippedString(XMLUni::fgPCDATAString)) + { + // Set the model to mixed + toFill.setModelType(DTDElementDecl::Mixed_Simple); + status = scanMixed(toFill); + + // + // If we are validating we have to check that there are no multiple + // uses of any child elements. + // + if (fScanner->getValidationScheme() == XMLScanner::Val_Always) + { + if (((const MixedContentModel*)toFill.getContentModel())->hasDups()) + fScanner->getValidator()->emitError(XMLValid::RepElemInMixed); + } + } + else + { + // + // We have to do a recursive scan of the content model. Create a + // buffer for it to use, for efficiency. It returns the top ofthe + // content spec node tree, which we set if successful. + // + toFill.setModelType(DTDElementDecl::Children); + XMLBufBid bbTmp(fBufMgr); + ContentSpecNode* resNode = scanChildren(toFill, bbTmp.getBuffer()); + status = (resNode != 0); + if (status) + toFill.setContentSpec(resNode); + } + + // Make sure we are on the same reader as where we started + if (curReader != fReaderMgr->getCurrentReaderNum() && fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::PartialMarkupInPE); + + return status; +} + + +void DTDScanner::scanDefaultDecl(DTDAttDef& toFill) +{ + if (fReaderMgr->skippedString(XMLUni::fgRequiredString)) + { + toFill.setDefaultType(XMLAttDef::Required); + return; + } + + if (fReaderMgr->skippedString(XMLUni::fgImpliedString)) + { + toFill.setDefaultType(XMLAttDef::Implied); + return; + } + + if (fReaderMgr->skippedString(XMLUni::fgFixedString)) + { + // + // There must be space before the fixed value. If there is not, then + // emit an error but keep going. + // + if (!fReaderMgr->skippedSpace()) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + else + fReaderMgr->skipPastSpaces(); + toFill.setDefaultType(XMLAttDef::Fixed); + } + else + { + toFill.setDefaultType(XMLAttDef::Default); + } + + // + // If we got here, its fixed or default, so we need to get a value. + // If we don't, then emit an error but just set the default value to + // an empty string and try to keep going. + // + // Check for PE ref or optional whitespace + checkForPERef(false, true); + + XMLBufBid bbValue(fBufMgr); + if (!scanAttValue(toFill.getFullName(), bbValue.getBuffer(), toFill.getType())) + fScanner->emitError(XMLErrs::ExpectedDefAttrDecl); + + toFill.setValue(bbValue.getRawBuffer()); +} + + +// +// This is called after seeing 'emitError(XMLErrs::ExpectedWhitespace); + + // Get a buffer for the element name and scan in the name + XMLBufBid bbName(fBufMgr); + if (!fReaderMgr->getName(bbName.getBuffer())) + { + fScanner->emitError(XMLErrs::ExpectedElementName); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // Look this guy up in the element decl pool + DTDElementDecl* decl = (DTDElementDecl*) fDTDGrammar->getElemDecl(fEmptyNamespaceId, 0, bbName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE); + + // + // If it does not exist, then we need to create it. If it does and + // its marked as declared, then that's an error, but we still need to + // scan over the content model so use the dummy declaration that the + // parsing code can fill in. + // + if (decl) + { + if (decl->isDeclared()) + { + if (fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::ElementAlreadyExists, bbName.getRawBuffer()); + + if (!fDumElemDecl) + fDumElemDecl = new (fMemoryManager) DTDElementDecl + ( + bbName.getRawBuffer() + , fEmptyNamespaceId + , DTDElementDecl::Any + , fMemoryManager + ); + else + fDumElemDecl->setElementName(bbName.getRawBuffer(),fEmptyNamespaceId); + } + } + else + { + // + // Create the new empty declaration to fill in and put it into + // the decl pool. + // + decl = new (fGrammarPoolMemoryManager) DTDElementDecl + ( + bbName.getRawBuffer() + , fEmptyNamespaceId + , DTDElementDecl::Any + , fGrammarPoolMemoryManager + ); + fDTDGrammar->putElemDecl(decl); + } + + // Set a flag for whether we will ignore this one + const bool isIgnored = (decl == fDumElemDecl); + + // Mark this one if being externally declared + decl->setExternalElemDeclaration(isReadingExternalEntity()); + + // Mark this one as being declared + decl->setCreateReason(XMLElementDecl::Declared); + + // Another check for a PE ref, with at least required whitespace + if (!checkForPERef(false, true)) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + + // And now scan the content model for this guy. + if (!scanContentSpec(*decl)) + { + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // Another check for a PE ref, but we don't require whitespace here + checkForPERef(false, true); + + // And we should have the ending angle bracket + if (!fReaderMgr->skippedChar(chCloseAngle)) + { + fScanner->emitError(XMLErrs::UnterminatedElementDecl, bbName.getRawBuffer()); + fReaderMgr->skipPastChar(chCloseAngle); + } + + // + // If we have a DTD handler tell it about the new element decl. We + // tell it if its one that can be ignored, cause its an override of a + // previously existing decl. If it is being ignored, only call back + // if advanced callbacks are enabled. + // + if (fDocTypeHandler) + fDocTypeHandler->elementDecl(*decl, isIgnored); +} + + +// +// This method will process a general or parameter entity reference. The +// entity name and entity text will be stored in the entity pool. The value +// of the entity will be scanned for any other parameter entity or char +// references which will be expanded. So the stored value can only have +// general entity references when done. +// +void DTDScanner::scanEntityDecl() +{ + // + // Space is required here, but we cannot check for a PE Ref since + // there could be a legal (no-ref) percent sign here. Since any + // entity that ended here would be illegal, we just skip spaces + // and then check for a percent. + // + if (!fReaderMgr->lookingAtSpace()) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + else + fReaderMgr->skipPastSpaces(); + bool isPEDecl = fReaderMgr->skippedChar(chPercent); + + // + // If a PE decl, then check if it is followed by a space; if it is so, + // eat the percent and check for spaces or a PE ref on the other side of it. + // Otherwise, it has to be an entity reference for a general entity. + // + if (isPEDecl) + { + if(!fReaderMgr->getCurrentReader()->isWhitespace(fReaderMgr->peekNextChar())) + { + isPEDecl=false; + while (true) + { + if (!expandPERef(false, false, true, false)) + fScanner->emitError(XMLErrs::ExpectedEntityRefName); + // And skip any more spaces in the expanded value + if (fReaderMgr->skippedSpace()) + fReaderMgr->skipPastSpaces(); + if (!fReaderMgr->skippedChar(chPercent)) + break; + } + } + else if (!checkForPERef(false, true)) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + } + + // + // Now lets get a name, which should be the name of the entity. We + // have to get a buffer for this. + // + XMLBufBid bbName(fBufMgr); + if (!fReaderMgr->getName(bbName.getBuffer())) + { + fScanner->emitError(XMLErrs::ExpectedPEName); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // If namespaces are enabled, then no colons allowed + if (fScanner->getDoNamespaces()) + { + if (XMLString::indexOf(bbName.getRawBuffer(), chColon) != -1) + fScanner->emitError(XMLErrs::ColonNotLegalWithNS); + } + + // + // See if this entity already exists. If so, then the existing one + // takes precendence. So we use the local dummy decl to parse into + // and just ignore the results. + // + DTDEntityDecl* entityDecl; + if (isPEDecl) + entityDecl = fPEntityDeclPool->getByKey(bbName.getRawBuffer()); + else + entityDecl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer()); + + if (entityDecl) + { + if (!fDumEntityDecl) + fDumEntityDecl = new (fMemoryManager) DTDEntityDecl(fMemoryManager); + fDumEntityDecl->setName(bbName.getRawBuffer()); + entityDecl = fDumEntityDecl; + } + else + { + // Its not in existence already, then create an entity decl for it + entityDecl = new (fGrammarPoolMemoryManager) DTDEntityDecl(bbName.getRawBuffer(), false, fGrammarPoolMemoryManager); + + // + // Set the declaration location. The parameter indicates whether its + // declared in the content/internal subset, so we know whether or not + // its in the external subset. + // + entityDecl->setDeclaredInIntSubset(fInternalSubset); + + // Add it to the appropriate entity decl pool + if (isPEDecl) + fPEntityDeclPool->put(entityDecl); + else + fDTDGrammar->putEntityDecl(entityDecl); + } + + // Set a flag that indicates whether we are ignoring this one + const bool isIgnored = (entityDecl == fDumEntityDecl); + + // Set the PE flag on it + entityDecl->setIsParameter(isPEDecl); + + // + // Space is legal (required actually) here so check for a PE ref. If + // we don't get our whitespace, then issue an error, but try to keep + // going. + // + if (!checkForPERef(false, true)) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + + // save the hasNoDTD status for Entity Constraint Checking + bool hasNoDTD = fScanner->getHasNoDTD(); + if (hasNoDTD && isPEDecl) + fScanner->setHasNoDTD(false); + + // According to the type call the value scanning method + if (!scanEntityDef(*entityDecl, isPEDecl)) + { + fReaderMgr->skipPastChar(chCloseAngle); + fScanner->setHasNoDTD(true); + fScanner->emitError(XMLErrs::ExpectedEntityValue); + return; + } + if (hasNoDTD) + fScanner->setHasNoDTD(true); + + // Space is legal (but not required) here so check for a PE ref + checkForPERef(false, true); + + // And then we have to have the closing angle bracket + if (!fReaderMgr->skippedChar(chCloseAngle)) + { + fScanner->emitError(XMLErrs::UnterminatedEntityDecl, entityDecl->getName()); + fReaderMgr->skipPastChar(chCloseAngle); + } + + // + // If we have a doc type handler, then call it. But only call it for + // ignored elements if advanced callbacks are enabled. + // + if (fDocTypeHandler) + fDocTypeHandler->entityDecl(*entityDecl, isPEDecl, isIgnored); +} + + +// +// This method will scan a general/character entity ref. It will either +// expand a char ref and return the value directly, or it will expand +// a general entity and a reader for it onto the reader stack. +// +// The return value indicates whether the value was returned directly or +// pushed as a reader or it failed. +// +// The escaped flag tells the caller whether the returnd parameter resulted +// from a character reference, which escapes the character in some cases. It +// only makes any difference if the return indicates the value was returned +// directly. +// +// NOTE: This is only called when scanning attribute values, so we always +// expand general entities. +// +DTDScanner::EntityExpRes +DTDScanner::scanEntityRef(XMLCh& firstCh, XMLCh& secondCh, bool& escaped) +{ + // Assume no escape and no second char + escaped = false; + secondCh = 0; + + // We have to insure its all done in a single entity + const XMLSize_t curReader = fReaderMgr->getCurrentReaderNum(); + + // + // If the next char is a pound, then its a character reference and we + // need to expand it always. + // + if (fReaderMgr->skippedChar(chPound)) + { + // + // Its a character reference, so scan it and get back the numeric + // value it represents. If it fails, just return immediately. + // + if (!scanCharRef(firstCh, secondCh)) + return EntityExp_Failed; + + if (curReader != fReaderMgr->getCurrentReaderNum()) + fScanner->emitError(XMLErrs::PartialMarkupInEntity); + + // Its now escaped since it was a char ref + escaped = true; + return EntityExp_Returned; + } + + // Get the name of the general entity + XMLBufBid bbName(fBufMgr); + if (!fReaderMgr->getName(bbName.getBuffer())) + { + fScanner->emitError(XMLErrs::ExpectedEntityRefName); + return EntityExp_Failed; + } + + // + // Next char must be a semi-colon. But if its not, just emit + // an error and try to continue. + // + if (!fReaderMgr->skippedChar(chSemiColon)) + fScanner->emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer()); + + // Make sure it was all in one entity reader + if (curReader != fReaderMgr->getCurrentReaderNum()) + fScanner->emitError(XMLErrs::PartialMarkupInEntity); + + // Look it up the name the general entity pool + XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer()); + + // If it does not exist, then obviously an error + if (!decl) + { + // XML 1.0 Section 4.1 + if (fScanner->getStandalone() || fScanner->getHasNoDTD()) { + fScanner->emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer()); + } + else { + if (fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer()); + } + + return EntityExp_Failed; + } + + + // + // XML 1.0 Section 4.1 + // If we are a standalone document, then it has to have been declared + // in the internal subset. + // + if (fScanner->getStandalone() && !decl->getDeclaredInIntSubset()) + fScanner->emitError(XMLErrs::IllegalRefInStandalone, bbName.getRawBuffer()); + + // + // If its a special char reference, then its escaped and we can return + // it directly. + // + if (decl->getIsSpecialChar()) + { + firstCh = decl->getValue()[0]; + escaped = true; + return EntityExp_Returned; + } + + if (decl->isExternal()) + { + // If its unparsed, then its not valid here + // XML 1.0 Section 4.4.4 the appearance of a reference to an unparsed entity is forbidden. + if (decl->isUnparsed()) + { + fScanner->emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer()); + return EntityExp_Failed; + } + + // We are in an attribute value, so not valid. + // XML 1.0 Section 4.4.4 a reference to an external entity in an attribute value is forbidden. + fScanner->emitError(XMLErrs::NoExtRefsInAttValue); + + // And now create a reader to read this entity + InputSource* srcUsed; + XMLReader* reader = fReaderMgr->createReader + ( + decl->getBaseURI() + , decl->getSystemId() + , decl->getPublicId() + , false + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , XMLReader::Source_External + , srcUsed + , fScanner->getCalculateSrcOfs() + , fScanner->getLowWaterMark() + , fScanner->getDisableDefaultEntityResolution() + ); + + // Put a janitor on the source so it gets cleaned up on exit + Janitor janSrc(srcUsed); + + // + // If the creation failed then throw an exception + // + if (!reader) + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager); + + // + // Push the reader. If its a recursive expansion, then emit an error + // and return an failure. + // + if (!fReaderMgr->pushReader(reader, decl)) + { + fScanner->emitError(XMLErrs::RecursiveEntity, decl->getName()); + return EntityExp_Failed; + } + + // If it starts with the XML string, then parse a text decl + if (fScanner->checkXMLDecl(true)) + scanTextDecl(); + } + else + { + // + // Create a reader over a memory stream over the entity value + // We force it to assume UTF-16 by passing in an encoding + // string. This way it won't both trying to predecode the + // first line, looking for an XML/TextDecl. + // + XMLReader* valueReader = fReaderMgr->createIntEntReader + ( + decl->getName() + , XMLReader::RefFrom_NonLiteral + , XMLReader::Type_General + , decl->getValue() + , decl->getValueLen() + , false + ); + + // + // Trt to push the entity reader onto the reader manager stack, + // where it will become the subsequent input. If it fails, that + // means the entity is recursive, so issue an error. The reader + // will have just been discarded, but we just keep going. + // + if (!fReaderMgr->pushReader(valueReader, decl)) + fScanner->emitError(XMLErrs::RecursiveEntity, decl->getName()); + } + + return EntityExp_Pushed; +} + + +// +// This method will scan a quoted literal of an entity value. It has to +// deal with replacement of PE references; however, since this is a DTD +// scanner, all such entity literals are in entity decls and therefore +// general entities are not expanded. +// +bool DTDScanner::scanEntityLiteral(XMLBuffer& toFill) +{ + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr->skipIfQuote(quoteCh)) + return false; + + // Get a buffer for pulling in entity names when we see GE refs + XMLBufBid bbName(fBufMgr); + XMLBuffer& nameBuf = bbName.getBuffer(); + + // Remember the current reader + const XMLSize_t orgReader = fReaderMgr->getCurrentReaderNum(); + + // + // Loop until we see the ending quote character, handling any references + // in the process. + // + XMLCh nextCh; + XMLCh secondCh = 0; + bool gotLeadingSurrogate = false; + while (true) + { + nextCh = fReaderMgr->getNextChar(); + + // + // Watch specifically for EOF and issue a more meaningful error + // if that occurs (since an unterminated quoted char can cause + // this easily.) + // + if (!nextCh) + { + fScanner->emitError(XMLErrs::UnterminatedEntityLiteral); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + // + // Break out on our terminating quote char when we are back in the + // same reader. Otherwise, we might trigger on a nested quote char + // in an expanded entity. + // + if ((nextCh == quoteCh) + && (fReaderMgr->getCurrentReaderNum() == orgReader)) + { + break; + } + + if (nextCh == chPercent) + { + // + // Put the PE's value on the reader stack and then jump back + // to the top to start processing it. The parameter indicates + // that it should not scan the reference's content as an external + // subset. + // + expandPERef(false, true, true); + continue; + } + + // + // Ok, now that all the other special stuff is checked, we can + // look for a general entity. In here, we cannot have a naked & + // and will only expand numerical char refs or the intrinsic char + // refs. Others will be left alone. + // + if (nextCh == chAmpersand) + { + // + // Here, we only expand numeric char refs, but not any general + // entities. However, the stupid XML spec requires that we check + // and make sure it does refer to a general entity if its not + // a char ref (i.e. no naked '&' chars.) + // + if (fReaderMgr->skippedChar(chPound)) + { + // If it failed, then just jump back to the top and try to pick up + if (!scanCharRef(nextCh, secondCh)) + { + gotLeadingSurrogate = false; + continue; + } + } + else + { + if (!fReaderMgr->getName(nameBuf)) + { + fScanner->emitError(XMLErrs::ExpectedEntityRefName); + } + else + { + // + // Since we are not expanding any of this, we have to + // put the amp and name into the target buffer as data. + // + toFill.append(chAmpersand); + toFill.append(nameBuf.getRawBuffer()); + + // Make sure we skipped a trailing semicolon + if (!fReaderMgr->skippedChar(chSemiColon)) + { + fScanner->emitError + ( + XMLErrs::UnterminatedEntityRef + , nameBuf.getRawBuffer() + ); + } + + // And make the new character the semicolon + nextCh = chSemiColon; + } + + // Either way here we reset the surrogate flag + gotLeadingSurrogate = false; + } + } + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + if (gotLeadingSurrogate) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + if (gotLeadingSurrogate) + { + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + } + else if (!fReaderMgr->getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError(XMLErrs::InvalidCharacter, tmpBuf); + fReaderMgr->skipPastChar(quoteCh); + return false; + } + gotLeadingSurrogate = false; + } + + // Looks ok, so add it to the literal + toFill.append(nextCh); + + if (secondCh) + { + toFill.append(secondCh); + secondCh=0; + } + } + + // + // If we got here and did not get back to the original reader level, + // then we propogated some entity out of the literal, so issue an + // error, but don't fail. + // + if (fReaderMgr->getCurrentReaderNum() != orgReader && fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::PartialMarkupInPE); + + return true; +} + + +// +// This method is called after the entity name has been scanned, and any +// PE referenced following the name is handled. The passed decl will be +// filled in with the info scanned. +// +bool DTDScanner::scanEntityDef(DTDEntityDecl& decl, const bool isPEDecl) +{ + // Its got to be an entity literal + if (fReaderMgr->lookingAtChar(chSingleQuote) + || fReaderMgr->lookingAtChar(chDoubleQuote)) + { + // Get a buffer for the literal + XMLBufBid bbValue(fBufMgr); + + if (!scanEntityLiteral(bbValue.getBuffer())) + return false; + + // Set it on the entity decl + decl.setValue(bbValue.getRawBuffer()); + return true; + } + + // + // Its got to be an external entity, so there must be an external id. + // Get buffers for them and scan an external id into them. + // + XMLBufBid bbPubId(fBufMgr); + XMLBufBid bbSysId(fBufMgr); + if (!scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), IDType_External)) + return false; + + decl.setIsExternal(true); + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr->getLastExtEntityInfo(lastInfo); + + // Fill in the id fields of the decl with the info we got + const XMLCh* publicId = bbPubId.getRawBuffer(); + const XMLCh* systemId = bbSysId.getRawBuffer(); + decl.setPublicId((publicId && *publicId) ? publicId : 0); + decl.setSystemId((systemId && *systemId) ? systemId : 0); + decl.setBaseURI((lastInfo.systemId && *lastInfo.systemId) ? lastInfo.systemId : 0); + + // If its a PE decl, we are done + bool gotSpaces = checkForPERef(false, true); + if (isPEDecl) + { + // + // Check for a common error here. NDATA is not allowed for PEs + // so check for the NDATA string. If found give a nice meaningful + // error and continue parsing to eat the NDATA text. + // + if (gotSpaces) + { + if (fReaderMgr->skippedString(XMLUni::fgNDATAString)) + fScanner->emitError(XMLErrs::NDATANotValidForPE); + } + else + { + return true; + } + } + + // If looking at close angle now, we are done + if (fReaderMgr->lookingAtChar(chCloseAngle)) + return true; + + // Else we had to have seem the whitespace + if (!gotSpaces) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + + // We now have to see a notation data string + if (!fReaderMgr->skippedString(XMLUni::fgNDATAString)) + fScanner->emitError(XMLErrs::ExpectedNDATA); + + // Space is required here, but try to go on if not + if (!checkForPERef(false, true)) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + + // Get a name + XMLBufBid bbName(fBufMgr); + if (!fReaderMgr->getName(bbName.getBuffer())) + { + fScanner->emitError(XMLErrs::ExpectedNotationName); + return false; + } + + // Set the decl's notation name + decl.setNotationName(bbName.getRawBuffer()); + + return true; +} + + +// +// This method is called after an attribute decl name or a notation decl has +// been scanned and then an opening parenthesis was see, indicating the list +// of values. It scans the enumeration values and creates a single string +// which has a single space between each value. +// +// The terminating close paren ends this scan. +// +bool DTDScanner::scanEnumeration( const DTDAttDef& attDef + , XMLBuffer& toFill + , const bool notation) +{ + // Reset the passed buffer + toFill.reset(); + + // Check for PE ref but don't require space + checkForPERef(false, true); + + // If this is a notation, we need an opening paren + if (notation) + { + if (!fReaderMgr->skippedChar(chOpenParen)) + fScanner->emitError(XMLErrs::ExpectedOpenParen); + } + + // We need a local buffer to use as well + XMLBufBid bbTmp(fBufMgr); + + while (true) + { + // Space is allowed here for either type so check for PE ref + checkForPERef(false, true); + + // And then get either a name or a name token + bool success; + if (notation) + success = fReaderMgr->getName(bbTmp.getBuffer()); + else + success = fReaderMgr->getNameToken(bbTmp.getBuffer()); + + if (!success) + { + fScanner->emitError + ( + XMLErrs::ExpectedEnumValue + , attDef.getFullName() + ); + return false; + } + + // Append this value to the target value + toFill.append(bbTmp.getRawBuffer(), bbTmp.getLen()); + + // Space is allowed here for either type so check for PE ref + checkForPERef(false, true); + + // Check for the terminating paren + if (fReaderMgr->skippedChar(chCloseParen)) + break; + + // And append a space separator + toFill.append(chSpace); + + // Check for the pipe character separator + if (!fReaderMgr->skippedChar(chPipe)) + { + fScanner->emitError(XMLErrs::ExpectedEnumSepOrParen); + return false; + } + } + return true; +} + + +bool DTDScanner::scanEq() +{ + fReaderMgr->skipPastSpaces(); + if (fReaderMgr->skippedChar(chEqual)) + { + fReaderMgr->skipPastSpaces(); + return true; + } + return false; +} + + +// +// This method is called when an external entity reference is seen in the +// DTD or an external DTD subset is encountered, and their contents pushed +// onto the reader stack. This method will scan that contents. +// +void DTDScanner::scanExtSubsetDecl(const bool inIncludeSect, const bool isDTD) +{ + // Indicate we are in the external subset now + FlagJanitor janContentFlag(&fInternalSubset, false); + + + bool bAcceptDecl = !inIncludeSect; + + // Get a buffer for whitespace + XMLBufBid bbSpace(fBufMgr); + + // + // If we have a doc type handler and we are not being called recursively + // to handle an include section, tell it the ext subset starts + // + if (fDocTypeHandler && isDTD && !inIncludeSect) + fDocTypeHandler->startExtSubset(); + + // + // We have to play a trick here if the current entity we are parsing + // is a PE. Because the spooling code will put out a whitespace before + // and after an expanded PE if its being scanned outside the context of + // a literal entity, this will confuse this external subset code. + // + // So, we see if that is what is happening and, if so, eat the single + // space, a check for the isScanningPERefOutOfLiteral()) + { + if (fReaderMgr->skippedSpace()) + { + if (fScanner->checkXMLDecl(true)) + { + scanTextDecl(); + bAcceptDecl = false; + + // Figure out how to do this + // fReaderMgr->unGet(chSpace); + } + } + } + + // Get the current reader number + const XMLSize_t orgReader = fReaderMgr->getCurrentReaderNum(); + + // + // Loop until we hit the end of the external subset entity. Note that + // we use a double loop here in order to avoid the overhead of doing + // the exception setup/teardown work on every loop. + // + bool inMarkup = false; + bool inCharData = false; + while (true) + { + bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' + try + { + while (true) + { + const XMLCh nextCh = fReaderMgr->peekNextChar(); + + if (!nextCh) + { + return; // nothing left + } + else if (nextCh == chOpenAngle) + { + // Get the reader we started this on + // XML 1.0 P28a Well-formedness constraint: PE Between Declarations + const XMLSize_t orgReader = fReaderMgr->getCurrentReaderNum(); + bool wasInPE = (fReaderMgr->getCurrentReader()->getType() == XMLReader::Type_PE); + + // + // Now scan the markup. Set the flag so that we will know that + // we were in markup if an end of entity exception occurs. + // + fReaderMgr->getNextChar(); + inMarkup = true; + scanMarkupDecl(bAcceptDecl); + inMarkup = false; + + // + // And see if we got back to the same level. If not, then its + // a partial markup error. + // + if (fReaderMgr->getCurrentReaderNum() != orgReader){ + if (wasInPE) + fScanner->emitError(XMLErrs::PEBetweenDecl); + else if (fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::PartialMarkupInPE); + } + + } + else if (fReaderMgr->getCurrentReader()->isWhitespace(nextCh)) + { + // + // If we have a doc type handler, and advanced callbacks are + // enabled, then gather up whitespace and call back. Otherwise + // just skip whitespaces. + // + if (fDocTypeHandler) + { + inCharData = true; + fReaderMgr->getSpaces(bbSpace.getBuffer()); + inCharData = false; + + fDocTypeHandler->doctypeWhitespace + ( + bbSpace.getRawBuffer() + , bbSpace.getLen() + ); + } + else + { + // + // If we hit an end of entity in the middle of white + // space, that's fine. We'll just come back in here + // again on the next round and skip some more. + // + fReaderMgr->skipPastSpaces(); + } + } + else if (nextCh == chPercent) + { + // + // Expand (and scan if external) the reference value. Tell + // it to throw an end of entity exception at the end of the + // entity. + // + fReaderMgr->getNextChar(); + expandPERef(true, false, false, true); + } + else if (inIncludeSect && (nextCh == chCloseSquare)) + { + // + // Its the end of a conditional include section. So scan it and + // decrement the include depth counter. + // + fReaderMgr->getNextChar(); + if (!fReaderMgr->skippedChar(chCloseSquare)) + { + fScanner->emitError(XMLErrs::ExpectedEndOfConditional); + fReaderMgr->skipPastChar(chCloseAngle); + } + else if (!fReaderMgr->skippedChar(chCloseAngle)) + { + fScanner->emitError(XMLErrs::ExpectedEndOfConditional); + fReaderMgr->skipPastChar(chCloseAngle); + } + return; + } + else + { + fReaderMgr->getNextChar(); + if (!fReaderMgr->getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + else + { + fScanner->emitError(XMLErrs::InvalidDocumentStructure); + } + + // Try to get realigned + static const XMLCh toSkip[] = + { + chPercent, chCloseSquare, chOpenAngle, chNull + }; + fReaderMgr->skipUntilInOrWS(toSkip); + } + bAcceptDecl = false; + } + } + catch(const EndOfEntityException& toCatch) + { + // + // If the external entity ended while we were in markup, then that's + // a partial markup error. + // + if (inMarkup) + { + fScanner->emitError(XMLErrs::PartialMarkupInEntity); + inMarkup = false; + } + + // If we were in char data, then send what we got + if (inCharData) + { + // Send what we got, then rethrow + if (fDocTypeHandler) + { + fDocTypeHandler->doctypeWhitespace + ( + bbSpace.getRawBuffer() + , bbSpace.getLen() + ); + } + inCharData = false; + } + + // + // If the entity that just ended was the entity that we started + // on, then this is the end of the external subset. + // + if (orgReader == toCatch.getReaderNum()) + bDoBreak=true; + } + if(bDoBreak) + break; + } + + // If we have a doc type handler, tell it the ext subset ends + if (fDocTypeHandler && isDTD && !inIncludeSect) + fDocTypeHandler->endExtSubset(); +} + + +// +// This method will scan for an id, either public or external. +// +// +// [75] ExternalID ::= 'SYSTEM' S SystemLiteral +// | 'PUBLIC' S PubidLiteral S SystemLiteral +// [83] PublicID ::= 'PUBLIC' S PubidLiteral +// +bool DTDScanner::scanId( XMLBuffer& pubIdToFill + , XMLBuffer& sysIdToFill + , const IDTypes whatKind) +{ + // Clean out both return buffers + pubIdToFill.reset(); + sysIdToFill.reset(); + + // + // Check first for the system id first. If we find it, and system id + // is one of the legal values, then lets try to scan it. + // + // 'SYSTEM' S SystemLiteral + if (fReaderMgr->skippedString(XMLUni::fgSysIDString)) + { + // If they were looking for a public id, then we failed + if (whatKind == IDType_Public) + { + fScanner->emitError(XMLErrs::ExpectedPublicId); + return false; + } + + // We must skip spaces + bool skippedSomething; + fReaderMgr->skipPastSpaces(skippedSomething); + if (!skippedSomething) + { + fScanner->emitError(XMLErrs::ExpectedWhitespace); + return false; + } + + // Get the system literal value + return scanSystemLiteral(sysIdToFill); + } + + // Now scan for public id + // 'PUBLIC' S PubidLiteral S SystemLiteral + // or + // 'PUBLIC' S PubidLiteral + + // If we don't have any public id string => Error + if (!fReaderMgr->skippedString(XMLUni::fgPubIDString)) { + fScanner->emitError(XMLErrs::ExpectedSystemOrPublicId); + return false; + } + + // + // So following this we must have whitespace, a public literal, whitespace, + // and a system literal. + // + bool skippedSomething; + fReaderMgr->skipPastSpaces(skippedSomething); + if (!skippedSomething) + { + fScanner->emitError(XMLErrs::ExpectedWhitespace); + + // + // Just in case, if they just forgot the whitespace but the next char + // is a single or double quote, then keep going. + // + const XMLCh chPeek = fReaderMgr->peekNextChar(); + if ((chPeek != chDoubleQuote) && (chPeek != chSingleQuote)) + return false; + } + + if (!scanPublicLiteral(pubIdToFill)) + return false; + + // If they wanted a public id, then this is all + if (whatKind == IDType_Public) + return true; + + // check if there is any space follows + bool hasSpace; + fReaderMgr->skipPastSpaces(hasSpace); + + // + // In order to recover best here we need to see if + // the next thing is a quote or not + // + const XMLCh chPeek = fReaderMgr->peekNextChar(); + const bool bIsQuote = ((chPeek == chDoubleQuote) + || (chPeek == chSingleQuote)); + + if (!hasSpace) + { + if (whatKind == IDType_External) + { + // + // If its an external Id, then we need to see the system id. + // So, emit the error. But, if the next char is a quote, don't + // give up since its probably going to work. The user just + // missed the separating space. Otherwise, fail. + // + fScanner->emitError(XMLErrs::ExpectedWhitespace); + if (!bIsQuote) + return false; + } + else + { + // + // We can legally return here. But, if the next char is a quote, + // then that's probably not what was desired, since its probably + // just that space was forgotten and there really is a system + // id to follow. + // + // So treat it like missing whitespace if so and keep going. + // Else, just return success. + // + if (bIsQuote) + fScanner->emitError(XMLErrs::ExpectedWhitespace); + else + return true; + } + } + + if (bIsQuote) { + // there is a quote coming, scan the system literal + if (!scanSystemLiteral(sysIdToFill)) + return false; + } + else { + // no quote, if expecting exteral id, this is an error + if (whatKind == IDType_External) + fScanner->emitError(XMLErrs::ExpectedQuotedString); + } + + return true; +} + + +// +// This method will scan the contents of an ignored section. It assumes that +// we already are in the body, i.e. we've seen closing markup. +// +void DTDScanner::scanIgnoredSection() +{ + // + // Depth starts at one because we are already in one section and want + // to parse until we hit its end. + // + unsigned long depth = 1; + bool gotLeadingSurrogate = false; + while (true) + { + const XMLCh nextCh = fReaderMgr->getNextChar(); + + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == chOpenAngle) + { + if (fReaderMgr->skippedChar(chBang) + && fReaderMgr->skippedChar(chOpenSquare)) + { + depth++; + } + } + else if (nextCh == chCloseSquare) + { + if (fReaderMgr->skippedChar(chCloseSquare)) + { + while (fReaderMgr->skippedChar(chCloseSquare)) + { + // Do nothing, just skip them + } + + if (fReaderMgr->skippedChar(chCloseAngle)) + { + depth--; + if (!depth) + break; + } + } + } + // Deal with surrogate pairs + else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + // Its a leading surrogate. If we already got one, then + // issue an error, else set leading flag to make sure that + // we look for a trailing next time. + if (gotLeadingSurrogate) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + // If its a trailing surrogate, make sure that we are + // prepared for that. Else, its just a regular char so make + // sure that we were not expected a trailing surrogate. + if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF)) + { + // Its trailing, so make sure we were expecting it + if (!gotLeadingSurrogate) + fScanner->emitError(XMLErrs::Unexpected2ndSurrogateChar); + } + else + { + // Its just a char, so make sure we were not expecting a + // trailing surrogate. + if (gotLeadingSurrogate) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + + // Its got to at least be a valid XML character + else if (!fReaderMgr->getCurrentReader()->isXMLChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + } + gotLeadingSurrogate = false; + } + } +} + + +// +// This method scans the entire internal subset. All we can have here is +// decl markup, and PE references. The expanded PE references must contain +// whole markup, so we don't have to worry about their content at this +// level. We just scan them, expand them, push them, and parse their content +// right there, via the expandERef() method. +// +bool DTDScanner::scanInternalSubset() +{ + // Indicate we are in the internal subset now + FlagJanitor janContentFlag(&fInternalSubset, true); + + // If we have a doc type handler, tell it the internal subset starts + if (fDocTypeHandler) + fDocTypeHandler->startIntSubset(); + + // Get a buffer for whitespace + XMLBufBid bbSpace(fBufMgr); + + bool noErrors = true; + while (true) + { + const XMLCh nextCh = fReaderMgr->peekNextChar(); + + // + // If we get an end of file marker, just unget it and return a + // failure status. The caller will then see the end of file and + // faill out correctly. + // + if (!nextCh) + return false; + + // Watch for the end of internal subset marker + if (nextCh == chCloseSquare) + { + fReaderMgr->getNextChar(); + break; + } + + if (nextCh == chPercent) + { + // + // Expand (and scan if external) the reference value. Tell + // it to set the reader to cause an end of entity exception + // when this reader dies, which is what the scanExtSubset + // method wants (who is called to scan this.) + // + fReaderMgr->getNextChar(); + expandPERef(true, false, false, true); + } + else if (nextCh == chOpenAngle) + { + // Remember this reader before we start the scan, for checking + // XML 1.0 P28a Well-formedness constraint: PE Between Declarations + const XMLSize_t orgReader = fReaderMgr->getCurrentReaderNum(); + bool wasInPE = (fReaderMgr->getCurrentReader()->getType() == XMLReader::Type_PE); + + // And scan this markup + fReaderMgr->getNextChar(); + scanMarkupDecl(false); + + // If we did not get back to entry level, then partial markup + if (fReaderMgr->getCurrentReaderNum() != orgReader) { + if (wasInPE) + fScanner->emitError(XMLErrs::PEBetweenDecl); + else if (fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::PartialMarkupInPE); + } + } + else if (fReaderMgr->getCurrentReader()->isWhitespace(nextCh)) + { + // + // IF we are doing advanced callbacks and have a doc type + // handler, then get the whitespace and call the doc type + // handler with it. Otherwise, just skip whitespace. + // + if (fDocTypeHandler) + { + fReaderMgr->getSpaces(bbSpace.getBuffer()); + fDocTypeHandler->doctypeWhitespace + ( + bbSpace.getRawBuffer() + , bbSpace.getLen() + ); + } + else + { + fReaderMgr->skipPastSpaces(); + } + } + else + { + // Not valid, so emit an error + XMLCh tmpBuf[9]; + XMLString::binToText + ( + fReaderMgr->getNextChar() + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError + ( + XMLErrs::InvalidCharacterInIntSubset + , tmpBuf + ); + + // + // If an '>', then probably an abnormally terminated + // internal subset so just return. + // + if (nextCh == chCloseAngle) + { + noErrors = false; + break; + } + + // + // Otherwise, try to sync back up by scanning forward for + // a reasonable start character. + // + static const XMLCh toSkip[] = + { + chPercent, chCloseSquare, chOpenAngle, chNull + }; + fReaderMgr->skipUntilInOrWS(toSkip); + } + } + + // If we have a doc type handler, tell it the internal subset ends + if (fDocTypeHandler) + fDocTypeHandler->endIntSubset(); + + return noErrors; +} + + +// +// This method is called once we see a < in the input of an int/ext subset, +// which indicates the start of some sort of markup. +// +void DTDScanner::scanMarkupDecl(const bool parseTextDecl) +{ + // + // We only have two valid first characters here. One is a ! which opens + // some markup decl. The other is a ?, which could begin either a PI + // or a text decl. If parseTextDecl is false, we cannot accept a text + // decl. + // + const XMLCh nextCh = fReaderMgr->getNextChar(); + + if (nextCh == chBang) + { + if (fReaderMgr->skippedChar(chDash)) + { + if (fReaderMgr->skippedChar(chDash)) + { + scanComment(); + } + else + { + fScanner->emitError(XMLErrs::CommentsMustStartWith); + fReaderMgr->skipPastChar(chCloseAngle); + } + } + else if (fReaderMgr->skippedChar(chOpenSquare)) + { + // + // Its a conditional section. This is only valid in the external + // subset, so issue an error if we aren't there. + // + if (fInternalSubset) + { + fScanner->emitError(XMLErrs::ConditionalSectInIntSubset); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // A PE ref can happen here, but space is not required + checkForPERef(false, true); + + if (fReaderMgr->skippedString(XMLUni::fgIncludeString)) + { + checkForPERef(false, true); + + // Check for the following open square bracket + if (!fReaderMgr->skippedChar(chOpenSquare)) + fScanner->emitError(XMLErrs::ExpectedINCLUDEBracket); + + // Get the reader we started this on + const XMLSize_t orgReader = fReaderMgr->getCurrentReaderNum(); + + checkForPERef(false, true); + + // + // Recurse back to the ext subset call again, telling it its + // in an include section. + // + scanExtSubsetDecl(true, false); + + // + // And see if we got back to the same level. If not, then its + // a partial markup error. + // + if (fReaderMgr->getCurrentReaderNum() != orgReader && fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::PartialMarkupInPE); + + } + else if (fReaderMgr->skippedString(XMLUni::fgIgnoreString)) + { + checkForPERef(false, true); + + // Check for the following open square bracket + if (!fReaderMgr->skippedChar(chOpenSquare)) + fScanner->emitError(XMLErrs::ExpectedINCLUDEBracket); + + // Get the reader we started this on + const XMLSize_t orgReader = fReaderMgr->getCurrentReaderNum(); + + // And scan over the ignored part + scanIgnoredSection(); + + // + // And see if we got back to the same level. If not, then its + // a partial markup error. + // + if (fReaderMgr->getCurrentReaderNum() != orgReader && fScanner->getValidationScheme() == XMLScanner::Val_Always) + fScanner->getValidator()->emitError(XMLValid::PartialMarkupInPE); + + } + else + { + fScanner->emitError(XMLErrs::ExpectedIncOrIgn); + fReaderMgr->skipPastChar(chCloseAngle); + } + } + else if (fReaderMgr->skippedString(XMLUni::fgAttListString)) + { + scanAttListDecl(); + } + else if (fReaderMgr->skippedString(XMLUni::fgElemString)) + { + scanElementDecl(); + } + else if (fReaderMgr->skippedString(XMLUni::fgEntityString)) + { + scanEntityDecl(); + } + else if (fReaderMgr->skippedString(XMLUni::fgNotationString)) + { + scanNotationDecl(); + } + else + { + fScanner->emitError(XMLErrs::ExpectedMarkupDecl); + fReaderMgr->skipPastChar(chCloseAngle); + } + } + else if (nextCh == chQuestion) + { + // It could be a PI or the XML declaration. Check for Decl + if (fScanner->checkXMLDecl(false)) + { + // If we are not accepting text decls, its an error + if (parseTextDecl) + { + scanTextDecl(); + } + else + { + // Emit the error and skip past this markup + fScanner->emitError(XMLErrs::TextDeclNotLegalHere); + fReaderMgr->skipPastChar(chCloseAngle); + } + } + else + { + // It has to be a PI + scanPI(); + } + } + else + { + // Can't be valid so emit error and try to skip past end of this decl + fScanner->emitError(XMLErrs::ExpectedMarkupDecl); + fReaderMgr->skipPastChar(chCloseAngle); + } +} + + +// +// This method is called for a mixed model element's content mode. We've +// already scanned past the '(PCDATA' part by the time we get here. So +// everything else is element names separated by | characters until we +// hit the end. The passed element decl's content model is filled in with +// the information found. +// +bool DTDScanner::scanMixed(DTDElementDecl& toFill) +{ + // + // The terminating star is only required if there is something more + // than (PCDATA). + // + bool starRequired = false; + + // Get a buffer to be used below to get element names + XMLBufBid bbName(fBufMgr); + XMLBuffer& nameBuf = bbName.getBuffer(); + + // + // Create an initial content spec node. Its just a leaf node with a + // PCDATA element id. This current node pointer will be pushed down the + // tree as we go. + // + ContentSpecNode* curNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + new (fGrammarPoolMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , XMLElementDecl::fgPCDataElemId + , fGrammarPoolMemoryManager + ) + , false + , fGrammarPoolMemoryManager + ); + + // + // Set the initial leaf as the temporary head. If we hit the first choice + // node, it will be set up here. When done, this is the node that's set + // as the content spec for the element. + // + ContentSpecNode* headNode = curNode; + + // Remember the original node so we can sense the first choice node + ContentSpecNode* orgNode = curNode; + + // + // We just loop around, getting the | character at the top and then + // looking for the next element name. We keep up with the last node + // and add each new one to its right node. + // + while (true) + { + // + // First of all we check for some grunt work details of skipping + // whitespace, expand PE refs, and catching invalid reps. + // + if (fReaderMgr->lookingAtChar(chPercent)) + { + // Expand it and continue + checkForPERef(false, true); + } + else if (fReaderMgr->skippedChar(chAsterisk)) + { + // + // Tell them they can't have reps in mixed model, but eat + // it and keep going if we are allowed to. + // + if (fScanner->emitErrorWillThrowException(XMLErrs::NoRepInMixed)) + { + delete headNode; + } + fScanner->emitError(XMLErrs::NoRepInMixed); + } + else if (fReaderMgr->skippedSpace()) + { + // Spaces are ok at this point, just eat them and continue + fReaderMgr->skipPastSpaces(); + } + else + { + if (!fReaderMgr->skippedChar(chPipe)) + { + // Has to be the closing paren now. + if (!fReaderMgr->skippedChar(chCloseParen)) + { + delete headNode; + fScanner->emitError(XMLErrs::UnterminatedContentModel, toFill.getElementName()->getLocalPart()); + return false; + } + + bool starSkipped = true; + if (!fReaderMgr->skippedChar(chAsterisk)) { + + starSkipped = false; + + if (starRequired) + { + if (fScanner->emitErrorWillThrowException(XMLErrs::ExpectedAsterisk)) + { + delete headNode; + } + fScanner->emitError(XMLErrs::ExpectedAsterisk); + } + } + + // + // Create a zero or more node and make the original head + // node its first child. + // + if (starRequired || starSkipped) { + headNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::ZeroOrMore + , headNode + , 0 + , true + , true + , fGrammarPoolMemoryManager + ); + } + + // Store the head node as the content spec of the element. + toFill.setContentSpec(headNode); + break; + } + + // Its more than just a PCDATA, so an ending star will be required now + starRequired = true; + + // Space is legal here so check for a PE ref, but don't require space + checkForPERef(false, true); + + // Get a name token + if (!fReaderMgr->getName(nameBuf)) + { + delete headNode; + fScanner->emitError(XMLErrs::ExpectedElementName); + return false; + } + + // + // Create a leaf node for it. If we can find the element id for + // this element, then use it. Else, we have to fault in an element + // decl, marked as created because of being in a content model. + // + XMLElementDecl* decl = fDTDGrammar->getElemDecl(fEmptyNamespaceId, 0, nameBuf.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE); + if (!decl) + { + decl = new (fGrammarPoolMemoryManager) DTDElementDecl + ( + nameBuf.getRawBuffer() + , fEmptyNamespaceId + , DTDElementDecl::Any + , fGrammarPoolMemoryManager + ); + decl->setCreateReason(XMLElementDecl::InContentModel); + decl->setExternalElemDeclaration(isReadingExternalEntity()); + fDTDGrammar->putElemDecl(decl); + } + + // + // If the current node is the original node, this is the first choice + // node, so create an initial choice node with the current node and + // the new element id. Store this as the head node. + // + // Otherwise, we have to steal the right node of the previous choice + // and weave in another choice node there, which has the old choice + // as its left and the new leaf as its right. + // + if (curNode == orgNode) + { + curNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::Choice + , curNode + , new (fGrammarPoolMemoryManager) ContentSpecNode + ( + decl->getElementName() + , fGrammarPoolMemoryManager + ) + , true + , true + , fGrammarPoolMemoryManager + ); + + // Remember the top node + headNode = curNode; + } + else + { + ContentSpecNode* oldRight = curNode->orphanSecond(); + curNode->setSecond + ( + new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::Choice + , oldRight + , new (fGrammarPoolMemoryManager) ContentSpecNode + ( + decl->getElementName() + , fGrammarPoolMemoryManager + ) + , true + , true + , fGrammarPoolMemoryManager + ) + ); + + // Make the new right node the current node + curNode = curNode->getSecond(); + } + } + } + + return true; +} + + +// +// This method is called when we see a 'emitError(XMLErrs::ExpectedWhitespace); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // + // And now we get a name, which is the name of the notation. Get a + // buffer for the name. + // + XMLBufBid bbName(fBufMgr); + if (!fReaderMgr->getName(bbName.getBuffer())) + { + fScanner->emitError(XMLErrs::ExpectedNotationName); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // If namespaces are enabled, then no colons allowed + if (fScanner->getDoNamespaces()) + { + if (XMLString::indexOf(bbName.getRawBuffer(), chColon) != -1) + fScanner->emitError(XMLErrs::ColonNotLegalWithNS); + } + + // Space is required here so check for a PE ref, and require space + if (!checkForPERef(false, true)) + { + fScanner->emitError(XMLErrs::ExpectedWhitespace); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // + // And scan an external or public id. We need buffers to use for both + // of these. + // + XMLBufBid bbPubId(fBufMgr); + XMLBufBid bbSysId(fBufMgr); + if (!scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), IDType_Either)) + { + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // We can have an optional space or PE ref here + checkForPERef(false, true); + + // + // See if it already exists. If so, add it to the notatino decl pool. + // Otherwise, if advanced callbacks are on, create a temp one and + // call out for that one. + // + XMLNotationDecl* decl = fDTDGrammar->getNotationDecl(bbName.getRawBuffer()); + bool isIgnoring = (decl != 0); + if (isIgnoring) + { + fScanner->emitError(XMLErrs::NotationAlreadyExists, bbName.getRawBuffer()); + } + else + { + // Fill in a new notation declaration and add it to the pool + const XMLCh* publicId = bbPubId.getRawBuffer(); + const XMLCh* systemId = bbSysId.getRawBuffer(); + ReaderMgr::LastExtEntityInfo lastInfo; + fReaderMgr->getLastExtEntityInfo(lastInfo); + + decl = new (fGrammarPoolMemoryManager) XMLNotationDecl + ( + bbName.getRawBuffer() + , (publicId && *publicId) ? publicId : 0 + , (systemId && *systemId) ? systemId : 0 + , (lastInfo.systemId && *lastInfo.systemId) ? lastInfo.systemId : 0 + , fGrammarPoolMemoryManager + ); + fDTDGrammar->putNotationDecl(decl); + } + + // + // If we have a document type handler, then tell it about this. If we + // are ignoring it, only call out if advanced callbacks are enabled. + // + if (fDocTypeHandler) + { + fDocTypeHandler->notationDecl + ( + *decl + , isIgnoring + ); + } + + // And one more optional space or PE ref + checkForPERef(false, true); + + // And skip the terminating bracket + if (!fReaderMgr->skippedChar(chCloseAngle)) + fScanner->emitError(XMLErrs::UnterminatedNotationDecl); +} + + +// +// Scans a PI and calls the appropriate callbacks. A PI can happen in either +// the document or the DTD, so it calls the appropriate handler according +// to the fInDocument flag. +// +// At entry we have just scanned the lookingAtSpace()) + { + fScanner->emitError(XMLErrs::PINameExpected); + fReaderMgr->skipPastSpaces(); + } + + // Get a buffer for the PI name and scan it in + XMLBufBid bbName(fBufMgr); + if (!fReaderMgr->getName(bbName.getBuffer())) + { + fScanner->emitError(XMLErrs::PINameExpected); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // Point the name pointer at the raw data + namePtr = bbName.getRawBuffer(); + + // See if it issome form of 'xml' and emit a warning + //if (!XMLString::compareIString(namePtr, XMLUni::fgXMLString)) + if (bbName.getLen() == 3 && + (((namePtr[0] == chLatin_x) || (namePtr[0] == chLatin_X)) && + ((namePtr[1] == chLatin_m) || (namePtr[1] == chLatin_M)) && + ((namePtr[2] == chLatin_l) || (namePtr[2] == chLatin_L)))) + fScanner->emitError(XMLErrs::NoPIStartsWithXML); + + // If namespaces are enabled, then no colons allowed + if (fScanner->getDoNamespaces()) + { + if (XMLString::indexOf(namePtr, chColon) != -1) + fScanner->emitError(XMLErrs::ColonNotLegalWithNS); + } + + // + // If we don't hit a space next, then the PI has no target. If we do + // then get out the target. Get a buffer for it as well + // + XMLBufBid bbTarget(fBufMgr); + if (fReaderMgr->skippedSpace()) + { + // Skip any leading spaces + fReaderMgr->skipPastSpaces(); + + bool gotLeadingSurrogate = false; + + // It does have a target, so lets move on to deal with that. + while (1) + { + const XMLCh nextCh = fReaderMgr->getNextChar(); + + // Watch for an end of file, which is always bad here + if (!nextCh) + { + fScanner->emitError(XMLErrs::UnterminatedPI); + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + } + + // Watch for potential terminating character + if (nextCh == chQuestion) + { + // It must be followed by '>' to be a termination of the target + if (fReaderMgr->skippedChar(chCloseAngle)) + break; + } + + // Check for correct surrogate pairs + if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF)) + { + if (gotLeadingSurrogate) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + else + gotLeadingSurrogate = true; + } + else + { + if (gotLeadingSurrogate) + { + if ((nextCh < 0xDC00) || (nextCh > 0xDFFF)) + fScanner->emitError(XMLErrs::Expected2ndSurrogateChar); + } + // Its got to at least be a valid XML character + else if (!fReaderMgr->getCurrentReader()->isXMLChar(nextCh)) { + + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError(XMLErrs::InvalidCharacter, tmpBuf); + } + + gotLeadingSurrogate = false; + } + bbTarget.append(nextCh); + } + } + else + { + // No target, but make sure its terminated ok + if (!fReaderMgr->skippedChar(chQuestion)) + { + fScanner->emitError(XMLErrs::UnterminatedPI); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + if (!fReaderMgr->skippedChar(chCloseAngle)) + { + fScanner->emitError(XMLErrs::UnterminatedPI); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + } + + // Point the target pointer at the raw data + targetPtr = bbTarget.getRawBuffer(); + + // + // If we have a handler, then call it. + // + if (fDocTypeHandler) + { + fDocTypeHandler->doctypePI + ( + namePtr + , targetPtr + ); + } +} + + +// +// This method scans a public literal. It must be quoted and all of its +// characters must be valid public id characters. The quotes are discarded +// and the results are returned. +// +bool DTDScanner::scanPublicLiteral(XMLBuffer& toFill) +{ + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr->skipIfQuote(quoteCh)) { + fScanner->emitError(XMLErrs::ExpectedQuotedString); + return false; + } + + while (true) + { + const XMLCh nextCh = fReaderMgr->getNextChar(); + + // Watch for EOF + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + + if (nextCh == quoteCh) + break; + + // + // If its not a valid public id char, then report it but keep going + // since that's the best recovery scheme. + // + if (!fReaderMgr->getCurrentReader()->isPublicIdChar(nextCh)) + { + XMLCh tmpBuf[9]; + XMLString::binToText + ( + nextCh + , tmpBuf + , 8 + , 16 + , fMemoryManager + ); + fScanner->emitError(XMLErrs::InvalidPublicIdChar, tmpBuf); + } + + toFill.append(nextCh); + } + return true; +} + + +// +// This method handles scanning in a quoted system literal. It expects to +// start on the open quote and returns after eating the ending quote. There +// are not really any restrictions on the contents of system literals. +// +bool DTDScanner::scanSystemLiteral(XMLBuffer& toFill) +{ + toFill.reset(); + + // Get the next char which must be a single or double quote + XMLCh quoteCh; + if (!fReaderMgr->skipIfQuote(quoteCh)) { + fScanner->emitError(XMLErrs::ExpectedQuotedString); + return false; + } + + XMLCh nextCh; + // Break out on terminating quote + while ((nextCh=fReaderMgr->getNextChar())!=quoteCh) + { + // Watch for EOF + if (!nextCh) + ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); + toFill.append(nextCh); + } + return true; +} + + + +// +// This method is called to scan a text decl line, which can be the first +// line in an external entity or external subset. +// +// On entry the ' +// +void DTDScanner::scanTextDecl() +{ + // Skip any subsequent whitespace before the version string + fReaderMgr->skipPastSpaces(); + + // Next should be the version string + XMLBufBid bbVersion(fBufMgr); + if (fReaderMgr->skippedString(XMLUni::fgVersionString)) + { + if (!scanEq()) + { + fScanner->emitError(XMLErrs::ExpectedEqSign); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // + // Followed by a single or double quoted version. Get a buffer for + // the string. + // + if (!getQuotedString(bbVersion.getBuffer())) + { + fScanner->emitError(XMLErrs::BadXMLVersion); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // If its not our supported version, issue an error but continue + if (XMLString::equals(bbVersion.getRawBuffer(), XMLUni::fgVersion1_1)) { + if (fScanner->getXMLVersion() != XMLReader::XMLV1_1) + fScanner->emitError(XMLErrs::UnsupportedXMLVersion, bbVersion.getRawBuffer()); + } + else if (!XMLString::equals(bbVersion.getRawBuffer(), XMLUni::fgVersion1_0)) + fScanner->emitError(XMLErrs::UnsupportedXMLVersion, bbVersion.getRawBuffer()); + } + + // Ok, now we must have an encoding string + XMLBufBid bbEncoding(fBufMgr); + fReaderMgr->skipPastSpaces(); + bool gotEncoding = false; + if (fReaderMgr->skippedString(XMLUni::fgEncodingString)) + { + // There must be a equal sign next + if (!scanEq()) + { + fScanner->emitError(XMLErrs::ExpectedEqSign); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // Followed by a single or double quoted version string + getQuotedString(bbEncoding.getBuffer()); + if (bbEncoding.isEmpty() || !XMLString::isValidEncName(bbEncoding.getRawBuffer())) + { + fScanner->emitError(XMLErrs::BadXMLEncoding, bbEncoding.getRawBuffer()); + fReaderMgr->skipPastChar(chCloseAngle); + return; + } + + // Indicate that we got an encoding + gotEncoding = true; + } + + // + // Encoding declarations are required in the external entity + // if there is a text declaration present + // + if (!gotEncoding) + { + fScanner->emitError(XMLErrs::EncodingRequired); + fReaderMgr->skipPastChar(chCloseAngle); + return; + + } + + fReaderMgr->skipPastSpaces(); + if (!fReaderMgr->skippedChar(chQuestion)) + { + fScanner->emitError(XMLErrs::UnterminatedXMLDecl); + fReaderMgr->skipPastChar(chCloseAngle); + } + else if (!fReaderMgr->skippedChar(chCloseAngle)) + { + fScanner->emitError(XMLErrs::UnterminatedXMLDecl); + fReaderMgr->skipPastChar(chCloseAngle); + } + + // + // If we have a document type handler and advanced callbacks are on, + // then call the TextDecl callback + // + if (fDocTypeHandler) + { + fDocTypeHandler->TextDecl + ( + bbVersion.getRawBuffer() + , bbEncoding.getRawBuffer() + ); + } + + // + // If we got an encoding string, then we have to call back on the reader + // to tell it what the encoding is. + // + if (!bbEncoding.isEmpty()) + { + if (!fReaderMgr->getCurrentReader()->setEncoding(bbEncoding.getRawBuffer())) + fScanner->emitError(XMLErrs::ContradictoryEncoding, bbEncoding.getRawBuffer()); + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/DTD/DTDScanner.hpp b/include/xercesc/validators/DTD/DTDScanner.hpp new file mode 100644 index 0000000..1ebbb46 --- /dev/null +++ b/include/xercesc/validators/DTD/DTDScanner.hpp @@ -0,0 +1,277 @@ +/* + * 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: DTDScanner.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DTDSCANNER_HPP) +#define XERCESC_INCLUDE_GUARD_DTDSCANNER_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLScanner; + +/* + * Default implementation of an XML DTD scanner. + */ +class DocTypeHandler; + +class VALIDATORS_EXPORT DTDScanner : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Class specific types + // + // EntityExpRes + // Returned from scanEntityRef() to indicate how the expanded text + // was treated. + // + // IDTypes + // Type of the ID + // ----------------------------------------------------------------------- + enum EntityExpRes + { + EntityExp_Failed + , EntityExp_Pushed + , EntityExp_Returned + }; + + enum IDTypes + { + IDType_Public + , IDType_External + , IDType_Either + }; + + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DTDScanner + ( + DTDGrammar* dtdGrammar + , DocTypeHandler* const docTypeHandler + , MemoryManager* const grammarPoolMemoryManager + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~DTDScanner(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + DocTypeHandler* getDocTypeHandler(); + const DocTypeHandler* getDocTypeHandler() const; + + // ----------------------------------------------------------------------- + // Setter methods + // + // setScannerInfo() is called by the scanner to tell the DTDScanner + // about the stuff it needs to have access to. + // ----------------------------------------------------------------------- + void setScannerInfo + ( + XMLScanner* const owningScanner + , ReaderMgr* const readerMgr + , XMLBufferMgr* const bufMgr + ); + + void setDocTypeHandler + ( + DocTypeHandler* const handlerToSet + ); + + void scanExtSubsetDecl(const bool inIncludeSect, const bool isDTD); + bool scanInternalSubset(); + bool scanId + ( + XMLBuffer& pubIdToFill + , XMLBuffer& sysIdToFill + , const IDTypes whatKind + ); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DTDScanner(const DTDScanner &); + DTDScanner& operator = (const DTDScanner&); + + // ----------------------------------------------------------------------- + // Private DTD scanning methods. These are all in XMLValidator2.cpp + // ----------------------------------------------------------------------- + bool checkForPERef + ( + const bool inLiteral + , const bool inMarkup + ); + bool expandPERef + ( + const bool scanExternal + , const bool inLiteral + , const bool inMarkup + , const bool throwEndOfExt = false + ); + bool getQuotedString(XMLBuffer& toFill); + XMLAttDef* scanAttDef(DTDElementDecl& elemDecl, XMLBuffer& bufToUse); + bool scanAttValue + ( + const XMLCh* const attrName + , XMLBuffer& toFill + , const XMLAttDef::AttTypes type + ); + void scanAttListDecl(); + ContentSpecNode* scanChildren + ( + const DTDElementDecl& elemDecl + , XMLBuffer& bufToUse + ); + bool scanCharRef(XMLCh& toFill, XMLCh& second); + void scanComment(); + bool scanContentSpec(DTDElementDecl& toFill); + void scanDefaultDecl(DTDAttDef& toFill); + void scanElementDecl(); + void scanEntityDecl(); + bool scanEntityDef(); + bool scanEntityLiteral(XMLBuffer& toFill); + bool scanEntityDef(DTDEntityDecl& decl, const bool isPEDecl); + EntityExpRes scanEntityRef(XMLCh& firstCh, XMLCh& secondCh, bool& escaped); + bool scanEnumeration + ( + const DTDAttDef& attDef + , XMLBuffer& toFill + , const bool notation + ); + bool scanEq(); + void scanIgnoredSection(); + void scanMarkupDecl(const bool parseTextDecl); + bool scanMixed(DTDElementDecl& toFill); + void scanNotationDecl(); + void scanPI(); + bool scanPublicLiteral(XMLBuffer& toFill); + bool scanSystemLiteral(XMLBuffer& toFill); + void scanTextDecl(); + bool isReadingExternalEntity(); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fDocTypeHandler + // This holds the optional doc type handler that can be installed + // and used to call back for all markup events. It is DTD specific. + // + // fDumAttDef + // fDumElemDecl + // fDumEntityDecl + // These are dummy objects into which mark decls are parsed when + // they are just overrides of previously declared markup decls. In + // such situations, the first one wins but we need to have somewhere + // to parse them into. So these are lazily created and used as needed + // when such markup decls are seen. + // + // fInternalSubset + // This is used to track whether we are in the internal subset or not, + // in which case we are in the external subset. + // + // fNextAttrId + // Since att defs are per-element, we don't have a validator wide + // attribute def pool. So we use a simpler data structure in each + // element decl to store its att defs, and we use this simple counter + // to apply a unique id to each new attribute. + // + // fDTDGrammar + // The DTD information we scanned like element decl, attribute decl + // are stored in this Grammar. + // + // fBufMgr + // This is the buffer manager of the scanner. This is provided as a + // convenience so that the DTDScanner doesn't have to create its own + // buffer manager during the parse process. + // + // fReaderMgr + // This is a pointer to the reader manager that is being used by the scanner. + // + // fScanner + // The pointer to the scanner to which this DTDScanner belongs + // + // fPEntityDeclPool + // This is a pool of EntityDecl objects, which contains all of the + // parameter entities that are declared in the DTD subsets. + // + // fEmptyNamespaceId + // The uri for all DTD decls + // + // fDocTypeReaderId + // The original reader in the fReaderMgr - to be compared against the + // current reader to decide whether we are processing an external/internal + // declaration + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + MemoryManager* fGrammarPoolMemoryManager; + DocTypeHandler* fDocTypeHandler; + DTDAttDef* fDumAttDef; + DTDElementDecl* fDumElemDecl; + DTDEntityDecl* fDumEntityDecl; + bool fInternalSubset; + unsigned int fNextAttrId; + DTDGrammar* fDTDGrammar; + XMLBufferMgr* fBufMgr; + ReaderMgr* fReaderMgr; + XMLScanner* fScanner; + NameIdPool* fPEntityDeclPool; + unsigned int fEmptyNamespaceId; + XMLSize_t fDocTypeReaderId; +}; + + +// --------------------------------------------------------------------------- +// DTDScanner: Getter methods +// --------------------------------------------------------------------------- +inline DocTypeHandler* DTDScanner::getDocTypeHandler() +{ + return fDocTypeHandler; +} + +inline const DocTypeHandler* DTDScanner::getDocTypeHandler() const +{ + return fDocTypeHandler; +} + + +// --------------------------------------------------------------------------- +// DTDScanner: Setter methods +// --------------------------------------------------------------------------- +inline void DTDScanner::setDocTypeHandler(DocTypeHandler* const handlerToSet) +{ + fDocTypeHandler = handlerToSet; +} + +// ----------------------------------------------------------------------- +// Helper methods +// ----------------------------------------------------------------------- +inline bool DTDScanner::isReadingExternalEntity() { + return (fDocTypeReaderId != fReaderMgr->getCurrentReaderNum()); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/DTD/DTDValidator.cpp b/include/xercesc/validators/DTD/DTDValidator.cpp new file mode 100644 index 0000000..eb2f67e --- /dev/null +++ b/include/xercesc/validators/DTD/DTDValidator.cpp @@ -0,0 +1,657 @@ +/* + * 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: DTDValidator.cpp 729944 2008-12-29 17:03:32Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// DTDValidator: Constructors and Destructor +// --------------------------------------------------------------------------- +DTDValidator::DTDValidator(XMLErrorReporter* const errReporter) : + + XMLValidator(errReporter) + , fDTDGrammar(0) +{ + reset(); +} + +DTDValidator::~DTDValidator() +{ +} + + +// --------------------------------------------------------------------------- +// DTDValidator: Implementation of the XMLValidator interface +// --------------------------------------------------------------------------- +bool DTDValidator::checkContent(XMLElementDecl* const elemDecl + , QName** const children + , XMLSize_t childCount + , XMLSize_t* indexFailingChild) +{ + // + // Look up the element id in our element decl pool. This will get us + // the element decl in our own way of looking at them. + // + if (!elemDecl) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, getScanner()->getMemoryManager()); + + // + // Get the content spec type of this element. This will tell us what + // to do to validate it. + // + const DTDElementDecl::ModelTypes modelType = ((DTDElementDecl*) elemDecl)->getModelType(); + + if (modelType == DTDElementDecl::Empty) + { + // + // We can do this one here. It cannot have any children. If it does + // we return 0 as the index of the first bad child. + // + if (childCount) + { + *indexFailingChild=0; + return false; + } + } + else if (modelType == DTDElementDecl::Any) + { + // We pass no judgement on this one, anything goes + } + else if ((modelType == DTDElementDecl::Mixed_Simple) + || (modelType == DTDElementDecl::Children)) + { + // Get the element's content model or fault it in + const XMLContentModel* elemCM = elemDecl->getContentModel(); + + // Ask it to validate and return its return + return elemCM->validateContent(children, childCount, getScanner()->getEmptyNamespaceId(), indexFailingChild, getScanner()->getMemoryManager()); + } + else + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, getScanner()->getMemoryManager()); + } + + // Went ok, so return success + return true; +} + + +void DTDValidator::faultInAttr(XMLAttr& toFill, const XMLAttDef& attDef) const +{ + toFill.set(0, attDef.getFullName(), attDef.getValue(), attDef.getType()); +} + +void DTDValidator::reset() +{ +} + + +bool DTDValidator::requiresNamespaces() const +{ + // Namespaces are not supported for DTDs + return false; +} + + +void +DTDValidator::validateAttrValue(const XMLAttDef* attDef + , const XMLCh* const attrValue + , bool preValidation + , const XMLElementDecl*) +{ + // + // Get quick refs to lost of of the stuff in the passed objects in + // order to simplify the code below, which will reference them very + // often. + // + const XMLAttDef::AttTypes type = attDef->getType(); + const XMLAttDef::DefAttTypes defType = attDef->getDefaultType(); + const XMLCh* const valueText = attDef->getValue(); + const XMLCh* const fullName = attDef->getFullName(); + const XMLCh* const enumList = attDef->getEnumeration(); + + // + // If the default type is fixed, then make sure the passed value maps + // to the fixed value. + // If during preContentValidation, the value we are validating is the fixed value itself + // so no need to compare. + // Only need to do this for regular attribute value validation + // + if (defType == XMLAttDef::Fixed && !preValidation) + { + if (!XMLString::equals(attrValue, valueText)) + emitError(XMLValid::NotSameAsFixedValue, fullName, attrValue, valueText); + } + + // + // If its a CDATA attribute, then we are done with any DTD level + // validation else do the rest. + // + if (type == XMLAttDef::CData) + return; + + + + // An empty string cannot be valid for any of the other types + if (!attrValue[0]) + { + emitError(XMLValid::InvalidEmptyAttValue, fullName); + return; + } + + // See whether we are doing multiple values or not + const bool multipleValues = + ( + (type == XMLAttDef::IDRefs) + || (type == XMLAttDef::Entities) + || (type == XMLAttDef::NmTokens) + || (type == XMLAttDef::Notation) + || (type == XMLAttDef::Enumeration) + ); + + // And whether we must check for a first name char + const bool firstNameChar = + ( + (type == XMLAttDef::ID) + || (type == XMLAttDef::IDRef) + || (type == XMLAttDef::IDRefs) + || (type == XMLAttDef::Entity) + || (type == XMLAttDef::Entities) + || (type == XMLAttDef::Notation) + ); + + // Whether it requires ref checking stuff + const bool isARefType + ( + (type == XMLAttDef::ID) + || (type == XMLAttDef::IDRef) + || (type == XMLAttDef::IDRefs) + ); + + // Some trigger flags to avoid issuing redundant errors and whatnot + bool alreadyCapped = false; + + // + // Make a copy of the text that we can mangle and get a pointer we can + // move through the value + // + + // Use a stack-based buffer, when possible... + XMLCh tempBuffer[100]; + + XMLCh* pszTmpVal = 0; + + ArrayJanitor janTmpVal(0); + + if (XMLString::stringLen(attrValue) < sizeof(tempBuffer) / sizeof(tempBuffer[0])) + { + XMLString::copyString(tempBuffer, attrValue); + pszTmpVal = tempBuffer; + } + else + { + janTmpVal.reset(XMLString::replicate(attrValue, getScanner()->getMemoryManager()), getScanner()->getMemoryManager()); + pszTmpVal = janTmpVal.get(); + } + + XMLCh* valPtr = pszTmpVal; + + bool doNamespace = getScanner()->getDoNamespaces(); + + while (true) + { + // + // Make sure the first character is a valid first name char, i.e. + // if its a Name value. For NmToken values we don't treat the first + // char any differently. + // + if (firstNameChar) + { + // If its not, emit and error but try to keep going + if (!getReaderMgr()->getCurrentReader()->isFirstNameChar(*valPtr)) + emitError(XMLValid::AttrValNotName, valPtr, fullName); + valPtr++; + } + + // Make sure all the remaining chars are valid name chars + while (*valPtr) + { + // + // If we hit a whitespace, its either a break between two + // or more values, or an error if we have a single value. + // + // + // XML1.0-3rd + // + // [6] Names ::= Name (#x20 Name)* + // [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* + // + // only and only ONE #x20 is allowed to be the delimiter + // + if (*valPtr==chSpace) + { + if (!multipleValues) + { + emitError(XMLValid::NoMultipleValues, fullName); + return; + } + + break; + } + + // Now this attribute can be of type + // ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENS, ENUMERATION + // All these must be valid XMLName + // If namespace is enabled, colon is not allowed in the first 6 + + if (doNamespace && *valPtr == chColon && firstNameChar) + emitError(XMLValid::ColonNotValidWithNS); + + if (!getReaderMgr()->getCurrentReader()->isNameChar(*valPtr)) + { + emitError(XMLValid::AttrValNotName, valPtr, fullName); + return; + } + valPtr++; + } + + // + // Cap it off at the current non-name char. If already capped, + // then remember this. + // + if (!(*valPtr)) + alreadyCapped = true; + *valPtr = 0; + + // + // If this type of attribute requires that we track reference + // stuff, then handle that. + // + if (isARefType) + { + if ((type == XMLAttDef::ID) + || (type == XMLAttDef::IDRef) + || (type == XMLAttDef::IDRefs)) + { + XMLRefInfo* find = getScanner()->getIDRefList()->get(pszTmpVal); + if (find) + { + if (find->getDeclared() && (type == XMLAttDef::ID)) + emitError(XMLValid::ReusedIDValue, pszTmpVal); + } + else + { + find = new (getScanner()->getMemoryManager()) XMLRefInfo + ( + pszTmpVal + , false + , false + , getScanner()->getMemoryManager() + ); + getScanner()->getIDRefList()->put((void*)find->getRefName(), find); + } + + // + // Mark it declared or used, which might be redundant in some cases + // but not worth checking + // + if (type == XMLAttDef::ID) + find->setDeclared(true); + else { + if (!preValidation) { + find->setUsed(true); + } + } + } + } + else if (!preValidation && ((type == XMLAttDef::Entity) || (type == XMLAttDef::Entities))) + { + // + // If its refering to a entity, then look up the name in the + // general entity pool. If not there, then its an error. If its + // not an external unparsed entity, then its an error. + // + // In case of pre-validation, the above errors should be ignored. + // + const XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(pszTmpVal); + if (decl) + { + if (!decl->isUnparsed()) + emitError(XMLValid::BadEntityRefAttr, pszTmpVal, fullName); + } + else + { + emitError + ( + XMLValid::UnknownEntityRefAttr + , fullName + , pszTmpVal + ); + } + } + else if ((type == XMLAttDef::Notation) || (type == XMLAttDef::Enumeration)) + { + // + // Make sure that this value maps to one of the enumeration or + // notation values in the enumList parameter. We don't have to + // look it up in the notation pool (if a notation) because we + // will look up the enumerated values themselves. If they are in + // the notation pool (after the DTD is parsed), then obviously + // this value will be legal since it matches one of them. + // + if (!XMLString::isInList(pszTmpVal, enumList)) + emitError(XMLValid::DoesNotMatchEnumList, pszTmpVal, fullName); + } + + // If not doing multiple values, then we are done + if (!multipleValues) + break; + + // + // If we are at the end, then break out now, else move up to the + // next char and update the base pointer. + // + if (alreadyCapped) + break; + + valPtr++; + pszTmpVal = valPtr; + } + +} + +void DTDValidator::preContentValidation(bool +#if defined(XERCES_DEBUG) + reuseGrammar +#endif + ,bool validateDefAttr) +{ + // + // Lets enumerate all of the elements in the element decl pool + // and put out an error for any that did not get declared. + // We also check all of the attributes as well. + // + NameIdPoolEnumerator elemEnum = fDTDGrammar->getElemEnumerator(); + fDTDGrammar->setValidated(true); + while (elemEnum.hasMoreElements()) + { + const DTDElementDecl& curElem = elemEnum.nextElement(); + const DTDElementDecl::CreateReasons reason = curElem.getCreateReason(); + + // + // See if this element decl was ever marked as declared. If + // not, then put out an error. In some cases its just + // a warning, such as being referenced in a content model. + // + if (reason != XMLElementDecl::Declared) + { + if (reason == XMLElementDecl::AttList) + { + getScanner()->emitError + ( + XMLErrs::UndeclaredElemInAttList + , curElem.getFullName() + ); + } + else if (reason == XMLElementDecl::AsRootElem) + { + // It's ok that the root element is not declared in the DTD + /* + emitError + ( + XMLValid::UndeclaredElemInDocType + , curElem.getFullName() + );*/ + } + else if (reason == XMLElementDecl::InContentModel) + { + getScanner()->emitError + ( + XMLErrs::UndeclaredElemInCM + , curElem.getFullName() + ); + } + else + { + #if defined(XERCES_DEBUG) + if(reuseGrammar && reason == XMLElementDecl::JustFaultIn){ + } + else + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::DTD_UnknownCreateReason, getScanner()->getMemoryManager()); + #endif + } + } + + // + // Check all of the attributes of the current element. + // We check for: + // + // 1) Multiple ID attributes + // 2) That all of the default values of attributes are + // valid for their type. + // 3) That for any notation types, that their lists + // of possible values refer to declared notations. + // + // 4) XML1.0(3rd edition) + // + // Validity constraint: One Notation Per Element Type + // An element type MUST NOT have more than one NOTATION attribute specified. + // + // Validity constraint: No Notation on Empty Element + // For compatibility, an attribute of type NOTATION MUST NOT be declared on an element declared EMPTY. + // + // Validity constraint: No Duplicate Tokens + // The notation names in a single NotationType attribute declaration, as well as + // the NmTokens in a single Enumeration attribute declaration, MUST all be distinct. + // + + XMLAttDefList& attDefList = curElem.getAttDefList(); + bool seenId = false; + bool seenNOTATION = false; + bool elemEmpty = (curElem.getModelType() == DTDElementDecl::Empty); + + for(XMLSize_t i=0; i entEnum = fDTDGrammar->getEntityEnumerator(); + while (entEnum.hasMoreElements()) + { + const DTDEntityDecl& curEntity = entEnum.nextElement(); + + if (!curEntity.getNotationName()) + continue; + + // It has a notation name, so look it up + if (!fDTDGrammar->getNotationDecl(curEntity.getNotationName())) + { + emitError + ( + XMLValid::NotationNotDeclared + , curEntity.getNotationName() + ); + } + } +} + +void DTDValidator::postParseValidation() +{ + // + // At this time, there is nothing to do here. The scanner itself handles + // ID/IDREF validation, since that is the same no matter what kind of + // validator. + // +} + +// +// We need to verify that all of its possible values +// (in the enum list) +// is distinct and +// refer to valid notations if toValidateNotation is set on +// +void DTDValidator::checkTokenList(const XMLAttDef& curAttDef + , bool toValidateNotation) +{ + + XMLCh* list = XMLString::replicate(curAttDef.getEnumeration(), getScanner()->getMemoryManager()); + ArrayJanitor janList(list, getScanner()->getMemoryManager()); + + // + // Search forward for a space or a null. If a null, + // we are done. If a space, cap it and look it up. + // + bool breakFlag = false; + XMLCh* listPtr = list; + XMLCh* lastPtr = listPtr; + while (true) + { + while (*listPtr && (*listPtr != chSpace)) + listPtr++; + + // + // If at the end, indicate we need to break after + // this one. Else, cap it off here. + // + if (!*listPtr) + breakFlag = true; + else + *listPtr++ = chNull; + + //distinction check + //there should be no same token found in the remaining list + if (XMLString::isInList(lastPtr, listPtr)) + { + emitError + ( + XMLValid::AttrDupToken + , curAttDef.getFullName() + , lastPtr + ); + } + + if (toValidateNotation && !fDTDGrammar->getNotationDecl(lastPtr)) + { + emitError + ( + XMLValid::UnknownNotRefAttr + , curAttDef.getFullName() + , lastPtr + ); + } + + // Break out if we hit the end last time + if (breakFlag) + break; + + // Else move upwards and try again + lastPtr = listPtr; + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/DTD/DTDValidator.hpp b/include/xercesc/validators/DTD/DTDValidator.hpp new file mode 100644 index 0000000..284bb82 --- /dev/null +++ b/include/xercesc/validators/DTD/DTDValidator.hpp @@ -0,0 +1,158 @@ +/* + * 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: DTDValidator.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DTDVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DTDVALIDATOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLMsgLoader; + + +// +// This is a derivative of the abstract validator interface. This class +// implements a validator that supports standard XML 1.0 DTD semantics. +// This class handles scanning the internal and external subsets of the +// DTD, and provides the standard validation services against the DTD info +// it found. +// +class VALIDATORS_EXPORT DTDValidator : public XMLValidator +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DTDValidator(XMLErrorReporter* const errReporter = 0); + virtual ~DTDValidator(); + + // ----------------------------------------------------------------------- + // Implementation of the XMLValidator interface + // ----------------------------------------------------------------------- + virtual bool checkContent + ( + XMLElementDecl* const elemDecl + , QName** const children + , XMLSize_t childCount + , XMLSize_t* indexFailingChild + ); + + virtual void faultInAttr + ( + XMLAttr& toFill + , const XMLAttDef& attDef + ) const; + + virtual void preContentValidation(bool reuseGrammar, + bool validateDefAttr = false); + + virtual void postParseValidation(); + + virtual void reset(); + + virtual bool requiresNamespaces() const; + + virtual void validateAttrValue + ( + const XMLAttDef* attDef + , const XMLCh* const attrValue + , bool preValidation = false + , const XMLElementDecl* elemDecl = 0 + ); + virtual void validateElement + ( + const XMLElementDecl* elemDef + ); + virtual Grammar* getGrammar() const; + virtual void setGrammar(Grammar* aGrammar); + + // ----------------------------------------------------------------------- + // Virtual DTD handler interface. + // ----------------------------------------------------------------------- + virtual bool handlesDTD() const; + + // ----------------------------------------------------------------------- + // Virtual Schema handler interface. handlesSchema() always return false. + // ----------------------------------------------------------------------- + virtual bool handlesSchema() const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DTDValidator(const DTDValidator &); + DTDValidator& operator = (const DTDValidator&); + + // ----------------------------------------------------------------------- + // Helper + // ----------------------------------------------------------------------- + void checkTokenList(const XMLAttDef& attDef + , bool toValidateNotation); + + // ----------------------------------------------------------------------- + // Private data members + // + // fDTDGrammar + // The DTD information stored. + // + // ----------------------------------------------------------------------- + DTDGrammar* fDTDGrammar; +}; + +// --------------------------------------------------------------------------- +// Virtual interface +// --------------------------------------------------------------------------- +inline Grammar* DTDValidator::getGrammar() const { + return fDTDGrammar; +} + +inline void DTDValidator::setGrammar(Grammar* aGrammar) { + fDTDGrammar = (DTDGrammar*) aGrammar; +} + +inline void DTDValidator::validateElement (const XMLElementDecl*) { + // no special DTD Element validation +} + +// --------------------------------------------------------------------------- +// DTDValidator: DTD handler interface +// --------------------------------------------------------------------------- +inline bool DTDValidator::handlesDTD() const +{ + // We definitely want to handle DTD scanning + return true; +} + +// --------------------------------------------------------------------------- +// DTDValidator: Schema handler interface +// --------------------------------------------------------------------------- +inline bool DTDValidator::handlesSchema() const +{ + // No Schema scanning + return false; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/DTD/DocTypeHandler.hpp b/include/xercesc/validators/DTD/DocTypeHandler.hpp new file mode 100644 index 0000000..e467edb --- /dev/null +++ b/include/xercesc/validators/DTD/DocTypeHandler.hpp @@ -0,0 +1,145 @@ +/* + * 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: DocTypeHandler.hpp 557282 2007-07-18 14:54:15Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOCTYPEHANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_DOCTYPEHANDLER_HPP + +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This abstract class defines the document type handler API's which can be +// used to process the DTD events generated by the DTDScanner as it scans the +// internal and external subset. + +class VALIDATORS_EXPORT DocTypeHandler +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DocTypeHandler() + { + } + + virtual ~DocTypeHandler() + { + } + + + // ----------------------------------------------------------------------- + // The document type handler virtual handler interface + // ----------------------------------------------------------------------- + virtual void attDef + ( + const DTDElementDecl& elemDecl + , const DTDAttDef& attDef + , const bool ignoring + ) = 0; + + virtual void doctypeComment + ( + const XMLCh* const comment + ) = 0; + + virtual void doctypeDecl + ( + const DTDElementDecl& elemDecl + , const XMLCh* const publicId + , const XMLCh* const systemId + , const bool hasIntSubset + , const bool hasExtSubset = false + ) = 0; + + virtual void doctypePI + ( + const XMLCh* const target + , const XMLCh* const data + ) = 0; + + virtual void doctypeWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + ) = 0; + + virtual void elementDecl + ( + const DTDElementDecl& decl + , const bool isIgnored + ) = 0; + + virtual void endAttList + ( + const DTDElementDecl& elemDecl + ) = 0; + + virtual void endIntSubset() = 0; + + virtual void endExtSubset() = 0; + + virtual void entityDecl + ( + const DTDEntityDecl& entityDecl + , const bool isPEDecl + , const bool isIgnored + ) = 0; + + virtual void resetDocType() = 0; + + virtual void notationDecl + ( + const XMLNotationDecl& notDecl + , const bool isIgnored + ) = 0; + + virtual void startAttList + ( + const DTDElementDecl& elemDecl + ) = 0; + + virtual void startIntSubset() = 0; + + virtual void startExtSubset() = 0; + + virtual void TextDecl + ( + const XMLCh* const versionStr + , const XMLCh* const encodingStr + ) = 0; + + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DocTypeHandler(const DocTypeHandler&); + DocTypeHandler& operator=(const DocTypeHandler&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/DTD/XMLDTDDescriptionImpl.cpp b/include/xercesc/validators/DTD/XMLDTDDescriptionImpl.cpp new file mode 100644 index 0000000..11b3544 --- /dev/null +++ b/include/xercesc/validators/DTD/XMLDTDDescriptionImpl.cpp @@ -0,0 +1,133 @@ +/* + * 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: XMLDTDDescriptionImpl.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLDTDDescriptionImpl: constructor and destructor +// --------------------------------------------------------------------------- +XMLDTDDescriptionImpl::XMLDTDDescriptionImpl(const XMLCh* const systemId + , MemoryManager* const memMgr ) +:XMLDTDDescription(memMgr) +,fSystemId(0) +,fRootName(0) +{ + if (systemId) + fSystemId = XMLString::replicate(systemId, memMgr); +} + +XMLDTDDescriptionImpl::~XMLDTDDescriptionImpl() +{ + if (fSystemId) + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fSystemId); + + if (fRootName) + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fRootName); +} + +const XMLCh* XMLDTDDescriptionImpl::getGrammarKey() const +{ + return getSystemId(); +} + +const XMLCh* XMLDTDDescriptionImpl::getRootName() const +{ + return fRootName; +} + +const XMLCh* XMLDTDDescriptionImpl::getSystemId() const +{ + return fSystemId; +} + +void XMLDTDDescriptionImpl::setRootName(const XMLCh* const rootName) +{ + if (fRootName) + { + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fRootName); + fRootName = 0; + } + + if (rootName) + fRootName = XMLString::replicate(rootName, XMLGrammarDescription::getMemoryManager()); +} + +void XMLDTDDescriptionImpl::setSystemId(const XMLCh* const systemId) +{ + if (fSystemId) + { + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fSystemId); + fSystemId = 0; + } + + if (systemId) + fSystemId = XMLString::replicate(systemId, XMLGrammarDescription::getMemoryManager()); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XMLDTDDescriptionImpl) + +void XMLDTDDescriptionImpl::serialize(XSerializeEngine& serEng) +{ + XMLDTDDescription::serialize(serEng); + + if (serEng.isStoring()) + { + serEng.writeString(fSystemId); + serEng.writeString(fRootName); + } + else + { + if (fSystemId) + { + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fSystemId); + } + + serEng.readString((XMLCh*&)fSystemId); + + //the original root name which came from the ctor needs deallocated + if (fRootName) + { + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fRootName); + } + + serEng.readString((XMLCh*&)fRootName); + } + +} + +XMLDTDDescriptionImpl::XMLDTDDescriptionImpl(MemoryManager* const memMgr) +:XMLDTDDescription(memMgr) +,fSystemId(0) +,fRootName(0) +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp b/include/xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp new file mode 100644 index 0000000..e065b0f --- /dev/null +++ b/include/xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp @@ -0,0 +1,108 @@ +/* + * 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: XMLDTDDescriptionImpl.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLDTDDESCRIPTIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLDTDDESCRIPTIONIMPL_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLPARSER_EXPORT XMLDTDDescriptionImpl : public XMLDTDDescription +{ +public : + // ----------------------------------------------------------------------- + /** @name constructor and destructor */ + // ----------------------------------------------------------------------- + //@{ + XMLDTDDescriptionImpl( + const XMLCh* const systemId + , MemoryManager* const memMgr + ); + + ~XMLDTDDescriptionImpl(); + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of GrammarDescription Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * getGrammarKey + * + */ + virtual const XMLCh* getGrammarKey() const ; + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of DTDDescription Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * Getter + * + */ + virtual const XMLCh* getRootName() const; + virtual const XMLCh* getSystemId() const; + + /** + * Setter + * + */ + virtual void setRootName(const XMLCh* const); + virtual void setSystemId(const XMLCh* const); + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLDTDDescriptionImpl) + + XMLDTDDescriptionImpl(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLDTDDescriptionImpl(const XMLDTDDescriptionImpl& ); + XMLDTDDescriptionImpl& operator=(const XMLDTDDescriptionImpl& ); + //@} + + // ----------------------------------------------------------------------- + // + // fSystemId: + // SYSTEM ID of the grammar + // + // fRootName: + // root name of the grammar + // + // ----------------------------------------------------------------------- + + const XMLCh* fSystemId; + const XMLCh* fRootName; + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/common/AllContentModel.cpp b/include/xercesc/validators/common/AllContentModel.cpp new file mode 100644 index 0000000..fc581bf --- /dev/null +++ b/include/xercesc/validators/common/AllContentModel.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 children(64, fMemoryManager); + ValueVectorOf 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 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 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 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 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 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 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& toFill + , ValueVectorOf& 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;igetMinOccurs();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 diff --git a/include/xercesc/validators/common/AllContentModel.hpp b/include/xercesc/validators/common/AllContentModel.hpp new file mode 100644 index 0000000..9ec5e02 --- /dev/null +++ b/include/xercesc/validators/common/AllContentModel.hpp @@ -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 +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class ContentSpecNode; + +// +// AllContentModel is a derivative of the abstract content model base +// class that handles the special case of feature in schema. If a model +// is , 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& toFill + , ValueVectorOf& 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 (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 diff --git a/include/xercesc/validators/common/CMAny.cpp b/include/xercesc/validators/common/CMAny.cpp new file mode 100644 index 0000000..535fe86 --- /dev/null +++ b/include/xercesc/validators/common/CMAny.cpp @@ -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 +#include +#include +#include + +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 diff --git a/include/xercesc/validators/common/CMAny.hpp b/include/xercesc/validators/common/CMAny.hpp new file mode 100644 index 0000000..d9a38e7 --- /dev/null +++ b/include/xercesc/validators/common/CMAny.hpp @@ -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 + +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 diff --git a/include/xercesc/validators/common/CMBinaryOp.cpp b/include/xercesc/validators/common/CMBinaryOp.cpp new file mode 100644 index 0000000..6d89eaf --- /dev/null +++ b/include/xercesc/validators/common/CMBinaryOp.cpp @@ -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 +#include +#include +#include +#include + +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 diff --git a/include/xercesc/validators/common/CMBinaryOp.hpp b/include/xercesc/validators/common/CMBinaryOp.hpp new file mode 100644 index 0000000..6331823 --- /dev/null +++ b/include/xercesc/validators/common/CMBinaryOp.hpp @@ -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 + +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 diff --git a/include/xercesc/validators/common/CMLeaf.hpp b/include/xercesc/validators/common/CMLeaf.hpp new file mode 100644 index 0000000..e3c4969 --- /dev/null +++ b/include/xercesc/validators/common/CMLeaf.hpp @@ -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 + + +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 diff --git a/include/xercesc/validators/common/CMNode.hpp b/include/xercesc/validators/common/CMNode.hpp new file mode 100644 index 0000000..6373a0c --- /dev/null +++ b/include/xercesc/validators/common/CMNode.hpp @@ -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 + +#include +#include + +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 diff --git a/include/xercesc/validators/common/CMRepeatingLeaf.hpp b/include/xercesc/validators/common/CMRepeatingLeaf.hpp new file mode 100644 index 0000000..7fbd58e --- /dev/null +++ b/include/xercesc/validators/common/CMRepeatingLeaf.hpp @@ -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 + + +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 diff --git a/include/xercesc/validators/common/CMStateSet.hpp b/include/xercesc/validators/common/CMStateSet.hpp new file mode 100644 index 0000000..30ef98f --- /dev/null +++ b/include/xercesc/validators/common/CMStateSet.hpp @@ -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 +#include +#include +#include +#include + +#if XERCES_HAVE_EMMINTRIN_H +# include +#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; indexfArraySize; 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;indexfBits[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; indexfDynamicBuffer->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 diff --git a/include/xercesc/validators/common/CMUnaryOp.cpp b/include/xercesc/validators/common/CMUnaryOp.cpp new file mode 100644 index 0000000..67cd900 --- /dev/null +++ b/include/xercesc/validators/common/CMUnaryOp.cpp @@ -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 +#include +#include + +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 diff --git a/include/xercesc/validators/common/CMUnaryOp.hpp b/include/xercesc/validators/common/CMUnaryOp.hpp new file mode 100644 index 0000000..a9b9d0e --- /dev/null +++ b/include/xercesc/validators/common/CMUnaryOp.hpp @@ -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 + + +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 diff --git a/include/xercesc/validators/common/ContentLeafNameTypeVector.cpp b/include/xercesc/validators/common/ContentLeafNameTypeVector.cpp new file mode 100644 index 0000000..c054b41 --- /dev/null +++ b/include/xercesc/validators/common/ContentLeafNameTypeVector.cpp @@ -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 + +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; ifLeafCount; 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= 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 diff --git a/include/xercesc/validators/common/ContentLeafNameTypeVector.hpp b/include/xercesc/validators/common/ContentLeafNameTypeVector.hpp new file mode 100644 index 0000000..d205adf --- /dev/null +++ b/include/xercesc/validators/common/ContentLeafNameTypeVector.hpp @@ -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 +#include + +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 diff --git a/include/xercesc/validators/common/ContentSpecNode.cpp b/include/xercesc/validators/common/ContentSpecNode.cpp new file mode 100644 index 0000000..793cc1c --- /dev/null +++ b/include/xercesc/validators/common/ContentSpecNode.cpp @@ -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 +#include +#include + +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; + 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 + diff --git a/include/xercesc/validators/common/ContentSpecNode.hpp b/include/xercesc/validators/common/ContentSpecNode.hpp new file mode 100644 index 0000000..da8dda0 --- /dev/null +++ b/include/xercesc/validators/common/ContentSpecNode.hpp @@ -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 +#include + +#include + +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 diff --git a/include/xercesc/validators/common/DFAContentModel.cpp b/include/xercesc/validators/common/DFAContentModel.cpp new file mode 100644 index 0000000..63a4099 --- /dev/null +++ b/include/xercesc/validators/common/DFAContentModel.cpp @@ -0,0 +1,1685 @@ +/* + * 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.cpp 901107 2010-01-20 08:45:02Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +struct CMStateSetHasher +{ + XMLSize_t getHashVal(const void *const key, XMLSize_t mod) + { + const CMStateSet* const pkey = (const CMStateSet*) key; + return ((pkey->hashCode()) % mod); + } + + bool equals(const void *const key1, const void *const key2) + { + const CMStateSet* const pkey1 = (const CMStateSet*) key1; + const CMStateSet* const pkey2 = (const CMStateSet*) key2; + return (*pkey1==*pkey2); + } +}; + +// --------------------------------------------------------------------------- +// DFAContentModel: Constructors and Destructor +// --------------------------------------------------------------------------- +DFAContentModel::DFAContentModel( const bool dtd + , ContentSpecNode* const elemContentSpec + , MemoryManager* const manager) : + + fElemMap(0) + , fElemMapType(0) + , fElemMapSize(0) + , fEmptyOk(false) + , fEOCPos(0) + , fFinalStateFlags(0) + , fFollowList(0) + , fHeadNode(0) + , fLeafCount(0) + , fLeafList(0) + , fLeafListType(0) + , fTransTable(0) + , fTransTableSize(0) + , fCountingStates(0) + , fDTD(dtd) + , fIsMixed(false) + , fLeafNameTypeVector(0) + , fMemoryManager(manager) +{ + // And build the DFA data structures + buildDFA(elemContentSpec); +} + +DFAContentModel::DFAContentModel( const bool dtd + , ContentSpecNode* const elemContentSpec + , const bool isMixed + , MemoryManager* const manager): + + fElemMap(0) + , fElemMapType(0) + , fElemMapSize(0) + , fEmptyOk(false) + , fEOCPos(0) + , fFinalStateFlags(0) + , fFollowList(0) + , fHeadNode(0) + , fLeafCount(0) + , fLeafList(0) + , fLeafListType(0) + , fTransTable(0) + , fTransTableSize(0) + , fCountingStates(0) + , fDTD(dtd) + , fIsMixed(isMixed) + , fLeafNameTypeVector(0) + , fMemoryManager(manager) +{ + // And build the DFA data structures + buildDFA(elemContentSpec); +} + +DFAContentModel::~DFAContentModel() +{ + // + // Clean up all the stuff that is not just temporary representation + // data that was cleaned up after building the DFA. + // + fMemoryManager->deallocate(fFinalStateFlags); //delete [] fFinalStateFlags; + + unsigned int index; + for (index = 0; index < fTransTableSize; index++) + fMemoryManager->deallocate(fTransTable[index]); //delete [] fTransTable[index]; + fMemoryManager->deallocate(fTransTable); //delete [] fTransTable; + + if(fCountingStates) + { + for (unsigned int j = 0; j < fTransTableSize; ++j) + delete fCountingStates[j]; + fMemoryManager->deallocate(fCountingStates); + } + + for (index = 0; index < fLeafCount; index++) + delete fElemMap[index]; + fMemoryManager->deallocate(fElemMap); //delete [] fElemMap; + + fMemoryManager->deallocate(fElemMapType); //delete [] fElemMapType; + fMemoryManager->deallocate(fLeafListType); //delete [] fLeafListType; + + delete fLeafNameTypeVector; +} + + +// --------------------------------------------------------------------------- +// DFAContentModel: Implementation of the ContentModel virtual interface +// --------------------------------------------------------------------------- +bool +DFAContentModel::validateContent( QName** const children + , XMLSize_t childCount + , unsigned int + , XMLSize_t* indexFailingChild + , MemoryManager* const) const +{ + // + // If there are no children, then either we fail on the 0th element + // or we return success. It depends upon whether this content model + // accepts empty content, which we determined earlier. + // + if (!childCount) + { + // success + if(fEmptyOk) + return true; + *indexFailingChild=0; + return false; + } + + // + // Lets loop through the children in the array and move our way + // through the states. Note that we use the fElemMap array to map + // an element index to a state index. + // + unsigned int curState = 0; + unsigned int nextState = 0; + unsigned int loopCount = 0; + unsigned int childIndex = 0; + for (; childIndex < childCount; childIndex++) + { + // Get the current element index out + const QName* curElem = children[childIndex]; + const XMLCh* curElemRawName = 0; + if (fDTD) + curElemRawName = curElem->getRawName(); + + // If this is text in a Schema mixed content model, skip it. + if ( fIsMixed && + ( curElem->getURI() == XMLElementDecl::fgPCDataElemId)) + continue; + + // Look up this child in our element map + unsigned int elemIndex = 0; + for (; elemIndex < fElemMapSize; elemIndex++) + { + const QName* inElem = fElemMap[elemIndex]; + if (fDTD) { + if (XMLString::equals(inElem->getRawName(), curElemRawName)) { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + else { + ContentSpecNode::NodeTypes type = fElemMapType[elemIndex]; + if (type == ContentSpecNode::Leaf) + { + if ((inElem->getURI() == curElem->getURI()) && + (XMLString::equals(inElem->getLocalPart(), curElem->getLocalPart()))) { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if ((type & 0x0f)== ContentSpecNode::Any) + { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + else if ((type & 0x0f) == ContentSpecNode::Any_NS) + { + if (inElem->getURI() == curElem->getURI()) + { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if ((type & 0x0f) == ContentSpecNode::Any_Other) + { + // Here we assume that empty string has id 1. + // + unsigned int uriId = curElem->getURI(); + if (uriId != 1 && uriId != inElem->getURI()) { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + } + }//for elemIndex + + // If "nextState" is -1, we found a match, but the transition is invalid + if (nextState == XMLContentModel::gInvalidTrans) + { + *indexFailingChild=childIndex; + return false; + } + + // If we didn't find it, then obviously not valid + if (elemIndex == fElemMapSize) + { + *indexFailingChild=childIndex; + return false; + } + + unsigned int nextLoop = 0; + if(!handleRepetitions(curElem, curState, loopCount, nextState, nextLoop, elemIndex, 0)) + { + *indexFailingChild=childIndex; + return false; + } + + curState = nextState; + loopCount = nextLoop; + nextState = 0; + + }//for childIndex + + // + // We transitioned all the way through the input list. However, that + // does not mean that we ended in a final state. So check whether + // our ending state is a final state. + // + if (!fFinalStateFlags[curState]) + { + *indexFailingChild=childIndex; + return false; + } + + // verify if we exited before the minOccurs was satisfied + if (fCountingStates != 0) { + Occurence* o = fCountingStates[curState]; + if (o != 0 && loopCount < (unsigned int)o->minOccurs) { + // not enough loops on the current state to be considered final. + *indexFailingChild=childIndex; + return false; + } + } + + //success + return true; +} + +bool DFAContentModel::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); + + if (childCount == 0) + { + if(fEmptyOk) + return true; + *indexFailingChild=0; + return false; + } + + // + // Lets loop through the children in the array and move our way + // through the states. Note that we use the fElemMap array to map + // an element index to a state index. + // + unsigned int curState = 0; + unsigned int loopCount = 0; + unsigned int nextState = 0; + unsigned int childIndex = 0; + for (; childIndex < childCount; childIndex++) + { + // Get the current element index out + QName* curElem = children[childIndex]; + + // If this is text in a Schema mixed content model, skip it. + if ( fIsMixed && + ( curElem->getURI() == XMLElementDecl::fgPCDataElemId)) + continue; + + // Look up this child in our element map + unsigned int elemIndex = 0; + for (; elemIndex < fElemMapSize; elemIndex++) + { + QName* inElem = fElemMap[elemIndex]; + ContentSpecNode::NodeTypes type = fElemMapType[elemIndex]; + if (type == ContentSpecNode::Leaf) + { + if (comparator.isEquivalentTo(curElem, inElem) ) + { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + + } + else if ((type & 0x0f)== ContentSpecNode::Any) + { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + else if ((type & 0x0f) == ContentSpecNode::Any_NS) + { + if (inElem->getURI() == curElem->getURI()) + { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if ((type & 0x0f) == ContentSpecNode::Any_Other) + { + // Here we assume that empty string has id 1. + // + unsigned int uriId = curElem->getURI(); + if (uriId != 1 && uriId != inElem->getURI()) + { + nextState = fTransTable[curState][elemIndex]; + if (nextState != XMLContentModel::gInvalidTrans) + break; + } + } + }//for elemIndex + + // If "nextState" is -1, we found a match, but the transition is invalid + if (nextState == XMLContentModel::gInvalidTrans) + { + *indexFailingChild=childIndex; + return false; + } + + // If we didn't find it, then obviously not valid + if (elemIndex == fElemMapSize) + { + *indexFailingChild=childIndex; + return false; + } + + unsigned int nextLoop = 0; + if(!handleRepetitions(curElem, curState, loopCount, nextState, nextLoop, elemIndex, &comparator)) + { + *indexFailingChild=childIndex; + return false; + } + + curState = nextState; + loopCount = nextLoop; + nextState = 0; + + }//for childIndex + + // + // We transitioned all the way through the input list. However, that + // does not mean that we ended in a final state. So check whether + // our ending state is a final state. + // + if (!fFinalStateFlags[curState]) + { + *indexFailingChild=childIndex; + return false; + } + + // verify if we exited before the minOccurs was satisfied + if (fCountingStates != 0) { + Occurence* o = fCountingStates[curState]; + if (o != 0) { + if (loopCount < (unsigned int)o->minOccurs) { + // not enough loops on the current state. + *indexFailingChild=childIndex; + return false; + } + } + } + + //success + return true; +} + +bool DFAContentModel::handleRepetitions(const QName* const curElem, + unsigned int curState, + unsigned int currentLoop, + unsigned int& nextState, + unsigned int& nextLoop, + XMLSize_t elemIndex, + SubstitutionGroupComparator * comparator) const +{ + nextLoop = 0; + if (fCountingStates != 0) { + nextLoop = currentLoop; + Occurence* o = fCountingStates[curState]; + if (o != 0) { + if (curState == nextState) { + if (++nextLoop > (unsigned int)o->maxOccurs && o->maxOccurs != -1) { + // It's likely that we looped too many times on the current state + // however it's possible that we actually matched another particle + // which allows the same name. + // + // Consider: + // + // + // + // + // + // + // and + // + // + // + // + // + // + // In the DFA there will be two transitions from the current state which + // allow "foo". Note that this is not a UPA violation. The ambiguity of which + // transition to take is resolved by the current value of the counter. Since + // we've already seen enough instances of the first "foo" perhaps there is + // another element declaration or wildcard deeper in the element map which + // matches. + unsigned int tempNextState = 0; + + while (++elemIndex < fElemMapSize) { + QName* inElem = fElemMap[elemIndex]; + ContentSpecNode::NodeTypes type = fElemMapType[elemIndex]; + if (type == ContentSpecNode::Leaf) + { + if(comparator!=0) { + if (comparator->isEquivalentTo(curElem, inElem) ) + { + tempNextState = fTransTable[curState][elemIndex]; + if (tempNextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if (fDTD) { + if (XMLString::equals(inElem->getRawName(), curElem->getRawName())) { + tempNextState = fTransTable[curState][elemIndex]; + if (tempNextState != XMLContentModel::gInvalidTrans) + break; + } + } + else { + if ((inElem->getURI() == curElem->getURI()) && + (XMLString::equals(inElem->getLocalPart(), curElem->getLocalPart()))) { + tempNextState = fTransTable[curState][elemIndex]; + if (tempNextState != XMLContentModel::gInvalidTrans) + break; + } + } + } + else if ((type & 0x0f)== ContentSpecNode::Any) + { + tempNextState = fTransTable[curState][elemIndex]; + if (tempNextState != XMLContentModel::gInvalidTrans) + break; + } + else if ((type & 0x0f) == ContentSpecNode::Any_NS) + { + if (inElem->getURI() == curElem->getURI()) + { + tempNextState = fTransTable[curState][elemIndex]; + if (tempNextState != XMLContentModel::gInvalidTrans) + break; + } + } + else if ((type & 0x0f) == ContentSpecNode::Any_Other) + { + // Here we assume that empty string has id 1. + // + unsigned int uriId = curElem->getURI(); + if (uriId != 1 && uriId != inElem->getURI()) + { + tempNextState = fTransTable[curState][elemIndex]; + if (tempNextState != XMLContentModel::gInvalidTrans) + break; + } + } + } + + // if we still can't find a match, report the error + if (elemIndex == fElemMapSize) + return false; + + // if we found a match, set the next state and reset the + // counter if the next state is a counting state. + nextState = tempNextState; + Occurence* o = fCountingStates[nextState]; + if (o != 0) { + nextLoop = (elemIndex == XMLSize_t (o->elemIndex)) ? 1 : 0; + } + } + } + else if (nextLoop < (unsigned int)o->minOccurs) { + // not enough loops on the current state. + return false; + } + else { + // Exiting a counting state. If we're entering a new + // counting state, reset the counter. + o = fCountingStates[nextState]; + if (o != 0) { + nextLoop = (elemIndex == XMLSize_t (o->elemIndex)) ? 1 : 0; + } + } + } + else { + o = fCountingStates[nextState]; + if (o != 0) { + // Entering a new counting state. Reset the counter. + // If we've already seen one instance of the looping + // particle set the counter to 1, otherwise set it + // to 0. + nextLoop = (elemIndex == XMLSize_t (o->elemIndex)) ? 1 : 0; + } + } + } + return true; +} + +// --------------------------------------------------------------------------- +// DFAContentModel: Private helper methods +// --------------------------------------------------------------------------- +void DFAContentModel::buildDFA(ContentSpecNode* const curNode) +{ + unsigned int index; + + // + // The first step we need to take is to rewrite the content model using + // our CMNode objects, and in the process get rid of any repetition short + // cuts, converting them into '*' style repetitions or getting rid of + // repetitions altogether. + // + // The conversions done are: + // + // x+ -> (x|x*) + // x? -> (x|epsilon) + // + // This is a relatively complex scenario. What is happening is that we + // create a top level binary node of which the special EOC value is set + // as the right side node. The the left side is set to the rewritten + // syntax tree. The source is the original content model info from the + // decl pool. The rewrite is done by buildSyntaxTree() which recurses the + // decl pool's content of the element and builds a new tree in the + // process. + // + // Note that, during this operation, we set each non-epsilon leaf node's + // DFA state position and count the number of such leafs, which is left + // in the fLeafCount member. + // + fLeafCount=countLeafNodes(curNode); + fEOCPos = fLeafCount++; + + // We need to build an array of references to the non-epsilon + // leaf nodes. We will put them in the array according to their position values + // + fLeafList = (CMLeaf**) fMemoryManager->allocate(fLeafCount*sizeof(CMLeaf*)); //new CMLeaf*[fLeafCount]; + fLeafListType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate + ( + fLeafCount * sizeof(ContentSpecNode::NodeTypes) + ); //new ContentSpecNode::NodeTypes[fLeafCount]; + // + // And, moving onward... We now need to build the follow position sets + // for all the nodes. So we allocate an array of pointers to state sets, + // one for each leaf node (i.e. each significant DFA position.) + // + fFollowList = (CMStateSet**) fMemoryManager->allocate + ( + fLeafCount * sizeof(CMStateSet*) + ); //new CMStateSet*[fLeafCount]; + for (index = 0; index < fLeafCount; index++) + fFollowList[index] = new (fMemoryManager) CMStateSet(fLeafCount, fMemoryManager); + + // The buildSyntaxTree function will recursively iterate over the ContentSpecNode + // and build the CMNode hierarchy; it will also put every leaf node in the fLeafList + // array, then calculate the first and last position sets of each node. This is + // cached away in each of the nodes. + // + // Along the way we also set the leaf count in each node as the maximum + // state count. They must know this in order to create their first/last + // position sets. + // + unsigned int counter=0; + CMNode* nodeOrgContent = buildSyntaxTree(curNode, counter); + // + // Check to see whether this content model can handle an empty content, + // which is something we need to optimize by looking now before we + // throw away the info that would tell us that. + // + // If the left node of the head (the top level of the original content) + // is nullable, then its true. + // + fEmptyOk = nodeOrgContent->isNullable(); + + // + // And handle specially the EOC node, which also must be numbered and + // counted as a non-epsilon leaf node. It could not be handled in the + // above tree build because it was created before all that started. We + // save the EOC position since its used during the DFA building loop. + // + CMLeaf* nodeEOC = new (fMemoryManager) CMLeaf + ( + new (fMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , XMLContentModel::gEOCFakeId + , fMemoryManager + ) + , fEOCPos + , true + , fLeafCount + , fMemoryManager + ); + fHeadNode = new (fMemoryManager) CMBinaryOp + ( + ContentSpecNode::Sequence + , nodeOrgContent + , nodeEOC + , fLeafCount + , fMemoryManager + ); + + // Put also the final EOC node in the leaf array + fLeafList[counter] = new (fMemoryManager) CMLeaf + ( + nodeEOC->getElement() + , nodeEOC->getPosition() + , fLeafCount + , fMemoryManager + ); + fLeafListType[counter] = ContentSpecNode::Leaf; + + // + // Now handle our top level. We use our left child's last pos set and our + // right child's first pos set, so get them now for convenience. + // + const CMStateSet& last = nodeOrgContent->getLastPos(); + const CMStateSet& first = nodeEOC->getFirstPos(); + + // + // Now, for every position which is in our left child's last set + // add all of the states in our right child's first set to the + // follow set for that position. + // + CMStateSetEnumerator enumLast(&last); + while(enumLast.hasMoreElements()) + { + XMLSize_t index=enumLast.nextElement(); + *fFollowList[index] |= first; + } + + // + // And finally the big push... Now we build the DFA using all the states + // and the tree we've built up. First we set up the various data + // structures we are going to use while we do this. + // + // First of all we need an array of unique element ids in our content + // model. For each transition table entry, we need a set of contiguous + // indices to represent the transitions for a particular input element. + // So we need to a zero based range of indexes that map to element types. + // This element map provides that mapping. + // + fElemMap = (QName**) fMemoryManager->allocate + ( + fLeafCount * sizeof(QName*) + ); //new QName*[fLeafCount]; + fElemMapType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate + ( + fLeafCount * sizeof(ContentSpecNode::NodeTypes) + ); //new ContentSpecNode::NodeTypes[fLeafCount]; + fElemMapSize = 0; + + Occurence** elemOccurenceMap=0; + for (unsigned int outIndex = 0; outIndex < fLeafCount; outIndex++) + { + fElemMap[outIndex] = new (fMemoryManager) QName(fMemoryManager); + + if ( (fLeafListType[outIndex] & 0x0f) != ContentSpecNode::Leaf ) + if (!fLeafNameTypeVector) + fLeafNameTypeVector = new (fMemoryManager) ContentLeafNameTypeVector(fMemoryManager); + + // Get the current leaf's element index + CMLeaf* leaf=fLeafList[outIndex]; + const QName* element = leaf->getElement(); + const XMLCh* elementRawName = 0; + if (fDTD && element) + elementRawName = element->getRawName(); + + // See if the current leaf node's element index is in the list + unsigned int inIndex = 0; + + for (; inIndex < fElemMapSize; inIndex++) + { + const QName* inElem = fElemMap[inIndex]; + if (fDTD) { + if (XMLString::equals(inElem->getRawName(), elementRawName)) { + break; + } + } + else { + if ((fElemMapType[inIndex] == fLeafListType[outIndex]) && + (inElem->getURI() == element->getURI()) && + (XMLString::equals(inElem->getLocalPart(), element->getLocalPart()))) { + break; + } + } + } + + // If it was not in the list, then add it and bump the map size + if (inIndex == fElemMapSize) + { + fElemMap[fElemMapSize]->setValues(*element); + if(leaf->isRepeatableLeaf()) + { + if (elemOccurenceMap == 0) { + elemOccurenceMap = (Occurence**)fMemoryManager->allocate(fLeafCount*sizeof(Occurence*)); + memset(elemOccurenceMap, 0, fLeafCount*sizeof(Occurence*)); + } + elemOccurenceMap[fElemMapSize] = new (fMemoryManager) Occurence(((CMRepeatingLeaf*)leaf)->getMinOccurs(), ((CMRepeatingLeaf*)leaf)->getMaxOccurs(), fElemMapSize); + } + fElemMapType[fElemMapSize] = fLeafListType[outIndex]; + ++fElemMapSize; + } + } + + // set up the fLeafNameTypeVector object if there is one. + if (fLeafNameTypeVector) { + fLeafNameTypeVector->setValues(fElemMap, fElemMapType, fElemMapSize); + } + + /*** + * Optimization(Jan, 2001); We sort fLeafList according to + * elemIndex which is *uniquely* associated to each leaf. + * We are *assuming* that each element appears in at least one leaf. + **/ + // don't forget to delete it +#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH + int *fLeafSorter = (int*) fMemoryManager->allocate + ( + (fLeafCount + fElemMapSize) * sizeof(int) + ); //new int[fLeafCount + fElemMapSize]; + unsigned int fSortCount = 0; + + for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) + { + const QName* element = fElemMap[elemIndex]; + const XMLCh* elementRawName = 0; + if (fDTD && element) + elementRawName = element->getRawName(); + + for (unsigned int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) + { + const QName* leaf = fLeafList[leafIndex]->getElement(); + if (fDTD) { + if (XMLString::equals(leaf->getRawName(), elementRawName)) { + fLeafSorter[fSortCount++] = leafIndex; + } + } + else { + if ((fElemMapType[elemIndex] == fLeafListType[leafIndex]) && + (leaf->getURI() == element->getURI()) && + (XMLString::equals(leaf->getLocalPart(), element->getLocalPart()))) { + fLeafSorter[fSortCount++] = leafIndex; + } + } + } + fLeafSorter[fSortCount++] = -1; + } +#endif + + // instead of using a single array with -1 to separate elements, use a bidimensional map + unsigned int** fLeafSorter = (unsigned int**)fMemoryManager->allocate(fElemMapSize * sizeof(unsigned int*)); + unsigned int* tmpSorter = (unsigned int*)fMemoryManager->allocate(fLeafCount * sizeof(unsigned int)); + for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) + { + const QName* element = fElemMap[elemIndex]; + const XMLCh* elementRawName = 0; + if (fDTD && element) + elementRawName = element->getRawName(); + + unsigned int fSortCount=0; + for (unsigned int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) + { + const QName* leaf = fLeafList[leafIndex]->getElement(); + if (fDTD) { + if (XMLString::equals(leaf->getRawName(), elementRawName)) { + tmpSorter[fSortCount++] = leafIndex; + } + } + else { + if ((fElemMapType[elemIndex] == fLeafListType[leafIndex]) && + (leaf->getURI() == element->getURI()) && + (XMLString::equals(leaf->getLocalPart(), element->getLocalPart()))) { + tmpSorter[fSortCount++] = leafIndex; + } + } + } + + fLeafSorter[elemIndex]=(unsigned int*)fMemoryManager->allocate((fSortCount+1) * sizeof(unsigned int)); + fLeafSorter[elemIndex][0]=fSortCount; + for (unsigned int index=0;indexdeallocate(tmpSorter); + + // + // Next lets create some arrays, some that that hold transient info + // during the DFA build and some that are permament. These are kind of + // sticky since we cannot know how big they will get, but we don't want + // to use any collection type classes because of performance. + // + // Basically they will probably be about fLeafCount*2 on average, but can + // be as large as 2^(fLeafCount*2), worst case. So we start with + // fLeafCount*4 as a middle ground. This will be very unlikely to ever + // have to expand though, it if does, the overhead will be somewhat ugly. + // + unsigned int curArraySize = fLeafCount * 4; + CMStateSet** statesToDo = (CMStateSet**) + fMemoryManager->allocate + ( + curArraySize * sizeof(CMStateSet*) + ); //new const CMStateSet*[curArraySize]; + fFinalStateFlags = (bool*) fMemoryManager->allocate + ( + curArraySize * sizeof(bool) + ); //new bool[curArraySize]; + fTransTable = (unsigned int**) fMemoryManager->allocate + ( + curArraySize * sizeof(unsigned int*) + ); //new unsigned int*[curArraySize]; + + // + // Ok we start with the initial set as the first pos set of the head node + // (which is the seq node that holds the content model and the EOC node.) + // + CMStateSet* setT = new (fMemoryManager) CMStateSet(fHeadNode->getFirstPos()); + + // + // Note on memory leak: Bugzilla#2707: + // =================================== + // The CMBinary, pointed to by fHeadNode, shall be released by + // deleted by itself. + // + // fLeafList[] maintains its **OWN** copy of CMLeaf to avoid double deletion + // of CMLeaf. + // + + delete fHeadNode; + + // + // Init our two state flags. Basically the unmarked state counter is + // always chasing the current state counter. When it catches up, that + // means we made a pass through that did not add any new states to the + // lists, at which time we are done. We could have used a expanding array + // of flags which we used to mark off states as we complete them, but + // this is easier though less readable maybe. + // + unsigned int unmarkedState = 0; + unsigned int curState = 0; + + // + // Init the first transition table entry, and put the initial state + // into the states to do list, then bump the current state. + // + fTransTable[curState] = makeDefStateList(); + statesToDo[curState] = setT; + curState++; + + // + // the stateTable is an auxiliary means to fast + // identification of new state created (instead + // of sequential loop statesToDo to find out), + // while the role that statesToDo plays remain unchanged. + // + RefHashTableOf *stateTable = + new (fMemoryManager) RefHashTableOf + ( + curArraySize + , true + , fMemoryManager + ); + //stateTable->put((CMStateSet*)setT, new (fMemoryManager) XMLInteger(0)); + + // + // Ok, almost done with the algorithm from hell... We now enter the + // loop where we go until the states done counter catches up with + // the states to do counter. + // + CMStateSet* newSet = 0; + while (unmarkedState < curState) + { + // + // Get the next unmarked state out of the list of states to do. + // And get the associated transition table entry. + // + setT = statesToDo[unmarkedState]; + unsigned int* transEntry = fTransTable[unmarkedState]; + + // Mark this one final if it contains the EOC state + fFinalStateFlags[unmarkedState] = setT->getBit(fEOCPos); + + // Bump up the unmarked state count, marking this state done + unmarkedState++; + +#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH + // Optimization(Jan, 2001) + unsigned int sorterIndex = 0; + // Optimization(Jan, 2001) +#endif + + // Loop through each possible input symbol in the element map + for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) + { + // + // Build up a set of states which is the union of all of the + // follow sets of DFA positions that are in the current state. If + // we gave away the new set last time through then create a new + // one. Otherwise, zero out the existing one. + // + if (!newSet) + newSet = new (fMemoryManager) CMStateSet + ( + fLeafCount + , fMemoryManager + ); + else + newSet->zeroBits(); + +#ifdef OBSOLETED +// unoptimized code + for (unsigned int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) + { + // If this leaf index (DFA position) is in the current set... + if (setT->getBit(leafIndex)) + { + // + // If this leaf is the current input symbol, then we want + // to add its follow list to the set of states to transition + // to from the current state. + // + const QName* leaf = fLeafList[leafIndex]->getElement(); + const QName* element = fElemMap[elemIndex]; + if (fDTD) { + if (XMLString::equals(leaf->getRawName(), element->getRawName())) { + *newSet |= *fFollowList[leafIndex]; + } + } + else { + if ((leaf->getURI() == element->getURI()) && + (XMLString::equals(leaf->getLocalPart(), element->getLocalPart()))) { + *newSet |= *fFollowList[leafIndex]; + } + } + } + } // for leafIndex +#endif + +#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH + // Optimization(Jan, 2001) + int leafIndex = fLeafSorter[sorterIndex++]; + + while (leafIndex != -1) + { + // If this leaf index (DFA position) is in the current set... + if (setT->getBit(leafIndex)) + { + // + // If this leaf is the current input symbol, then we + // want to add its follow list to the set of states to + // transition to from the current state. + // + *newSet |= *fFollowList[leafIndex]; + } + leafIndex = fLeafSorter[sorterIndex++]; + } // while (leafIndex != -1) +#endif + + unsigned int* fLeafIndexes=fLeafSorter[elemIndex]; + unsigned int fNumItems=fLeafIndexes[0]; + if(fNumItems!=0) + { + // The algorithm requires finding the leaf that is present both in the bitfield of the current state, and in the + // list of places where the currently tested item can appear. When this occurs, the follow list of this parent item + // is added to the bitfield representing the next state. + // Both the bitfield and the list of places are sorted, so we can analyze them in two ways; either iterating over the + // parent items, testing the bitfield for the existence of the parent (N times a constant Tb), or by iterating over the + // bitfield (restricted to the range of the sorted list of places), using a binary search to locate the leaf in the + // sorted list of places (M times log(N) testing operations Ts) + // Assuming that the time to test a bit is roughly the same of the time needed to compute the average of two integers, + // plus a couple of comparisons and additions, we compare N agains M*log(N) to decide which algorithm should be faster given + // the two sets + if(fNumItems <= setT->getBitCountInRange(fLeafIndexes[1], fLeafIndexes[fNumItems])*log((float)fNumItems)) + { + for(unsigned int i=1; i<=fNumItems; ++i) + if(setT->getBit(fLeafIndexes[i])) + { + // + // If this leaf is the current input symbol, then we + // want to add its follow list to the set of states to + // transition to from the current state. + // + *newSet |= *fFollowList[ fLeafIndexes[i] ]; + } + } + else + { + // Further optimization: given that the bitfield enumerator returns the numbers in order, + // every time we raise the lower marker we know it will true also for the next bits, so + // the next binary search will not start from 1 but from this index + unsigned int lowIndex = 1; + // Start the enumerator from the first index in the sorted list of places, + // as nothing before that point will match + CMStateSetEnumerator enumBits(setT, fLeafIndexes[1]); + while(enumBits.hasMoreElements()) + { + unsigned int bitIndex=enumBits.nextElement(); + // if this leaf is greater than the last index in the sorted list of places, + // nothing can be found from now on, so get out of here + if(bitIndex > fLeafIndexes[fNumItems]) + break; + + // Check if this leaf index (DFA position) is in the current set + // (using binary search: the indexes are sorted) + unsigned int first=lowIndex,last=fNumItems,i; + while(first<=last) + { + i=(first+last)/2; + if(fLeafIndexes[i]>bitIndex) + last=i-1; + else if(fLeafIndexes[i]isEmpty()) + { + // + // Search the 'states to do' list to see if this new + // state set is already in there. + // + /*** + unsigned int stateIndex = 0; + for (; stateIndex < curState; stateIndex++) + { + if (*statesToDo[stateIndex] == *newSet) + break; + } + ***/ + + XMLInteger *stateObj = stateTable->get(newSet); + unsigned int stateIndex = (stateObj == 0 ? curState : stateObj->intValue()); + + // If we did not find it, then add it + if (stateIndex == curState) + { + // + // Put this new state into the states to do and init + // a new entry at the same index in the transition + // table. + // + statesToDo[curState] = newSet; + fTransTable[curState] = makeDefStateList(); + stateTable->put + ( + newSet + , new (fMemoryManager) XMLInteger(curState) + ); + + // We now have a new state to do so bump the count + curState++; + + // + // Null out the new set to indicate we adopted it. This + // will cause the creation of a new set on the next time + // around the loop. + // + newSet = 0; + } + + // + // Now set this state in the transition table's entry for this + // element (using its index), with the DFA state we will move + // to from the current state when we see this input element. + // + transEntry[elemIndex] = stateIndex; + + // Expand the arrays if we're full + if (curState == curArraySize) + { + // + // Yikes, we overflowed the initial array size, so we've + // got to expand all of these arrays. So adjust up the + // size by 50% and allocate new arrays. + // + const unsigned int newSize = (unsigned int)(curArraySize * 1.5); + CMStateSet** newToDo = (CMStateSet**) + fMemoryManager->allocate + ( + newSize * sizeof(CMStateSet*) + ); //new const CMStateSet*[newSize]; + bool* newFinalFlags = (bool*) fMemoryManager->allocate + ( + newSize * sizeof(bool) + ); //new bool[newSize]; + unsigned int** newTransTable = (unsigned int**) + fMemoryManager->allocate + ( + newSize * sizeof(unsigned int*) + ); //new unsigned int*[newSize]; + + // Copy over all of the existing content + for (unsigned int expIndex = 0; expIndex < curArraySize; expIndex++) + { + newToDo[expIndex] = statesToDo[expIndex]; + newFinalFlags[expIndex] = fFinalStateFlags[expIndex]; + newTransTable[expIndex] = fTransTable[expIndex]; + } + + // Clean up the old stuff + fMemoryManager->deallocate(statesToDo); //delete [] statesToDo; + fMemoryManager->deallocate(fFinalStateFlags); //delete [] fFinalStateFlags; + fMemoryManager->deallocate(fTransTable); //delete [] fTransTable; + + // Store the new array size and pointers + curArraySize = newSize; + statesToDo = newToDo; + fFinalStateFlags = newFinalFlags; + fTransTable = newTransTable; + } //if (curState == curArraySize) + } //if (!newSet->isEmpty()) + } // for elemIndex + } //while + + // Store the current state count in the trans table size + fTransTableSize = curState; + + // + // Fill in the occurence information for each looping state + // if we're using counters. + // + if (elemOccurenceMap != 0) { + fCountingStates = (Occurence**)fMemoryManager->allocate(fTransTableSize*sizeof(Occurence)); + memset(fCountingStates, 0, fTransTableSize*sizeof(Occurence*)); + for (unsigned int i = 0; i < fTransTableSize; ++i) { + unsigned int * transitions = fTransTable[i]; + for (unsigned int j = 0; j < fElemMapSize; ++j) { + if (i == transitions[j]) { + Occurence* old=elemOccurenceMap[j]; + if(old!=0) + fCountingStates[i] = new (fMemoryManager) Occurence(old->minOccurs, old->maxOccurs, old->elemIndex); + break; + } + } + } + for (unsigned int j = 0; j < fLeafCount; ++j) { + if(elemOccurenceMap[j]!=0) + delete elemOccurenceMap[j]; + } + fMemoryManager->deallocate(elemOccurenceMap); + } + + // If the last temp set was not stored, then clean it up + if (newSet) + delete newSet; + + // + // Now we can clean up all of the temporary data that was needed during + // DFA build. + // + + for (index = 0; index < fLeafCount; index++) + delete fFollowList[index]; + fMemoryManager->deallocate(fFollowList); //delete [] fFollowList; + + // + // removeAll() will delete all data, XMLInteger, + // while the keys are to be deleted by the + // deletion of statesToDo. + // + delete stateTable; + + for (index = 0; index < curState; index++) + delete statesToDo[index]; + fMemoryManager->deallocate(statesToDo); //delete [] statesToDo; + + for (index = 0; index < fLeafCount; index++) + delete fLeafList[index]; + fMemoryManager->deallocate(fLeafList); //delete [] fLeafList; + +#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH + fMemoryManager->deallocate(fLeafSorter); //delete [] fLeafSorter; +#endif + for (index=0; index < fElemMapSize; index++) + fMemoryManager->deallocate(fLeafSorter[index]); + fMemoryManager->deallocate(fLeafSorter); +} + +unsigned int DFAContentModel::countLeafNodes(ContentSpecNode* const curNode) +{ + unsigned int count = 0; + + // Get the spec type of the passed node + const ContentSpecNode::NodeTypes curType = curNode->getType(); + + if ((curType & 0x0f) == ContentSpecNode::Any + || (curType & 0x0f) == ContentSpecNode::Any_Other + || (curType & 0x0f) == ContentSpecNode::Any_NS + || curType == ContentSpecNode::Leaf + || curType == ContentSpecNode::Loop) + { + count++; + } + else + { + // + // Its not a leaf, so we have to recurse its left and maybe right + // nodes. Save both values before we recurse and trash the node. + // + ContentSpecNode* leftNode = curNode->getFirst(); + ContentSpecNode* rightNode = curNode->getSecond(); + + // Detect if we have a deep tree that can be analyzed using a loop instead of recursion + unsigned int nLoopCount=0; + ContentSpecNode* cursor=curNode; + while(cursor->getType()==ContentSpecNode::Sequence && cursor->getFirst() && cursor->getFirst()->getSecond()==rightNode) + { + nLoopCount++; + cursor=cursor->getFirst(); + } + if(nLoopCount!=0) + { + count += countLeafNodes(cursor); + for(unsigned int i=0;igetType(); + + if ((curType & 0x0f) == ContentSpecNode::Any + || (curType & 0x0f) == ContentSpecNode::Any_Other + || (curType & 0x0f) == ContentSpecNode::Any_NS) + { + retNode = new (fMemoryManager) CMAny + ( + curType + , curNode->getElement()->getURI() + , curIndex + , fLeafCount + , fMemoryManager + ); + fLeafList[curIndex] = new (fMemoryManager) CMLeaf + ( + new (fMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , curNode->getElement()->getURI() + , fMemoryManager + ) + , curIndex + , true + , fLeafCount + , fMemoryManager + ); + fLeafListType[curIndex] = curType; + ++curIndex; + } + else if (curType == ContentSpecNode::Leaf) + { + // + // Create a new leaf node, and pass it the current leaf count, which + // is its DFA state position. Bump the leaf count after storing it. + // This makes the positions zero based since we store first and then + // increment. + // + retNode = new (fMemoryManager) CMLeaf + ( + curNode->getElement() + , curIndex + , fLeafCount + , fMemoryManager + ); + fLeafList[curIndex] = new (fMemoryManager) CMLeaf + ( + curNode->getElement() + , curIndex + , fLeafCount + , fMemoryManager + ); + fLeafListType[curIndex] = ContentSpecNode::Leaf; + ++curIndex; + } + else if (curType == ContentSpecNode::Loop) + { + // + // Create a new leaf node, and pass it the current leaf count, which + // is its DFA state position. Bump the leaf count after storing it. + // This makes the positions zero based since we store first and then + // increment. + // + retNode = new (fMemoryManager) CMRepeatingLeaf + ( + curNode->getFirst()->getElement() + , curNode->getMinOccurs() + , curNode->getMaxOccurs() + , curIndex + , fLeafCount + , fMemoryManager + ); + fLeafList[curIndex] = new (fMemoryManager) CMRepeatingLeaf + ( + curNode->getFirst()->getElement() + , curNode->getMinOccurs() + , curNode->getMaxOccurs() + , curIndex + , fLeafCount + , fMemoryManager + ); + fLeafListType[curIndex] = curNode->getFirst()->getType(); + ++curIndex; + } + else + { + // + // Its not a leaf, so we have to recurse its left and maybe right + // nodes. Save both values before we recurse and trash the node. + // + ContentSpecNode* leftNode = curNode->getFirst(); + ContentSpecNode* rightNode = curNode->getSecond(); + + // Detect if we have a deep tree that can be analyzed using a loop instead of recursion + unsigned int nLoopCount=0; + ContentSpecNode* cursor=curNode; + while(cursor->getType()==ContentSpecNode::Sequence && cursor->getFirst() && cursor->getFirst()->getSecond()==rightNode) + { + nLoopCount++; + cursor=cursor->getFirst(); + } + if(nLoopCount!=0) + { + retNode = buildSyntaxTree(cursor, curIndex); + for(unsigned int i=0;igetLastPos(); + const CMStateSet& first = newRight->getFirstPos(); + + // + // Now, for every position which is in our left child's last set + // add all of the states in our right child's first set to the + // follow set for that position. + // + CMStateSetEnumerator enumLast(&last); + while(enumLast.hasMoreElements()) + { + XMLSize_t index=enumLast.nextElement(); + *fFollowList[index] |= first; + } + retNode = new (fMemoryManager) CMBinaryOp + ( + ContentSpecNode::Sequence + , retNode + , newRight + , fLeafCount + , fMemoryManager + ); + } + return retNode; + } + + if (((curType & 0x0f) == ContentSpecNode::Choice) + || ((curType & 0x0f) == ContentSpecNode::Sequence)) + { + // + // Recurse on both children, and return a binary op node with the + // two created sub nodes as its children. The node type is the + // same type as the source. + // + CMNode* newLeft = buildSyntaxTree(leftNode, curIndex); + CMNode* newRight = buildSyntaxTree(rightNode, curIndex); + if(((curType & 0x0f) == ContentSpecNode::Sequence)) + { + // + // Now handle our level. We use our left child's last pos set and our + // right child's first pos set, so get them now for convenience. + // + const CMStateSet& last = newLeft->getLastPos(); + const CMStateSet& first = newRight->getFirstPos(); + + // + // Now, for every position which is in our left child's last set + // add all of the states in our right child's first set to the + // follow set for that position. + // + CMStateSetEnumerator enumLast(&last); + while(enumLast.hasMoreElements()) + { + XMLSize_t index=enumLast.nextElement(); + *fFollowList[index] |= first; + } + } + retNode = new (fMemoryManager) CMBinaryOp + ( + curType + , newLeft + , newRight + , fLeafCount + , fMemoryManager + ); + } + else if (curType == ContentSpecNode::ZeroOrMore + || curType == ContentSpecNode::ZeroOrOne + || curType == ContentSpecNode::OneOrMore) + { + CMNode* newChild = buildSyntaxTree(leftNode, curIndex); + if (curType == ContentSpecNode::ZeroOrMore + || curType == ContentSpecNode::OneOrMore) + { + // + // Now handle our level. We use our own first and last position + // sets, so get them up front. + // + const CMStateSet& first = newChild->getFirstPos(); + const CMStateSet& last = newChild->getLastPos(); + + // + // For every position which is in our last position set, add all + // of our first position states to the follow set for that + // position. + // + CMStateSetEnumerator enumLast(&last); + while(enumLast.hasMoreElements()) + { + XMLSize_t index=enumLast.nextElement(); + *fFollowList[index] |= first; + } + } + // This one is fine as is, just change to our form + retNode = new (fMemoryManager) CMUnaryOp + ( + curType + , newChild + , fLeafCount + , fMemoryManager + ); + } + else + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager); + } + } + // fault in the first and last pos, then delete it children + retNode->getFirstPos(); + retNode->getLastPos(); + retNode->orphanChild(); + return retNode; +} + +// +// gInvalidTrans is used to represent bad transitions in the transition table +// entry for each state. So each entry is initialized to that value. This +// method creates a new entry and initializes it. +// +unsigned int* DFAContentModel::makeDefStateList() const +{ + unsigned int* retArray = (unsigned int*) fMemoryManager->allocate + ( + fElemMapSize * sizeof(unsigned int) + ); //new unsigned int[fElemMapSize]; + for (unsigned int index = 0; index < fElemMapSize; index++) + retArray[index] = XMLContentModel::gInvalidTrans; + return retArray; +} + +ContentLeafNameTypeVector* DFAContentModel::getContentLeafNameTypeVector() const +{ + //later change it to return the data member + return fLeafNameTypeVector; +} + +void DFAContentModel::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); + + unsigned int i, j, k; + + // Rename the URI back + for (i = 0; i < fElemMapSize; i++) { + + unsigned int orgURIIndex = fElemMap[i]->getURI(); + + if ((orgURIIndex != XMLContentModel::gEOCFakeId) && + (orgURIIndex != XMLContentModel::gEpsilonFakeId) && + (orgURIIndex != XMLElementDecl::fgInvalidElemId) && + (orgURIIndex != XMLElementDecl::fgPCDataElemId)) { + fElemMap[i]->setURI(pContentSpecOrgURI[orgURIIndex]); + } + } + + // Unique Particle Attribution + // Store the conflict results between any two elements in fElemMap + // 0 - not yet tested, 1 - conflict, (-1) - no conflict + signed char** conflictTable = (signed char**) fMemoryManager->allocate + ( + fElemMapSize * sizeof(signed char*) + ); + + // initialize the conflict table + for (j = 0; j < fElemMapSize; j++) { + conflictTable[j] = (signed char*) fMemoryManager->allocate + ( + fElemMapSize * sizeof(signed char) + ); + memset(conflictTable[j], 0, fElemMapSize*sizeof(signed char)); + } + + // for each state, check whether it has overlap transitions + for (i = 0; i < fTransTableSize; i++) { + for (j = 0; j < fElemMapSize; j++) { + for (k = j+1; k < fElemMapSize; k++) { + if (fTransTable[i][j] != XMLContentModel::gInvalidTrans && + fTransTable[i][k] != XMLContentModel::gInvalidTrans && + conflictTable[j][k] == 0) { + + // If this is text in a Schema mixed content model, skip it. + if ( fIsMixed && + (( fElemMap[j]->getURI() == XMLElementDecl::fgPCDataElemId) || + ( fElemMap[k]->getURI() == XMLElementDecl::fgPCDataElemId))) + continue; + + if (XercesElementWildcard::conflict(pGrammar, + fElemMapType[j], + fElemMap[j], + fElemMapType[k], + fElemMap[k], + &comparator)) { + if (fCountingStates != 0) { + Occurence* o = fCountingStates[i]; + // If "i" is a counting state and exactly one of the transitions + // loops back to "i" then the two particles do not overlap if + // minOccurs == maxOccurs. + if (o != 0 && + ((fTransTable[i][j] == i) ^ (fTransTable[i][k] == i)) && + o->minOccurs == o->maxOccurs) { + conflictTable[j][k] = -1; + continue; + } + } + conflictTable[j][k] = 1; + + XMLBuffer buf1(1023, fMemoryManager); + if (((fElemMapType[j] & 0x0f) == ContentSpecNode::Any) || + ((fElemMapType[j] & 0x0f) == ContentSpecNode::Any_NS)) + buf1.set(SchemaSymbols::fgATTVAL_TWOPOUNDANY); + else if ((fElemMapType[j] & 0x0f) == ContentSpecNode::Any_Other) + buf1.set(SchemaSymbols::fgATTVAL_TWOPOUNDOTHER); + else + buf1.set(fElemMap[j]->getRawName()); + + XMLBuffer buf2(1023, fMemoryManager); + if (((fElemMapType[k] & 0x0f) == ContentSpecNode::Any) || + ((fElemMapType[k] & 0x0f) == ContentSpecNode::Any_NS)) + buf2.set(SchemaSymbols::fgATTVAL_TWOPOUNDANY); + else if ((fElemMapType[k] & 0x0f) == ContentSpecNode::Any_Other) + buf2.set(SchemaSymbols::fgATTVAL_TWOPOUNDOTHER); + else + buf2.set(fElemMap[k]->getRawName()); + + pValidator->emitError(XMLValid::UniqueParticleAttributionFail, + pComplexTypeName, + buf1.getRawBuffer(), + buf2.getRawBuffer()); + } + else + conflictTable[j][k] = -1; + } + } + } + } + + for (i = 0; i < fElemMapSize; i++) + fMemoryManager->deallocate(conflictTable[i]); + fMemoryManager->deallocate(conflictTable); +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/common/DFAContentModel.hpp b/include/xercesc/validators/common/DFAContentModel.hpp new file mode 100644 index 0000000..dcb583d --- /dev/null +++ b/include/xercesc/validators/common/DFAContentModel.hpp @@ -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 +#include +#include +#include + +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 + diff --git a/include/xercesc/validators/common/Grammar.cpp b/include/xercesc/validators/common/Grammar.cpp new file mode 100644 index 0000000..40bac4a --- /dev/null +++ b/include/xercesc/validators/common/Grammar.cpp @@ -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 + +//since we need to dynamically created each and every derivatives +//during deserialization by XSerializeEngine>>Derivative, we got +//to include all hpp + +#include +#include +#include + +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<>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 diff --git a/include/xercesc/validators/common/Grammar.hpp b/include/xercesc/validators/common/Grammar.hpp new file mode 100644 index 0000000..bf73c47 --- /dev/null +++ b/include/xercesc/validators/common/Grammar.hpp @@ -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 + +#include +#include +#include + +#include + +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 diff --git a/include/xercesc/validators/common/GrammarResolver.cpp b/include/xercesc/validators/common/GrammarResolver.cpp new file mode 100644 index 0000000..94ec102 --- /dev/null +++ b/include/xercesc/validators/common/GrammarResolver.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +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(29, true, manager); + + /*** + * Grammars in this set are not owned + */ + fGrammarFromPool = new (manager) RefHashTableOf(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 (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 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 +GrammarResolver::getGrammarEnumerator() const +{ + return RefHashTableOfEnumerator(fGrammarBucket, false, fMemoryManager); +} + +RefHashTableOfEnumerator +GrammarResolver::getReferencedGrammarEnumerator() const +{ + return RefHashTableOfEnumerator(fGrammarFromPool, false, fMemoryManager); +} + +RefHashTableOfEnumerator +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 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 grammarEnum(fGrammarBucket, false, fMemoryManager); + ValueVectorOf 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 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 diff --git a/include/xercesc/validators/common/GrammarResolver.hpp b/include/xercesc/validators/common/GrammarResolver.hpp new file mode 100644 index 0000000..6c86eda --- /dev/null +++ b/include/xercesc/validators/common/GrammarResolver.hpp @@ -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 +#include +#include +#include + +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 getGrammarEnumerator() const; + + /** + * Get an enumeration of the referenced Grammars + * + * @return enumeration of referenced Grammars + */ + RefHashTableOfEnumerator getReferencedGrammarEnumerator() const; + + /** + * Get an enumeration of the cached Grammars in the Grammar pool + * + * @return enumeration of the cached Grammars in Grammar pool + */ + RefHashTableOfEnumerator 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* 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* fGrammarBucket; + RefHashTableOf* fGrammarFromPool; + DatatypeValidatorFactory* fDataTypeReg; + MemoryManager* fMemoryManager; + XMLGrammarPool* fGrammarPool; + XSModel* fXSModel; + XSModel* fGrammarPoolXSModel; + ValueVectorOf* 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* GrammarResolver::getGrammarsToAddToXSModel() +{ + return fGrammarsToAddToXSModel; +} + +inline DatatypeValidatorFactory* GrammarResolver::getBuiltinDatatypeValidatorFactory() +{ + return fDataTypeReg; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/common/MixedContentModel.cpp b/include/xercesc/validators/common/MixedContentModel.cpp new file mode 100644 index 0000000..d5d726e --- /dev/null +++ b/include/xercesc/validators/common/MixedContentModel.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 children(64, fMemoryManager); + ValueVectorOf 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& toFill + , ValueVectorOf& 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 diff --git a/include/xercesc/validators/common/MixedContentModel.hpp b/include/xercesc/validators/common/MixedContentModel.hpp new file mode 100644 index 0000000..c11f9e3 --- /dev/null +++ b/include/xercesc/validators/common/MixedContentModel.hpp @@ -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 +#include +#include + +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: +// +// +// +// 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& toFill + , ValueVectorOf& 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 always 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 diff --git a/include/xercesc/validators/common/SimpleContentModel.cpp b/include/xercesc/validators/common/SimpleContentModel.cpp new file mode 100644 index 0000000..9fd0a49 --- /dev/null +++ b/include/xercesc/validators/common/SimpleContentModel.cpp @@ -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 +#include +#include +#include +#include + +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 + diff --git a/include/xercesc/validators/common/SimpleContentModel.hpp b/include/xercesc/validators/common/SimpleContentModel.hpp new file mode 100644 index 0000000..36be0d8 --- /dev/null +++ b/include/xercesc/validators/common/SimpleContentModel.hpp @@ -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 +#include + +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 diff --git a/include/xercesc/validators/datatype/AbstractNumericFacetValidator.cpp b/include/xercesc/validators/datatype/AbstractNumericFacetValidator.cpp new file mode 100644 index 0000000..4e27a2d --- /dev/null +++ b/include/xercesc/validators/datatype/AbstractNumericFacetValidator.cpp @@ -0,0 +1,972 @@ +/* + * 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: AbstractNumericFacetValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +//since we need to dynamically created each and every derivatives +//during deserialization by XSerializeEngine>>Derivative, we got +//to include all hpp +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +const int AbstractNumericFacetValidator::INDETERMINATE = 2; + +#define REPORT_FACET_ERROR(val1, val2, except_code, manager) \ + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException \ + , except_code \ + , val1->getFormattedString() \ + , val2->getFormattedString() \ + , manager); + +#define FROM_BASE_VALUE_SPACE(val, facetFlag, except_code, manager) \ + if ((thisFacetsDefined & facetFlag) != 0) \ +{ \ + try \ +{ \ + numBase->checkContent(val->getRawData(), (ValidationContext*)0, false, manager); \ +} \ + catch ( XMLException& ) \ +{ \ + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException \ + , except_code \ + , val->getRawData() \ + , manager); \ +} \ +} + + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +AbstractNumericFacetValidator::~AbstractNumericFacetValidator() +{ + if (!fMaxInclusiveInherited && fMaxInclusive) + delete fMaxInclusive; + + if (!fMaxExclusiveInherited && fMaxExclusive) + delete fMaxExclusive; + + if (!fMinInclusiveInherited && fMinInclusive) + delete fMinInclusive; + + if (!fMinExclusiveInherited && fMinExclusive) + delete fMinExclusive; + + //~RefVectorOf will delete all adopted elements + if (!fEnumerationInherited && fEnumeration) + delete fEnumeration; + + if (!fEnumerationInherited && fStrEnumeration) + delete fStrEnumeration; +} + +AbstractNumericFacetValidator::AbstractNumericFacetValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:DatatypeValidator(baseValidator, facets, finalSet, type, manager) +, fMaxInclusiveInherited(false) +, fMaxExclusiveInherited(false) +, fMinInclusiveInherited(false) +, fMinExclusiveInherited(false) +, fEnumerationInherited(false) +, fMaxInclusive(0) +, fMaxExclusive(0) +, fMinInclusive(0) +, fMinExclusive(0) +, fEnumeration(0) +, fStrEnumeration(0) +{ + //do not invoke init() here !!! +} + +// +// P1. Enumeration +// +void AbstractNumericFacetValidator::init(RefArrayVectorOf* const enums + , MemoryManager* const manager) +{ + + fStrEnumeration = enums; // save the literal value + // which is needed for getEnumString() + + if (enums) + { + setFacetsDefined(DatatypeValidator::FACET_ENUMERATION); + } + + assignFacet(manager); + inspectFacet(manager); + inspectFacetBase(manager); + inheritFacet(); +} + +// +// Assign facets +// assign common facets +// assign additional facet +// +void AbstractNumericFacetValidator::assignFacet(MemoryManager* const manager) +{ + + RefHashTableOf* facets = getFacets(); + + if (!facets) // no facets defined + return; + + XMLCh* key; + + RefHashTableOfEnumerator e(facets, false, manager); + + while (e.hasMoreElements()) + { + KVStringPair pair = e.nextElement(); + key = pair.getKey(); + XMLCh* value = pair.getValue(); + + if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN)) + { + setPattern(value); + if (getPattern()) + setFacetsDefined(DatatypeValidator::FACET_PATTERN); + // do not construct regex until needed + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MAXINCLUSIVE)) + { + try + { + setMaxInclusive(value); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_MaxIncl, value, manager); + } + setFacetsDefined(DatatypeValidator::FACET_MAXINCLUSIVE); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MAXEXCLUSIVE)) + { + try + { + setMaxExclusive(value); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_MaxExcl, value, manager); + } + setFacetsDefined(DatatypeValidator::FACET_MAXEXCLUSIVE); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MININCLUSIVE)) + { + try + { + setMinInclusive(value); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_MinIncl, value, manager); + } + setFacetsDefined(DatatypeValidator::FACET_MININCLUSIVE); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MINEXCLUSIVE)) + { + try + { + setMinExclusive(value); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_MinExcl, value, manager); + } + setFacetsDefined(DatatypeValidator::FACET_MINEXCLUSIVE); + } + else if (XMLString::equals(key, SchemaSymbols::fgATT_FIXED)) + { + unsigned int val; + bool retStatus; + try + { + retStatus = XMLString::textToBin(value, val, fMemoryManager); + } + catch (RuntimeException&) + { + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_internalError_fixed, manager); + } + + if (!retStatus) + { + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_internalError_fixed, manager); + } + + setFixed(val); + //no setFacetsDefined here + + } + else + { + assignAdditionalFacet(key, value, manager); + } + + }//while + +}// end of assigneFacet() + +// +// Check facet among self +// check common facets +// check Additional Facet Constraint +// +void AbstractNumericFacetValidator::inspectFacet(MemoryManager* const manager) +{ + + int thisFacetsDefined = getFacetsDefined(); + XMLNumber *thisMaxInclusive = getMaxInclusive(); + XMLNumber *thisMaxExclusive = getMaxExclusive(); + XMLNumber *thisMinInclusive = getMinInclusive(); + XMLNumber *thisMinExclusive = getMinExclusive(); + + if (!thisFacetsDefined) + return; + + // non co-existence checking + // check 4.3.8.c1 error: maxInclusive + maxExclusive + if (((thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) ) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_max_Incl_Excl, manager); + + // non co-existence checking + // check 4.3.9.c1 error: minInclusive + minExclusive + if (((thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) ) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_min_Incl_Excl, manager); + + // + // minExclusive < minInclusive <= maxInclusive < maxExclusive + // + // check 4.3.7.c1 must: minInclusive <= maxInclusive + if (((thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) ) + { + int result = compareValues(thisMinInclusive, thisMaxInclusive); + if ( result == 1 || result == INDETERMINATE ) + { + REPORT_FACET_ERROR(thisMinInclusive + , thisMaxInclusive + , XMLExcepts::FACET_maxIncl_minIncl + , manager) + } + } + + // check 4.3.8.c2 must: minExclusive <= maxExclusive + if ( ((thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) ) + { + int result = compareValues(getMinExclusive(), getMaxExclusive()); + if ( result == 1 || result == INDETERMINATE ) + { + REPORT_FACET_ERROR(thisMinExclusive + , thisMaxExclusive + , XMLExcepts::FACET_maxExcl_minExcl + , manager) + } + } + + // check 4.3.9.c2 must: minExclusive < maxInclusive + if ( ((thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) ) + { + int result = compareValues(getMinExclusive(), getMaxInclusive()); + if ( result != -1 ) + { + REPORT_FACET_ERROR(thisMinExclusive + , thisMaxInclusive + , XMLExcepts::FACET_maxIncl_minExcl + , manager) + } + } + + // check 4.3.10.c1 must: minInclusive < maxExclusive + if ( ((thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) ) + { + int result = compareValues(getMinInclusive(), getMaxExclusive()); + if ( result != -1) + { + REPORT_FACET_ERROR(thisMinInclusive + , thisMaxExclusive + , XMLExcepts::FACET_maxExcl_minIncl + , manager) + } + } + + checkAdditionalFacetConstraints(manager); + +}// end of inspectFacet() + +// +// Check vs base +// check common facets +// check enumeration +// check Additional Facet Constraint +// +void AbstractNumericFacetValidator::inspectFacetBase(MemoryManager* const manager) +{ + + AbstractNumericFacetValidator* numBase = (AbstractNumericFacetValidator*) getBaseValidator(); + int thisFacetsDefined = getFacetsDefined(); + + if ( (!thisFacetsDefined && !fEnumeration) || + !numBase ) + return; + + int baseFacetsDefined = numBase->getFacetsDefined(); + + XMLNumber *thisMaxInclusive = getMaxInclusive(); + XMLNumber *thisMaxExclusive = getMaxExclusive(); + XMLNumber *thisMinInclusive = getMinInclusive(); + XMLNumber *thisMinExclusive = getMinExclusive(); + + XMLNumber *baseMaxInclusive = numBase->getMaxInclusive(); + XMLNumber *baseMaxExclusive = numBase->getMaxExclusive(); + XMLNumber *baseMinInclusive = numBase->getMinInclusive(); + XMLNumber *baseMinExclusive = numBase->getMinExclusive(); + int baseFixed = numBase->getFixed(); + + // this + // minExclusive maxExclusive + // minInclusive maxInclusive + // + // base + // minExclusive maxExclusive + // minInclusive maxInclusive + // + + // check 4.3.7.c2 error: + // maxInclusive > base.maxInclusive && maxInclusive != base.maxInclusive if (base.fixed) + // maxInclusive >= base.maxExclusive + // maxInclusive < base.minInclusive + // maxInclusive <= base.minExclusive + + if ((thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) + { + if ((baseFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) + { + int result = compareValues(thisMaxInclusive, baseMaxInclusive); + + if (((baseFixed & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) && + (result != 0 )) + { + REPORT_FACET_ERROR(thisMaxInclusive + , baseMaxInclusive + , XMLExcepts::FACET_maxIncl_base_fixed + , manager) + } + + if (result == 1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMaxInclusive + , baseMaxInclusive + , XMLExcepts::FACET_maxIncl_base_maxIncl + , manager) + } + + } + + if ((baseFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) + { + int result = compareValues(thisMaxInclusive, baseMaxExclusive); + if (result != -1 ) + { + REPORT_FACET_ERROR(thisMaxInclusive + , baseMaxExclusive + , XMLExcepts::FACET_maxIncl_base_maxExcl + , manager) + } + } + + + if ((baseFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) + { + int result = compareValues(thisMaxInclusive, baseMinInclusive); + if (result == -1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMaxInclusive + , baseMinInclusive + , XMLExcepts::FACET_maxIncl_base_minIncl + , manager) + } + } + + if ((baseFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) + { + int result = compareValues(thisMaxInclusive, baseMinExclusive); + if (result != 1 ) + { + REPORT_FACET_ERROR(thisMaxInclusive + , baseMinExclusive + , XMLExcepts::FACET_maxIncl_base_minExcl + , manager) + } + } + + } + + // check 4.3.8.c3 error: + // maxExclusive > base.maxExclusive && maxExclusive != base.maxExclusive if (base.fixed) + // maxExclusive > base.maxInclusive + // maxExclusive <= base.minInclusive + // maxExclusive <= base.minExclusive + + if ((thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) + { + if (( baseFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) + { + int result = compareValues(thisMaxExclusive, baseMaxExclusive); + + if (((baseFixed & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) && + (result != 0 )) + { + REPORT_FACET_ERROR(thisMaxExclusive + , baseMaxExclusive + , XMLExcepts::FACET_maxExcl_base_fixed + , manager) + } + + if (result == 1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMaxExclusive + , baseMaxExclusive + , XMLExcepts::FACET_maxExcl_base_maxExcl + , manager) + } + + /** + * Schema Errata + * E2-16 maxExclusive + * + * derived type's maxExclusive must either be + * 1) equal to base' maxExclusive or + * 2) from the base type value space + * + */ + if (result != 0) + { + FROM_BASE_VALUE_SPACE(thisMaxExclusive + , DatatypeValidator::FACET_MAXEXCLUSIVE + , XMLExcepts::FACET_maxExcl_notFromBase + , manager) + } + } + else // base has no maxExclusive + { + FROM_BASE_VALUE_SPACE(thisMaxExclusive + , DatatypeValidator::FACET_MAXEXCLUSIVE + , XMLExcepts::FACET_maxExcl_notFromBase + , manager) + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) + { + int result = compareValues(thisMaxExclusive, baseMaxInclusive); + if (result == 1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMaxExclusive + , baseMaxInclusive + , XMLExcepts::FACET_maxExcl_base_maxIncl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) + { + int result = compareValues(thisMaxExclusive, baseMinExclusive); + if (result != 1) + { + REPORT_FACET_ERROR(thisMaxExclusive + , baseMinExclusive + , XMLExcepts::FACET_maxExcl_base_minExcl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) + { + int result = compareValues(thisMaxExclusive, baseMinInclusive); + if (result != 1) + { + REPORT_FACET_ERROR(thisMaxExclusive + , baseMinInclusive + , XMLExcepts::FACET_maxExcl_base_minIncl + , manager) + } + } + } + + // check 4.3.9.c3 error: + // minExclusive < base.minExclusive minExclusive != base.minExclusive if (base.fixed) + // minExclusive > base.maxInclusive ??? minExclusive >= base.maxInclusive + // minExclusive < base.minInclusive + // minExclusive >= base.maxExclusive + + if ((thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) + { + if (( baseFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) + { + int result = compareValues(thisMinExclusive, baseMinExclusive); + + if (((baseFixed & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) && + (result != 0 )) + { + REPORT_FACET_ERROR(thisMinExclusive + , baseMinExclusive + , XMLExcepts::FACET_minExcl_base_fixed + , manager) + } + + if (result == -1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMinExclusive + , baseMinExclusive + , XMLExcepts::FACET_minExcl_base_minExcl + , manager) + } + + /** + * Schema Errata + * E2-16 maxExclusive + * + * derived type's minExclusive must either be + * 1) equal to base' minxExclusive or + * 2) from the base type value space + * + * Note: deduced from, not explicitly expressed in the Errata + */ + if (result != 0) + { + FROM_BASE_VALUE_SPACE(thisMinExclusive + , DatatypeValidator::FACET_MINEXCLUSIVE + , XMLExcepts::FACET_minExcl_notFromBase + , manager) + } + } + else // base has no minExclusive + { + + FROM_BASE_VALUE_SPACE(thisMinExclusive + , DatatypeValidator::FACET_MINEXCLUSIVE + , XMLExcepts::FACET_minExcl_notFromBase + , manager) + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) + { + int result = compareValues(thisMinExclusive, baseMaxInclusive); + if (result == 1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMinExclusive + , baseMaxInclusive + , XMLExcepts::FACET_minExcl_base_maxIncl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) + { + int result = compareValues(thisMinExclusive, baseMinInclusive); + if (result == -1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMinExclusive + , baseMinInclusive + , XMLExcepts::FACET_minExcl_base_minIncl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) + { + int result = compareValues(thisMinExclusive, baseMaxExclusive); + if (result != -1) + { + REPORT_FACET_ERROR(thisMinExclusive + , baseMaxExclusive + , XMLExcepts::FACET_minExcl_base_maxExcl + , manager) + } + } + + } + + // check 4.3.10.c2 error: + // minInclusive < base.minInclusive minInclusive != base.minInclusive if (base.fixed) + // minInclusive > base.maxInclusive + // minInclusive <= base.minExclusive + // minInclusive >= base.maxExclusive + + + if ((thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) + { + if ((baseFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) + { + int result = compareValues(thisMinInclusive, baseMinInclusive); + + if (((baseFixed & DatatypeValidator::FACET_MININCLUSIVE) != 0) && + (result != 0 )) + { + REPORT_FACET_ERROR(thisMinInclusive + , baseMinInclusive + , XMLExcepts::FACET_minIncl_base_fixed + , manager) + } + + if (result == -1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMinInclusive + , baseMinInclusive + , XMLExcepts::FACET_minIncl_base_minIncl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) + { + int result = compareValues(thisMinInclusive, baseMaxInclusive); + if (result == 1 || result == INDETERMINATE) + { + REPORT_FACET_ERROR(thisMinInclusive + , baseMaxInclusive + , XMLExcepts::FACET_minIncl_base_maxIncl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) + { + int result = compareValues(thisMinInclusive, baseMinExclusive); + if (result != 1) + { + REPORT_FACET_ERROR(thisMinInclusive + , baseMinExclusive + , XMLExcepts::FACET_minIncl_base_minExcl + , manager) + } + } + + if (( baseFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) + { + int result = compareValues(thisMinInclusive, baseMaxExclusive); + if (result != -1) + { + REPORT_FACET_ERROR(thisMinInclusive + , baseMaxExclusive + , XMLExcepts::FACET_minIncl_base_maxExcl + , manager) + } + } + + } + + checkAdditionalFacetConstraintsBase(manager); + + // check 4.3.5.c0 must: enumeration values from the value space of base + // + // In fact, the values in the enumeration shall go through validation + // of this class as well. + // this->checkContent(value, false); + // + if ( ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0) && + ( fStrEnumeration )) + { + setEnumeration(manager); + } + + // + // maxInclusive, maxExclusive, minInclusive and minExclusive + // shall come from the base's value space as well + // + + FROM_BASE_VALUE_SPACE(thisMaxInclusive + , DatatypeValidator::FACET_MAXINCLUSIVE + , XMLExcepts::FACET_maxIncl_notFromBase + , manager) + + FROM_BASE_VALUE_SPACE(thisMinInclusive + , DatatypeValidator::FACET_MININCLUSIVE + , XMLExcepts::FACET_minIncl_notFromBase + , manager) + +} //end of inspectFacetBase + +// +// Inherit facet from base +// a. inherit common facets +// b. inherit additional facet +// +void AbstractNumericFacetValidator::inheritFacet() +{ + + AbstractNumericFacetValidator* numBase = (AbstractNumericFacetValidator*) getBaseValidator(); + if (!numBase) + return; + + int thisFacetsDefined = getFacetsDefined(); + int baseFacetsDefined = numBase->getFacetsDefined(); + + // inherit enumeration + if ((( baseFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) == 0)) + { + fEnumeration = numBase->fEnumeration; + fEnumerationInherited = true; + setFacetsDefined(DatatypeValidator::FACET_ENUMERATION); + } + + // inherit maxInclusive + if ((( baseFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) == 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) == 0) ) + { + fMaxInclusive = numBase->getMaxInclusive(); + fMaxInclusiveInherited = true; + setFacetsDefined(DatatypeValidator::FACET_MAXINCLUSIVE); + } + + // inherit maxExclusive + if ((( baseFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) == 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) == 0) ) + { + fMaxExclusive = numBase->getMaxExclusive(); + fMaxExclusiveInherited = true; + setFacetsDefined(DatatypeValidator::FACET_MAXEXCLUSIVE); + } + + // inherit minExclusive + if ((( baseFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) == 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) == 0) ) + { + fMinInclusive = numBase->getMinInclusive(); + fMinInclusiveInherited = true; + setFacetsDefined(DatatypeValidator::FACET_MININCLUSIVE); + } + + // inherit minExclusive + if ((( baseFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) == 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) == 0) ) + { + fMinExclusive = numBase->getMinExclusive(); + fMinExclusiveInherited = true; + setFacetsDefined(DatatypeValidator::FACET_MINEXCLUSIVE); + } + + inheritAdditionalFacet(); + + // inherit "fixed" option + setFixed(getFixed() | numBase->getFixed()); + +} + +const RefArrayVectorOf* AbstractNumericFacetValidator::getEnumString() const +{ + return (fEnumerationInherited? getBaseValidator()->getEnumString() : fStrEnumeration ); +} + + +void AbstractNumericFacetValidator::checkAdditionalFacetConstraints(MemoryManager* const) const +{ + return; +} + +void AbstractNumericFacetValidator::checkAdditionalFacetConstraintsBase(MemoryManager* const) const +{ + return; +} + +void AbstractNumericFacetValidator::inheritAdditionalFacet() +{ + return; +} + +void AbstractNumericFacetValidator::assignAdditionalFacet( const XMLCh* const key + , const XMLCh* const + , MemoryManager* const manager) +{ + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , key + , manager); +} + + + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(AbstractNumericFacetValidator) + +/*** + * This dv needs to serialize/deserialize four boundary data members + * which are derivatives of XMLlNumber. + * The derivatives of this class, namely, Deciamldv, Doubledv, Floatdv and + * DateTimedv needs to write a typeEnum into the binary data stream, so + * during loading, this method reads the typeEnum first, and then instantiate + * the right type of objects, say XMLDouble, XMLFloat, XMLBigDecimal and + * XMLDateTime. + * + * + ***/ +void AbstractNumericFacetValidator::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + + /*** + * don't move this line out of the if statement, + * it is done purposely to allow AbstractNumericFacetValidator + * read the number type information before DatatypeValidator + * during loading + ***/ + DatatypeValidator::serialize(serEng); + + // need not write type info for the XMLNumber since + // the derivative class has done that + storeClusive(serEng, fMaxInclusiveInherited, fMaxInclusive); + storeClusive(serEng, fMaxExclusiveInherited, fMaxExclusive); + storeClusive(serEng, fMinInclusiveInherited, fMinInclusive); + storeClusive(serEng, fMinExclusiveInherited, fMinExclusive); + + serEng< + * Serialize RefVectorOf + ***/ + XTemplateSerializer::storeObject(fStrEnumeration, serEng); + XTemplateSerializer::storeObject(fEnumeration, serEng); + + } + else + { + // Read the number type info for the XMLNumber FIRST!!! + int nType; + XMLNumber::NumberType numType; + serEng>>nType; + numType = (XMLNumber::NumberType) nType; + + DatatypeValidator::serialize(serEng); + + loadClusive(serEng, fMaxInclusiveInherited, fMaxInclusive, numType, 1); + loadClusive(serEng, fMaxExclusiveInherited, fMaxExclusive, numType, 2); + loadClusive(serEng, fMinInclusiveInherited, fMinInclusive, numType, 3); + loadClusive(serEng, fMinExclusiveInherited, fMinExclusive, numType, 4); + + serEng>>fEnumerationInherited; + + /*** + * Deserialize RefArrayVectorOf + * Deserialize RefVectorOf + ***/ + XTemplateSerializer::loadObject(&fStrEnumeration, 8, true, serEng); + XTemplateSerializer::loadObject(&fEnumeration, 8, true, numType, serEng); + + } + +} + +// +// A user defined dv may inherit any of the Max/Min/Inc/Exc from a +// built dv, which will create its own Max/Min/Inc/Exc during the +// loading. Therefore if the user defined store and load this +// facet, and does not own it, that will cause leakage. +// +// To avoid checking if the facet belongs to a builtIn dv or not, we +// do this way, for any inherited *clusive, we will not store it, and later +// on during loading, we get it from the base dv. +// +void AbstractNumericFacetValidator::storeClusive(XSerializeEngine& serEng + , bool inherited + , XMLNumber* data) +{ + serEng<>inherited; + + if (!inherited) + data = XMLNumber::loadNumber(numType, serEng); + else + { + AbstractNumericFacetValidator* basedv = (AbstractNumericFacetValidator*) getBaseValidator(); + + switch(flag) + { + case 1: + data = basedv->getMaxInclusive(); + break; + case 2: + data = basedv->getMaxExclusive(); + break; + case 3: + data = basedv->getMinInclusive(); + break; + case 4: + data = basedv->getMinExclusive(); + break; + default: + break; + } + + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file AbstractNumericFacetValidator::cpp + */ diff --git a/include/xercesc/validators/datatype/AbstractNumericFacetValidator.hpp b/include/xercesc/validators/datatype/AbstractNumericFacetValidator.hpp new file mode 100644 index 0000000..855a09e --- /dev/null +++ b/include/xercesc/validators/datatype/AbstractNumericFacetValidator.hpp @@ -0,0 +1,201 @@ +/* + * 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: AbstractNumericFacetValidator.hpp 673155 2008-07-01 17:55:39Z dbertoni $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ABSTRACT_NUMERIC_FACET_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ABSTRACT_NUMERIC_FACET_VALIDATOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT AbstractNumericFacetValidator : public DatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructor. */ + //@{ + + virtual ~AbstractNumericFacetValidator(); + + //@} + + virtual const RefArrayVectorOf* getEnumString() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(AbstractNumericFacetValidator) + +protected: + + AbstractNumericFacetValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + void init(RefArrayVectorOf* const enums + , MemoryManager* const manager); + + // + // Abstract interface + // + virtual void assignAdditionalFacet(const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager); + + virtual void inheritAdditionalFacet(); + + virtual void checkAdditionalFacetConstraints(MemoryManager* const manager) const; + + virtual void checkAdditionalFacetConstraintsBase(MemoryManager* const manager) const; + + virtual int compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue) = 0; + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) = 0; + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- + + virtual void setMaxInclusive(const XMLCh* const) = 0; + + virtual void setMaxExclusive(const XMLCh* const) = 0; + + virtual void setMinInclusive(const XMLCh* const) = 0; + + virtual void setMinExclusive(const XMLCh* const) = 0; + + virtual void setEnumeration(MemoryManager* const manager) = 0; + + static const int INDETERMINATE; + +public: +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + + inline XMLNumber* getMaxInclusive() const; + + inline XMLNumber* getMaxExclusive() const; + + inline XMLNumber* getMinInclusive() const; + + inline XMLNumber* getMinExclusive() const; + + inline RefVectorOf* getEnumeration() const; + +protected: + // ----------------------------------------------------------------------- + // Protected data members + // + // Allow access to derived class + // + // ----------------------------------------------------------------------- + bool fMaxInclusiveInherited; + bool fMaxExclusiveInherited; + bool fMinInclusiveInherited; + bool fMinExclusiveInherited; + bool fEnumerationInherited; + + XMLNumber* fMaxInclusive; + XMLNumber* fMaxExclusive; + XMLNumber* fMinInclusive; + XMLNumber* fMinExclusive; + + RefVectorOf* fEnumeration; // save the actual value + RefArrayVectorOf* fStrEnumeration; + +private: + + void assignFacet(MemoryManager* const manager); + + void inspectFacet(MemoryManager* const manager); + + void inspectFacetBase(MemoryManager* const manager); + + void inheritFacet(); + + void storeClusive(XSerializeEngine& + , bool + , XMLNumber*); + + void loadClusive(XSerializeEngine& + , bool& + , XMLNumber*& + , XMLNumber::NumberType + , int ); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + AbstractNumericFacetValidator(const AbstractNumericFacetValidator&); + AbstractNumericFacetValidator& operator=(const AbstractNumericFacetValidator&); +}; + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + +inline XMLNumber* AbstractNumericFacetValidator::getMaxInclusive() const +{ + return fMaxInclusive; +} + +inline XMLNumber* AbstractNumericFacetValidator::getMaxExclusive() const +{ + return fMaxExclusive; +} + +inline XMLNumber* AbstractNumericFacetValidator::getMinInclusive() const +{ + return fMinInclusive; +} + +inline XMLNumber* AbstractNumericFacetValidator::getMinExclusive() const +{ + return fMinExclusive; +} + +inline RefVectorOf* AbstractNumericFacetValidator::getEnumeration() const +{ + return fEnumeration; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file AbstractNumericFacetValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/AbstractNumericValidator.cpp b/include/xercesc/validators/datatype/AbstractNumericValidator.cpp new file mode 100644 index 0000000..32355e4 --- /dev/null +++ b/include/xercesc/validators/datatype/AbstractNumericValidator.cpp @@ -0,0 +1,181 @@ +/* + * 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: AbstractNumericValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +#define REPORT_VALUE_ERROR(val1, val2, except_code, manager) \ + ThrowXMLwithMemMgr2(InvalidDatatypeValueException \ + , except_code \ + , val1->getFormattedString() \ + , val2->getFormattedString() \ + , manager); + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +AbstractNumericValidator::~AbstractNumericValidator() +{} + +AbstractNumericValidator::AbstractNumericValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:AbstractNumericFacetValidator(baseValidator, facets, finalSet, type, manager) +{ + //do not invoke init() here !!! +} + +void AbstractNumericValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + checkContent(content, context, false, manager); +} + +void AbstractNumericValidator::boundsCheck(const XMLNumber* const theData + , MemoryManager* const manager) +{ + int thisFacetsDefined = getFacetsDefined(); + int result; + + if (thisFacetsDefined == 0) + return; + + // must be < MaxExclusive + if ( (thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0 ) + { + result = compareValues(theData, getMaxExclusive()); + if ( result != -1) + { + REPORT_VALUE_ERROR(theData + , getMaxExclusive() + , XMLExcepts::VALUE_exceed_maxExcl + , manager) + } + } + + // must be <= MaxInclusive + if ( (thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0 ) + { + result = compareValues(theData, getMaxInclusive()); + if (result == 1) + { + REPORT_VALUE_ERROR(theData + , getMaxInclusive() + , XMLExcepts::VALUE_exceed_maxIncl + , manager) + } + } + + // must be >= MinInclusive + if ( (thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0 ) + { + result = compareValues(theData, getMinInclusive()); + if (result == -1) + { + REPORT_VALUE_ERROR(theData + , getMinInclusive() + , XMLExcepts::VALUE_exceed_minIncl + , manager) + } + } + + // must be > MinExclusive + if ( (thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0 ) + { + result = compareValues(theData, getMinExclusive()); + if (result != 1) + { + REPORT_VALUE_ERROR(theData + , getMinExclusive() + , XMLExcepts::VALUE_exceed_minExcl + , manager) + } + } +} + +const XMLCh* AbstractNumericValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : fMemoryManager; + + if (toValidate) + { + AbstractNumericValidator* temp = (AbstractNumericValidator*) this; + + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + // XMLAbstractDoubleFloat::getCanonicalRepresentation handles + // exceptional cases + return XMLAbstractDoubleFloat::getCanonicalRepresentation(rawData, toUse); + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(AbstractNumericValidator) + +void AbstractNumericValidator::serialize(XSerializeEngine& serEng) +{ + AbstractNumericFacetValidator::serialize(serEng); + + /*** + * Need not to do anything else here + * + * Note: its derivatives, Doubledv, Floatdv and Decimaldv writes + * number type info into the binary data stream to be read + * by AbstractNumericFacetVaildator during loading, therefore + * this class can NOT write/read anything into/from the binary + * data stream. + * + * Later on, if this class has to write/read something into/from + * the binary data stream, we need to add a numberType data + * to XMLNumber and let AbstractNumericFacetValidator to write/read + * this number type info. + ***/ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file AbstractNumericValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/AbstractNumericValidator.hpp b/include/xercesc/validators/datatype/AbstractNumericValidator.hpp new file mode 100644 index 0000000..eeab902 --- /dev/null +++ b/include/xercesc/validators/datatype/AbstractNumericValidator.hpp @@ -0,0 +1,109 @@ +/* + * 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: AbstractNumericValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ABSTRACT_NUMERIC_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ABSTRACT_NUMERIC_VALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT AbstractNumericValidator : public AbstractNumericFacetValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructor. */ + //@{ + + virtual ~AbstractNumericValidator(); + + //@} + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(AbstractNumericValidator) + +protected: + + AbstractNumericValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + inline void init(RefArrayVectorOf* const enums + , MemoryManager* const manager); + + // + // Abstract interface + // + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) = 0; + + void boundsCheck(const XMLNumber* const + , MemoryManager* const manager); + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + AbstractNumericValidator(const AbstractNumericValidator&); + AbstractNumericValidator& operator=(const AbstractNumericValidator&); +}; + +inline void AbstractNumericValidator::init(RefArrayVectorOf* const enums + , MemoryManager* const manager) +{ + AbstractNumericFacetValidator::init(enums, manager); +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file AbstractNumericValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/AbstractStringValidator.cpp b/include/xercesc/validators/datatype/AbstractStringValidator.cpp new file mode 100644 index 0000000..3a82989 --- /dev/null +++ b/include/xercesc/validators/datatype/AbstractStringValidator.cpp @@ -0,0 +1,770 @@ +/* + * 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: AbstractStringValidator.cpp 834826 2009-11-11 10:03:53Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static const int BUF_LEN = 64; + +#define REPORT_FACET_ERROR(val1, val2, except_code, manager) \ + XMLCh value1[BUF_LEN+1]; \ + XMLCh value2[BUF_LEN+1]; \ + XMLString::sizeToText(val1, value1, BUF_LEN, 10, manager); \ + XMLString::sizeToText(val2, value2, BUF_LEN, 10, manager); \ + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException \ + , except_code \ + , value1 \ + , value2 \ + , manager); + +#define REPORT_VALUE_ERROR(data, val1, val2, except_code, manager) \ + XMLCh value1[BUF_LEN+1]; \ + XMLCh value2[BUF_LEN+1]; \ + XMLString::sizeToText(val1, value1, BUF_LEN, 10, manager); \ + XMLString::sizeToText(val2, value2, BUF_LEN, 10, manager); \ + ThrowXMLwithMemMgr3(InvalidDatatypeValueException \ + , except_code \ + , data \ + , value1 \ + , value2 \ + , manager); + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +AbstractStringValidator::~AbstractStringValidator() +{ + //~RefVectorOf will delete all adopted elements + if ( !fEnumerationInherited && fEnumeration) + { + delete fEnumeration; + fEnumeration = 0; + } +} + +AbstractStringValidator::AbstractStringValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:DatatypeValidator(baseValidator, facets, finalSet, type, manager) +,fLength(0) +,fMaxLength(SchemaSymbols::fgINT_MAX_VALUE) +,fMinLength(0) +,fEnumerationInherited(false) +,fEnumeration(0) +{ + // init() is invoked from derived class's ctor instead of from + // here to allow correct resolution of virutal method, such as + // assigneAdditionalFacet(), inheritAdditionalFacet(). +} + +void AbstractStringValidator::init(RefArrayVectorOf* const enums + ,MemoryManager* const manager) +{ + + if (enums) + { + setEnumeration(enums, false); + normalizeEnumeration(manager); + } + + assignFacet(manager); + inspectFacet(manager); + inspectFacetBase(manager); + inheritFacet(); + +} + +// +// Assign facets +// assign common facets +// assign additional facet +// +void AbstractStringValidator::assignFacet(MemoryManager* const manager) +{ + + RefHashTableOf* facets = getFacets(); + + if (!facets) + return; + + XMLCh* key; + RefHashTableOfEnumerator e(facets, false, manager); + + while (e.hasMoreElements()) + { + KVStringPair pair = e.nextElement(); + key = pair.getKey(); + XMLCh* value = pair.getValue(); + + if (XMLString::equals(key, SchemaSymbols::fgELT_LENGTH)) + { + int val; + try + { + val = XMLString::parseInt(value, manager); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_Len, value, manager); + } + + if ( val < 0 ) + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_NonNeg_Len, value, manager); + + setLength(val); + setFacetsDefined(DatatypeValidator::FACET_LENGTH); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MINLENGTH)) + { + int val; + try + { + val = XMLString::parseInt(value, manager); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_minLen, value, manager); + } + + if ( val < 0 ) + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_NonNeg_minLen, value, manager); + + setMinLength(val); + setFacetsDefined(DatatypeValidator::FACET_MINLENGTH); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_MAXLENGTH)) + { + int val; + try + { + val = XMLString::parseInt(value, manager); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_maxLen, value, manager); + } + + if ( val < 0 ) + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_NonNeg_maxLen, value, manager); + + setMaxLength(val); + setFacetsDefined(DatatypeValidator::FACET_MAXLENGTH); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN)) + { + setPattern(value); + if (getPattern()) + setFacetsDefined(DatatypeValidator::FACET_PATTERN); + // do not construct regex until needed + } + else if (XMLString::equals(key, SchemaSymbols::fgATT_FIXED)) + { + unsigned int val; + bool retStatus; + try + { + retStatus = XMLString::textToBin(value, val, fMemoryManager); + } + catch (RuntimeException&) + { + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_internalError_fixed, manager); + } + + if (!retStatus) + { + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_internalError_fixed, manager); + } + + setFixed(val); + //no setFacetsDefined here + } + // + // else if (XMLString::equals(key, SchemaSymbols::fgELT_SPECIAL_TOKEN)) + // TODO + // + // Note: whitespace is taken care of by TraverseSchema. + // + else + { + assignAdditionalFacet(key, value, manager); + } + }//while +}//end of assigneFacet() + +// +// Check facet among self +// check common facets +// check Additional Facet Constraint +// +void AbstractStringValidator::inspectFacet(MemoryManager* const manager) +{ + + int thisFacetsDefined = getFacetsDefined(); + + if (!thisFacetsDefined) + return; + + // check 4.3.1.c1 error: length & (maxLength | minLength) + if ((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) != 0) + { + if ((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) != 0) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_Len_maxLen, manager); + else if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) != 0)) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_Len_minLen, manager); + } + + // check 4.3.2.c1 must: minLength <= maxLength + if ((thisFacetsDefined & (DatatypeValidator::FACET_MINLENGTH + |DatatypeValidator::FACET_MAXLENGTH)) != 0) + { + XMLSize_t thisMinLength = getMinLength(); + XMLSize_t thisMaxLength = getMaxLength(); + if ( thisMinLength > thisMaxLength ) + { + REPORT_FACET_ERROR(thisMaxLength + , thisMinLength + , XMLExcepts::FACET_maxLen_minLen + , manager) + } + } + +}// end of inspectFacet() + +// +// Check vs base +// check common facets +// check enumeration +// check Additional Facet Constraint +// +void AbstractStringValidator::inspectFacetBase(MemoryManager* const manager) +{ + + AbstractStringValidator *pBaseValidator = (AbstractStringValidator*) getBaseValidator(); + int thisFacetsDefined = getFacetsDefined(); + + if ( (!thisFacetsDefined && !fEnumeration) || + (!pBaseValidator) ) + return; + + int baseFacetsDefined = pBaseValidator->getFacetsDefined(); + + XMLSize_t thisLength = getLength(); + XMLSize_t thisMinLength = getMinLength(); + XMLSize_t thisMaxLength = getMaxLength(); + + XMLSize_t baseLength = pBaseValidator->getLength(); + XMLSize_t baseMinLength = pBaseValidator->getMinLength(); + XMLSize_t baseMaxLength = pBaseValidator->getMaxLength(); + int baseFixed = pBaseValidator->getFixed(); + + /*** + check facets against base.facets + Note: later we need to check the "fix" option of the base type + and apply that to every individual facet. + ***/ + + /*** + Non coexistence of derived' length and base' (minLength | maxLength) + base' length and derived' (minLength | maxLength) + + E2-35 + It is an error for both length and either of minLength or maxLength to be members of {facets}, + unless they are specified in different derivation steps in which case the following must be true: + the {value} of minLength <= the {value} of length <= the {value} of maxLength + ***/ + + // error: length > base.maxLength + // length < base.minLength + if ((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) !=0) + { + if (((baseFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) !=0) && + (thisLength > baseMaxLength) ) + { + REPORT_FACET_ERROR(thisLength + , baseMaxLength + , XMLExcepts::FACET_Len_baseMaxLen + , manager) + } + + if (((baseFacetsDefined & DatatypeValidator::FACET_MINLENGTH) !=0) && + (thisLength < baseMinLength) ) + { + REPORT_FACET_ERROR(thisLength + , baseMinLength + , XMLExcepts::FACET_Len_baseMinLen + , manager) + } + } + + // error: baseLength > maxLength + // baseLength < minLength + if ((baseFacetsDefined & DatatypeValidator::FACET_LENGTH) !=0) + { + if (((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) !=0) && + (baseLength > thisMaxLength) ) + { + REPORT_FACET_ERROR(thisMaxLength + , baseLength + , XMLExcepts::FACET_maxLen_baseLen + , manager) + } + + if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) !=0) && + (baseLength < thisMinLength) ) + { + REPORT_FACET_ERROR(thisMinLength + , baseLength + , XMLExcepts::FACET_minLen_baseLen + , manager) + } + } + + // check 4.3.1.c2 error: length != base.length + if (((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) !=0) && + ((baseFacetsDefined & DatatypeValidator::FACET_LENGTH) !=0)) + { + if ( thisLength != baseLength ) + { + REPORT_FACET_ERROR(thisLength + , baseLength + , XMLExcepts::FACET_Len_baseLen + , manager) + } + } + + /*** + |--- derived ---| + base.minLength <= minLength <= maxLength <= base.maxLength + |------------------- base -------------------| + ***/ + + // check 4.3.2.c1 must: minLength <= base.maxLength + if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH ) != 0) && + ((baseFacetsDefined & DatatypeValidator::FACET_MAXLENGTH ) != 0)) + { + if ( thisMinLength > baseMaxLength ) + { + REPORT_FACET_ERROR(thisMinLength + , baseMaxLength + , XMLExcepts::FACET_minLen_basemaxLen + , manager) + } + } + + // check 4.3.2.c2 error: minLength < base.minLength + if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) !=0) && + ((baseFacetsDefined & DatatypeValidator::FACET_MINLENGTH) != 0)) + { + if ((baseFixed & DatatypeValidator::FACET_MINLENGTH) !=0) + { + if ( thisMinLength != baseMinLength ) + { + REPORT_FACET_ERROR(thisMinLength + , baseMinLength + , XMLExcepts::FACET_minLen_base_fixed + , manager) + } + + } + else + { + if ( thisMinLength < baseMinLength ) + { + REPORT_FACET_ERROR(thisMinLength + , baseMinLength + , XMLExcepts::FACET_minLen_baseminLen + , manager) + } + } + } + + // check 4.3.2.c1 must: base.minLength <= maxLength + if (((baseFacetsDefined & DatatypeValidator::FACET_MINLENGTH) !=0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) !=0)) + { + if ( baseMinLength > thisMaxLength ) + { + REPORT_FACET_ERROR(thisMaxLength + , baseMinLength + , XMLExcepts::FACET_maxLen_baseminLen + , manager) + } + } + + // check 4.3.3.c1 error: maxLength > base.maxLength + if (((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) !=0) && + ((baseFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) !=0)) + { + if ((baseFixed & DatatypeValidator::FACET_MAXLENGTH) !=0) + { + if ( thisMaxLength != baseMaxLength ) + { + REPORT_FACET_ERROR(thisMaxLength + , baseMaxLength + , XMLExcepts::FACET_maxLen_base_fixed + , manager) + } + } + else + { + if ( thisMaxLength > baseMaxLength ) + { + REPORT_FACET_ERROR(thisMaxLength + , baseMaxLength + , XMLExcepts::FACET_maxLen_basemaxLen + , manager) + } + } + } + + // check 4.3.5.c0 must: enumeration values from the value space of base + if ( ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0) && + (getEnumeration() !=0)) + { + XMLSize_t i = 0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + // ask parent do a complete check + pBaseValidator->checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager); +#if 0 +// spec says that only base has to checkContent + // enum shall pass this->checkContent() as well. + checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager); +#endif + } + } + + checkAdditionalFacetConstraints(manager); + +} //end of inspectFacetBase + +// +// Inherit facet from base +// a. inherit common facets +// b. inherit additional facet +// +void AbstractStringValidator::inheritFacet() +{ + /*** + P3. Inherit facets from base.facets + + The reason of this inheriting (or copying values) is to ease + schema constraint checking, so that we need NOT trace back to our + very first base validator in the hierachy. Instead, we are pretty + sure checking against immediate base validator is enough. + ***/ + + AbstractStringValidator *pBaseValidator = (AbstractStringValidator*) getBaseValidator(); + + if (!pBaseValidator) + return; + + int thisFacetsDefined = getFacetsDefined(); + int baseFacetsDefined = pBaseValidator->getFacetsDefined(); + + // inherit length + if (((baseFacetsDefined & DatatypeValidator::FACET_LENGTH) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) == 0)) + { + setLength(pBaseValidator->getLength()); + setFacetsDefined(DatatypeValidator::FACET_LENGTH); + } + + // inherit minLength + if (((baseFacetsDefined & DatatypeValidator::FACET_MINLENGTH) !=0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) == 0)) + { + setMinLength(pBaseValidator->getMinLength()); + setFacetsDefined(DatatypeValidator::FACET_MINLENGTH); + } + + // inherit maxLength + if (((baseFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) !=0) && + ((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) == 0)) + { + setMaxLength(pBaseValidator->getMaxLength()); + setFacetsDefined(DatatypeValidator::FACET_MAXLENGTH); + } + + // inherit enumeration + if (((baseFacetsDefined & DatatypeValidator::FACET_ENUMERATION) !=0) && + ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) == 0)) + { + setEnumeration(pBaseValidator->getEnumeration(), true); + } + + // we don't inherit pattern + + // inherit "fixed" option + setFixed(getFixed() | pBaseValidator->getFixed()); + + // inherit additional facet + inheritAdditionalFacet(); + +} // end of inheritance + + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int AbstractStringValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const) +{ + return XMLString::compareString(lValue, rValue); +} + +void AbstractStringValidator::validate( const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + checkContent(content, context, false, manager); +} + +void AbstractStringValidator::checkContent( const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager + ) +{ + + //validate against base validator if any + AbstractStringValidator *pBaseValidator = (AbstractStringValidator*) this->getBaseValidator(); + if (pBaseValidator) + pBaseValidator->checkContent(content, context, true, manager); + + int thisFacetsDefined = getFacetsDefined(); + + // we check pattern first + if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + checkValueSpace(content, manager); + XMLSize_t length = getLength(content, manager); + + if (((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) != 0) && + (length > getMaxLength())) + { + REPORT_VALUE_ERROR(content + , length + , getMaxLength() + , XMLExcepts::VALUE_GT_maxLen + , manager) + } + + if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) != 0) && + (length < getMinLength())) + { + REPORT_VALUE_ERROR(content + , length + , getMinLength() + , XMLExcepts::VALUE_LT_minLen + , manager) + } + + if (((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) != 0) && + (length != getLength())) + { + REPORT_VALUE_ERROR(content + , length + , getLength() + , XMLExcepts::VALUE_NE_Len + , manager) + } + + if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0)) + { + XMLCh* normContent = XMLString::replicate(content, manager); + ArrayJanitor jan(normContent, manager); + normalizeContent(normContent, manager); + + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (XMLString::equals(normContent, getEnumeration()->elementAt(i))) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } + + checkAdditionalFacet(content, manager); + +} + +const RefArrayVectorOf* AbstractStringValidator::getEnumString() const +{ + return getEnumeration(); +} + +void AbstractStringValidator::normalizeEnumeration(MemoryManager* const manager) +{ + AbstractStringValidator *pBaseValidator = (AbstractStringValidator*) getBaseValidator(); + + if (!fEnumeration || !pBaseValidator) + return; + + int baseFacetsDefined = pBaseValidator->getFacetsDefined(); + if ((baseFacetsDefined & DatatypeValidator::FACET_WHITESPACE) == 0) + return; + + short whiteSpace = pBaseValidator->getWSFacet(); + + if ( whiteSpace == DatatypeValidator::PRESERVE ) + { + return; + } + else if ( whiteSpace == DatatypeValidator::REPLACE ) + { + XMLSize_t enumLength = getEnumeration()->size(); + for ( XMLSize_t i=0; i < enumLength; i++) + { + XMLString::replaceWS(getEnumeration()->elementAt(i), manager); + } + } + else if ( whiteSpace == DatatypeValidator::COLLAPSE ) + { + XMLSize_t enumLength = getEnumeration()->size(); + for ( XMLSize_t i=0; i < enumLength; i++) + { + XMLString::collapseWS(getEnumeration()->elementAt(i), manager); + } + } +} + +void AbstractStringValidator::normalizeContent(XMLCh* const, MemoryManager* const) const +{ + // default implementation: do nothing + return; +} + + +void AbstractStringValidator::checkAdditionalFacetConstraints(MemoryManager* const) const +{ + return; +} + +void AbstractStringValidator::checkAdditionalFacet(const XMLCh* const + , MemoryManager* const) const +{ + return; +} + +void AbstractStringValidator::inheritAdditionalFacet() +{ + return; +} + +void AbstractStringValidator::assignAdditionalFacet( const XMLCh* const key + , const XMLCh* const + , MemoryManager* const manager) +{ + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , key + , manager); +} + +XMLSize_t AbstractStringValidator::getLength(const XMLCh* const content + , MemoryManager* const) const +{ + return XMLString::stringLen(content); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(AbstractStringValidator) + +void AbstractStringValidator::serialize(XSerializeEngine& serEng) +{ + + DatatypeValidator::serialize(serEng); + + if (serEng.isStoring()) + { + serEng.writeSize (fLength); + serEng.writeSize (fMaxLength); + serEng.writeSize (fMinLength); + serEng< + * + ***/ + XTemplateSerializer::storeObject(fEnumeration, serEng); + + } + else + { + serEng.readSize (fLength); + serEng.readSize (fMaxLength); + serEng.readSize (fMinLength); + serEng>>fEnumerationInherited; + + /*** + * + * Deserialize RefArrayVectorOf + * + ***/ + XTemplateSerializer::loadObject(&fEnumeration, 8, true, serEng); + + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file AbstractStringValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/AbstractStringValidator.hpp b/include/xercesc/validators/datatype/AbstractStringValidator.hpp new file mode 100644 index 0000000..a2ab2c7 --- /dev/null +++ b/include/xercesc/validators/datatype/AbstractStringValidator.hpp @@ -0,0 +1,250 @@ +/* + * 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: AbstractStringValidator.hpp 695949 2008-09-16 15:57:44Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ABSTRACT_STRING_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ABSTRACT_STRING_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT AbstractStringValidator : public DatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructor. */ + //@{ + + virtual ~AbstractStringValidator(); + + //@} + + virtual const RefArrayVectorOf* getEnumString() const; + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(AbstractStringValidator) + +protected: + + AbstractStringValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + void init(RefArrayVectorOf* const enums + , MemoryManager* const manager); + + // + // Abstract interface + // + virtual void assignAdditionalFacet(const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager); + + virtual void inheritAdditionalFacet(); + + virtual void checkAdditionalFacetConstraints(MemoryManager* const manager) const; + + virtual void checkAdditionalFacet(const XMLCh* const content + , MemoryManager* const manager) const; + + virtual XMLSize_t getLength(const XMLCh* const content + , MemoryManager* const manager) const; + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) = 0; + + // + // to Allow ListDTV to overwrite + // + virtual void inspectFacetBase(MemoryManager* const manager); + + virtual void inheritFacet(); + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + + /* + ** Base64BinaryDatatypeValidator to overwrite + */ + virtual void normalizeEnumeration(MemoryManager* const manager); + + virtual void normalizeContent(XMLCh* const, MemoryManager* const manager) const; + +public: +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + + inline XMLSize_t getLength() const; + + inline XMLSize_t getMaxLength() const; + + inline XMLSize_t getMinLength() const; + + inline RefArrayVectorOf* getEnumeration() const; + +protected: +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- + + inline void setLength(XMLSize_t); + + inline void setMaxLength(XMLSize_t); + + inline void setMinLength(XMLSize_t); + + inline void setEnumeration(RefArrayVectorOf*, bool); + +private: + + void assignFacet(MemoryManager* const manager); + + void inspectFacet(MemoryManager* const manager); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + AbstractStringValidator(const AbstractStringValidator&); + AbstractStringValidator& operator=(const AbstractStringValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // ----------------------------------------------------------------------- + XMLSize_t fLength; + XMLSize_t fMaxLength; + XMLSize_t fMinLength; + bool fEnumerationInherited; + RefArrayVectorOf* fEnumeration; +}; + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + +inline XMLSize_t AbstractStringValidator::getLength() const +{ + return fLength; +} + +inline XMLSize_t AbstractStringValidator::getMaxLength() const +{ + return fMaxLength; +} + +inline XMLSize_t AbstractStringValidator::getMinLength() const +{ + return fMinLength; +} + +inline RefArrayVectorOf* AbstractStringValidator:: getEnumeration() const +{ + return fEnumeration; +} + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- + +inline void AbstractStringValidator::setLength(XMLSize_t newLength) +{ + fLength = newLength; +} + +inline void AbstractStringValidator::setMaxLength(XMLSize_t newMaxLength) +{ + fMaxLength = newMaxLength; +} + +inline void AbstractStringValidator::setMinLength(XMLSize_t newMinLength) +{ + fMinLength = newMinLength; +} + +inline void AbstractStringValidator::setEnumeration(RefArrayVectorOf* enums + , bool inherited) +{ + if (enums) + { + if ( !fEnumerationInherited && fEnumeration) + delete fEnumeration; + + fEnumeration = enums; + fEnumerationInherited = inherited; + setFacetsDefined(DatatypeValidator::FACET_ENUMERATION); + } +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file AbstractStringValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/AnySimpleTypeDatatypeValidator.cpp b/include/xercesc/validators/datatype/AnySimpleTypeDatatypeValidator.cpp new file mode 100644 index 0000000..eb10bfe --- /dev/null +++ b/include/xercesc/validators/datatype/AnySimpleTypeDatatypeValidator.cpp @@ -0,0 +1,98 @@ +/* + * 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: AnySimpleTypeDatatypeValidator.cpp 637054 2008-03-14 11:08:37Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// AnySimpleTypeDatatypeValidator: Constructors and Destructor +// --------------------------------------------------------------------------- +AnySimpleTypeDatatypeValidator::AnySimpleTypeDatatypeValidator(MemoryManager* const manager) + : DatatypeValidator(0, 0, SchemaSymbols::XSD_RESTRICTION, DatatypeValidator::AnySimpleType, manager) +{ + setWhiteSpace(DatatypeValidator::PRESERVE); + setFinite(true); +} + +AnySimpleTypeDatatypeValidator::~AnySimpleTypeDatatypeValidator() +{ + +} + +// --------------------------------------------------------------------------- +// DatatypeValidators: Compare methods +// --------------------------------------------------------------------------- +int AnySimpleTypeDatatypeValidator::compare( const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const) +{ + return XMLString::compareString(lValue, rValue); +} + +// --------------------------------------------------------------------------- +// AnySimpleTypeDatatypeValidator: Instance methods +// --------------------------------------------------------------------------- +DatatypeValidator* AnySimpleTypeDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int + , MemoryManager* const manager +) +{ + // We own them, so we will delete them first + delete facets; + delete enums; + + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::DV_InvalidOperation, manager); + + // to satisfy some compilers + return 0; +} + +const RefArrayVectorOf* AnySimpleTypeDatatypeValidator::getEnumString() const +{ + return 0; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(AnySimpleTypeDatatypeValidator) + +void AnySimpleTypeDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file AnySimpleTypeDatatypeValidator.cpp + */ + diff --git a/include/xercesc/validators/datatype/AnySimpleTypeDatatypeValidator.hpp b/include/xercesc/validators/datatype/AnySimpleTypeDatatypeValidator.hpp new file mode 100644 index 0000000..2d0670d --- /dev/null +++ b/include/xercesc/validators/datatype/AnySimpleTypeDatatypeValidator.hpp @@ -0,0 +1,180 @@ +/* + * 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: AnySimpleTypeDatatypeValidator.hpp 637054 2008-03-14 11:08:37Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ANYSIMPLETYPEDATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ANYSIMPLETYPEDATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT AnySimpleTypeDatatypeValidator : public DatatypeValidator +{ +public: + // ----------------------------------------------------------------------- + // Public Constructor + // ----------------------------------------------------------------------- + /** @name Constructor */ + //@{ + + AnySimpleTypeDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Public Destructor + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + + virtual ~AnySimpleTypeDatatypeValidator(); + + //@} + + virtual const RefArrayVectorOf* getEnumString() const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Getter Functions */ + //@{ + + /** + * Returns whether the type is atomic or not + */ + virtual bool isAtomic() const; + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * Checks that the "content" string is valid datatype. + * If invalid, a Datatype validation exception is thrown. + * + * @param content A string containing the content to be validated + * + */ + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Checks whether a given type can be used as a substitute + * + * @param toCheck A datatype validator of the type to be used as a + * substitute + * + */ + + virtual bool isSubstitutableBy(const DatatypeValidator* const toCheck); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compares content in the Domain value vs. lexical value. + * + * @param value1 string to compare + * + * @param value2 string to compare + * + */ + virtual int compare(const XMLCh* const value1, const XMLCh* const value2 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(AnySimpleTypeDatatypeValidator) + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + AnySimpleTypeDatatypeValidator(const AnySimpleTypeDatatypeValidator&); + AnySimpleTypeDatatypeValidator& operator=(const AnySimpleTypeDatatypeValidator&); +}; + + +// --------------------------------------------------------------------------- +// DatatypeValidator: Getters +// --------------------------------------------------------------------------- +inline bool AnySimpleTypeDatatypeValidator::isAtomic() const { + + return false; +} + +// --------------------------------------------------------------------------- +// DatatypeValidators: Validation methods +// --------------------------------------------------------------------------- +inline bool +AnySimpleTypeDatatypeValidator::isSubstitutableBy(const DatatypeValidator* const) +{ + return true; +} + +inline void +AnySimpleTypeDatatypeValidator::validate(const XMLCh* const + , ValidationContext* const + , MemoryManager* const) +{ + return; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file AnySimpleTypeDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/AnyURIDatatypeValidator.cpp b/include/xercesc/validators/datatype/AnyURIDatatypeValidator.cpp new file mode 100644 index 0000000..d553b4a --- /dev/null +++ b/include/xercesc/validators/datatype/AnyURIDatatypeValidator.cpp @@ -0,0 +1,199 @@ +/* + * 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: AnyURIDatatypeValidator.cpp 676796 2008-07-15 05:04:13Z dbertoni $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +AnyURIDatatypeValidator::AnyURIDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::AnyURI, manager) +{} + +AnyURIDatatypeValidator::~AnyURIDatatypeValidator() +{ +} + +AnyURIDatatypeValidator::AnyURIDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::AnyURI, manager) +{ + init(enums, manager); +} + +DatatypeValidator* AnyURIDatatypeValidator::newInstance( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +{ + return (DatatypeValidator*) new (manager) AnyURIDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void AnyURIDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + bool validURI = true; + + // check 3.2.17.c0 must: URI (rfc 2396/2723) + try + { + // Support for relative URLs + // According to Java 1.1: URLs may also be specified with a + // String and the URL object that it is related to. + // + XMLSize_t len = XMLString::stringLen(content); + if (len) + { + // Encode special characters using XLink 5.4 algorithm + XMLBuffer encoded((len*3)+1, manager); + encode(content, len, encoded, manager); + validURI = XMLUri::isValidURI(true, encoded.getRawBuffer(), true); + } + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_URI_Malformed + , content + , manager); + } + + if (!validURI) { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_URI_Malformed + , content + , manager); + } +} + +/*** + * To encode special characters in anyURI, by using %HH to represent + * special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', etc. + * and non-ASCII characters (whose value >= 128). + ***/ +void AnyURIDatatypeValidator::encode(const XMLCh* const content, const XMLSize_t len, XMLBuffer& encoded, MemoryManager* const manager) +{ + static const bool needEscapeMap[] = { + true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , /* 0x00 to 0x0F need escape */ + true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , /* 0x10 to 0x1F need escape */ + true , false, true , false, false, false, false, false, false, false, false, false, false, false, false, false, /* 0x20:' ', 0x22:'"' */ + false, false, false, false, false, false, false, false, false, false, false, false, true , false, true , false, /* 0x3C:'<', 0x3E:'>' */ + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, true , false, true , false, /* 0x5C:'\\', 0x5E:'^' */ + true , false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, /* 0x60:'`' */ + false, false, false, false, false, false, false, false, false, false, false, true , true , true , true , true /* 0x7B:'{', 0x7C:'|', 0x7D:'}', 0x7E:'~', 0x7F:DEL */ + }; + + // For each character in content + XMLSize_t i; + for (i = 0; i < len; i++) + { + int ch = (int)content[i]; + // If it's not an ASCII character, break here, and use UTF-8 encoding + if (ch >= 128) + break; + + if (needEscapeMap[ch]) + { + char tempStr[3] = "\0"; + sprintf(tempStr, "%02X", ch); + encoded.append('%'); + encoded.append((XMLCh)tempStr[0]); + encoded.append((XMLCh)tempStr[1]); + } + else + { + encoded.append((XMLCh)ch); + } + } + + // we saw some non-ascii character + if (i < len) { + // get UTF-8 bytes for the remaining sub-string + const XMLCh* remContent = (XMLCh*)&content[i]; + const XMLSize_t remContentLen = len - i; + XMLByte* UTF8Byte = (XMLByte*)manager->allocate((remContentLen*4+1) * sizeof(XMLByte)); + XMLSize_t charsEaten; + + XMLUTF8Transcoder transcoder(XMLUni::fgUTF8EncodingString, remContentLen*4+1, manager); + XMLSize_t utf8Len = transcoder.transcodeTo(remContent, remContentLen, UTF8Byte, remContentLen*4, charsEaten, XMLTranscoder::UnRep_RepChar); + assert(charsEaten == remContentLen); + + XMLSize_t j; + for (j = 0; j < utf8Len; j++) { + XMLByte b = UTF8Byte[j]; + if (b >= 128 || needEscapeMap[b]) + { + char tempStr[3] = "\0"; + sprintf(tempStr, "%02X", b); + encoded.append('%'); + encoded.append((XMLCh)tempStr[0]); + encoded.append((XMLCh)tempStr[1]); + } + else + { + encoded.append((XMLCh)b); + } + } + manager->deallocate(UTF8Byte); + } +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(AnyURIDatatypeValidator) + +void AnyURIDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file AnyURIDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/AnyURIDatatypeValidator.hpp b/include/xercesc/validators/datatype/AnyURIDatatypeValidator.hpp new file mode 100644 index 0000000..1c2e3dc --- /dev/null +++ b/include/xercesc/validators/datatype/AnyURIDatatypeValidator.hpp @@ -0,0 +1,95 @@ +/* + * 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: AnyURIDatatypeValidator.hpp 608951 2008-01-04 18:21:22Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ANYURI_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ANYURI_DATATYPEVALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLBuffer; + +class VALIDATORS_EXPORT AnyURIDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + AnyURIDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + AnyURIDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~AnyURIDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(AnyURIDatatypeValidator) + +protected: + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + AnyURIDatatypeValidator(const AnyURIDatatypeValidator&); + AnyURIDatatypeValidator& operator=(const AnyURIDatatypeValidator&); + void encode(const XMLCh* const content, const XMLSize_t len, XMLBuffer& encoded, MemoryManager* const manager); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file AnyURIDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/Base64BinaryDatatypeValidator.cpp b/include/xercesc/validators/datatype/Base64BinaryDatatypeValidator.cpp new file mode 100644 index 0000000..66922e4 --- /dev/null +++ b/include/xercesc/validators/datatype/Base64BinaryDatatypeValidator.cpp @@ -0,0 +1,124 @@ +/* + * 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: Base64BinaryDatatypeValidator.cpp 695949 2008-09-16 15:57:44Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +Base64BinaryDatatypeValidator::Base64BinaryDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::Base64Binary, manager) +{} + +Base64BinaryDatatypeValidator::~Base64BinaryDatatypeValidator() +{} + +Base64BinaryDatatypeValidator::Base64BinaryDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::Base64Binary, manager) +{ + init(enums, manager); +} + +DatatypeValidator* Base64BinaryDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) Base64BinaryDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void Base64BinaryDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + if (!content || !*content) + return; + + if (Base64::getDataLength(content, manager, Base64::Conf_Schema) < 0) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_Not_Base64 + , content + , manager); + } +} + +XMLSize_t Base64BinaryDatatypeValidator::getLength(const XMLCh* const content + , MemoryManager* const manager) const +{ + if (!content || !*content) + return 0; + + return (XMLSize_t)Base64::getDataLength(content, manager, Base64::Conf_Schema); +} + +void Base64BinaryDatatypeValidator::normalizeEnumeration(MemoryManager* const manager) +{ + + XMLSize_t enumLength = getEnumeration()->size(); + for ( XMLSize_t i=0; i < enumLength; i++) + { + XMLString::removeWS(getEnumeration()->elementAt(i), manager); + } + +} + +void Base64BinaryDatatypeValidator::normalizeContent(XMLCh* const content + , MemoryManager* const manager) const +{ + XMLString::removeWS(content, manager); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(Base64BinaryDatatypeValidator) + +void Base64BinaryDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file Base64BinaryDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/Base64BinaryDatatypeValidator.hpp b/include/xercesc/validators/datatype/Base64BinaryDatatypeValidator.hpp new file mode 100644 index 0000000..c4c6ee4 --- /dev/null +++ b/include/xercesc/validators/datatype/Base64BinaryDatatypeValidator.hpp @@ -0,0 +1,100 @@ +/* + * 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: Base64BinaryDatatypeValidator.hpp 695949 2008-09-16 15:57:44Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BASE64BINARY_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_BASE64BINARY_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT Base64BinaryDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + Base64BinaryDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + Base64BinaryDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~Base64BinaryDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(Base64BinaryDatatypeValidator) + +protected: + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + + virtual XMLSize_t getLength(const XMLCh* const content + , MemoryManager* const manager) const; + + virtual void normalizeEnumeration(MemoryManager* const manager); + + virtual void normalizeContent(XMLCh* const, MemoryManager* const manager) const; + +private: + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + Base64BinaryDatatypeValidator(const Base64BinaryDatatypeValidator&); + Base64BinaryDatatypeValidator& operator=(const Base64BinaryDatatypeValidator&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file Base64BinaryDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/BooleanDatatypeValidator.cpp b/include/xercesc/validators/datatype/BooleanDatatypeValidator.cpp new file mode 100644 index 0000000..be7072f --- /dev/null +++ b/include/xercesc/validators/datatype/BooleanDatatypeValidator.cpp @@ -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: BooleanDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +BooleanDatatypeValidator::BooleanDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Boolean, manager) +{ + + // Set Facets if any defined + if ( facets ) + { + + // Boolean shall NOT have enumeration + if (enums) { + delete enums; + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , "enumeration" + , manager); + } + + XMLCh* key; + XMLCh* value; + RefHashTableOfEnumerator e(facets, false, manager); + + while (e.hasMoreElements()) + { + KVStringPair pair = e.nextElement(); + key = pair.getKey(); + value = pair.getValue(); + + if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN)) + { + setPattern(value); + setFacetsDefined(DatatypeValidator::FACET_PATTERN); + } + else + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , key + , manager); + } + + } + + }// End of facet setting +} + +void BooleanDatatypeValidator::checkContent( const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + + //validate against base validator if any + BooleanDatatypeValidator *pBaseValidator = (BooleanDatatypeValidator*) this->getBaseValidator(); + if (pBaseValidator !=0) + pBaseValidator->checkContent(content, context, true, manager); + + // we check pattern first + if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + unsigned int i = 0; + for ( ; i < XMLUni::fgBooleanValueSpaceArraySize; i++ ) + { + if ( XMLString::equals(content, XMLUni::fgBooleanValueSpace[i])) + break; + } + + if (i == XMLUni::fgBooleanValueSpaceArraySize) + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_Invalid_Name + , content + , SchemaSymbols::fgDT_BOOLEAN + , manager); + //Not valid boolean type + +} + +int BooleanDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const) +{ + // need to check by bool semantics + // 1 == true + // 0 == false + + if (XMLString::equals(lValue, XMLUni::fgBooleanValueSpace[0])|| + XMLString::equals(lValue, XMLUni::fgBooleanValueSpace[2])) + { + if (XMLString::equals(rValue, XMLUni::fgBooleanValueSpace[0]) || + XMLString::equals(rValue, XMLUni::fgBooleanValueSpace[2])) + return 0; + } + else + if (XMLString::equals(lValue, XMLUni::fgBooleanValueSpace[1]) || + XMLString::equals(lValue, XMLUni::fgBooleanValueSpace[3])) + { + if (XMLString::equals(rValue, XMLUni::fgBooleanValueSpace[1]) || + XMLString::equals(rValue, XMLUni::fgBooleanValueSpace[3])) + return 0; + } + + return 1; +} + +const RefArrayVectorOf* BooleanDatatypeValidator::getEnumString() const +{ + return 0; +} + +/*** + * 3.2.2.2 Canonical representation + * + * The canonical representation for boolean is the set of literals {true, false}. + ***/ +const XMLCh* BooleanDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + + MemoryManager* toUse = memMgr? memMgr : getMemoryManager(); + + if (toValidate) + { + BooleanDatatypeValidator *temp = (BooleanDatatypeValidator*) this; + + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + return ( XMLString::equals(rawData, XMLUni::fgBooleanValueSpace[0]) || + XMLString::equals(rawData, XMLUni::fgBooleanValueSpace[2]) ) ? + XMLString::replicate(XMLUni::fgBooleanValueSpace[0], toUse) : + XMLString::replicate(XMLUni::fgBooleanValueSpace[1], toUse) ; + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(BooleanDatatypeValidator) + +void BooleanDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file BooleanDatatypeValidator.cpp + */ + diff --git a/include/xercesc/validators/datatype/BooleanDatatypeValidator.hpp b/include/xercesc/validators/datatype/BooleanDatatypeValidator.hpp new file mode 100644 index 0000000..05f7083 --- /dev/null +++ b/include/xercesc/validators/datatype/BooleanDatatypeValidator.hpp @@ -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: BooleanDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_BOOLEAN_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_BOOLEAN_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT BooleanDatatypeValidator : public DatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructor. */ + //@{ + + BooleanDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + BooleanDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~BooleanDatatypeValidator(); + + //@} + + virtual const RefArrayVectorOf* getEnumString() const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Getter Functions */ + //@{ + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(BooleanDatatypeValidator) + +private: + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + + // ----------------------------------------------------------------------- + // Unimplemented methods. + // ----------------------------------------------------------------------- + BooleanDatatypeValidator(const BooleanDatatypeValidator&); + BooleanDatatypeValidator& operator=(const BooleanDatatypeValidator&); + +}; + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +inline BooleanDatatypeValidator::BooleanDatatypeValidator(MemoryManager* const manager) +:DatatypeValidator(0, 0, 0, DatatypeValidator::Boolean, manager) +{ + setFinite(true); +} + +inline BooleanDatatypeValidator::~BooleanDatatypeValidator() +{ +} + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- + +inline DatatypeValidator* BooleanDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) BooleanDatatypeValidator(this, facets, enums, finalSet, manager); +} + +inline void BooleanDatatypeValidator::validate( const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + checkContent(content, context, false, manager); +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file BooleanDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/DatatypeValidator.cpp b/include/xercesc/validators/datatype/DatatypeValidator.cpp new file mode 100644 index 0000000..18c9d4b --- /dev/null +++ b/include/xercesc/validators/datatype/DatatypeValidator.cpp @@ -0,0 +1,546 @@ +/* + * 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: DatatypeValidator.cpp 555320 2007-07-11 16:05:13Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +//since we need to dynamically created each and every derivatives +//during deserialization by XSerializeEngine>>Derivative, we got +//to include all hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static const int DV_BUILTIN = -1; +static const int DV_NORMAL = -2; +static const int DV_ZERO = -3; + +static const int TYPENAME_ZERO = -1; +static const int TYPENAME_S4S = -2; +static const int TYPENAME_NORMAL = -3; + +// --------------------------------------------------------------------------- +// DatatypeValidator: Constructors and Destructor +// --------------------------------------------------------------------------- +DatatypeValidator::DatatypeValidator(DatatypeValidator* const baseValidator, + RefHashTableOf* const facets, + const int finalSet, + const ValidatorType type, + MemoryManager* const manager) + : fAnonymous(false) + , fFinite(false) + , fBounded(false) + , fNumeric(false) + , fWhiteSpace(COLLAPSE) + , fFinalSet(finalSet) + , fFacetsDefined(0) + , fFixed(0) + , fType(type) + , fOrdered(XSSimpleTypeDefinition::ORDERED_FALSE) + , fBaseValidator(baseValidator) + , fFacets(facets) + , fPattern(0) + , fRegex(0) + , fTypeName(0) + , fTypeLocalName(XMLUni::fgZeroLenString) + , fTypeUri(XMLUni::fgZeroLenString) + , fMemoryManager(manager) +{ +} + +DatatypeValidator::~DatatypeValidator() +{ + cleanUp(); +} + +const XMLCh* DatatypeValidator::getWSstring(const short theType) const +{ + switch (theType) + { + case PRESERVE: + return SchemaSymbols::fgWS_PRESERVE; + case REPLACE: + return SchemaSymbols::fgWS_REPLACE; + case COLLAPSE: + return SchemaSymbols::fgWS_COLLAPSE; + default: + return SchemaSymbols::fgWS_PRESERVE; + } + +} + +void DatatypeValidator::setTypeName(const XMLCh* const name, const XMLCh* const uri) +{ + if (fTypeName) { + + fMemoryManager->deallocate(fTypeName); + fTypeName = 0; + } + + if (name || uri) { + + XMLSize_t nameLen = XMLString::stringLen(name); + XMLSize_t uriLen = XMLString::stringLen(uri); + + fTypeName = (XMLCh*) fMemoryManager->allocate + ( + (nameLen + uriLen + 2)*sizeof(XMLCh) + ); + fTypeUri = fTypeName; + fTypeLocalName = &fTypeName[uriLen+1]; + + if (uri) + XMLString::moveChars(fTypeName, uri, uriLen+1); + else + fTypeName[0] = chNull; + + if (name) + XMLString::moveChars(&fTypeName[uriLen+1], name, nameLen+1); + else + fTypeName[uriLen+1] = chNull; + } + else + { + fTypeUri = fTypeLocalName = XMLUni::fgZeroLenString; + } +} + +void DatatypeValidator::setTypeName(const XMLCh* const typeName) +{ + if (fTypeName) + { + fMemoryManager->deallocate(fTypeName); + fTypeName = 0; + } + + if (typeName) + { + XMLSize_t nameLen = XMLString::stringLen(typeName); + int commaOffset = XMLString::indexOf(typeName, chComma); + + fTypeName = (XMLCh*) fMemoryManager->allocate + ( + (nameLen + 1) * sizeof(XMLCh) + ); + XMLString::moveChars(fTypeName, typeName, nameLen+1); + + if ( commaOffset == -1) { + fTypeUri = SchemaSymbols::fgURI_SCHEMAFORSCHEMA; + fTypeLocalName = fTypeName; + } + else { + fTypeUri = fTypeName; + fTypeLocalName = &fTypeName[commaOffset+1]; + fTypeName[commaOffset] = chNull; + } + } + else + { + fTypeUri = fTypeLocalName = XMLUni::fgZeroLenString; + } +} + +// --------------------------------------------------------------------------- +// DatatypeValidator: CleanUp methods +// --------------------------------------------------------------------------- +void DatatypeValidator::cleanUp() { + + delete fFacets; + delete fRegex; + if (fPattern) + fMemoryManager->deallocate(fPattern);//delete [] fPattern; + if (fTypeName) + fMemoryManager->deallocate(fTypeName); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(DatatypeValidator) + +void DatatypeValidator::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng< + ***/ + XTemplateSerializer::storeObject(fFacets, serEng); + + serEng.writeString(fPattern); + + if (fTypeUri==XMLUni::fgZeroLenString) + { + serEng<>fAnonymous; + serEng>>fFinite; + serEng>>fBounded; + serEng>>fNumeric; + + serEng>>fWhiteSpace; + serEng>>fFinalSet; + serEng>>fFacetsDefined; + serEng>>fFixed; + + int type; + serEng>>type; + fType=(ValidatorType)type; + + serEng>>type; + fOrdered = (XSSimpleTypeDefinition::ORDERING)type; + + + fBaseValidator = loadDV(serEng); + + /*** + * + * Deserialize RefHashTableOf + * + ***/ + XTemplateSerializer::loadObject(&fFacets, 29, true, serEng); + serEng.readString(fPattern); + + /*** + * Recreate through setTypeName() + * fTypeName + ***/ + + int flag; + serEng>>flag; + + if ( TYPENAME_ZERO == flag ) + { + setTypeName(0); + } + else if ( TYPENAME_S4S == flag ) + { + XMLCh* typeLocalName; + serEng.readString(typeLocalName); + ArrayJanitor janName(typeLocalName, fMemoryManager); + + setTypeName(typeLocalName); + } + else // TYPENAME_NORMAL + { + XMLCh* typeLocalName; + serEng.readString(typeLocalName); + ArrayJanitor janName(typeLocalName, fMemoryManager); + + XMLCh* typeUri; + serEng.readString(typeUri); + ArrayJanitor janUri(typeUri, fMemoryManager); + + setTypeName(typeLocalName, typeUri); + } + + /*** + * don't serialize fRegex + ***/ + fRegex = new (fMemoryManager) RegularExpression(fPattern, SchemaSymbols::fgRegEx_XOption, fMemoryManager); + + } + +} + +/*** + * + * When deserialized, we need to know, exactly what + * validator was serialized here. + * + * Design Issue: + * + * This extra type information is only necessary when + * we need to create and deserialize an DatatypeValidator + * derivative by operator >>, but not by object.serialize(). + * Therefore it is appropriate to save this type info by + * hosting object rather than by derivative.serialize(). + * + * + ***/ +void DatatypeValidator::storeDV(XSerializeEngine& serEng + , DatatypeValidator* const dv) +{ + if (dv) + { + //builtIndv + if (dv == DatatypeValidatorFactory::getBuiltInRegistry()->get(dv->getTypeLocalName())) + { + serEng<getTypeLocalName()); + } + else + { + serEng<getType(); + serEng<>flag; + + if (DV_BUILTIN == flag) + { + XMLCh* dvName; + serEng.readString(dvName); + ArrayJanitor janName(dvName, serEng.getMemoryManager()); + + return DatatypeValidatorFactory::getBuiltInRegistry()->get(dvName); + } + else if (DV_ZERO == flag) + { + return 0; + } + + int type; + serEng>>type; + + switch((ValidatorType)type) + { + case String: + StringDatatypeValidator* stringdv; + serEng>>stringdv; + return stringdv; + case AnyURI: + AnyURIDatatypeValidator* anyuridv; + serEng>>anyuridv; + return anyuridv; + case QName: + QNameDatatypeValidator* qnamedv; + serEng>>qnamedv; + return qnamedv; + case Name: + NameDatatypeValidator* namedv; + serEng>>namedv; + return namedv; + case NCName: + NCNameDatatypeValidator* ncnamedv; + serEng>>ncnamedv; + return ncnamedv; + case Boolean: + BooleanDatatypeValidator* booleandv; + serEng>>booleandv; + return booleandv; + case Float: + FloatDatatypeValidator* floatdv; + serEng>>floatdv; + return floatdv; + case Double: + DoubleDatatypeValidator* doubledv; + serEng>>doubledv; + return doubledv; + case Decimal: + DecimalDatatypeValidator* decimaldv; + serEng>>decimaldv; + return decimaldv; + case HexBinary: + HexBinaryDatatypeValidator* hexbinarydv; + serEng>>hexbinarydv; + return hexbinarydv; + case Base64Binary: + Base64BinaryDatatypeValidator* base64binarydv; + serEng>>base64binarydv; + return base64binarydv; + case Duration: + DurationDatatypeValidator* durationdv; + serEng>>durationdv; + return durationdv; + case DateTime: + DateTimeDatatypeValidator* datetimedv; + serEng>>datetimedv; + return datetimedv; + case Date: + DateDatatypeValidator* datedv; + serEng>>datedv; + return datedv; + case Time: + TimeDatatypeValidator* timedv; + serEng>>timedv; + return timedv; + case MonthDay: + MonthDayDatatypeValidator* monthdaydv; + serEng>>monthdaydv; + return monthdaydv; + case YearMonth: + YearMonthDatatypeValidator* yearmonthdv; + serEng>>yearmonthdv; + return yearmonthdv; + case Year: + YearDatatypeValidator* yeardv; + serEng>>yeardv; + return yeardv; + case Month: + MonthDatatypeValidator* monthdv; + serEng>>monthdv; + return monthdv; + case Day: + DayDatatypeValidator* daydv; + serEng>>daydv; + return daydv; + case ID: + IDDatatypeValidator* iddv; + serEng>>iddv; + return iddv; + case IDREF: + IDREFDatatypeValidator* idrefdv; + serEng>>idrefdv; + return idrefdv; + case ENTITY: + ENTITYDatatypeValidator* entitydv; + serEng>>entitydv; + return entitydv; + case NOTATION: + NOTATIONDatatypeValidator* notationdv; + serEng>>notationdv; + return notationdv; + case List: + ListDatatypeValidator* listdv; + serEng>>listdv; + return listdv; + case Union: + UnionDatatypeValidator* uniondv; + serEng>>uniondv; + return uniondv; + case AnySimpleType: + AnySimpleTypeDatatypeValidator* anysimpletypedv; + serEng>>anysimpletypedv; + return anysimpletypedv; + case UnKnown: + return 0; + default: //we treat this same as UnKnown + return 0; + } + +} + +/** + * Canonical Representation + * + */ +const XMLCh* DatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : fMemoryManager; + + if (toValidate) + { + DatatypeValidator *temp = (DatatypeValidator*) this; + + try + { + temp->validate(rawData, 0, toUse); + } + catch (...) + { + return 0; + } + } + + return XMLString::replicate(rawData, toUse); +} + + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DatatypeValidator.cpp + */ + diff --git a/include/xercesc/validators/datatype/DatatypeValidator.hpp b/include/xercesc/validators/datatype/DatatypeValidator.hpp new file mode 100644 index 0000000..58a91be --- /dev/null +++ b/include/xercesc/validators/datatype/DatatypeValidator.hpp @@ -0,0 +1,750 @@ +/* + * 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: DatatypeValidator.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DATATYPEVALIDATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class MemoryManager; + +/** + * DataTypeValidator defines the interface that data type validators must + * obey. These validators can be supplied by the application writer and may + * be useful as standalone code as well as plugins to the validator + * architecture. + * + * Notice: + * The datatype validator will own the facets hashtable passed to it during + * construction, which means that the datatype validator will be responsible + * for the deletion. The facets hashtable will be created during parsing and + * passed to the appropriate datatype validator which in turn will delete it + * upon its destruction. + * + */ + + +class VALIDATORS_EXPORT DatatypeValidator : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constant data + // ----------------------------------------------------------------------- + //facets + enum { + FACET_LENGTH = 1, + FACET_MINLENGTH = 1<<1, + FACET_MAXLENGTH = 1<<2, + FACET_PATTERN = 1<<3, + FACET_ENUMERATION = 1<<4, + FACET_MAXINCLUSIVE = 1<<5, + FACET_MAXEXCLUSIVE = 1<<6, + FACET_MININCLUSIVE = 1<<7, + FACET_MINEXCLUSIVE = 1<<8, + FACET_TOTALDIGITS = 1<<9, + FACET_FRACTIONDIGITS = 1<<10, + FACET_ENCODING = 1<<11, + FACET_DURATION = 1<<12, + FACET_PERIOD = 1<<13, + FACET_WHITESPACE = 1<<14 + }; + + //2.4.2.6 whiteSpace - Datatypes + enum { + PRESERVE = 0, + REPLACE = 1, + COLLAPSE = 2 + }; + + enum ValidatorType { + String, + AnyURI, + QName, + Name, + NCName, + Boolean, + Float, + Double, + Decimal, + HexBinary, + Base64Binary, + Duration, + DateTime, + Date, + Time, + MonthDay, + YearMonth, + Year, + Month, + Day, + ID, + IDREF, + ENTITY, + NOTATION, + List, + Union, + AnySimpleType, + UnKnown + }; + + // ----------------------------------------------------------------------- + // Public Destructor + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + + virtual ~DatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Getter Functions */ + //@{ + + /** + * Returns the final values of the simpleType + */ + int getFinalSet() const; + + /** + * Returns the datatype facet if any is set. + */ + RefHashTableOf* getFacets() const; + + /** + * Returns default value (collapse) for whiteSpace facet. + * This function is overwritten in StringDatatypeValidator. + */ + short getWSFacet () const; + + /** + * Returns the base datatype validator if set. + */ + DatatypeValidator* getBaseValidator() const; + + /** + * Returns the 'class' type of datatype validator + */ + ValidatorType getType() const; + + /** + * Returns whether the type is atomic or not + * + * To be redefined in List/Union validators + */ + virtual bool isAtomic() const; + + /** + * Returns the datatype enumeration if any is set. + * Derived class shall provide their own copy. + */ + virtual const RefArrayVectorOf* getEnumString() const = 0; + + /** + * returns true if this type is anonymous + **/ + bool getAnonymous() const; + + /** + * sets this type to be anonymous + **/ + void setAnonymous(); + + /** + * Fundamental Facet: ordered + */ + XSSimpleTypeDefinition::ORDERING getOrdered() const; + + /** + * Fundamental Facet: cardinality. + */ + bool getFinite() const; + + /** + * Fundamental Facet: bounded. + */ + bool getBounded() const; + + /** + * Fundamental Facet: numeric. + */ + bool getNumeric() const; + + /** + * Canonical Representation + * + * Derivative datatype may overwrite this method once + * it has its own canonical representation other than + * the default one. + * + * @param rawData: data in raw string + * @param memMgr: memory manager + * @param toValiate: to validate the raw string or not + * + * @return: canonical representation of the data + * + * Note: + * + * 1. the return value is kept in memory allocated + * by the memory manager passed in or by dv's + * if no memory manager is provided. + * + * 2. client application is responsible for the + * proper deallocation of the memory allocated + * for the returned value. + * + * 3. In the case where the rawData is not valid + * with regards to the fundamental datatype, + * a null string is returned. + * + */ + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * Checks that the "content" string is valid datatype. + * If invalid, a Datatype validation exception is thrown. + * + * @param content A string containing the content to be validated + * + */ + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ) = 0; + + /** + * Checks whether a given type can be used as a substitute + * + * @param toCheck A datatype validator of the type to be used as a + * substitute + * + * To be redefined in UnionDatatypeValidator + */ + + virtual bool isSubstitutableBy(const DatatypeValidator* const toCheck); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compares content in the Domain value vs. lexical value. + * + * e.g. If type is a float then 1.0 may be equivalent to 1 even though + * both are lexically different. + * + * @param value1 string to compare + * + * @param value2 string to compare + * + * We will provide a default behavior that should be redefined at the + * children level, if necessary (i.e. boolean case). + */ + virtual int compare(const XMLCh* const value1, const XMLCh* const value2 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ) = 0; + + /** + * Returns the uri,name of the type this validator is for + */ + const XMLCh* getTypeName() const; + + /** + * sets the uri,name that this validator is for - typeName is uri,name string. + * due to the internals of xerces this will set the uri to be the schema uri if + * there is no comma in typeName + */ + void setTypeName(const XMLCh* const typeName); + + /** + * sets the uri,name that this validator is for + */ + void setTypeName(const XMLCh* const name, const XMLCh* const uri); + + /** + * Returns the uri of the type this validator is for + */ + const XMLCh* getTypeUri() const; + + /** + * Returns the name of the type this validator is for + */ + const XMLCh* getTypeLocalName() const; + + /** + * Returns the plugged-in memory manager + */ + MemoryManager* getMemoryManager() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DatatypeValidator) + + /*** + * + * Serialize DatatypeValidator derivative + * + * Param + * serEng: serialize engine + * dv: DatatypeValidator derivative + * + * Return: + * + ***/ + static void storeDV(XSerializeEngine& serEng + , DatatypeValidator* const dv); + + /*** + * + * Create a DatatypeValidator derivative from the binary + * stream. + * + * Param + * serEng: serialize engine + * + * Return: + * DatatypeValidator derivative + * + ***/ + static DatatypeValidator* loadDV(XSerializeEngine& serEng); + +protected: + // ----------------------------------------------------------------------- + // Protected Constructors + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + /** + * + * @param baseValidator The base datatype validator for derived + * validators. Null if native validator. + * + * @param facets A hashtable of datatype facets (except enum). + * + * @param finalSet 'final' value of the simpleType + */ + + DatatypeValidator(DatatypeValidator* const baseValidator, + RefHashTableOf* const facets, + const int finalSet, + const ValidatorType type, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@} + + + friend class DatatypeValidatorFactory; + friend class XSObjectFactory; + + /** + * facetDefined + */ + int getFacetsDefined() const; + void setFacetsDefined(int); + + /** + * fixed + */ + int getFixed() const; + void setFixed(int); + + + /** + * fPattern + */ + const XMLCh* getPattern() const; + void setPattern(const XMLCh* ); + + /** + * fRegex + */ + RegularExpression* getRegex() const; + void setRegex(RegularExpression* const); + + /** + * set fType + */ + void setType(ValidatorType); + + /** + * set fWhiteSpace + */ + void setWhiteSpace(short); + + /** + * get WSString + */ + const XMLCh* getWSstring(const short WSType) const; + + /** + * Fundamental Facet: ordered + */ + void setOrdered(XSSimpleTypeDefinition::ORDERING ordered); + + /** + * Fundamental Facet: cardinality. + */ + void setFinite(bool finite); + + /** + * Fundamental Facet: bounded. + */ + void setBounded(bool bounded); + + /** + * Fundamental Facet: numeric. + */ + void setNumeric(bool numeric); + +private: + // ----------------------------------------------------------------------- + // CleanUp methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DatatypeValidator(const DatatypeValidator&); + DatatypeValidator& operator=(const DatatypeValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fFinalSet + // stores "final" values of simpleTypes + // + // fBaseValidator + // This is a pointer to a base datatype validator. If value is null, + // it means we have a native datatype validator not a derived one. + // + // fFacets + // This is a hashtable of dataype facets. + // + // fType + // Stores the class type of datatype validator + // + // fFacetsDefined + // Stores the constaiting facets flag + // + // fPattern + // the pointer to the String of the pattern. The actual data is + // in the Facets. + // + // fRegex + // pointer to the RegularExpress object + // + // + // fFixed + // if {fixed} is true, then types for which this type is the + // {base type definition} cannot specify a value for a specific + // facet. + // + // fTypeName + // the uri,name of the type this validator will validate + // + // fTypeLocalName + // the name of the type this validator will validate + // + // fTypeUri + // the uri of the type this validator will validate + // fAnonymous + // true if this type is anonynous + // + // ----------------------------------------------------------------------- + bool fAnonymous; + bool fFinite; + bool fBounded; + bool fNumeric; + + short fWhiteSpace; + int fFinalSet; + int fFacetsDefined; + int fFixed; + + ValidatorType fType; + XSSimpleTypeDefinition::ORDERING fOrdered; + + DatatypeValidator* fBaseValidator; + RefHashTableOf* fFacets; + XMLCh* fPattern; + RegularExpression* fRegex; + XMLCh* fTypeName; + const XMLCh* fTypeLocalName; + const XMLCh* fTypeUri; + +protected: + // ----------------------------------------------------------------------- + // Protected data members + // + // fMemoryManager + // Pluggable memory manager for dynamic allocation/deallocation. + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + +}; + + +// --------------------------------------------------------------------------- +// DatatypeValidator: Getters +// --------------------------------------------------------------------------- +inline int DatatypeValidator::getFinalSet() const { + + return fFinalSet; +} + +inline RefHashTableOf* DatatypeValidator::getFacets() const { + + return fFacets; +} + +inline DatatypeValidator* DatatypeValidator::getBaseValidator() const { + + return fBaseValidator; +} + +inline short DatatypeValidator::getWSFacet() const { + + return fWhiteSpace; +} + +inline DatatypeValidator::ValidatorType DatatypeValidator::getType() const +{ + return fType; +} + +inline int DatatypeValidator::getFacetsDefined() const +{ + return fFacetsDefined; +} + +inline int DatatypeValidator::getFixed() const +{ + return fFixed; +} + +inline const XMLCh* DatatypeValidator::getPattern() const +{ + return fPattern; +} + +inline RegularExpression* DatatypeValidator::getRegex() const +{ + return fRegex; +} + +inline const XMLCh* DatatypeValidator::getTypeName() const +{ + return fTypeName; +} + +inline bool DatatypeValidator::getAnonymous() const +{ + return fAnonymous; +} + +inline const XMLCh* DatatypeValidator::getTypeLocalName() const +{ + return fTypeLocalName; +} + +inline const XMLCh* DatatypeValidator::getTypeUri() const +{ + return fTypeUri; +} + +inline MemoryManager* DatatypeValidator::getMemoryManager() const +{ + return fMemoryManager; +} + +inline XSSimpleTypeDefinition::ORDERING DatatypeValidator::getOrdered() const +{ + return fOrdered; +} + +inline bool DatatypeValidator::getFinite() const +{ + return fFinite; +} + +inline bool DatatypeValidator::getBounded() const +{ + return fBounded; +} + +inline bool DatatypeValidator::getNumeric() const +{ + return fNumeric; +} + +// --------------------------------------------------------------------------- +// DatatypeValidator: Setters +// --------------------------------------------------------------------------- +inline void DatatypeValidator::setType(ValidatorType theType) +{ + fType = theType; +} + +inline void DatatypeValidator::setWhiteSpace(short newValue) +{ + fWhiteSpace = newValue; +} + +inline void DatatypeValidator::setFacetsDefined(int facets) +{ + fFacetsDefined |= facets; +} + +inline void DatatypeValidator::setFixed(int fixed) +{ + fFixed |= fixed; +} + +inline void DatatypeValidator::setPattern(const XMLCh* pattern) +{ + if (fPattern) { + fMemoryManager->deallocate(fPattern);//delete [] fPattern; + delete fRegex; + } + fPattern = XMLString::replicate(pattern, fMemoryManager); + fRegex = new (fMemoryManager) RegularExpression(fPattern, SchemaSymbols::fgRegEx_XOption, fMemoryManager); +} + +inline void DatatypeValidator::setRegex(RegularExpression* const regex) +{ + fRegex = regex; +} + +inline bool DatatypeValidator::isAtomic() const { + + return true; +} + +inline void DatatypeValidator::setAnonymous() { + fAnonymous = true; +} + +inline void DatatypeValidator::setOrdered(XSSimpleTypeDefinition::ORDERING ordered) +{ + fOrdered = ordered; +} + +inline void DatatypeValidator::setFinite(bool finite) +{ + fFinite = finite; +} + +inline void DatatypeValidator::setBounded(bool bounded) +{ + fBounded = bounded; +} + +inline void DatatypeValidator::setNumeric(bool numeric) +{ + fNumeric = numeric; +} + +// --------------------------------------------------------------------------- +// DatatypeValidators: Compare methods +// --------------------------------------------------------------------------- +inline int DatatypeValidator::compare(const XMLCh* const lValue, + const XMLCh* const rValue + , MemoryManager* const) +{ + return XMLString::compareString(lValue, rValue); +} + +// --------------------------------------------------------------------------- +// DatatypeValidators: Validation methods +// --------------------------------------------------------------------------- +inline bool +DatatypeValidator::isSubstitutableBy(const DatatypeValidator* const toCheck) +{ + const DatatypeValidator* dv = toCheck; + + while (dv != 0) { + + if (dv == this) { + return true; + } + + dv = dv->getBaseValidator(); + } + + return false; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/DatatypeValidatorFactory.cpp b/include/xercesc/validators/datatype/DatatypeValidatorFactory.cpp new file mode 100644 index 0000000..26d5e11 --- /dev/null +++ b/include/xercesc/validators/datatype/DatatypeValidatorFactory.cpp @@ -0,0 +1,900 @@ +/* + * 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: DatatypeValidatorFactory.cpp 932887 2010-04-11 13:04:59Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: Local const data +// --------------------------------------------------------------------------- +const XMLCh fgTokPattern[] = +{ + chBackSlash, chLatin_c, chPlus, chNull +}; + +//E2-43 +//[+\-]?[0-9]+ +const XMLCh fgIntegerPattern[] = +{ + chOpenSquare, chPlus, chBackSlash, chDash, chCloseSquare, chQuestion, + chOpenSquare, chDigit_0, chDash, chDigit_9, chCloseSquare, chPlus, chNull +}; + +//"\\i\\c*" +const XMLCh fgNamePattern[] = +{ + chBackSlash, chLatin_i, chBackSlash, chLatin_c, chAsterisk, chNull +}; + +//"[\\i-[:]][\\c-[:]]*" +const XMLCh fgNCNamePattern[] = +{ + chOpenSquare, chBackSlash, chLatin_i, chDash, chOpenSquare, chColon, chCloseSquare, + chCloseSquare, chOpenSquare, chBackSlash, chLatin_c, chDash, chOpenSquare, + chColon, chCloseSquare, chCloseSquare, chAsterisk, chNull +}; + + + +const XMLCh fgP0Y[] = +{ + chLatin_P, chDigit_0, chLatin_Y, chNull +}; + +const XMLCh fgP1Y[] = +{ + chLatin_P, chDigit_1, chLatin_Y, chNull +}; + +const XMLCh fgP100Y[] = +{ + chLatin_P, chDigit_1, chDigit_0, chDigit_0, chLatin_Y, chNull +}; + +const XMLCh fgPT24H[] = +{ + chLatin_P, chLatin_T, chDigit_2, chDigit_4, chLatin_H, chNull +}; + +const XMLCh fgP1M[] = +{ + chLatin_P, chDigit_1, chLatin_M, chNull +}; + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: Static member data +// --------------------------------------------------------------------------- +RefHashTableOf* DatatypeValidatorFactory::fBuiltInRegistry = 0; +RefHashTableOf* DatatypeValidatorFactory::fCanRepRegistry = 0; + +void XMLInitializer::initializeDatatypeValidatorFactory() +{ + // @@ This is ugly. Need to make expandRegistryToFullSchemaSet + // static. + // + DatatypeValidatorFactory *dvFactory = new DatatypeValidatorFactory(); + if (dvFactory) { + dvFactory->expandRegistryToFullSchemaSet(); + delete dvFactory; + } +} + +void XMLInitializer::terminateDatatypeValidatorFactory() +{ + delete DatatypeValidatorFactory::fBuiltInRegistry; + DatatypeValidatorFactory::fBuiltInRegistry = 0; + + delete DatatypeValidatorFactory::fCanRepRegistry; + DatatypeValidatorFactory::fCanRepRegistry = 0; +} + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: Constructors and Destructor +// --------------------------------------------------------------------------- +DatatypeValidatorFactory::DatatypeValidatorFactory(MemoryManager* const manager) + : fUserDefinedRegistry(0) + , fMemoryManager(manager) +{ +} + +DatatypeValidatorFactory::~DatatypeValidatorFactory() +{ + cleanUp(); +} + + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: Reset methods +// --------------------------------------------------------------------------- +void DatatypeValidatorFactory::resetRegistry() { + + if (fUserDefinedRegistry != 0) { + fUserDefinedRegistry->removeAll(); + } +} + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: Registry initialization methods +// --------------------------------------------------------------------------- +void DatatypeValidatorFactory::expandRegistryToFullSchemaSet() +{ + //Initialize common Schema/DTD Datatype validator set + fBuiltInRegistry = new RefHashTableOf(29); + + DatatypeValidator *dv = new StringDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_STRING, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_STRING, dv); + + dv = new NOTATIONDatatypeValidator(); + dv->setTypeName(XMLUni::fgNotationString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) XMLUni::fgNotationString, dv); + + dv = new AnySimpleTypeDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_ANYSIMPLETYPE, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_ANYSIMPLETYPE, dv); + + dv = new BooleanDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_BOOLEAN, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_BOOLEAN, dv); + + dv = new DecimalDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_DECIMAL, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_DECIMAL, dv); + + dv = new HexBinaryDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_HEXBINARY, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_HEXBINARY, dv); + + dv = new Base64BinaryDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_BASE64BINARY, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_BASE64BINARY, dv); + + dv = new DoubleDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_DOUBLE, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_DOUBLE, dv); + + dv = new FloatDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_FLOAT, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_FLOAT, dv); + + dv = new AnyURIDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_ANYURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_ANYURI, dv); + + dv = new QNameDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_QNAME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_QNAME, dv); + + dv = new DateTimeDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_DATETIME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_DATETIME, dv); + + dv = new DateDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_DATE, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_DATE, dv); + + dv = new TimeDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_TIME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_TIME, dv); + + dv = new DayDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_DAY, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_DAY, dv); + + dv = new MonthDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_MONTH, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_MONTH, dv); + + dv = new MonthDayDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_MONTHDAY, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_MONTHDAY, dv); + + dv = new YearDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_YEAR, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_YEAR, dv); + + dv = new YearMonthDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_YEARMONTH, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_YEARMONTH, dv); + + dv = new DurationDatatypeValidator(); + dv->setTypeName(SchemaSymbols::fgDT_DURATION, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_DURATION, dv); + + // REVISIT + // We are creating a lot of Hashtables for the facets of the different + // validators. It's better to have some kind of a memory pool and ask + // the pool to give us a new instance of the hashtable. + RefHashTableOf* facets = new RefHashTableOf(3); + + // Create 'normalizedString' datatype validator + facets->put((void*) SchemaSymbols::fgELT_WHITESPACE, + new KVStringPair(SchemaSymbols::fgELT_WHITESPACE, SchemaSymbols::fgWS_REPLACE)); + + createDatatypeValidator(SchemaSymbols::fgDT_NORMALIZEDSTRING, + getDatatypeValidator(SchemaSymbols::fgDT_STRING), + facets, 0, false, 0, false); + + // Create 'token' datatype validator + facets = new RefHashTableOf(3); + facets->put((void*) SchemaSymbols::fgELT_WHITESPACE, + new KVStringPair(SchemaSymbols::fgELT_WHITESPACE, SchemaSymbols::fgWS_COLLAPSE)); + + createDatatypeValidator(SchemaSymbols::fgDT_TOKEN, + getDatatypeValidator(SchemaSymbols::fgDT_NORMALIZEDSTRING), + facets, 0, false, 0, false); + + + dv = new NameDatatypeValidator(getDatatypeValidator(SchemaSymbols::fgDT_TOKEN), 0, 0, 0); + dv->setTypeName(SchemaSymbols::fgDT_NAME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_NAME, dv); + + + dv = new NCNameDatatypeValidator(getDatatypeValidator(SchemaSymbols::fgDT_NAME), 0, 0, 0); + dv->setTypeName(SchemaSymbols::fgDT_NCNAME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) SchemaSymbols::fgDT_NCNAME, dv); + + // Create 'NMTOKEN' datatype validator + facets = new RefHashTableOf(3); + + facets->put((void*) SchemaSymbols::fgELT_PATTERN , + new KVStringPair(SchemaSymbols::fgELT_PATTERN,fgTokPattern)); + facets->put((void*) SchemaSymbols::fgELT_WHITESPACE, + new KVStringPair(SchemaSymbols::fgELT_WHITESPACE, SchemaSymbols::fgWS_COLLAPSE)); + + createDatatypeValidator(XMLUni::fgNmTokenString, + getDatatypeValidator(SchemaSymbols::fgDT_TOKEN),facets, 0, false, 0, false); + + // Create 'NMTOKENS' datatype validator + facets = new RefHashTableOf(2); + facets->put((void*) SchemaSymbols::fgELT_MINLENGTH, + new KVStringPair(SchemaSymbols::fgELT_MINLENGTH, XMLUni::fgValueOne)); + + createDatatypeValidator(XMLUni::fgNmTokensString, + getDatatypeValidator(XMLUni::fgNmTokenString), facets, 0, true, 0, false); + + // Create 'language' datatype validator + facets = new RefHashTableOf(3); + + facets->put((void*) SchemaSymbols::fgELT_PATTERN, + new KVStringPair(SchemaSymbols::fgELT_PATTERN, XMLUni::fgLangPattern)); + + createDatatypeValidator(SchemaSymbols::fgDT_LANGUAGE, + getDatatypeValidator(SchemaSymbols::fgDT_TOKEN), + facets, 0, false, 0, false); + + // Create 'integer' datatype validator + facets = new RefHashTableOf(3); + + facets->put((void*) SchemaSymbols::fgELT_FRACTIONDIGITS, + new KVStringPair(SchemaSymbols::fgELT_FRACTIONDIGITS, XMLUni::fgValueZero)); + + facets->put((void*) SchemaSymbols::fgELT_PATTERN, + new KVStringPair(SchemaSymbols::fgELT_PATTERN, fgIntegerPattern)); + + createDatatypeValidator(SchemaSymbols::fgDT_INTEGER, + getDatatypeValidator(SchemaSymbols::fgDT_DECIMAL), + facets, 0, false, 0, false); + + // Create 'nonPositiveInteger' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgValueZero)); + + createDatatypeValidator(SchemaSymbols::fgDT_NONPOSITIVEINTEGER, + getDatatypeValidator(SchemaSymbols::fgDT_INTEGER), + facets, 0, false, 0, false); + + // Create 'negativeInteger' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgNegOne)); + + createDatatypeValidator(SchemaSymbols::fgDT_NEGATIVEINTEGER, + getDatatypeValidator(SchemaSymbols::fgDT_NONPOSITIVEINTEGER), + facets, 0, false, 0, false); + + // Create 'long' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgLongMaxInc)); + facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, XMLUni::fgLongMinInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_LONG, + getDatatypeValidator(SchemaSymbols::fgDT_INTEGER), + facets, 0, false, 0, false); + + // Create 'int' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgIntMaxInc)); + facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, XMLUni::fgIntMinInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_INT, + getDatatypeValidator(SchemaSymbols::fgDT_LONG), + facets, 0, false, 0, false); + + // Create 'short' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgShortMaxInc)); + facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, XMLUni::fgShortMinInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_SHORT, + getDatatypeValidator(SchemaSymbols::fgDT_INT), + facets, 0, false, 0 ,false); + + // Create 'byte' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgByteMaxInc)); + facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, XMLUni::fgByteMinInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_BYTE, + getDatatypeValidator(SchemaSymbols::fgDT_SHORT), + facets, 0, false, 0, false); + + // Create 'nonNegativeInteger' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, XMLUni::fgValueZero)); + + createDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER, + getDatatypeValidator(SchemaSymbols::fgDT_INTEGER), + facets, 0, false, 0, false); + + // Create 'unsignedLong' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgULongMaxInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_ULONG, + getDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER), + facets, 0, false, 0, false); + + // Create 'unsignedInt' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgUIntMaxInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_UINT, + getDatatypeValidator(SchemaSymbols::fgDT_ULONG), + facets, 0, false, 0, false); + + // Create 'unsignedShort' datatypeValidator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgUShortMaxInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_USHORT, + getDatatypeValidator(SchemaSymbols::fgDT_UINT), + facets, 0, false, 0, false); + + // Create 'unsignedByte' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MAXINCLUSIVE, XMLUni::fgUByteMaxInc)); + + createDatatypeValidator(SchemaSymbols::fgDT_UBYTE, + getDatatypeValidator(SchemaSymbols::fgDT_USHORT), + facets, 0, false, 0, false); + + // Create 'positiveInteger' datatype validator + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, + new KVStringPair(SchemaSymbols::fgELT_MININCLUSIVE, XMLUni::fgValueOne)); + + createDatatypeValidator(SchemaSymbols::fgDT_POSITIVEINTEGER, + getDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER), + facets, 0, false, 0, false); + + // Create 'ID', 'IDREF' and 'ENTITY' datatype validator + dv = new IDDatatypeValidator(getDatatypeValidator(SchemaSymbols::fgDT_NCNAME), 0, 0, 0); + dv->setTypeName(XMLUni::fgIDString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) XMLUni::fgIDString, dv); + + dv = new IDREFDatatypeValidator(getDatatypeValidator(SchemaSymbols::fgDT_NCNAME), 0, 0, 0); + dv->setTypeName(XMLUni::fgIDRefString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) XMLUni::fgIDRefString, dv); + + dv = new ENTITYDatatypeValidator(getDatatypeValidator(SchemaSymbols::fgDT_NCNAME), 0, 0, 0); + dv->setTypeName(XMLUni::fgEntityString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuiltInRegistry->put((void*) XMLUni::fgEntityString, dv); + + facets = new RefHashTableOf(2); + facets->put((void*) SchemaSymbols::fgELT_MINLENGTH, + new KVStringPair(SchemaSymbols::fgELT_MINLENGTH, XMLUni::fgValueOne)); + + // Create 'IDREFS' datatype validator + createDatatypeValidator + ( + XMLUni::fgIDRefsString + , getDatatypeValidator(XMLUni::fgIDRefString) + , facets + , 0 + , true + , 0 + , false + ); + + facets = new RefHashTableOf(2); + + facets->put((void*) SchemaSymbols::fgELT_MINLENGTH, + new KVStringPair(SchemaSymbols::fgELT_MINLENGTH, XMLUni::fgValueOne)); + + // Create 'ENTITIES' datatype validator + createDatatypeValidator + ( + XMLUni::fgEntitiesString + , getDatatypeValidator(XMLUni::fgEntityString) + , facets + , 0 + , true + , 0 + , false + ); + + initCanRepRegistory(); +} + + +/*** + * + * For Decimal-derivated, an instance of DecimalDatatypeValidator + * can be used by the primitive datatype, decimal, or any one of + * the derivated datatypes, such as int, long, unsighed short, just + * name a few, or any user-defined datatypes, which may derivate from + * either the primitive datatype, decimal, or from any one of those + * decimal derivated datatypes, or other user-defined datatypes, which + * in turn, indirectly derivate from decimal or decimal-derived. + * + * fCanRepRegisty captures deciaml dv and its derivatives. + * + ***/ +void DatatypeValidatorFactory::initCanRepRegistory() +{ + + /*** + * key: dv + * data: XMLCanRepGroup + ***/ + fCanRepRegistry = new RefHashTableOf(29, true); + + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_DECIMAL), + new XMLCanRepGroup(XMLCanRepGroup::Decimal)); + + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_INTEGER), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_LONG), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_INT), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_SHORT), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_BYTE), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_POSITIVEINTEGER), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_signed)); + + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_NEGATIVEINTEGER), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_unsigned)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_ULONG), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_unsigned)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_UINT), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_unsigned)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_USHORT), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_unsigned)); + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_UBYTE), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_unsigned)); + + fCanRepRegistry->put((void*) getDatatypeValidator(SchemaSymbols::fgDT_NONPOSITIVEINTEGER), + new XMLCanRepGroup(XMLCanRepGroup::Decimal_Derived_npi)); +} + +/*** + * + * For any dv other than Decimaldv, return String only. + * Later on if support to dv other than Decimaldv arise, we may + * add them fCanRepRegistry during DatatypeValidatorFactory::initCanRepRegistory() + * + ***/ +XMLCanRepGroup::CanRepGroup DatatypeValidatorFactory::getCanRepGroup(const DatatypeValidator* const dv) +{ + if (!dv) + return XMLCanRepGroup::String; + + DatatypeValidator *curdv = (DatatypeValidator*) dv; + + while (curdv) + { + if (fCanRepRegistry->containsKey(curdv)) + return fCanRepRegistry->get(curdv)->getGroup(); + else + curdv = curdv->getBaseValidator(); + } + + return XMLCanRepGroup::String; +} + +DatatypeValidator* DatatypeValidatorFactory::getBuiltInBaseValidator(const DatatypeValidator* const dv) +{ + DatatypeValidator *curdv = (DatatypeValidator*)dv; + + while (curdv) + { + if (curdv == getBuiltInRegistry()->get(curdv->getTypeLocalName())) + return curdv; + else + curdv = curdv->getBaseValidator(); + } + + return 0; +} + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: factory methods +// --------------------------------------------------------------------------- +DatatypeValidator* DatatypeValidatorFactory::createDatatypeValidator +( + const XMLCh* const typeName + , DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const bool isDerivedByList + , const int finalSet + , const bool isUserDefined + , MemoryManager* const userManager +) +{ + if (baseValidator == 0) { + + if (facets) { + Janitor janFacets(facets); + } + + if (enums) { + Janitor janEnums(enums); + } + + return 0; + } + + DatatypeValidator* datatypeValidator = 0; + MemoryManager* const manager = (isUserDefined) + ? userManager : XMLPlatformUtils::fgMemoryManager; + + if (isDerivedByList) { + datatypeValidator = new (manager) ListDatatypeValidator(baseValidator, facets, enums, finalSet, manager); + + // Set PSVI information for Ordered, Numeric, Bounded & Finite + datatypeValidator->setOrdered(XSSimpleTypeDefinition::ORDERED_FALSE); + datatypeValidator->setNumeric(false); + if (facets && + ((facets->get(SchemaSymbols::fgELT_LENGTH) || + (facets->get(SchemaSymbols::fgELT_MINLENGTH) && facets->get(SchemaSymbols::fgELT_MAXLENGTH))))) + { + datatypeValidator->setBounded(true); + datatypeValidator->setFinite(true); + } + else + { + datatypeValidator->setBounded(false); + datatypeValidator->setFinite(false); + } + } + else { + + if ((baseValidator->getType() != DatatypeValidator::String) && facets) { + + KVStringPair* value = facets->get(SchemaSymbols::fgELT_WHITESPACE); + + if (value != 0) { + facets->removeKey(SchemaSymbols::fgELT_WHITESPACE); + } + } + + datatypeValidator = baseValidator->newInstance + ( + facets + , enums + , finalSet + , manager + ); + + // Set PSVI information for Ordered, Numeric, Bounded & Finite + datatypeValidator->setOrdered(baseValidator->getOrdered()); + datatypeValidator->setNumeric(baseValidator->getNumeric()); + RefHashTableOf* baseFacets = baseValidator->getFacets(); + if (facets && + ((facets->get(SchemaSymbols::fgELT_MININCLUSIVE) || + facets->get(SchemaSymbols::fgELT_MINEXCLUSIVE) || + (baseFacets && (baseFacets->get(SchemaSymbols::fgELT_MININCLUSIVE) || + baseFacets->get(SchemaSymbols::fgELT_MINEXCLUSIVE))))) && + (facets->get(SchemaSymbols::fgELT_MAXINCLUSIVE) || + facets->get(SchemaSymbols::fgELT_MAXEXCLUSIVE) || + (baseFacets && ((baseFacets->get(SchemaSymbols::fgELT_MAXINCLUSIVE) || + baseFacets->get(SchemaSymbols::fgELT_MAXEXCLUSIVE)))))) + { + datatypeValidator->setBounded(true); + } + else + { + datatypeValidator->setBounded(false); + } + if (baseValidator->getFinite()) + { + datatypeValidator->setFinite(true); + } + else if (!facets) + { + datatypeValidator->setFinite(false); + } + else if (facets->get(SchemaSymbols::fgELT_LENGTH) || facets->get(SchemaSymbols::fgELT_MAXLENGTH) || + facets->get(SchemaSymbols::fgELT_TOTALDIGITS)) + { + datatypeValidator->setFinite(true); + } + //for efficiency use this instead of rechecking... + //else if ((facets->get(SchemaSymbols::fgELT_MININCLUSIVE) || facets->get(SchemaSymbols::fgELT_MINEXCLUSIVE)) && + // (facets->get(SchemaSymbols::fgELT_MAXINCLUSIVE) || facets->get(SchemaSymbols::fgELT_MAXEXCLUSIVE))) + else if (datatypeValidator->getBounded() || + datatypeValidator->getType() == DatatypeValidator::Date || + datatypeValidator->getType() == DatatypeValidator::YearMonth || + datatypeValidator->getType() == DatatypeValidator::Year || + datatypeValidator->getType() == DatatypeValidator::MonthDay || + datatypeValidator->getType() == DatatypeValidator::Day || + datatypeValidator->getType() == DatatypeValidator::Month) + { + if (facets->get(SchemaSymbols::fgELT_FRACTIONDIGITS)) + { + datatypeValidator->setFinite(true); + } + else + { + datatypeValidator->setFinite(false); + } + } + else + { + datatypeValidator->setFinite(false); + } + } + + if (datatypeValidator != 0) { + + if (isUserDefined) { + + if (!fUserDefinedRegistry) { + fUserDefinedRegistry = new (userManager) RefHashTableOf(29, userManager); + } + + fUserDefinedRegistry->put((void *)typeName, datatypeValidator); + } + else { + fBuiltInRegistry->put((void *)typeName, datatypeValidator); + } + + datatypeValidator->setTypeName(typeName); + } + + return datatypeValidator; +} + +static DatatypeValidator::ValidatorType getPrimitiveDV(DatatypeValidator::ValidatorType validationDV) +{ + if (validationDV == DatatypeValidator::ID || + validationDV == DatatypeValidator::IDREF || + validationDV == DatatypeValidator::ENTITY) + { + return DatatypeValidator::String; + } + return validationDV; +} + +DatatypeValidator* DatatypeValidatorFactory::createDatatypeValidator +( + const XMLCh* const typeName + , RefVectorOf* const validators + , const int finalSet + , const bool userDefined + , MemoryManager* const userManager +) +{ + if (validators == 0) + return 0; + + DatatypeValidator* datatypeValidator = 0; + MemoryManager* const manager = (userDefined) + ? userManager : XMLPlatformUtils::fgMemoryManager; + + datatypeValidator = new (manager) UnionDatatypeValidator(validators, finalSet, manager); + + if (datatypeValidator != 0) { + + if (userDefined) { + + if (!fUserDefinedRegistry) { + fUserDefinedRegistry = new (userManager) RefHashTableOf(29, userManager); + } + + fUserDefinedRegistry->put((void *)typeName, datatypeValidator); + } + else { + fBuiltInRegistry->put((void *)typeName, datatypeValidator); + } + datatypeValidator->setTypeName(typeName); + + // Set PSVI information for Ordered, Numeric, Bounded & Finite + XMLSize_t valSize = validators->size(); + if (valSize) + { + DatatypeValidator::ValidatorType ancestorId = getPrimitiveDV(validators->elementAt(0)->getType()); + + // For a union the ORDERED {value} is partial unless one of the following: + // 1. If every member of {member type definitions} is derived from a common ancestor other than the simple ur-type, then {value} is the same as that ancestor's ordered facet. + // 2. If every member of {member type definitions} has a {value} of false for the ordered facet, then {value} is false. + bool allOrderedFalse = true; + bool commonAnc = ancestorId != DatatypeValidator::AnySimpleType; + bool allNumeric = true; + bool allBounded = true; + bool allFinite = true; + + for(XMLSize_t i = 0 ; (i < valSize) && (commonAnc || allOrderedFalse || allNumeric || allBounded || allFinite); i++) + { + // for the other member types, check whether the value is false + // and whether they have the same ancestor as the first one + if (commonAnc) + commonAnc = ancestorId == getPrimitiveDV(validators->elementAt(i)->getType()); + if (allOrderedFalse) + allOrderedFalse = validators->elementAt(i)->getOrdered() == XSSimpleTypeDefinition::ORDERED_FALSE; + + if (allNumeric && !validators->elementAt(i)->getNumeric()) + { + allNumeric = false; + } + if (allBounded && (!validators->elementAt(i)->getBounded() || + ancestorId != getPrimitiveDV(validators->elementAt(i)->getType()))) + { + allBounded = false; + } + if (allFinite && !validators->elementAt(i)->getFinite()) + { + allFinite = false; + } + } + if (commonAnc) + { + datatypeValidator->setOrdered(validators->elementAt(0)->getOrdered()); + } + else if (allOrderedFalse) + { + datatypeValidator->setOrdered(XSSimpleTypeDefinition::ORDERED_FALSE); + } + else + { + datatypeValidator->setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); + } + datatypeValidator->setNumeric(allNumeric); + datatypeValidator->setBounded(allBounded); + datatypeValidator->setFinite(allFinite); + } + else // size = 0 + { + datatypeValidator->setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); + datatypeValidator->setNumeric(true); + datatypeValidator->setBounded(true); + datatypeValidator->setFinite(true); + } + } + return datatypeValidator; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DatatypeValidatorFactory) + +void DatatypeValidatorFactory::serialize(XSerializeEngine& serEng) +{ + + // Need not to serialize static data member, fBuiltInRegistry + + if (serEng.isStoring()) + { + /*** + * Serialize RefHashTableOf + ***/ + XTemplateSerializer::storeObject(fUserDefinedRegistry, serEng); + } + else + { + /*** + * Deserialize RefHashTableOf + ***/ + XTemplateSerializer::loadObject(&fUserDefinedRegistry, 29, true, serEng); + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DatatypeValidatorFactory.cpp + */ diff --git a/include/xercesc/validators/datatype/DatatypeValidatorFactory.hpp b/include/xercesc/validators/datatype/DatatypeValidatorFactory.hpp new file mode 100644 index 0000000..c4ec0e8 --- /dev/null +++ b/include/xercesc/validators/datatype/DatatypeValidatorFactory.hpp @@ -0,0 +1,285 @@ +/* + * 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: DatatypeValidatorFactory.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DATATYPEVALIDATORFACTORY_HPP) +#define XERCESC_INCLUDE_GUARD_DATATYPEVALIDATORFACTORY_HPP + +/** + * This class implements a factory of Datatype Validators. Internally the + * DatatypeValidators are kept in a registry. + * There is one instance of DatatypeValidatorFactory per Parser. + * There is one datatype Registry per instance of DatatypeValidatorFactory, + * such registry is first allocated with the number DatatypeValidators needed. + * e.g. + * If Parser finds an XML document with a DTD, a registry of DTD validators (only + * 9 validators) get initialized in the registry. + * The initialization process consist of instantiating the Datatype and + * facets and registering the Datatype into registry table. + * This implementation uses a Hashtable as a registry. The datatype validators created + * by the factory will be deleted by the registry. + * + * As the Parser parses an instance document it knows if validation needs + * to be checked. If no validation is necessary we should not instantiate a + * DatatypeValidatorFactory. + * If validation is needed, we need to instantiate a DatatypeValidatorFactory. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// DatatypeValidatorFactory: Local declaration +// --------------------------------------------------------------------------- +typedef RefHashTableOf KVStringPairHashTable; +typedef RefHashTableOf DVHashTable; +typedef RefArrayVectorOf XMLChRefVector; + + +class VALIDATORS_EXPORT DatatypeValidatorFactory : public XSerializable, public XMemory +{ +public: + + // ----------------------------------------------------------------------- + // Public Constructors and Destructor + // ----------------------------------------------------------------------- + /** @name Constructors */ + //@{ + + DatatypeValidatorFactory + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** @name Destructor. */ + //@{ + + ~DatatypeValidatorFactory(); + + //@} + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Getter Functions */ + //@{ + + /** + * Returns the datatype validator + * + * @param dvType Datatype validator name/type + */ + DatatypeValidator* getDatatypeValidator(const XMLCh* const dvType) const; + + /** + * Returns the user defined registry of types + **/ + DVHashTable* getUserDefinedRegistry() const; + + + /** + * Returns the built in registry of types + **/ + static DVHashTable* getBuiltInRegistry(); + + //@} + + private: + /** + * Initializes registry with primitive and derived Simple types. + * + * This method does not clear the registry to clear the registry you + * have to call resetRegistry. + * + * The net effect of this method is to start with the smallest set of + * datatypes needed by the validator. + * + * If we start with Schema's then we initialize to full set of + * validators. + */ + void expandRegistryToFullSchemaSet(); + + public: + // ----------------------------------------------------------------------- + // Canonical Representation Group + // ----------------------------------------------------------------------- + void initCanRepRegistory(); + + static XMLCanRepGroup::CanRepGroup getCanRepGroup(const DatatypeValidator* const); + + static DatatypeValidator* getBuiltInBaseValidator(const DatatypeValidator* const); + + // ----------------------------------------------------------------------- + // Validator Factory methods + // ----------------------------------------------------------------------- + /** @name Validator Factory Functions */ + //@{ + + /** + * Creates a new datatype validator of type baseValidator's class and + * adds it to the registry + * + * @param typeName Datatype validator name + * + * @param baseValidator Base datatype validator + * + * @param facets datatype facets if any + * + * @param enums vector of values for enum facet + * + * @param isDerivedByList Indicates whether the datatype is derived by + * list or not + * + * @param finalSet 'final' values of the simpleType + * + * @param isUserDefined Indicates whether the datatype is built-in or + * user defined + */ + DatatypeValidator* createDatatypeValidator + ( + const XMLCh* const typeName + , DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const bool isDerivedByList + , const int finalSet = 0 + , const bool isUserDefined = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Creates a new datatype validator of type UnionDatatypeValidator and + * adds it to the registry + * + * @param typeName Datatype validator name + * + * @param validators Vector of datatype validators + * + * @param finalSet 'final' values of the simpleType + * + * @param isUserDefined Indicates whether the datatype is built-in or + * user defined + */ + DatatypeValidator* createDatatypeValidator + ( + const XMLCh* const typeName + , RefVectorOf* const validators + , const int finalSet + , const bool isUserDefined = true + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Reset datatype validator registry + */ + void resetRegistry(); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DatatypeValidatorFactory) + +private: + + // ----------------------------------------------------------------------- + // CleanUp methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DatatypeValidatorFactory(const DatatypeValidatorFactory&); + DatatypeValidatorFactory& operator=(const DatatypeValidatorFactory&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fUserDefinedRegistry + // This is a hashtable of user defined dataype validators. + // + // fBuiltInRegistry + // This is a hashtable of built-in primitive datatype validators. + // ----------------------------------------------------------------------- + XERCES_CPP_NAMESPACE_QUALIFIER RefHashTableOf* fUserDefinedRegistry; + static XERCES_CPP_NAMESPACE_QUALIFIER RefHashTableOf* fBuiltInRegistry; + static XERCES_CPP_NAMESPACE_QUALIFIER RefHashTableOf* fCanRepRegistry; + XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* const fMemoryManager; + + friend class XPath2ContextImpl; + friend class XMLInitializer; +}; + +inline DatatypeValidator* +DatatypeValidatorFactory::getDatatypeValidator(const XMLCh* const dvType) const +{ + if (dvType) { + if (fBuiltInRegistry && fBuiltInRegistry->containsKey(dvType)) { + return fBuiltInRegistry->get(dvType); + } + + if (fUserDefinedRegistry && fUserDefinedRegistry->containsKey(dvType)) { + return fUserDefinedRegistry->get(dvType); + + } + } + return 0; +} + +inline DVHashTable* +DatatypeValidatorFactory::getUserDefinedRegistry() const { + return fUserDefinedRegistry; +} + +inline DVHashTable* +DatatypeValidatorFactory::getBuiltInRegistry() { + return fBuiltInRegistry; +} +// --------------------------------------------------------------------------- +// DatatypeValidator: CleanUp methods +// --------------------------------------------------------------------------- +inline void DatatypeValidatorFactory::cleanUp() { + + if (fUserDefinedRegistry) + { + delete fUserDefinedRegistry; + fUserDefinedRegistry = 0; + } +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DatatypeValidatorFactory.hpp + */ diff --git a/include/xercesc/validators/datatype/DateDatatypeValidator.cpp b/include/xercesc/validators/datatype/DateDatatypeValidator.cpp new file mode 100644 index 0000000..f2dec9d --- /dev/null +++ b/include/xercesc/validators/datatype/DateDatatypeValidator.cpp @@ -0,0 +1,140 @@ +/* + * 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: DateDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DateDatatypeValidator::DateDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::Date, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +DateDatatypeValidator::DateDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::Date, manager) +{ + init(enums, manager); +} + +DateDatatypeValidator::~DateDatatypeValidator() +{} + +DatatypeValidator* DateDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) DateDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* DateDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseDate(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void DateDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseDate(); +} + +const XMLCh* DateDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : fMemoryManager; + + if (toValidate) + { + DateDatatypeValidator* temp = (DateDatatypeValidator*) this; + + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + try + { + XMLDateTime aDateTime(rawData, toUse); + aDateTime.parseDate(); + return aDateTime.getDateCanonicalRepresentation(toUse); + } + catch (...) + { + return 0; + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DateDatatypeValidator) + +void DateDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DateDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/DateDatatypeValidator.hpp b/include/xercesc/validators/datatype/DateDatatypeValidator.hpp new file mode 100644 index 0000000..e2bc8a6 --- /dev/null +++ b/include/xercesc/validators/datatype/DateDatatypeValidator.hpp @@ -0,0 +1,101 @@ +/* + * 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: DateDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DATE_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DATE_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT DateDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + DateDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DateDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~DateDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DateDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DateDatatypeValidator(const DateDatatypeValidator&); + DateDatatypeValidator& operator=(const DateDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DateDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/DateTimeDatatypeValidator.cpp b/include/xercesc/validators/datatype/DateTimeDatatypeValidator.cpp new file mode 100644 index 0000000..f45705e --- /dev/null +++ b/include/xercesc/validators/datatype/DateTimeDatatypeValidator.cpp @@ -0,0 +1,140 @@ +/* + * 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: DateTimeDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DateTimeDatatypeValidator::DateTimeDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::DateTime, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +DateTimeDatatypeValidator::DateTimeDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::DateTime, manager) +{ + init(enums, manager); +} + +DateTimeDatatypeValidator::~DateTimeDatatypeValidator() +{} + +DatatypeValidator* DateTimeDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) DateTimeDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* DateTimeDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseDateTime(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void DateTimeDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseDateTime(); +} + +const XMLCh* DateTimeDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : fMemoryManager; + + if (toValidate) + { + DateTimeDatatypeValidator* temp = (DateTimeDatatypeValidator*) this; + + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + try + { + XMLDateTime aDateTime(rawData, toUse); + aDateTime.parseDateTime(); + return aDateTime.getDateTimeCanonicalRepresentation(toUse); + } + catch (...) + { + return 0; + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DateTimeDatatypeValidator) + +void DateTimeDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DateTimeDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/DateTimeDatatypeValidator.hpp b/include/xercesc/validators/datatype/DateTimeDatatypeValidator.hpp new file mode 100644 index 0000000..cd486ad --- /dev/null +++ b/include/xercesc/validators/datatype/DateTimeDatatypeValidator.hpp @@ -0,0 +1,102 @@ +/* + * 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: DateTimeDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DATETIME_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DATETIME_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT DateTimeDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + DateTimeDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DateTimeDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~DateTimeDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DateTimeDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DateTimeDatatypeValidator(const DateTimeDatatypeValidator&); + DateTimeDatatypeValidator& operator=(const DateTimeDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DateTimeDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/DateTimeValidator.cpp b/include/xercesc/validators/datatype/DateTimeValidator.cpp new file mode 100644 index 0000000..801ad2d --- /dev/null +++ b/include/xercesc/validators/datatype/DateTimeValidator.cpp @@ -0,0 +1,303 @@ +/* + * 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: DateTimeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Macro +// --------------------------------------------------------------------------- +#define REPORT_VALUE_ERROR(val1, val2, except_code, manager) \ + ThrowXMLwithMemMgr2(InvalidDatatypeValueException \ + , except_code \ + , val1->getRawData() \ + , val2->getRawData() \ + , manager); + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DateTimeValidator::~DateTimeValidator() +{ +} + +DateTimeValidator::DateTimeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:AbstractNumericFacetValidator(baseValidator, facets, finalSet, type, manager) +{ + //do not invoke init() here !!! +} + +void DateTimeValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + checkContent(content, context, false, manager); +} + +int DateTimeValidator::compare(const XMLCh* const value1 + , const XMLCh* const value2 + , MemoryManager* const manager) +{ + try + { + XMLDateTime *pDate1 = parse(value1, manager); + Janitor jName1(pDate1); + XMLDateTime *pDate2 = parse(value2, manager); + Janitor jName2(pDate2); + int result = compareDates(pDate1, pDate2, true); + return (result==INDETERMINATE)? -1 : result; + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) // RuntimeException e + { + return -1; // revisit after implement compareDates() + } + +} + + +void DateTimeValidator::checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + //validate against base validator if any + DateTimeValidator *pBaseValidator = (DateTimeValidator*) this->getBaseValidator(); + if (pBaseValidator) + pBaseValidator->checkContent(content, context, true, manager); + + int thisFacetsDefined = getFacetsDefined(); + + // we check pattern first + if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + // the derived classes' parse() method constructs an + // XMLDateTime object anc invokes appropriate XMLDateTime's + // parser to parse the content. + XMLDateTime dateTimeValue(content, manager); + XMLDateTime* dateTime = &dateTimeValue; + + parse(dateTime); + + // must be < MaxExclusive + if ((thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0) + { + if (compareValues(dateTime, getMaxExclusive()) != XMLDateTime::LESS_THAN) + { + REPORT_VALUE_ERROR( dateTime + , getMaxExclusive() + , XMLExcepts::VALUE_exceed_maxExcl + , manager) + } + } + + // must be <= MaxInclusive + if ((thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0) + { + int result = compareValues(dateTime, getMaxInclusive()); + if ( result == XMLDateTime::GREATER_THAN || result == XMLDateTime::INDETERMINATE ) + { + REPORT_VALUE_ERROR( dateTime + , getMaxInclusive() + , XMLExcepts::VALUE_exceed_maxIncl + , manager) + } + } + + // must be >= MinInclusive + if ((thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0) + { + int result = compareValues(dateTime, getMinInclusive()); + if (result == XMLDateTime::LESS_THAN || result == XMLDateTime::INDETERMINATE) + { + REPORT_VALUE_ERROR( dateTime + , getMinInclusive() + , XMLExcepts::VALUE_exceed_minIncl + , manager) + } + } + + // must be > MinExclusive + if ( (thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0 ) + { + if (compareValues(dateTime, getMinExclusive()) != XMLDateTime::GREATER_THAN) + { + REPORT_VALUE_ERROR( dateTime + , getMinExclusive() + , XMLExcepts::VALUE_exceed_minExcl + , manager) + } + } + + if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0)) + { + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (compareValues(dateTime, getEnumeration()->elementAt(i)) == XMLDateTime::EQUAL) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } +} + +// +// Comparision methods +// +int DateTimeValidator::compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue) +{ + return compareDates((XMLDateTime*) lValue, (XMLDateTime*) rValue, true); +} + +/** + * Compare algorithm described in dateDime (3.2.7). + * Duration datatype overwrites this method + * + * @param date1 normalized date representation of the first value + * @param date2 normalized date representation of the second value + * @param strict + * @return less, greater, less_equal, greater_equal, equal + */ +int DateTimeValidator::compareDates(const XMLDateTime* const date1 + , const XMLDateTime* const date2 + , bool) +{ + return XMLDateTime::compare(date1, date2); +} + +// +// In fact, the proper way of the following set*() shall be +// { +// if (fMaxInclusive) +// delete fMaxInclusive; +// +// fMaxInclusive = parse(value); +// +// } +// +// But we know this function is invoked once and only once +// since there is no duplicated facet passed in, therefore +// fMaxInclusive is alwasy zero before, so for the +// sake of performance, we do not do the checking/delete. +// + +void DateTimeValidator::setMaxInclusive(const XMLCh* const value) +{ + fMaxInclusive = parse(value, fMemoryManager); +} + +void DateTimeValidator::setMaxExclusive(const XMLCh* const value) +{ + fMaxExclusive = parse(value, fMemoryManager); +} + +void DateTimeValidator::setMinInclusive(const XMLCh* const value) +{ + fMinInclusive = parse(value, fMemoryManager); +} + +void DateTimeValidator::setMinExclusive(const XMLCh* const value) +{ + fMinExclusive = parse(value, fMemoryManager); +} + +void DateTimeValidator::setEnumeration(MemoryManager* const) +{ +// to do: do we need to check against base value space??? + + if (!fStrEnumeration) + return; + + XMLSize_t enumLength = fStrEnumeration->size(); + fEnumeration = new (fMemoryManager) RefVectorOf(enumLength, true, fMemoryManager); + fEnumerationInherited = false; + + for ( XMLSize_t i = 0; i < enumLength; i++) + fEnumeration->insertElementAt(parse(fStrEnumeration->elementAt(i), fMemoryManager), i); + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(DateTimeValidator) + +void DateTimeValidator::serialize(XSerializeEngine& serEng) +{ + /*** + * + * Note: All its derivatives share the same number type, that is + * XMLNumber::DateTime, so this class would write it. + ***/ + + if (serEng.isStoring()) + { + serEng<<(int) XMLNumber::DateTime; + } + + AbstractNumericFacetValidator::serialize(serEng); + + //dateTime can be instantiated during checkContent(), so don't serialize it. +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DateTimeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/DateTimeValidator.hpp b/include/xercesc/validators/datatype/DateTimeValidator.hpp new file mode 100644 index 0000000..3f6f0e1 --- /dev/null +++ b/include/xercesc/validators/datatype/DateTimeValidator.hpp @@ -0,0 +1,126 @@ +/* + * 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: DateTimeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DATETIME_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DATETIME_VALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT DateTimeValidator : public AbstractNumericFacetValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public dtor + // ----------------------------------------------------------------------- + /** @name Constructor. */ + //@{ + + virtual ~DateTimeValidator(); + + //@} + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual int compare(const XMLCh* const value1 + , const XMLCh* const value2 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DateTimeValidator) + +protected: + + // ----------------------------------------------------------------------- + // ctor used by derived class + // ----------------------------------------------------------------------- + DateTimeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // + // Abstract interface + // + + virtual int compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue); + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + + virtual void setMaxInclusive(const XMLCh* const); + + virtual void setMaxExclusive(const XMLCh* const); + + virtual void setMinInclusive(const XMLCh* const); + + virtual void setMinExclusive(const XMLCh* const); + + virtual void setEnumeration(MemoryManager* const manager); + +protected: + + // ----------------------------------------------------------------------- + // helper interface: to be implemented/overwritten by derived class + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager) = 0; + virtual void parse(XMLDateTime* const) = 0; + + // to be overwritten by duration + virtual int compareDates(const XMLDateTime* const lValue + , const XMLDateTime* const rValue + , bool strict); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DateTimeValidator(const DateTimeValidator&); + DateTimeValidator& operator=(const DateTimeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DateTimeValidator.hpp + */ + + diff --git a/include/xercesc/validators/datatype/DayDatatypeValidator.cpp b/include/xercesc/validators/datatype/DayDatatypeValidator.cpp new file mode 100644 index 0000000..ff22db9 --- /dev/null +++ b/include/xercesc/validators/datatype/DayDatatypeValidator.cpp @@ -0,0 +1,107 @@ +/* + * 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: DayDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DayDatatypeValidator::DayDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::Day, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +DayDatatypeValidator::DayDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::Day, manager) +{ + init(enums, manager); +} + +DayDatatypeValidator::~DayDatatypeValidator() +{} + +DatatypeValidator* DayDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) DayDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* DayDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseDay(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void DayDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseDay(); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DayDatatypeValidator) + +void DayDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DayDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/DayDatatypeValidator.hpp b/include/xercesc/validators/datatype/DayDatatypeValidator.hpp new file mode 100644 index 0000000..c66c59b --- /dev/null +++ b/include/xercesc/validators/datatype/DayDatatypeValidator.hpp @@ -0,0 +1,95 @@ +/* + * 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: DayDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DAY_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DAY_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT DayDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor*/ + //@{ + + DayDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DayDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~DayDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DayDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DayDatatypeValidator(const DayDatatypeValidator&); + DayDatatypeValidator& operator=(const DayDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DayDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/DecimalDatatypeValidator.cpp b/include/xercesc/validators/datatype/DecimalDatatypeValidator.cpp new file mode 100644 index 0000000..31172e6 --- /dev/null +++ b/include/xercesc/validators/datatype/DecimalDatatypeValidator.cpp @@ -0,0 +1,615 @@ +/* + * 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: DecimalDatatypeValidator.cpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static const int BUF_LEN = 64; + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DecimalDatatypeValidator::DecimalDatatypeValidator(MemoryManager* const manager) +:AbstractNumericValidator(0, 0, 0, DatatypeValidator::Decimal, manager) +, fTotalDigits(0) +, fFractionDigits(0) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_TOTAL); + setNumeric(true); +} + +DecimalDatatypeValidator::DecimalDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractNumericValidator(baseValidator, facets, finalSet, DatatypeValidator::Decimal, manager) +, fTotalDigits(0) +, fFractionDigits(0) +{ + init(enums, manager); +} + +DecimalDatatypeValidator::~DecimalDatatypeValidator() +{ +} + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int DecimalDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const manager) +{ + XMLBigDecimal lObj(lValue, manager); + XMLBigDecimal rObj(rValue, manager); + + return compareValues(&lObj, &rObj); +} + +DatatypeValidator* DecimalDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) DecimalDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// ----------------------------------------------------------------------- +// ctor provided to be used by derived classes +// ----------------------------------------------------------------------- +DecimalDatatypeValidator::DecimalDatatypeValidator(DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:AbstractNumericValidator(baseValidator, facets, finalSet, type, manager) +, fTotalDigits(0) +, fFractionDigits(0) +{ + //do not invoke init here !!! +} + +void DecimalDatatypeValidator::assignAdditionalFacet(const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager) +{ + if (XMLString::equals(key, SchemaSymbols::fgELT_TOTALDIGITS)) + { + int val; + try + { + val = XMLString::parseInt(value, manager); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_TotalDigit, value, manager); + } + + // check 4.3.11.c0 must: totalDigits > 0 + if ( val <= 0 ) + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_PosInt_TotalDigit, value, manager); + + setTotalDigits(val); + setFacetsDefined(DatatypeValidator::FACET_TOTALDIGITS); + } + else if (XMLString::equals(key, SchemaSymbols::fgELT_FRACTIONDIGITS)) + { + int val; + try + { + val = XMLString::parseInt(value, manager); + } + catch (NumberFormatException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_FractDigit, value, manager); + } + + // check 4.3.12.c0 must: fractionDigits > 0 + if ( val < 0 ) + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_NonNeg_FractDigit, value, manager); + + setFractionDigits(val); + setFacetsDefined(DatatypeValidator::FACET_FRACTIONDIGITS); + } + else + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , key + , manager); + } +} + +void DecimalDatatypeValidator::inheritAdditionalFacet() +{ + + DecimalDatatypeValidator *numBase = (DecimalDatatypeValidator*) getBaseValidator(); + + if (!numBase) + return; + + int thisFacetsDefined = getFacetsDefined(); + int baseFacetsDefined = numBase->getFacetsDefined(); + + // inherit totalDigits + if ((( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) == 0) ) + { + setTotalDigits(numBase->fTotalDigits); + setFacetsDefined(DatatypeValidator::FACET_TOTALDIGITS); + } + + // inherit fractionDigits + if ((( baseFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) && + (( thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) == 0) ) + { + setFractionDigits(numBase->fFractionDigits); + setFacetsDefined(DatatypeValidator::FACET_FRACTIONDIGITS); + } +} + +void DecimalDatatypeValidator::checkAdditionalFacetConstraints(MemoryManager* const manager) const +{ + int thisFacetsDefined = getFacetsDefined(); + + // check 4.3.12.c1 must: fractionDigits <= totalDigits + if ( ((thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) && + ((thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) ) + { + if ( fFractionDigits > fTotalDigits ) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(getFractionDigits(), value1, BUF_LEN, 10, manager); + XMLString::binToText(getTotalDigits(), value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_TotDigit_FractDigit + , value2 + , value1 + , manager); + } + } + +} + +void DecimalDatatypeValidator::checkAdditionalFacetConstraintsBase(MemoryManager* const manager) const +{ + + DecimalDatatypeValidator *numBase = (DecimalDatatypeValidator*) getBaseValidator(); + + if (!numBase) + return; + + int thisFacetsDefined = getFacetsDefined(); + int baseFacetsDefined = numBase->getFacetsDefined(); + + // check 4.3.11.c1 error: totalDigits > base.totalDigits + // totalDigits != base.totalDigits if (base.fixed) + if (( thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) + { + if ( (( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) && + ( fTotalDigits > numBase->fTotalDigits )) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(fTotalDigits, value1, BUF_LEN, 10, manager); + XMLString::binToText(numBase->fTotalDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_totalDigit_base_totalDigit + , value1 + , value2 + , manager); + } + + if ( (( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) && + (( numBase->getFixed() & DatatypeValidator::FACET_TOTALDIGITS) != 0) && + ( fTotalDigits != numBase->fTotalDigits )) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(fTotalDigits, value1, BUF_LEN, 10, manager); + XMLString::binToText(numBase->fTotalDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_totalDigit_base_fixed + , value1 + , value2 + , manager); + } + } + + if (( thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) + { + // check question error: fractionDigits > base.fractionDigits ??? + if ( (( baseFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) && + ( fFractionDigits > numBase->fFractionDigits )) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(fFractionDigits, value1, BUF_LEN, 10, manager); + XMLString::binToText(numBase->fFractionDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_fractDigit_base_fractDigit + , value1 + , value2 + , manager); + } + + // check question error: fractionDigits > base.totalDigits ??? + if ( (( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) && + ( fFractionDigits > numBase->fTotalDigits )) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(fFractionDigits, value1, BUF_LEN, 10, manager); + XMLString::binToText(numBase->fTotalDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_fractDigit_base_totalDigit + , value1 + , value2 + , manager); + } + + // fractionDigits != base.fractionDigits if (base.fixed) + if ( (( baseFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) && + (( numBase->getFixed() & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) && + ( fFractionDigits != numBase->fFractionDigits )) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(fFractionDigits, value1, BUF_LEN, 10, manager); + XMLString::binToText(numBase->fFractionDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_fractDigit_base_fixed + , value1 + , value2 + , manager); + } + } + +} + +int DecimalDatatypeValidator::compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue) +{ + return XMLBigDecimal::compareValues((XMLBigDecimal*) lValue, (XMLBigDecimal*) rValue, + ((XMLBigDecimal*)lValue)->getMemoryManager()); +} + +void DecimalDatatypeValidator::setMaxInclusive(const XMLCh* const value) +{ + fMaxInclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager); +} + +void DecimalDatatypeValidator::setMaxExclusive(const XMLCh* const value) +{ + fMaxExclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager); +} + +void DecimalDatatypeValidator::setMinInclusive(const XMLCh* const value) +{ + fMinInclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager); +} + +void DecimalDatatypeValidator::setMinExclusive(const XMLCh* const value) +{ + fMinExclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager); +} + +void DecimalDatatypeValidator::setEnumeration(MemoryManager* const manager) +{ + // check 4.3.5.c0 must: enumeration values from the value space of base + // + // 1. shall be from base value space + // 2. shall be from current value space as well ( shall go through boundsCheck() ) + // + if (!fStrEnumeration) + return; + + XMLSize_t i = 0; + XMLSize_t enumLength = fStrEnumeration->size(); + + DecimalDatatypeValidator *numBase = (DecimalDatatypeValidator*) getBaseValidator(); + if (numBase) + { + try + { + for ( i = 0; i < enumLength; i++) + { + numBase->checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager); + } + } + catch (XMLException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_enum_base + , fStrEnumeration->elementAt(i) + , manager); + } + } +#if 0 +// spec says that only base has to checkContent + // We put the this->checkContent in a separate loop + // to not block original message with in that method. + // + for ( i = 0; i < enumLength; i++) + { + checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager); + } +#endif + fEnumeration = new (manager) RefVectorOf(enumLength, true, manager); + fEnumerationInherited = false; + + for ( i = 0; i < enumLength; i++) + { + fEnumeration->insertElementAt(new (manager) XMLBigDecimal(fStrEnumeration->elementAt(i), manager), i); + } + +} + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericValidator +// ----------------------------------------------------------------------- +void DecimalDatatypeValidator::checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + //validate against base validator if any + DecimalDatatypeValidator *pBase = (DecimalDatatypeValidator*) this->getBaseValidator(); + if (pBase) + pBase->checkContent(content, context, true, manager); + + int thisFacetsDefined = getFacetsDefined(); + + // we check pattern first + if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + XMLBigDecimal compareDataValue(content, manager); + XMLBigDecimal* compareData = &compareDataValue; + + if (getEnumeration()) + { + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (compareValues(compareData, (XMLBigDecimal*) getEnumeration()->elementAt(i)) ==0 ) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } + + boundsCheck(compareData, manager); + + if ( (thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0 ) + { + if ( compareData->getScale() > fFractionDigits ) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(compareData->getScale(), value1, BUF_LEN, 10, manager); + XMLString::binToText(fFractionDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr3(InvalidDatatypeFacetException + , XMLExcepts::VALUE_exceed_fractDigit + , compareData->getRawData() + , value1 + , value2 + , manager); + } + } + + if ( (thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0 ) + { + if ( compareData->getTotalDigit() > fTotalDigits ) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(compareData->getTotalDigit(), value1, BUF_LEN, 10, manager); + XMLString::binToText(fTotalDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr3(InvalidDatatypeFacetException + , XMLExcepts::VALUE_exceed_totalDigit + , compareData->getRawData() + , value1 + , value2 + , manager); + } + + /*** + E2-44 totalDigits + ... by restricting it to numbers that are expressible as i x 10^-n + where i and n are integers such that |i| < 10^totalDigits and 0 <= n <= totalDigits. + ***/ + + if ( compareData->getScale() > fTotalDigits ) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::binToText(compareData->getScale(), value1, BUF_LEN, 10, manager); + XMLString::binToText(fTotalDigits, value2, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr3(InvalidDatatypeFacetException + , XMLExcepts::VALUE_exceed_totalDigit + , compareData->getRawData() + , value1 + , value2 + , manager); + } + } +} + +/*** + * 3.2.3 decimal + * + * . the preceding optional "+" sign is prohibited. + * . The decimal point is required. + * . Leading and trailing zeroes are prohibited subject to the following: + * there must be at least one digit to the right and to the left of the decimal point which may be a zero. + * + * + * 3.3.13 integer + * 3.3.16 long + * 3.3.17 int + * 3.3.18 short + * 3.3.19 byte + * 3.3.20 nonNegativeInteger + * 3.3.25 positiveInteger + * + * . the preceding optional "+" sign is prohibited and + * . leading zeroes are prohibited. + * + * + * E2-27 + * 3.3.14 nonPositiveInteger + * + * . In the canonical form for zero, the sign must be omitted. + * . leading zeroes are prohibited. + * + * 3.3.15 negativeInteger + * 3.3.21 unsignedLong + * 3.3.22 unsignedInt + * 3.3.23 unsignedShort + * 3.3.24 unsignedByte + * + * . leading zeroes are prohibited. + * + * Summary: + * . leading zeros are prohibited for all three groups + * . '-' is required for nonPositiveInteger if it is zero + * + ***/ + +const XMLCh* DecimalDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : fMemoryManager; + DecimalDatatypeValidator* temp = (DecimalDatatypeValidator*) this; + + if (toValidate) + { + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + // XMLBigInteger::getCanonicalRepresentation and + // XMLBigDecimal::getCanonicalRepresentation will handle exceptional cases + XMLCanRepGroup::CanRepGroup dvType = DatatypeValidatorFactory::getCanRepGroup(temp); + + if ((dvType == XMLCanRepGroup::Decimal_Derived_signed) || + (dvType == XMLCanRepGroup::Decimal_Derived_unsigned) || + (dvType == XMLCanRepGroup::Decimal_Derived_npi) ) + { + return XMLBigInteger::getCanonicalRepresentation(rawData, toUse, dvType == XMLCanRepGroup::Decimal_Derived_npi); + } + else if (dvType == XMLCanRepGroup::Decimal) + { + return XMLBigDecimal::getCanonicalRepresentation(rawData, toUse); + } + else //in case? + { + return XMLString::replicate(rawData, toUse); + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DecimalDatatypeValidator) + +void DecimalDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + /*** + * Note: + * + * During storing, we need write the specific number + * type info before calling base::serialize(). + * + * While loading, we do nothing here + ***/ + + if (serEng.isStoring()) + { + serEng<<(int) (XMLNumber::BigDecimal); + } + + AbstractNumericValidator::serialize(serEng); + + //don't serialize XMLBigDecimal* + if (serEng.isStoring()) + { + serEng<>fTotalDigits; + serEng>>fFractionDigits; + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DecimalDatatypeValidator::cpp + */ diff --git a/include/xercesc/validators/datatype/DecimalDatatypeValidator.hpp b/include/xercesc/validators/datatype/DecimalDatatypeValidator.hpp new file mode 100644 index 0000000..e4e67c8 --- /dev/null +++ b/include/xercesc/validators/datatype/DecimalDatatypeValidator.hpp @@ -0,0 +1,218 @@ +/* + * 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: DecimalDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DECIMAL_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DECIMAL_DATATYPEVALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLBigDecimal; + +class VALIDATORS_EXPORT DecimalDatatypeValidator : public AbstractNumericValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + DecimalDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DecimalDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~DecimalDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DecimalDatatypeValidator) + +protected: + +// ----------------------------------------------------------------------- +// ctor provided to be used by derived classes +// ----------------------------------------------------------------------- + DecimalDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericFacetValidator +// ----------------------------------------------------------------------- + + virtual void assignAdditionalFacet(const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager); + + virtual void inheritAdditionalFacet(); + + virtual void checkAdditionalFacetConstraints(MemoryManager* const manager) const; + + virtual void checkAdditionalFacetConstraintsBase(MemoryManager* const manager) const; + + virtual int compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue); + + virtual void setMaxInclusive(const XMLCh* const); + + virtual void setMaxExclusive(const XMLCh* const); + + virtual void setMinInclusive(const XMLCh* const); + + virtual void setMinExclusive(const XMLCh* const); + + virtual void setEnumeration(MemoryManager* const manager); + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericValidator +// ----------------------------------------------------------------------- + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); +public: + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + + inline unsigned int getTotalDigits() const; + + inline unsigned int getFractionDigits() const; + +private: +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- + + inline void setTotalDigits(unsigned int); + + inline void setFractionDigits(unsigned int); + + // ----------------------------------------------------------------------- + // Private data members + // + // ----------------------------------------------------------------------- + unsigned int fTotalDigits; + unsigned int fFractionDigits; + + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DecimalDatatypeValidator(const DecimalDatatypeValidator&); + DecimalDatatypeValidator& operator=(const DecimalDatatypeValidator&); +}; + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + +inline unsigned int DecimalDatatypeValidator::getTotalDigits() const +{ + return fTotalDigits; +} + +inline unsigned int DecimalDatatypeValidator::getFractionDigits() const +{ + return fFractionDigits; +} + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- + +inline void DecimalDatatypeValidator::setTotalDigits(unsigned int newTotalDigits) +{ + fTotalDigits = newTotalDigits; +} + +inline void DecimalDatatypeValidator::setFractionDigits(unsigned int newFractionDigits) +{ + fFractionDigits = newFractionDigits; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DecimalDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/DoubleDatatypeValidator.cpp b/include/xercesc/validators/datatype/DoubleDatatypeValidator.cpp new file mode 100644 index 0000000..a8e62fd --- /dev/null +++ b/include/xercesc/validators/datatype/DoubleDatatypeValidator.cpp @@ -0,0 +1,256 @@ +/* + * 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: DoubleDatatypeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DoubleDatatypeValidator::DoubleDatatypeValidator(MemoryManager* const manager) +:AbstractNumericValidator(0, 0, 0, DatatypeValidator::Double, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); + setBounded(true); + setFinite(true); + setNumeric(true); +} + +DoubleDatatypeValidator::DoubleDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractNumericValidator(baseValidator, facets, finalSet, DatatypeValidator::Double, manager) +{ + init(enums, manager); +} + +DoubleDatatypeValidator::~DoubleDatatypeValidator() +{} + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int DoubleDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const manager) +{ + XMLDouble lObj(lValue, manager); + XMLDouble rObj(rValue, manager); + + return compareValues(&lObj, &rObj); +} + +DatatypeValidator* DoubleDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) DoubleDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// ----------------------------------------------------------------------- +// ctor provided to be used by derived classes +// ----------------------------------------------------------------------- +DoubleDatatypeValidator::DoubleDatatypeValidator(DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:AbstractNumericValidator(baseValidator, facets, finalSet, type, manager) +{ + //do not invoke init here !!! +} + +int DoubleDatatypeValidator::compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue) +{ + return XMLDouble::compareValues((XMLDouble*) lValue, (XMLDouble*) rValue); +} + +void DoubleDatatypeValidator::setMaxInclusive(const XMLCh* const value) +{ + fMaxInclusive = new (fMemoryManager) XMLDouble(value, fMemoryManager); +} + +void DoubleDatatypeValidator::setMaxExclusive(const XMLCh* const value) +{ + fMaxExclusive = new (fMemoryManager) XMLDouble(value, fMemoryManager); +} + +void DoubleDatatypeValidator::setMinInclusive(const XMLCh* const value) +{ + fMinInclusive = new (fMemoryManager) XMLDouble(value, fMemoryManager); +} + +void DoubleDatatypeValidator::setMinExclusive(const XMLCh* const value) +{ + fMinExclusive = new (fMemoryManager) XMLDouble(value, fMemoryManager); +} + +void DoubleDatatypeValidator::setEnumeration(MemoryManager* const manager) +{ + // check 4.3.5.c0 must: enumeration values from the value space of base + // + // 1. shall be from base value space + // 2. shall be from current value space as well ( shall go through boundsCheck() ) + // + if (!fStrEnumeration) + return; + + XMLSize_t i = 0; + XMLSize_t enumLength = fStrEnumeration->size(); + + DoubleDatatypeValidator *numBase = (DoubleDatatypeValidator*) getBaseValidator(); + if (numBase) + { + try + { + for ( i = 0; i < enumLength; i++) + { + numBase->checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager); + } + } + catch (XMLException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_enum_base + , fStrEnumeration->elementAt(i) + , manager); + + } + } + +#if 0 +// spec says that only base has to checkContent + // We put the this->checkContent in a separate loop + // to not block original message with in that method. + // + for ( i = 0; i < enumLength; i++) + { + checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager); + } +#endif + + fEnumeration = new (manager) RefVectorOf(enumLength, true, manager); + fEnumerationInherited = false; + + for ( i = 0; i < enumLength; i++) + { + fEnumeration->insertElementAt(new (manager) XMLDouble(fStrEnumeration->elementAt(i), manager), i); + } +} + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericValidator +// ----------------------------------------------------------------------- + +void DoubleDatatypeValidator::checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + + //validate against base validator if any + DoubleDatatypeValidator *pBase = (DoubleDatatypeValidator*) this->getBaseValidator(); + if (pBase) + pBase->checkContent(content, context, true, manager); + + // we check pattern first + if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + XMLDouble theValue(content, manager); + XMLDouble *theData = &theValue; + + if (getEnumeration()) + { + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (compareValues(theData, (XMLDouble*) getEnumeration()->elementAt(i)) ==0 ) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } + + boundsCheck(theData, manager); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DoubleDatatypeValidator) + +void DoubleDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + /*** + * Note: + * + * During storing, we need write the specific number + * type info before calling base::serialize(). + * + * While loading, we do nothing here + ***/ + + if (serEng.isStoring()) + { + serEng<<(int) (XMLNumber::Double); + } + + AbstractNumericValidator::serialize(serEng); + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DoubleDatatypeValidator::cpp + */ diff --git a/include/xercesc/validators/datatype/DoubleDatatypeValidator.hpp b/include/xercesc/validators/datatype/DoubleDatatypeValidator.hpp new file mode 100644 index 0000000..545c102 --- /dev/null +++ b/include/xercesc/validators/datatype/DoubleDatatypeValidator.hpp @@ -0,0 +1,146 @@ +/* + * 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: DoubleDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DOUBLE_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DOUBLE_DATATYPEVALIDATOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT DoubleDatatypeValidator : public AbstractNumericValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + DoubleDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DoubleDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~DoubleDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DoubleDatatypeValidator) + +protected: + +// ----------------------------------------------------------------------- +// ctor provided to be used by derived classes +// ----------------------------------------------------------------------- + DoubleDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericFacetValidator +// ----------------------------------------------------------------------- + + virtual int compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue); + + virtual void setMaxInclusive(const XMLCh* const); + + virtual void setMaxExclusive(const XMLCh* const); + + virtual void setMinInclusive(const XMLCh* const); + + virtual void setMinExclusive(const XMLCh* const); + + virtual void setEnumeration(MemoryManager* const manager); + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericValidator +// ----------------------------------------------------------------------- + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DoubleDatatypeValidator(const DoubleDatatypeValidator &); + DoubleDatatypeValidator& operator = (const DoubleDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DoubleDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/DurationDatatypeValidator.cpp b/include/xercesc/validators/datatype/DurationDatatypeValidator.cpp new file mode 100644 index 0000000..5831fda --- /dev/null +++ b/include/xercesc/validators/datatype/DurationDatatypeValidator.cpp @@ -0,0 +1,114 @@ +/* + * 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: DurationDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +DurationDatatypeValidator::DurationDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::Duration, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +DurationDatatypeValidator::DurationDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::Duration, manager) +{ + init(enums, manager); +} + +DurationDatatypeValidator::~DurationDatatypeValidator() +{} + +DatatypeValidator* DurationDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) DurationDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* DurationDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseDuration(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void DurationDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseDuration(); +} + +int DurationDatatypeValidator::compareDates(const XMLDateTime* const date1 + , const XMLDateTime* const date2 + , bool strict) +{ + return XMLDateTime::compare(date1, date2, strict); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(DurationDatatypeValidator) + +void DurationDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DurationDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/DurationDatatypeValidator.hpp b/include/xercesc/validators/datatype/DurationDatatypeValidator.hpp new file mode 100644 index 0000000..ba08224 --- /dev/null +++ b/include/xercesc/validators/datatype/DurationDatatypeValidator.hpp @@ -0,0 +1,98 @@ +/* + * 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: DurationDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_DURATION_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_DURATION_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT DurationDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor. */ + //@{ + + DurationDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + DurationDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~DurationDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(DurationDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + virtual int compareDates(const XMLDateTime* const + , const XMLDateTime* const + , bool ); +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + DurationDatatypeValidator(const DurationDatatypeValidator &); + DurationDatatypeValidator& operator = (const DurationDatatypeValidator&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file DurationDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/ENTITYDatatypeValidator.cpp b/include/xercesc/validators/datatype/ENTITYDatatypeValidator.cpp new file mode 100644 index 0000000..157e4f5 --- /dev/null +++ b/include/xercesc/validators/datatype/ENTITYDatatypeValidator.cpp @@ -0,0 +1,125 @@ +/* + * 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: ENTITYDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +ENTITYDatatypeValidator::ENTITYDatatypeValidator(MemoryManager* const manager) +:StringDatatypeValidator(0, 0, 0, DatatypeValidator::ENTITY, manager) +{} + +ENTITYDatatypeValidator::ENTITYDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::ENTITY, manager) +{ + init(enums, manager); +} + +ENTITYDatatypeValidator::~ENTITYDatatypeValidator() +{} + +DatatypeValidator* ENTITYDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) ENTITYDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int ENTITYDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const) +{ + return ( XMLString::equals(lValue, rValue)? 0 : -1); +} + +void ENTITYDatatypeValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + // use StringDatatypeValidator (which in turn, invoke + // the baseValidator) to validate content against + // facets if any. + // + StringDatatypeValidator::validate(content, context, manager); + + // + // parse the entity iff an EntityDeclPool is provided + // + if (context) + { + context->checkEntity(content); + } + +} + +void ENTITYDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + // + // 3.3.11 check must: "NCName" + // + if ( !XMLChar1_0::isValidNCName(content, XMLString::stringLen(content)) ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_Invalid_NCName + , content + , manager); + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(ENTITYDatatypeValidator) + +void ENTITYDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + StringDatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + + /** + * End of file ENTITYDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/ENTITYDatatypeValidator.hpp b/include/xercesc/validators/datatype/ENTITYDatatypeValidator.hpp new file mode 100644 index 0000000..f8f9865 --- /dev/null +++ b/include/xercesc/validators/datatype/ENTITYDatatypeValidator.hpp @@ -0,0 +1,144 @@ +/* + * 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: ENTITYDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ENTITY_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ENTITY_DATATYPEVALIDATOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT ENTITYDatatypeValidator : public StringDatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor. */ + //@{ + + ENTITYDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ENTITYDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~ENTITYDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(ENTITYDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes + // + ENTITYDatatypeValidator(DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type); + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ENTITYDatatypeValidator(const ENTITYDatatypeValidator&); + ENTITYDatatypeValidator& operator = (const ENTITYDatatypeValidator&); + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file ENTITYDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/FloatDatatypeValidator.cpp b/include/xercesc/validators/datatype/FloatDatatypeValidator.cpp new file mode 100644 index 0000000..1a418e7 --- /dev/null +++ b/include/xercesc/validators/datatype/FloatDatatypeValidator.cpp @@ -0,0 +1,255 @@ +/* + * 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: FloatDatatypeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +FloatDatatypeValidator::FloatDatatypeValidator(MemoryManager* const manager) +:AbstractNumericValidator(0, 0, 0, DatatypeValidator::Float, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); + setBounded(true); + setFinite(true); + setNumeric(true); +} + +FloatDatatypeValidator::FloatDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractNumericValidator(baseValidator, facets, finalSet, DatatypeValidator::Float, manager) +{ + init(enums, manager); +} + +FloatDatatypeValidator::~FloatDatatypeValidator() +{} + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int FloatDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const manager) +{ + XMLFloat lObj(lValue, manager); + XMLFloat rObj(rValue, manager); + + return compareValues(&lObj, &rObj); +} + +DatatypeValidator* FloatDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) FloatDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// ----------------------------------------------------------------------- +// ctor provided to be used by derived classes +// ----------------------------------------------------------------------- +FloatDatatypeValidator::FloatDatatypeValidator(DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:AbstractNumericValidator(baseValidator, facets, finalSet, type, manager) +{ + //do not invoke init here !!! +} + +int FloatDatatypeValidator::compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue) +{ + return XMLFloat::compareValues((XMLFloat*) lValue, (XMLFloat*) rValue); +} + +void FloatDatatypeValidator::setMaxInclusive(const XMLCh* const value) +{ + fMaxInclusive = new (fMemoryManager) XMLFloat(value, fMemoryManager); +} + +void FloatDatatypeValidator::setMaxExclusive(const XMLCh* const value) +{ + fMaxExclusive = new (fMemoryManager) XMLFloat(value, fMemoryManager); +} + +void FloatDatatypeValidator::setMinInclusive(const XMLCh* const value) +{ + fMinInclusive = new (fMemoryManager) XMLFloat(value, fMemoryManager); +} + +void FloatDatatypeValidator::setMinExclusive(const XMLCh* const value) +{ + fMinExclusive = new (fMemoryManager) XMLFloat(value, fMemoryManager); +} + +void FloatDatatypeValidator::setEnumeration(MemoryManager* const manager) +{ + // check 4.3.5.c0 must: enumeration values from the value space of base + // + // 1. shall be from base value space + // 2. shall be from current value space as well ( shall go through boundsCheck() ) + // + if (!fStrEnumeration) + return; + + XMLSize_t i = 0; + XMLSize_t enumLength = fStrEnumeration->size(); + + FloatDatatypeValidator *numBase = (FloatDatatypeValidator*) getBaseValidator(); + if (numBase) + { + try + { + for ( i = 0; i < enumLength; i++) + { + numBase->checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager); + } + } + catch (XMLException&) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_enum_base + , fStrEnumeration->elementAt(i) + , manager); + + } + } +#if 0 +// spec says that only base has to checkContent + // We put the this->checkContent in a separate loop + // to not block original message with in that method. + // + for ( i = 0; i < enumLength; i++) + { + checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager); + } +#endif + + fEnumeration = new (fMemoryManager) RefVectorOf(enumLength, true, fMemoryManager); + fEnumerationInherited = false; + + for ( i = 0; i < enumLength; i++) + { + fEnumeration->insertElementAt(new (fMemoryManager) XMLFloat(fStrEnumeration->elementAt(i), fMemoryManager), i); + } +} + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericValidator +// ----------------------------------------------------------------------- +void FloatDatatypeValidator::checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + + //validate against base validator if any + FloatDatatypeValidator *pBase = (FloatDatatypeValidator*) this->getBaseValidator(); + if (pBase) + pBase->checkContent(content, context, true, manager); + + // we check pattern first + if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + XMLFloat theValue(content, manager); + XMLFloat *theData = &theValue; + + if (getEnumeration() != 0) + { + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (compareValues(theData, (XMLFloat*) getEnumeration()->elementAt(i))==0) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } + + boundsCheck(theData, manager); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(FloatDatatypeValidator) + +void FloatDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + /*** + * Note: + * + * During storing, we need write the specific number + * type info before calling base::serialize(). + * + * While loading, we do nothing here + ***/ + + if (serEng.isStoring()) + { + serEng<<(int) (XMLNumber::Float); + } + + AbstractNumericValidator::serialize(serEng); + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file FloatDatatypeValidator::cpp + */ diff --git a/include/xercesc/validators/datatype/FloatDatatypeValidator.hpp b/include/xercesc/validators/datatype/FloatDatatypeValidator.hpp new file mode 100644 index 0000000..ff05c37 --- /dev/null +++ b/include/xercesc/validators/datatype/FloatDatatypeValidator.hpp @@ -0,0 +1,145 @@ +/* + * 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: FloatDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_FLOAT_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_FLOAT_DATATYPEVALIDATOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT FloatDatatypeValidator : public AbstractNumericValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + FloatDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + FloatDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~FloatDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(FloatDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // ctor provided to be used by derived classes + // ----------------------------------------------------------------------- + FloatDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // ----------------------------------------------------------------------- + // Abstract interface from AbstractNumericFacetValidator + // ----------------------------------------------------------------------- + + virtual int compareValues(const XMLNumber* const lValue + , const XMLNumber* const rValue); + + virtual void setMaxInclusive(const XMLCh* const); + + virtual void setMaxExclusive(const XMLCh* const); + + virtual void setMinInclusive(const XMLCh* const); + + virtual void setMinExclusive(const XMLCh* const); + + virtual void setEnumeration(MemoryManager* const manager); + +// ----------------------------------------------------------------------- +// Abstract interface from AbstractNumericValidator +// ----------------------------------------------------------------------- + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + FloatDatatypeValidator(const FloatDatatypeValidator&); + FloatDatatypeValidator& operator = (const FloatDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file FloatDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/HexBinaryDatatypeValidator.cpp b/include/xercesc/validators/datatype/HexBinaryDatatypeValidator.cpp new file mode 100644 index 0000000..1618a3b --- /dev/null +++ b/include/xercesc/validators/datatype/HexBinaryDatatypeValidator.cpp @@ -0,0 +1,101 @@ +/* + * 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: HexBinaryDatatypeValidator.cpp 695949 2008-09-16 15:57:44Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +HexBinaryDatatypeValidator::HexBinaryDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::HexBinary, manager) +{} + +HexBinaryDatatypeValidator::~HexBinaryDatatypeValidator() +{} + +HexBinaryDatatypeValidator::HexBinaryDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::HexBinary, manager) +{ + init(enums, manager); +} + +DatatypeValidator* HexBinaryDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) HexBinaryDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void HexBinaryDatatypeValidator::checkValueSpace(const XMLCh* const content, + MemoryManager* const manager) +{ + if (HexBin::getDataLength(content) < 0) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_Not_HexBin + , content + , manager); + } +} + +XMLSize_t HexBinaryDatatypeValidator::getLength(const XMLCh* const content + , MemoryManager* const) const +{ + return (XMLSize_t)HexBin::getDataLength(content); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(HexBinaryDatatypeValidator) + +void HexBinaryDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file HexBinaryDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/HexBinaryDatatypeValidator.hpp b/include/xercesc/validators/datatype/HexBinaryDatatypeValidator.hpp new file mode 100644 index 0000000..ca820d6 --- /dev/null +++ b/include/xercesc/validators/datatype/HexBinaryDatatypeValidator.hpp @@ -0,0 +1,101 @@ +/* + * 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: HexBinaryDatatypeValidator.hpp 695949 2008-09-16 15:57:44Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_HEXBINARY_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_HEXBINARY_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT HexBinaryDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + HexBinaryDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + HexBinaryDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~HexBinaryDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(HexBinaryDatatypeValidator) + +protected: + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + + virtual XMLSize_t getLength(const XMLCh* const content + , MemoryManager* const manager) const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + HexBinaryDatatypeValidator(const HexBinaryDatatypeValidator&); + HexBinaryDatatypeValidator& operator=(const HexBinaryDatatypeValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // Nil. + // ----------------------------------------------------------------------- +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file HexBinaryDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/IDDatatypeValidator.cpp b/include/xercesc/validators/datatype/IDDatatypeValidator.cpp new file mode 100644 index 0000000..eed724a --- /dev/null +++ b/include/xercesc/validators/datatype/IDDatatypeValidator.cpp @@ -0,0 +1,123 @@ +/* + * 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: IDDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +IDDatatypeValidator::IDDatatypeValidator(MemoryManager* const manager) +:StringDatatypeValidator(0, 0, 0, DatatypeValidator::ID, manager) +{} + +IDDatatypeValidator::IDDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::ID, manager) +{ + init(enums, manager); +} + +IDDatatypeValidator::~IDDatatypeValidator() +{} + +DatatypeValidator* IDDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) IDDatatypeValidator(this, facets, enums, finalSet, manager); +} + +IDDatatypeValidator::IDDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, type, manager) +{ + // do not invoke init() here!!! +} + +void IDDatatypeValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + // use StringDatatypeValidator (which in turn, invoke + // the baseValidator) to validate content against + // facets if any. + // + StringDatatypeValidator::validate(content, context, manager); + + // storing IDs to the global ID table + if (context) + { + context->addId(content); + } + +} + +void IDDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + // + // 3.3.8 check must: "NCName" + // + if ( !XMLChar1_0::isValidNCName(content, XMLString::stringLen(content)) ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_Invalid_NCName + , content + , manager); + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IDDatatypeValidator) + +void IDDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + StringDatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IDDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/IDDatatypeValidator.hpp b/include/xercesc/validators/datatype/IDDatatypeValidator.hpp new file mode 100644 index 0000000..1088c7d --- /dev/null +++ b/include/xercesc/validators/datatype/IDDatatypeValidator.hpp @@ -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: IDDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_ID_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_ID_DATATYPEVALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT IDDatatypeValidator : public StringDatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + IDDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + IDDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~IDDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IDDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes + // + IDDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IDDatatypeValidator(const IDDatatypeValidator&); + IDDatatypeValidator& operator=(const IDDatatypeValidator&); + // ----------------------------------------------------------------------- + // Private data members + // + // + // ----------------------------------------------------------------------- +}; + +XERCES_CPP_NAMESPACE_END + +#endif +/** + * End of file IDDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/IDREFDatatypeValidator.cpp b/include/xercesc/validators/datatype/IDREFDatatypeValidator.cpp new file mode 100644 index 0000000..dd0f6cf --- /dev/null +++ b/include/xercesc/validators/datatype/IDREFDatatypeValidator.cpp @@ -0,0 +1,125 @@ +/* + * 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: IDREFDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +IDREFDatatypeValidator::IDREFDatatypeValidator(MemoryManager* const manager) +:StringDatatypeValidator(0, 0, 0, DatatypeValidator::IDREF, manager) +{} + +IDREFDatatypeValidator::IDREFDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::IDREF, manager) +{ + init(enums, manager); +} + +IDREFDatatypeValidator::~IDREFDatatypeValidator() +{} + +DatatypeValidator* IDREFDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) IDREFDatatypeValidator(this, facets, enums, finalSet, manager); +} + +IDREFDatatypeValidator::IDREFDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, type, manager) +{ + // do not invoke init() here!!! +} + +void IDREFDatatypeValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + // use StringDatatypeValidator (which in turn, invoke + // the baseValidator) to validate content against + // facets if any. + // + StringDatatypeValidator::validate(content, context, manager); + + // this is different from java, since we always add, while + // in java, it is done as told. REVISIT. + // + if (context) + { + context->addIdRef(content); + } + +} + +void IDREFDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + // + // 3.3.9 check must: "NCName" + // + if ( !XMLChar1_0::isValidNCName(content, XMLString::stringLen(content)) ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_Invalid_NCName + , content + , manager); + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IDREFDatatypeValidator) + +void IDREFDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + StringDatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IDREFDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/IDREFDatatypeValidator.hpp b/include/xercesc/validators/datatype/IDREFDatatypeValidator.hpp new file mode 100644 index 0000000..01d7309 --- /dev/null +++ b/include/xercesc/validators/datatype/IDREFDatatypeValidator.hpp @@ -0,0 +1,135 @@ +/* + * 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: IDREFDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IDREF_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_IDREF_DATATYPEVALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT IDREFDatatypeValidator : public StringDatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + IDREFDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + IDREFDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~IDREFDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IDREFDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes + // + IDREFDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IDREFDatatypeValidator(const IDREFDatatypeValidator&); + IDREFDatatypeValidator& operator=(const IDREFDatatypeValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // + // ----------------------------------------------------------------------- + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IDREFDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/InvalidDatatypeFacetException.hpp b/include/xercesc/validators/datatype/InvalidDatatypeFacetException.hpp new file mode 100644 index 0000000..d62412d --- /dev/null +++ b/include/xercesc/validators/datatype/InvalidDatatypeFacetException.hpp @@ -0,0 +1,34 @@ +/* + * 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: InvalidDatatypeFacetException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_INVALIDDATATYPEFACETEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_INVALIDDATATYPEFACETEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(InvalidDatatypeFacetException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/datatype/InvalidDatatypeValueException.hpp b/include/xercesc/validators/datatype/InvalidDatatypeValueException.hpp new file mode 100644 index 0000000..6ec8e5c --- /dev/null +++ b/include/xercesc/validators/datatype/InvalidDatatypeValueException.hpp @@ -0,0 +1,34 @@ +/* + * 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: InvalidDatatypeValueException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_INVALIDDATATYPEVALUEEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_INVALIDDATATYPEVALUEEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(InvalidDatatypeValueException, XMLUTIL_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/datatype/ListDatatypeValidator.cpp b/include/xercesc/validators/datatype/ListDatatypeValidator.cpp new file mode 100644 index 0000000..d6039b1 --- /dev/null +++ b/include/xercesc/validators/datatype/ListDatatypeValidator.cpp @@ -0,0 +1,459 @@ +/* + * 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: ListDatatypeValidator.cpp 695949 2008-09-16 15:57:44Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static const int BUF_LEN = 64; + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +ListDatatypeValidator::ListDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::List, manager) +,fContent(0) +{} + +ListDatatypeValidator::ListDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::List, manager) +,fContent(0) +{ + // + // baseValidator shall either + // an atomic DTV which servers as itemType, or + // another ListDTV from which, this ListDTV is derived by restriction. + // + // In either case, it shall be not null + // + if (!baseValidator) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_List_Null_baseValidator, manager); + + init(enums, manager); +} + +ListDatatypeValidator::~ListDatatypeValidator() +{} + +DatatypeValidator* ListDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) ListDatatypeValidator(this, facets, enums, finalSet, manager); +} + + +int ListDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const manager) +{ + DatatypeValidator* theItemTypeDTV = getItemTypeDTV(); + BaseRefVectorOf* lVector = XMLString::tokenizeString(lValue, manager); + Janitor > janl(lVector); + BaseRefVectorOf* rVector = XMLString::tokenizeString(rValue, manager); + Janitor > janr(rVector); + + XMLSize_t lNumberOfTokens = lVector->size(); + XMLSize_t rNumberOfTokens = rVector->size(); + + if (lNumberOfTokens < rNumberOfTokens) + return -1; + else if (lNumberOfTokens > rNumberOfTokens) + return 1; + else + { //compare each token + for ( XMLSize_t i = 0; i < lNumberOfTokens; i++) + { + int returnValue = theItemTypeDTV->compare(lVector->elementAt(i), rVector->elementAt(i), manager); + if (returnValue != 0) + return returnValue; //REVISIT: does it make sense to return -1 or +1..? + } + return 0; + } + +} + +void ListDatatypeValidator::validate( const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + setContent(content); + BaseRefVectorOf* tokenVector = XMLString::tokenizeString(content, manager); + Janitor > janName(tokenVector); + checkContent(tokenVector, content, context, false, manager); +} + +void ListDatatypeValidator::checkContent( const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + setContent(content); + BaseRefVectorOf* tokenVector = XMLString::tokenizeString(content, manager); + Janitor > janName(tokenVector); + checkContent(tokenVector, content, context, asBase, manager); +} + +// +// here content is a list of items +// +void ListDatatypeValidator::checkContent( BaseRefVectorOf* tokenVector + , const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + DatatypeValidator* bv = getBaseValidator(); + + if (bv->getType() == DatatypeValidator::List) + ((ListDatatypeValidator*)bv)->checkContent(tokenVector, content, context, true, manager); + else + { // the ultimate itemType DTV + for (unsigned int i = 0; i < tokenVector->size(); i++) + bv->validate(tokenVector->elementAt(i), context, manager); + } + + int thisFacetsDefined = getFacetsDefined(); + + // we check pattern first + if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + //check every item in the list as a whole + if (getRegex()->matches(content, manager) == false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + XMLSize_t tokenNumber = tokenVector->size(); + + if (((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) != 0) && + (tokenNumber > getMaxLength())) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager); + XMLString::sizeToText(getMaxLength(), value2, BUF_LEN, 10, manager); + + ThrowXMLwithMemMgr3(InvalidDatatypeValueException + , XMLExcepts::VALUE_GT_maxLen + , getContent() + , value1 + , value2 + , manager); + } + + if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) != 0) && + (tokenNumber < getMinLength())) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager); + XMLString::sizeToText(getMinLength(), value2, BUF_LEN, 10, manager); + + ThrowXMLwithMemMgr3(InvalidDatatypeValueException + , XMLExcepts::VALUE_LT_minLen + , getContent() + , value1 + , value2 + , manager); + } + + if (((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) != 0) && + (tokenNumber != AbstractStringValidator::getLength())) + { + XMLCh value1[BUF_LEN+1]; + XMLCh value2[BUF_LEN+1]; + XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager); + XMLString::sizeToText(AbstractStringValidator::getLength(), value2, BUF_LEN, 10, manager); + + ThrowXMLwithMemMgr3(InvalidDatatypeValueException + , XMLExcepts::VALUE_NE_Len + , getContent() + , value1 + , value2 + , manager); + } + + if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0)) + { + XMLSize_t i; + XMLSize_t enumLength = getEnumeration()->size(); + + for ( i = 0; i < enumLength; i++) + { + //optimization: we do a lexical comparision first + // this may be faster for string and its derived + if (XMLString::equals(getEnumeration()->elementAt(i), getContent())) + break; // a match found + + // do a value space check + // this is needed for decimal (and probably other types + // such as datetime related) + // eg. + // tokenVector = "1 2 3.0 4" vs enumeration = "1 2 3 4.0" + // + if (valueSpaceCheck(tokenVector, getEnumeration()->elementAt(i), manager)) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, getContent(), manager); + + } // enumeration + +} + +bool ListDatatypeValidator::valueSpaceCheck(BaseRefVectorOf* tokenVector + , const XMLCh* const enumStr + , MemoryManager* const manager) const +{ + DatatypeValidator* theItemTypeDTV = getItemTypeDTV(); + BaseRefVectorOf* enumVector = XMLString::tokenizeString(enumStr, manager); + Janitor > janName(enumVector); + + if (tokenVector->size() != enumVector->size()) + return false; + + for ( unsigned int j = 0; j < tokenVector->size(); j++ ) + { + if (theItemTypeDTV->compare(tokenVector->elementAt(j), enumVector->elementAt(j), manager) != 0) + return false; + } + + return true; +} + +DatatypeValidator* ListDatatypeValidator::getItemTypeDTV() const +{ + DatatypeValidator* bdv = this->getBaseValidator(); + + while (bdv->getType() == DatatypeValidator::List) + bdv = bdv->getBaseValidator(); + + return bdv; +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void ListDatatypeValidator::checkValueSpace(const XMLCh* const + , MemoryManager* const) +{} + +XMLSize_t ListDatatypeValidator::getLength(const XMLCh* const content + , MemoryManager* const manager) const +{ + BaseRefVectorOf* tokenVector = XMLString::tokenizeString(content, manager); + Janitor > janName(tokenVector); + + return tokenVector->size(); +} + +void ListDatatypeValidator::inspectFacetBase(MemoryManager* const manager) +{ + + // + // we are pretty sure baseValidator is not null + // + + if (getBaseValidator()->getType() == DatatypeValidator::List) + { + AbstractStringValidator::inspectFacetBase(manager); + } + else + { + // the first level ListDTV + // check 4.3.5.c0 must: enumeration values from the value space of base + if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) && + (getEnumeration() !=0) ) + { + XMLSize_t i; + XMLSize_t enumLength = getEnumeration()->size(); + try + { + for ( i = 0; i < enumLength; i++) + { + // ask the itemType for a complete check + BaseRefVectorOf* tempList = XMLString::tokenizeString(getEnumeration()->elementAt(i), manager); + Janitor > jan(tempList); + XMLSize_t tokenNumber = tempList->size(); + + try + { + for ( XMLSize_t j = 0; j < tokenNumber; j++) + getBaseValidator()->validate(tempList->elementAt(j), (ValidationContext*)0, manager); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } +#if 0 +// spec says that only base has to checkContent + // enum shall pass this->checkContent() as well. + checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager); +#endif + } + } + + catch ( XMLException& ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_enum_base + , getEnumeration()->elementAt(i) + , manager); + } + + } + + } + +}// End of inspectFacetBase() + +void ListDatatypeValidator::inheritFacet() +{ + + //iff the base validator is List, then we inherit + // + if (getBaseValidator()->getType() == DatatypeValidator::List) + { + AbstractStringValidator::inheritFacet(); + } + +} + +/*** + * 2.5.1.2 List datatypes + * + * The canonical-lexical-representation for the list datatype is defined as + * the lexical form in which each item in the list has the canonical + * lexical representation of its itemType. + ***/ +const XMLCh* ListDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : getMemoryManager(); + ListDatatypeValidator* temp = (ListDatatypeValidator*) this; + temp->setContent(rawData); + BaseRefVectorOf* tokenVector = XMLString::tokenizeString(rawData, toUse); + Janitor > janName(tokenVector); + + if (toValidate) + { + try + { + temp->checkContent(tokenVector, rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + XMLSize_t retBufSize = 2 * XMLString::stringLen(rawData); + XMLCh* retBuf = (XMLCh*) toUse->allocate(retBufSize * sizeof(XMLCh)); + retBuf[0] = 0; + XMLCh* retBufPtr = retBuf; + DatatypeValidator* itemDv = this->getItemTypeDTV(); + + try + { + for (unsigned int i = 0; i < tokenVector->size(); i++) + { + XMLCh* itemCanRep = (XMLCh*) itemDv->getCanonicalRepresentation(tokenVector->elementAt(i), toUse, false); + XMLSize_t itemLen = XMLString::stringLen(itemCanRep); + + if(retBufPtr+itemLen+2 >= retBuf+retBufSize) + { + // need to resize + XMLCh * oldBuf = retBuf; + retBuf = (XMLCh*) toUse->allocate(retBufSize * sizeof(XMLCh) * 4); + memcpy(retBuf, oldBuf, retBufSize * sizeof(XMLCh )); + retBufPtr = (retBufPtr - oldBuf) + retBuf; + toUse->deallocate(oldBuf); + retBufSize <<= 2; + } + + XMLString::catString(retBufPtr, itemCanRep); + retBufPtr = retBufPtr + itemLen; + *(retBufPtr++) = chSpace; + *(retBufPtr) = chNull; + toUse->deallocate(itemCanRep); + } + + return retBuf; + + } + catch (...) + { + return 0; + } +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(ListDatatypeValidator) + +void ListDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); + + //don't serialize fContent, since it is NOT owned and + //will be reset each time validate()/checkContent() invoked. +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file ListDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/ListDatatypeValidator.hpp b/include/xercesc/validators/datatype/ListDatatypeValidator.hpp new file mode 100644 index 0000000..817d39b --- /dev/null +++ b/include/xercesc/validators/datatype/ListDatatypeValidator.hpp @@ -0,0 +1,226 @@ +/* + * 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: ListDatatypeValidator.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_LIST_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_LIST_DATATYPEVALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT ListDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + ListDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ListDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~ListDatatypeValidator(); + + //@} + + /** @name Getter Functions */ + //@{ + /** + * Returns whether the type is atomic or not + */ + virtual bool isAtomic() const; + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + DatatypeValidator* getItemTypeDTV() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(ListDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes: No + // + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + + virtual XMLSize_t getLength(const XMLCh* const content + , MemoryManager* const manager) const; + + // + // Overwrite AbstractStringValidator's + // + virtual void inspectFacetBase(MemoryManager* const manager); + + virtual void inheritFacet(); + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + +private: + + void checkContent( BaseRefVectorOf* tokenVector + , const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager + ); + + bool valueSpaceCheck(BaseRefVectorOf* tokenVector + , const XMLCh* const enumStr + , MemoryManager* const manager) const; + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- + + inline const XMLCh* getContent() const; + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- + + inline void setContent(const XMLCh* const content); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ListDatatypeValidator(const ListDatatypeValidator&); + ListDatatypeValidator& operator=(const ListDatatypeValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fContent + // temporary var referencing the content to be validated, + // for error reporting purpose. + // + // ----------------------------------------------------------------------- + const XMLCh* fContent; +}; + +// ----------------------------------------------------------------------- +// Getter methods +// ----------------------------------------------------------------------- +inline const XMLCh* ListDatatypeValidator::getContent() const +{ + return fContent; +} + +inline bool ListDatatypeValidator::isAtomic() const +{ + return false; +} + +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- +inline void ListDatatypeValidator::setContent(const XMLCh* const content) +{ + fContent = content; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file ListDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/MonthDatatypeValidator.cpp b/include/xercesc/validators/datatype/MonthDatatypeValidator.cpp new file mode 100644 index 0000000..2270104 --- /dev/null +++ b/include/xercesc/validators/datatype/MonthDatatypeValidator.cpp @@ -0,0 +1,108 @@ +/* + * 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: MonthDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +MonthDatatypeValidator::MonthDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::Month, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +MonthDatatypeValidator::MonthDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::Month, manager) +{ + init(enums, manager); +} + +MonthDatatypeValidator::~MonthDatatypeValidator() +{} + +DatatypeValidator* MonthDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) MonthDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* MonthDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseMonth(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void MonthDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseMonth(); +} + + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(MonthDatatypeValidator) + +void MonthDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file MonthDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/MonthDatatypeValidator.hpp b/include/xercesc/validators/datatype/MonthDatatypeValidator.hpp new file mode 100644 index 0000000..6697507 --- /dev/null +++ b/include/xercesc/validators/datatype/MonthDatatypeValidator.hpp @@ -0,0 +1,95 @@ +/* + * 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: MonthDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_MONTH_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_MONTH_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT MonthDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + MonthDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + MonthDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~MonthDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(MonthDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + MonthDatatypeValidator(const MonthDatatypeValidator&); + MonthDatatypeValidator& operator=(const MonthDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file MonthDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/MonthDayDatatypeValidator.cpp b/include/xercesc/validators/datatype/MonthDayDatatypeValidator.cpp new file mode 100644 index 0000000..039a00b --- /dev/null +++ b/include/xercesc/validators/datatype/MonthDayDatatypeValidator.cpp @@ -0,0 +1,108 @@ +/* + * 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: MonthDayDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +MonthDayDatatypeValidator::MonthDayDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::MonthDay, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +MonthDayDatatypeValidator::MonthDayDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::MonthDay, manager) +{ + init(enums, manager); +} + +MonthDayDatatypeValidator::~MonthDayDatatypeValidator() +{} + +DatatypeValidator* MonthDayDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) MonthDayDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* MonthDayDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseMonthDay(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void MonthDayDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseMonthDay(); +} + + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(MonthDayDatatypeValidator) + +void MonthDayDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file MonthDayDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/MonthDayDatatypeValidator.hpp b/include/xercesc/validators/datatype/MonthDayDatatypeValidator.hpp new file mode 100644 index 0000000..e805976 --- /dev/null +++ b/include/xercesc/validators/datatype/MonthDayDatatypeValidator.hpp @@ -0,0 +1,95 @@ +/* + * 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: MonthDayDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_MONTHDAY_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_MONTHDAY_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT MonthDayDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + MonthDayDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + MonthDayDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~MonthDayDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(MonthDayDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + MonthDayDatatypeValidator(const MonthDayDatatypeValidator&); + MonthDayDatatypeValidator& operator=(const MonthDayDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file MonthDayDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/NCNameDatatypeValidator.cpp b/include/xercesc/validators/datatype/NCNameDatatypeValidator.cpp new file mode 100644 index 0000000..05d07ea --- /dev/null +++ b/include/xercesc/validators/datatype/NCNameDatatypeValidator.cpp @@ -0,0 +1,128 @@ +/* + * 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: NCNameDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +NCNameDatatypeValidator::NCNameDatatypeValidator(MemoryManager* const manager) +:StringDatatypeValidator(0, 0, 0, DatatypeValidator::NCName, manager) +{} + +NCNameDatatypeValidator::~NCNameDatatypeValidator() +{} + +NCNameDatatypeValidator::NCNameDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::NCName, manager) +{ + init(enums, manager); +} + +DatatypeValidator* NCNameDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) NCNameDatatypeValidator(this, facets, enums, finalSet, manager); +} + +NCNameDatatypeValidator::NCNameDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, type, manager) +{ + // do not invoke init() here!!! +} + +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int NCNameDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const) +{ + return ( XMLString::equals(lValue, rValue)? 0 : -1); +} + +void NCNameDatatypeValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + // use StringDatatypeValidator (which in turn, invoke + // the baseValidator) to validate content against + // facets if any. + // + StringDatatypeValidator::validate(content, context, manager); + + return; +} + +void NCNameDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + // + // 3.3.7 check must: "NCName" + // + if ( !XMLChar1_0::isValidNCName(content, XMLString::stringLen(content)) ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_Invalid_NCName + , content + , manager); + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(NCNameDatatypeValidator) + +void NCNameDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + StringDatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + + /** + * End of file NCNameDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/NCNameDatatypeValidator.hpp b/include/xercesc/validators/datatype/NCNameDatatypeValidator.hpp new file mode 100644 index 0000000..f39c489 --- /dev/null +++ b/include/xercesc/validators/datatype/NCNameDatatypeValidator.hpp @@ -0,0 +1,152 @@ +/* + * 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: NCNameDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_NCNAME_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_NCNAME_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT NCNameDatatypeValidator : public StringDatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + NCNameDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + NCNameDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~NCNameDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(NCNameDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes + // + NCNameDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + NCNameDatatypeValidator(const NCNameDatatypeValidator&); + NCNameDatatypeValidator& operator=(const NCNameDatatypeValidator&); + // ----------------------------------------------------------------------- + // Private data members + // + // + // ----------------------------------------------------------------------- + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file NCNameDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/NOTATIONDatatypeValidator.cpp b/include/xercesc/validators/datatype/NOTATIONDatatypeValidator.cpp new file mode 100644 index 0000000..246102c --- /dev/null +++ b/include/xercesc/validators/datatype/NOTATIONDatatypeValidator.cpp @@ -0,0 +1,154 @@ +/* + * 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: NOTATIONDatatypeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +NOTATIONDatatypeValidator::NOTATIONDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::NOTATION, manager) +{} + +NOTATIONDatatypeValidator::~NOTATIONDatatypeValidator() +{} + +NOTATIONDatatypeValidator::NOTATIONDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::NOTATION, manager) +{ + init(enums, manager); +} + +DatatypeValidator* NOTATIONDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) NOTATIONDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void NOTATIONDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + + if (!XMLString::isValidNOTATION(content, manager)) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_NOTATION_Invalid + , content + , manager); + } + +} + +void NOTATIONDatatypeValidator::checkContent( const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager + ) +{ + + //validate against base validator if any + NOTATIONDatatypeValidator *pBaseValidator = (NOTATIONDatatypeValidator*) this->getBaseValidator(); + if (pBaseValidator) + pBaseValidator->checkContent(content, context, true, manager); + + int thisFacetsDefined = getFacetsDefined(); + + // we check pattern first + if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + checkValueSpace(content, manager); + + if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0)) + { + XMLCh* normContent = XMLString::replicate(content, manager); + ArrayJanitor jan(normContent, manager); + normalizeContent(normContent, manager); + + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (XMLString::equals(normContent, getEnumeration()->elementAt(i))) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } + + checkAdditionalFacet(content, manager); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(NOTATIONDatatypeValidator) + +void NOTATIONDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file NOTATIONDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/NOTATIONDatatypeValidator.hpp b/include/xercesc/validators/datatype/NOTATIONDatatypeValidator.hpp new file mode 100644 index 0000000..6f5b9e5 --- /dev/null +++ b/include/xercesc/validators/datatype/NOTATIONDatatypeValidator.hpp @@ -0,0 +1,103 @@ +/* + * 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: NOTATIONDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_NOTATION_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_NOTATION_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT NOTATIONDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + NOTATIONDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + NOTATIONDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual ~NOTATIONDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(NOTATIONDatatypeValidator) + +protected: + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + NOTATIONDatatypeValidator(const NOTATIONDatatypeValidator&); + NOTATIONDatatypeValidator& operator=(const NOTATIONDatatypeValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // Nil + // ----------------------------------------------------------------------- +}; + +XERCES_CPP_NAMESPACE_END + +#endif +/** + * End of file NOTATIONDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/NameDatatypeValidator.cpp b/include/xercesc/validators/datatype/NameDatatypeValidator.cpp new file mode 100644 index 0000000..8e32c76 --- /dev/null +++ b/include/xercesc/validators/datatype/NameDatatypeValidator.cpp @@ -0,0 +1,128 @@ +/* + * 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: NameDatatypeValidator.cpp 558817 2007-07-23 18:12:54Z cargilld $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +NameDatatypeValidator::NameDatatypeValidator(MemoryManager* const manager) +:StringDatatypeValidator(0, 0, 0, DatatypeValidator::Name, manager) +{} + +NameDatatypeValidator::~NameDatatypeValidator() +{} + +NameDatatypeValidator::NameDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Name, manager) +{ + init(enums, manager); +} + +DatatypeValidator* NameDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) NameDatatypeValidator(this, facets, enums, finalSet, manager); +} + +NameDatatypeValidator::NameDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:StringDatatypeValidator(baseValidator, facets, finalSet, type, manager) +{ + // do not invoke init() here!!! +} +// ----------------------------------------------------------------------- +// Compare methods +// ----------------------------------------------------------------------- +int NameDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const) +{ + return ( XMLString::equals(lValue, rValue)? 0 : -1); +} + +void NameDatatypeValidator::validate(const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + // use StringDatatypeValidator (which in turn, invoke + // the baseValidator) to validate content against + // facets if any. + // + StringDatatypeValidator::validate(content, context, manager); + + return; +} + +void NameDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + // + // 3.3.6 check must: "Name" + // + if ( !XMLChar1_0::isValidName(content)) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_Invalid_Name + , content + , SchemaSymbols::fgDT_NAME + , manager); + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(NameDatatypeValidator) + +void NameDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + StringDatatypeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + + /** + * End of file NameDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/NameDatatypeValidator.hpp b/include/xercesc/validators/datatype/NameDatatypeValidator.hpp new file mode 100644 index 0000000..9930426 --- /dev/null +++ b/include/xercesc/validators/datatype/NameDatatypeValidator.hpp @@ -0,0 +1,151 @@ +/* + * 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: NameDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_NAME_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_NAME_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT NameDatatypeValidator : public StringDatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + NameDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + NameDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~NameDatatypeValidator(); + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + virtual int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(NameDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes + // + NameDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + NameDatatypeValidator(const NameDatatypeValidator&); + NameDatatypeValidator& operator=(const NameDatatypeValidator&); + // ----------------------------------------------------------------------- + // Private data members + // + // + // ----------------------------------------------------------------------- + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file NameDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/QNameDatatypeValidator.cpp b/include/xercesc/validators/datatype/QNameDatatypeValidator.cpp new file mode 100644 index 0000000..8fe91c7 --- /dev/null +++ b/include/xercesc/validators/datatype/QNameDatatypeValidator.cpp @@ -0,0 +1,272 @@ +/* + * 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: QNameDatatypeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +QNameDatatypeValidator::QNameDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::QName, manager) +{} + +QNameDatatypeValidator::~QNameDatatypeValidator() +{} + +QNameDatatypeValidator::QNameDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::QName, manager) +{ + init(enums, manager); +} + +DatatypeValidator* QNameDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) QNameDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void QNameDatatypeValidator::checkValueSpace(const XMLCh* const content + , MemoryManager* const manager) +{ + // + // check 3.2.18.c0 must: QName + // + + if ( !XMLChar1_0::isValidQName(content, XMLString::stringLen(content)) ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_QName_Invalid + , content + , manager); + } +} + +void QNameDatatypeValidator::checkContent( const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager + ) +{ + + //validate against base validator if any + QNameDatatypeValidator *pBaseValidator = (QNameDatatypeValidator*) this->getBaseValidator(); + if (pBaseValidator) + pBaseValidator->checkContent(content, context, true, manager); + + int thisFacetsDefined = getFacetsDefined(); + + // we check pattern first + if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) ==false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + checkValueSpace(content, manager); + + int colonPos = 0; + XMLCh* prefix = 0; + ArrayJanitor jan(prefix, manager); + + if (context) { + prefix = XMLString::replicate(content, manager); + jan.reset(prefix, manager); + normalizeContent(prefix, manager); + + colonPos = XMLString::indexOf(content, chColon); + if (colonPos > 0) { + prefix[colonPos] = chNull; + if (context->isPrefixUnknown(prefix)) { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_QName_Invalid2 + , content + , manager); + } + } + } + +#if 0 + if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0)) + { + XMLCh* normContent = XMLString::replicate(content, manager); + ArrayJanitor jan(normContent, manager); + normalizeContent(normContent, manager); + + int i=0; + int enumLength = getEnumeration()->size(); + for ( ; i < enumLength; i++) + { + if (XMLString::equals(normContent, getEnumeration()->elementAt(i))) + break; + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } + + +#else + if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0) && context) + { + XMLCh* localName; + if (colonPos > 0) { + localName = prefix + colonPos + 1; + } + else { + localName = prefix; + } + + XMLCh* enumPrefix; + XMLCh* enumLocalName; + XMLSize_t i=0; + XMLSize_t enumLength = getEnumeration()->size(); + bool foundURIId = false; + const XMLCh* normURI = 0; + // The +=2 is because the enumeration has prefix:localname as one entry followed + // by the URI string for the prefix as the next entry. + for ( ; i < enumLength; i+=2) + { + enumPrefix = XMLString::replicate(getEnumeration()->elementAt(i), manager); + ArrayJanitor janEnum(enumPrefix, manager); + colonPos = XMLString::indexOf(enumPrefix, chColon, 0, manager); + + if (colonPos != -1) { + enumLocalName = enumPrefix + colonPos + 1; + enumPrefix[colonPos] = chNull; + } + else { + enumLocalName = enumPrefix; + } + + if (XMLString::equals(localName, enumLocalName)) { + if (colonPos < 0) + break; + + // now need to see if the prefix URI's are the same + if (!foundURIId) { + normURI = context->getURIForPrefix(prefix); + foundURIId = true; + } + if (XMLString::equals(normURI, getEnumeration()->elementAt(i+1))) + break; + } + } + + if (i == enumLength) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + } +#endif + + checkAdditionalFacet(content, manager); +} + +// +// Check vs base +// check common facets +// check enumeration +// check Additional Facet Constraint +// +void QNameDatatypeValidator::inspectFacetBase(MemoryManager* const manager) +{ + + QNameDatatypeValidator *pBaseValidator = (QNameDatatypeValidator*) getBaseValidator(); + int thisFacetsDefined = getFacetsDefined(); + + if ( (!thisFacetsDefined && !getEnumeration()) || + (!pBaseValidator) ) + return; + + // check 4.3.5.c0 must: enumeration values from the value space of base + if ( ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0) && + (getEnumeration() !=0)) + { + XMLSize_t i = 0; + XMLSize_t enumLength = getEnumeration()->size(); + // The +=2 is because the enumeration has prefix:localname as one entry followed + // by the URI string for the prefix as the next entry. + for ( ; i < enumLength; i+=2) + { + // ask parent do a complete check + pBaseValidator->checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager); +#if 0 +// spec says that only base has to checkContent + // enum shall pass this->checkContent() as well. + checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager); +#endif + } + } + + checkAdditionalFacetConstraints(manager); + +} //end of inspectFacetBase + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(QNameDatatypeValidator) + +void QNameDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file QNameDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/QNameDatatypeValidator.hpp b/include/xercesc/validators/datatype/QNameDatatypeValidator.hpp new file mode 100644 index 0000000..0451fdf --- /dev/null +++ b/include/xercesc/validators/datatype/QNameDatatypeValidator.hpp @@ -0,0 +1,106 @@ +/* + * 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: QNameDatatypeValidator.hpp 577322 2007-09-19 14:58:04Z cargilld $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_QNAME_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_QNAME_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT QNameDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + QNameDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + QNameDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~QNameDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(QNameDatatypeValidator) + +protected: + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + + virtual void inspectFacetBase(MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + QNameDatatypeValidator(const QNameDatatypeValidator&); + QNameDatatypeValidator& operator=(const QNameDatatypeValidator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // Nil + // ----------------------------------------------------------------------- + +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file QNameDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/StringDatatypeValidator.cpp b/include/xercesc/validators/datatype/StringDatatypeValidator.cpp new file mode 100644 index 0000000..aad14f8 --- /dev/null +++ b/include/xercesc/validators/datatype/StringDatatypeValidator.cpp @@ -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: StringDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +StringDatatypeValidator::StringDatatypeValidator(MemoryManager* const manager) +:AbstractStringValidator(0, 0, 0, DatatypeValidator::String, manager) +{ + setWhiteSpace(DatatypeValidator::PRESERVE); +} + +StringDatatypeValidator::StringDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String, manager) +{ + setWhiteSpace(DatatypeValidator::PRESERVE); + init(enums, manager); +} + +StringDatatypeValidator::~StringDatatypeValidator() +{} + +DatatypeValidator* StringDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) StringDatatypeValidator(this, facets, enums, finalSet, manager); +} + +StringDatatypeValidator::StringDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager) +:AbstractStringValidator(baseValidator, facets, finalSet, type, manager) +{ + setWhiteSpace(DatatypeValidator::PRESERVE); + // do not invoke init() here!!! +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- +void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager) +{ + if (XMLString::equals(key, SchemaSymbols::fgELT_WHITESPACE)) + { + // whiteSpace = preserve | replace | collapse + if (XMLString::equals(value, SchemaSymbols::fgWS_PRESERVE)) + setWhiteSpace(DatatypeValidator::PRESERVE); + else if (XMLString::equals(value, SchemaSymbols::fgWS_REPLACE)) + setWhiteSpace(DatatypeValidator::REPLACE); + else if (XMLString::equals(value, SchemaSymbols::fgWS_COLLAPSE)) + setWhiteSpace(DatatypeValidator::COLLAPSE); + else + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value, manager); + //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'."); + + setFacetsDefined(DatatypeValidator::FACET_WHITESPACE); + } + else + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , key + , manager); + } +} + +void StringDatatypeValidator::inheritAdditionalFacet() +{ + StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator(); + + if (!pBaseValidator) + return; + + // inherit whitespace + if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) && + ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0)) + { + setWhiteSpace(getBaseValidator()->getWSFacet()); + setFacetsDefined(DatatypeValidator::FACET_WHITESPACE); + } +} + +void StringDatatypeValidator::checkAdditionalFacetConstraints(MemoryManager* const manager) const +{ + + StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator(); + + if (!pBaseValidator) + return; + + short thisWSFacet = getWSFacet(); + short baseWSFacet = pBaseValidator->getWSFacet(); + + // check 4.3.6.c1 error: whitespace + if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) && + ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )) + { + if ((baseWSFacet == DatatypeValidator::COLLAPSE) && + ((thisWSFacet == DatatypeValidator::PRESERVE) || + (thisWSFacet == DatatypeValidator::REPLACE))) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse, manager); + + if ((baseWSFacet == DatatypeValidator::REPLACE) && + (thisWSFacet == DatatypeValidator::PRESERVE)) + ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace, manager); + + if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) && + ( thisWSFacet != baseWSFacet)) + { + ThrowXMLwithMemMgr2(InvalidDatatypeFacetException + , XMLExcepts::FACET_whitespace_base_fixed + , getWSstring(thisWSFacet) + , getWSstring(baseWSFacet) + , manager); + } + } + +} + +void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content + , MemoryManager* const manager) const +{ + // + // check WhiteSpace + // + if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ) + { + if ( getWSFacet() == DatatypeValidator::REPLACE ) + { + if (!XMLString::isWSReplaced(content)) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content, manager); + } + else if ( getWSFacet() == DatatypeValidator::COLLAPSE ) + { + if (!XMLString::isWSCollapsed(content)) + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content, manager); + } + + } +} + +void StringDatatypeValidator::checkValueSpace(const XMLCh* const + , MemoryManager* const) +{} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(StringDatatypeValidator) + +void StringDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + AbstractStringValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file StringDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/StringDatatypeValidator.hpp b/include/xercesc/validators/datatype/StringDatatypeValidator.hpp new file mode 100644 index 0000000..7437bdc --- /dev/null +++ b/include/xercesc/validators/datatype/StringDatatypeValidator.hpp @@ -0,0 +1,114 @@ +/* + * 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: StringDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_STRING_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_STRING_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT StringDatatypeValidator : public AbstractStringValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + StringDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + StringDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~StringDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(StringDatatypeValidator) + +protected: + + // + // ctor provided to be used by derived classes + // + StringDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , const int finalSet + , const ValidatorType type + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual void assignAdditionalFacet(const XMLCh* const key + , const XMLCh* const value + , MemoryManager* const manager); + + virtual void inheritAdditionalFacet(); + + virtual void checkAdditionalFacetConstraints(MemoryManager* const manager) const; + + virtual void checkAdditionalFacet(const XMLCh* const content + , MemoryManager* const manager) const; + + virtual void checkValueSpace(const XMLCh* const content + , MemoryManager* const manager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + StringDatatypeValidator(const StringDatatypeValidator&); + StringDatatypeValidator& operator=(const StringDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file StringDatatypeValidator.hpp + */ diff --git a/include/xercesc/validators/datatype/TimeDatatypeValidator.cpp b/include/xercesc/validators/datatype/TimeDatatypeValidator.cpp new file mode 100644 index 0000000..b27b029 --- /dev/null +++ b/include/xercesc/validators/datatype/TimeDatatypeValidator.cpp @@ -0,0 +1,140 @@ +/* + * 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: TimeDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +TimeDatatypeValidator::TimeDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::Time, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +TimeDatatypeValidator::TimeDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::Time, manager) +{ + init(enums, manager); +} + +TimeDatatypeValidator::~TimeDatatypeValidator() +{} + +DatatypeValidator* TimeDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) TimeDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* TimeDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseTime(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void TimeDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseTime(); +} + +const XMLCh* TimeDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : fMemoryManager; + + if (toValidate) + { + TimeDatatypeValidator* temp = (TimeDatatypeValidator*) this; + + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + try + { + XMLDateTime aDateTime(rawData, toUse); + aDateTime.parseTime(); + return aDateTime.getTimeCanonicalRepresentation(toUse); + } + catch (...) + { + return 0; + } + +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(TimeDatatypeValidator) + +void TimeDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file TimeDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/TimeDatatypeValidator.hpp b/include/xercesc/validators/datatype/TimeDatatypeValidator.hpp new file mode 100644 index 0000000..9e91784 --- /dev/null +++ b/include/xercesc/validators/datatype/TimeDatatypeValidator.hpp @@ -0,0 +1,104 @@ +/* + * 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: TimeDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_TIME_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_TIME_DATATYPE_VALIDATOR_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT TimeDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + TimeDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + TimeDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~TimeDatatypeValidator(); + + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(TimeDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + TimeDatatypeValidator(const TimeDatatypeValidator&); + TimeDatatypeValidator& operator=(const TimeDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file TimeDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/UnionDatatypeValidator.cpp b/include/xercesc/validators/datatype/UnionDatatypeValidator.cpp new file mode 100644 index 0000000..cc5b4bb --- /dev/null +++ b/include/xercesc/validators/datatype/UnionDatatypeValidator.cpp @@ -0,0 +1,465 @@ +/* + * 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: UnionDatatypeValidator.cpp 677559 2008-07-17 11:35:27Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +static const unsigned int BUF_LEN = 64; + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +UnionDatatypeValidator::UnionDatatypeValidator(MemoryManager* const manager) +:DatatypeValidator(0, 0, 0, DatatypeValidator::Union, manager) +,fEnumerationInherited(false) +,fMemberTypesInherited(false) +,fEnumeration(0) +,fMemberTypeValidators(0) + +{} + +UnionDatatypeValidator::~UnionDatatypeValidator() +{ + cleanUp(); +} + +UnionDatatypeValidator::UnionDatatypeValidator( + RefVectorOf* const memberTypeValidators + , const int finalSet + , MemoryManager* const manager) +:DatatypeValidator(0, 0, finalSet, DatatypeValidator::Union, manager) +,fEnumerationInherited(false) +,fMemberTypesInherited(false) +,fEnumeration(0) +,fMemberTypeValidators(0) +{ + if ( !memberTypeValidators ) + { + ThrowXMLwithMemMgr(InvalidDatatypeFacetException + , XMLExcepts::FACET_Union_Null_memberTypeValidators, manager); + } + + // no pattern, no enumeration + fMemberTypeValidators = memberTypeValidators; +} + +typedef JanitorMemFunCall CleanupType; + +UnionDatatypeValidator::UnionDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager + , RefVectorOf* const memberTypeValidators + , const bool memberTypesInherited + ) +:DatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Union, manager) +,fEnumerationInherited(false) +,fMemberTypesInherited(memberTypesInherited) +,fEnumeration(0) +,fMemberTypeValidators(memberTypeValidators) +{ + // + // baseValidator another UnionDTV from which, + // this UnionDTV is derived by restriction. + // it shall be not null + // + if (!baseValidator) + { + ThrowXMLwithMemMgr(InvalidDatatypeFacetException + , XMLExcepts::FACET_Union_Null_baseValidator, manager); + } + + if (baseValidator->getType() != DatatypeValidator::Union) + { + XMLCh value1[BUF_LEN+1]; + XMLString::binToText(baseValidator->getType(), value1, BUF_LEN, 10, manager); + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Union_invalid_baseValidatorType + , value1 + , manager); + } + + CleanupType cleanup(this, &UnionDatatypeValidator::cleanUp); + + try + { + init(baseValidator, facets, enums, manager); + } + catch(const OutOfMemoryException&) + { + // Don't cleanup when out of memory, since executing the + // code can cause problems. + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +void UnionDatatypeValidator::init(DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , MemoryManager* const manager) +{ + if (enums) + setEnumeration(enums, false); + + // Set Facets if any defined + if (facets) + { + XMLCh* key; + XMLCh* value; + RefHashTableOfEnumerator e(facets, false, manager); + + while (e.hasMoreElements()) + { + KVStringPair pair = e.nextElement(); + key = pair.getKey(); + value = pair.getValue(); + + if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN)) + { + setPattern(value); + if (getPattern()) + setFacetsDefined(DatatypeValidator::FACET_PATTERN); + // do not construct regex until needed + } + else + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_Invalid_Tag + , key + , manager); + } + }//while + + /*** + Schema constraint: Part I -- self checking + ***/ + // Nil + + /*** + Schema constraint: Part II base vs derived checking + ***/ + // check 4.3.5.c0 must: enumeration values from the value space of base + if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) && + (getEnumeration() !=0)) + { + XMLSize_t i = 0; + XMLSize_t enumLength = getEnumeration()->size(); + try + { + for ( ; i < enumLength; i++) + { + // ask parent do a complete check + // + // enum need NOT be passed this->checkContent() + // since there are no other facets for Union, parent + // checking is good enough. + // + baseValidator->validate(getEnumeration()->elementAt(i), (ValidationContext*)0, manager); + + } + } + + catch ( XMLException& ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeFacetException + , XMLExcepts::FACET_enum_base + , getEnumeration()->elementAt(i) + , manager); + } + } + + }// End of Facet setting + + /*** + Inherit facets from base.facets + + The reason of this inheriting (or copying values) is to ease + schema constraint checking, so that we need NOT trace back to our + very first base validator in the hierachy. Instead, we are pretty + sure checking against immediate base validator is enough. + ***/ + + UnionDatatypeValidator *pBaseValidator = (UnionDatatypeValidator*) baseValidator; + + // inherit enumeration + if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) !=0) && + ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) == 0)) + { + setEnumeration(pBaseValidator->getEnumeration(), true); + } + +} + +// +// 1) the bottom level UnionDTV would check against +// pattern and enumeration as well +// 2) each UnionDTV(s) above the bottom level UnionDTV and +// below the native UnionDTV (the top level DTV) +// would check against pattern only. +// 3) the natvie Union DTV (the top level DTV) would invoke +// memberTypeValidator to validate +// +void UnionDatatypeValidator::checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager) +{ + + DatatypeValidator* bv = getBaseValidator(); + if (bv) + ((UnionDatatypeValidator*)bv)->checkContent(content, context, true, manager); + else + { // 3) native union type + // check content against each member type validator in Union + // report an error only in case content is not valid against all member datatypes. + // + bool memTypeValid = false; + for ( unsigned int i = 0; i < fMemberTypeValidators->size(); ++i ) + { + if ( memTypeValid ) + break; + + try + { + fMemberTypeValidators->elementAt(i)->validate(content, context, manager); + memTypeValid = true; + + //set the validator of the type actually used to validate the content + DatatypeValidator *dtv = fMemberTypeValidators->elementAt(i); + // context will be null during schema construction + if(context) + context->setValidatingMemberType(dtv); + } + catch (XMLException&) + { + //absorbed + } + } // for + + if ( !memTypeValid ) + { + ThrowXMLwithMemMgr1(InvalidDatatypeValueException + , XMLExcepts::VALUE_no_match_memberType + , content + , manager); + //( "Content '"+content+"' does not match any union types" ); + } + } + + // 1) and 2). we check pattern first + if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 ) + { + if (getRegex()->matches(content, manager) == false) + { + ThrowXMLwithMemMgr2(InvalidDatatypeValueException + , XMLExcepts::VALUE_NotMatch_Pattern + , content + , getPattern() + , manager); + } + } + + // if this is a base validator, we only need to check pattern facet + // all other facet were inherited by the derived type + if (asBase) + return; + + if ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0 && + (getEnumeration() != 0)) + { + + // If the content match (compare equal) any enumeration with + // any of the member types, it is considerd valid. + // + RefVectorOf* memberDTV = getMemberTypeValidators(); + RefArrayVectorOf* tmpEnum = getEnumeration(); + XMLSize_t memberTypeNumber = memberDTV->size(); + XMLSize_t enumLength = tmpEnum->size(); + + for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex) + { + for ( XMLSize_t enumIndex = 0; enumIndex < enumLength; ++enumIndex) + { + try + { + if (memberDTV->elementAt(memberIndex)->compare(content, tmpEnum->elementAt(enumIndex), manager) == 0) + return; + } + catch (XMLException&) + { + //absorbed + } + } // for enumIndex + } // for memberIndex + + ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); + + } // enumeration + +} + +// +// +// +int UnionDatatypeValidator::compare(const XMLCh* const lValue + , const XMLCh* const rValue + , MemoryManager* const manager) +{ + RefVectorOf* memberDTV = getMemberTypeValidators(); + XMLSize_t memberTypeNumber = memberDTV->size(); + + for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex) + { + // 'compare' can throw exceptions when the datatype is not valid, or just + // return -1; so attempt to validate both values to get the right validator + try + { + memberDTV->elementAt(memberIndex)->validate(lValue, 0, manager); + memberDTV->elementAt(memberIndex)->validate(rValue, 0, manager); + if (memberDTV->elementAt(memberIndex)->compare(lValue, rValue, manager) ==0) + return 0; + } + catch (XMLException&) + { + //absorbed + } + } + + //REVISIT: what does it mean for UNION1 to be or UNION2 ? + // As long as -1 or +1 indicates an unequality, return either of them is ok. + return -1; +} + +const RefArrayVectorOf* UnionDatatypeValidator::getEnumString() const +{ + return getEnumeration(); +} + +/*** + * 2.5.1.3 Union datatypes + * + * The canonical-lexical-representation for a union datatype is defined as the lexical form + * in which the values have the canonical lexical representation of the appropriate memberTypes. + ***/ +const XMLCh* UnionDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData + , MemoryManager* const memMgr + , bool toValidate) const +{ + MemoryManager* toUse = memMgr? memMgr : getMemoryManager(); + UnionDatatypeValidator* temp = (UnionDatatypeValidator*) this; + + if (toValidate) + { + try + { + temp->checkContent(rawData, 0, false, toUse); + } + catch (...) + { + return 0; + } + } + + //get the native unionDv + UnionDatatypeValidator* bdv = (UnionDatatypeValidator*) temp->getBaseValidator(); + while (bdv) + { + temp = bdv; + bdv = (UnionDatatypeValidator*) temp->getBaseValidator(); + } + + //let the member dv which recognize the rawData, to return + //us the canonical form + for ( unsigned int i = 0; i < temp->fMemberTypeValidators->size(); ++i ) + { + try + { + temp->fMemberTypeValidators->elementAt(i)->validate(rawData, 0, toUse); + return temp->fMemberTypeValidators->elementAt(i)->getCanonicalRepresentation(rawData, toUse, false); + } + catch (XMLException&) + { + //absorbed + } + } + + //if no member dv recognize it + return 0; +} + + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(UnionDatatypeValidator) + +void UnionDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + + DatatypeValidator::serialize(serEng); + + if (serEng.isStoring()) + { + serEng< + * Serialize RefVectorOf + ***/ + XTemplateSerializer::storeObject(fEnumeration, serEng); + XTemplateSerializer::storeObject(fMemberTypeValidators, serEng); + } + else + { + serEng>>fEnumerationInherited; + serEng>>fMemberTypesInherited; + + /*** + * Deserialize RefArrayVectorOf + * Deserialize RefVectorOf + ***/ + XTemplateSerializer::loadObject(&fEnumeration, 8, true, serEng); + XTemplateSerializer::loadObject(&fMemberTypeValidators, 4, false, serEng); + } +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file UnionDatatypeValidator.cpp + */ diff --git a/include/xercesc/validators/datatype/UnionDatatypeValidator.hpp b/include/xercesc/validators/datatype/UnionDatatypeValidator.hpp new file mode 100644 index 0000000..5e328b5 --- /dev/null +++ b/include/xercesc/validators/datatype/UnionDatatypeValidator.hpp @@ -0,0 +1,320 @@ +/* + * 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: UnionDatatypeValidator.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_UNION_DATATYPEVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_UNION_DATATYPEVALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT UnionDatatypeValidator : public DatatypeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor. */ + //@{ + + UnionDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // + // constructor for native Union datatype validator + // + // + // + // + UnionDatatypeValidator + ( + RefVectorOf* const memberTypeValidators + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // + // constructor for derived Union datatype validator + // + // + // + // + // + // + // + UnionDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , RefVectorOf* const memberTypeValidators = 0 + , const bool memberTypesInherited = true + ); + + virtual ~UnionDatatypeValidator(); + + //@} + + virtual const RefArrayVectorOf* getEnumString() const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + /** @name Getter Functions */ + //@{ + /** + * Returns whether the type is atomic or not + */ + virtual bool isAtomic() const; + + virtual const XMLCh* getCanonicalRepresentation + ( + const XMLCh* const rawData + , MemoryManager* const memMgr = 0 + , bool toValidate = false + ) const; + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * validate that a string matches the boolean datatype + * @param content A string containing the content to be validated + * + * @exception throws InvalidDatatypeException if the content is + * is not valid. + */ + + virtual void validate + ( + const XMLCh* const content + , ValidationContext* const context = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /** + * Checks whether a given type can be used as a substitute + * + * @param toCheck A datatype validator of the type to be used as a + * substitute + * + * To be redefined in UnionDatatypeValidator + */ + + virtual bool isSubstitutableBy(const DatatypeValidator* const toCheck); + + //@} + + // ----------------------------------------------------------------------- + // Compare methods + // ----------------------------------------------------------------------- + /** @name Compare Function */ + //@{ + + /** + * Compare two boolean data types + * + * @param content1 + * @param content2 + * @return + */ + int compare(const XMLCh* const, const XMLCh* const + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(UnionDatatypeValidator) + + + RefVectorOf* getMemberTypeValidators() const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + UnionDatatypeValidator(const UnionDatatypeValidator&); + UnionDatatypeValidator& operator=(const UnionDatatypeValidator&); + + virtual void checkContent(const XMLCh* const content + , ValidationContext* const context + , bool asBase + , MemoryManager* const manager); + + void init(DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , MemoryManager* const manager); + + void cleanUp(); + + RefArrayVectorOf* getEnumeration() const; + + void setEnumeration(RefArrayVectorOf*, bool); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fEnumeration + // we own it (or not, depending on state of fEnumerationInherited). + // + // fMemberTypeValidators + // we own it (or not, depending on the state of fMemberTypesInherited). + // + // ----------------------------------------------------------------------- + + bool fEnumerationInherited; + bool fMemberTypesInherited; + RefArrayVectorOf* fEnumeration; + RefVectorOf* fMemberTypeValidators; +}; + +inline DatatypeValidator* UnionDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) UnionDatatypeValidator(this, facets, enums, finalSet, manager, fMemberTypeValidators, true); +} + +inline void UnionDatatypeValidator::validate( const XMLCh* const content + , ValidationContext* const context + , MemoryManager* const manager) +{ + checkContent(content, context, false, manager); +} + +inline void UnionDatatypeValidator::cleanUp() +{ + //~RefVectorOf will delete all adopted elements + if ( !fEnumerationInherited && fEnumeration) + delete fEnumeration; + + if (!fMemberTypesInherited && fMemberTypeValidators) + delete fMemberTypeValidators; + +} + +inline RefArrayVectorOf* UnionDatatypeValidator:: getEnumeration() const +{ + return fEnumeration; +} + +inline void UnionDatatypeValidator::setEnumeration(RefArrayVectorOf* enums + , bool inherited) +{ + if (enums) + { + if ( !fEnumerationInherited && fEnumeration) + delete fEnumeration; + + fEnumeration = enums; + fEnumerationInherited = inherited; + setFacetsDefined(DatatypeValidator::FACET_ENUMERATION); + } +} + +// +// get the native UnionDTV's fMemberTypeValidators +// +inline +RefVectorOf* UnionDatatypeValidator::getMemberTypeValidators() const +{ + return this->fMemberTypeValidators; +} + +inline bool UnionDatatypeValidator::isAtomic() const { + + + + if (!fMemberTypeValidators) { + return false; + } + + XMLSize_t memberSize = fMemberTypeValidators->size(); + + for (XMLSize_t i=0; i < memberSize; i++) { + if (!fMemberTypeValidators->elementAt(i)->isAtomic()) { + return false; + } + } + + return true; +} + +inline bool UnionDatatypeValidator::isSubstitutableBy(const DatatypeValidator* const toCheck) { + + if (toCheck == this) { + return true; + } + + if (fMemberTypeValidators) { + XMLSize_t memberSize = fMemberTypeValidators->size(); + + for (XMLSize_t i=0; i < memberSize; i++) { + if ((fMemberTypeValidators->elementAt(i)->getType() == DatatypeValidator::Union) && + (fMemberTypeValidators->elementAt(i) == toCheck)) + return false; + if (fMemberTypeValidators->elementAt(i)->isSubstitutableBy(toCheck)) { + return true; + } + } + } + return false; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file UnionDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/XMLCanRepGroup.cpp b/include/xercesc/validators/datatype/XMLCanRepGroup.cpp new file mode 100644 index 0000000..6cfb642 --- /dev/null +++ b/include/xercesc/validators/datatype/XMLCanRepGroup.cpp @@ -0,0 +1,44 @@ +/* + * 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: XMLCanRepGroup.cpp 471747 2006-11-06 14:31:56Z amassari $ + * + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +XMLCanRepGroup::~XMLCanRepGroup() +{ +} + +XMLCanRepGroup::XMLCanRepGroup(CanRepGroup val) +:fData(val) +{ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file DatatypeValidator.cpp + */ + diff --git a/include/xercesc/validators/datatype/XMLCanRepGroup.hpp b/include/xercesc/validators/datatype/XMLCanRepGroup.hpp new file mode 100644 index 0000000..586ebbd --- /dev/null +++ b/include/xercesc/validators/datatype/XMLCanRepGroup.hpp @@ -0,0 +1,75 @@ +/* + * 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: XMLCanRepGroup.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLCANREPGROUP_HPP) +#define XERCESC_INCLUDE_GUARD_XMLCANREPGROUP_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT XMLCanRepGroup : public XMemory +{ +public: + + enum CanRepGroup { + Boolean, + DoubleFloat, + DateTime, + Time, + Decimal, + Decimal_Derived_signed, + Decimal_Derived_unsigned, + Decimal_Derived_npi, + String + }; + + ~XMLCanRepGroup(); + + XMLCanRepGroup(CanRepGroup val); + + inline CanRepGroup getGroup() const; + +private: + + CanRepGroup fData; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XMLCanRepGroup(const XMLCanRepGroup&); + XMLCanRepGroup& operator=(const XMLCanRepGroup&); + +}; + +inline XMLCanRepGroup::CanRepGroup XMLCanRepGroup::getGroup() const +{ + return fData; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XMLCanRepGroup.hpp + */ + diff --git a/include/xercesc/validators/datatype/YearDatatypeValidator.cpp b/include/xercesc/validators/datatype/YearDatatypeValidator.cpp new file mode 100644 index 0000000..bb7d2ed --- /dev/null +++ b/include/xercesc/validators/datatype/YearDatatypeValidator.cpp @@ -0,0 +1,107 @@ +/* + * 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: YearDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +YearDatatypeValidator::YearDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::Year, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +YearDatatypeValidator::YearDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::Year, manager) +{ + init(enums, manager); +} + +YearDatatypeValidator::~YearDatatypeValidator() +{} + +DatatypeValidator* YearDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) YearDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* YearDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseYear(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void YearDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseYear(); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(YearDatatypeValidator) + +void YearDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file YearDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/YearDatatypeValidator.hpp b/include/xercesc/validators/datatype/YearDatatypeValidator.hpp new file mode 100644 index 0000000..20d22b7 --- /dev/null +++ b/include/xercesc/validators/datatype/YearDatatypeValidator.hpp @@ -0,0 +1,95 @@ +/* + * 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: YearDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_YEAR_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_YEAR_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT YearDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + YearDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + YearDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~YearDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(YearDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + YearDatatypeValidator(const YearDatatypeValidator&); + YearDatatypeValidator& operator=(const YearDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file YearDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/datatype/YearMonthDatatypeValidator.cpp b/include/xercesc/validators/datatype/YearMonthDatatypeValidator.cpp new file mode 100644 index 0000000..13d4ccf --- /dev/null +++ b/include/xercesc/validators/datatype/YearMonthDatatypeValidator.cpp @@ -0,0 +1,108 @@ +/* + * 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: YearMonthDatatypeValidator.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Constructors and Destructor +// --------------------------------------------------------------------------- +YearMonthDatatypeValidator::YearMonthDatatypeValidator(MemoryManager* const manager) +:DateTimeValidator(0, 0, 0, DatatypeValidator::YearMonth, manager) +{ + setOrdered(XSSimpleTypeDefinition::ORDERED_PARTIAL); +} + +YearMonthDatatypeValidator::YearMonthDatatypeValidator( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager) +:DateTimeValidator(baseValidator, facets, finalSet, DatatypeValidator::YearMonth, manager) +{ + init(enums, manager); +} + +YearMonthDatatypeValidator::~YearMonthDatatypeValidator() +{} + +DatatypeValidator* YearMonthDatatypeValidator::newInstance +( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager +) +{ + return (DatatypeValidator*) new (manager) YearMonthDatatypeValidator(this, facets, enums, finalSet, manager); +} + +// +// caller need to release the date created here +// +XMLDateTime* YearMonthDatatypeValidator::parse(const XMLCh* const content, MemoryManager* const manager) +{ + XMLDateTime *pRetDate = new (manager) XMLDateTime(content, manager); + Janitor jan(pRetDate); + + try + { + pRetDate->parseYearMonth(); + } + catch(const OutOfMemoryException&) + { + jan.release(); + + throw; + } + + return jan.release(); +} + +void YearMonthDatatypeValidator::parse(XMLDateTime* const pDate) +{ + pDate->parseYearMonth(); +} + + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(YearMonthDatatypeValidator) + +void YearMonthDatatypeValidator::serialize(XSerializeEngine& serEng) +{ + DateTimeValidator::serialize(serEng); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file YearMonthDatatypeValidator::cpp + */ + diff --git a/include/xercesc/validators/datatype/YearMonthDatatypeValidator.hpp b/include/xercesc/validators/datatype/YearMonthDatatypeValidator.hpp new file mode 100644 index 0000000..98a5632 --- /dev/null +++ b/include/xercesc/validators/datatype/YearMonthDatatypeValidator.hpp @@ -0,0 +1,95 @@ +/* + * 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: YearMonthDatatypeValidator.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_YEARMONTH_DATATYPE_VALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_YEARMONTH_DATATYPE_VALIDATOR_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT YearMonthDatatypeValidator : public DateTimeValidator +{ +public: + + // ----------------------------------------------------------------------- + // Public ctor/dtor + // ----------------------------------------------------------------------- + /** @name Constructors and Destructor */ + //@{ + + YearMonthDatatypeValidator + ( + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + YearMonthDatatypeValidator + ( + DatatypeValidator* const baseValidator + , RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~YearMonthDatatypeValidator(); + + //@} + + /** + * Returns an instance of the base datatype validator class + * Used by the DatatypeValidatorFactory. + */ + virtual DatatypeValidator* newInstance + ( + RefHashTableOf* const facets + , RefArrayVectorOf* const enums + , const int finalSet + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(YearMonthDatatypeValidator) + +protected: + + // ----------------------------------------------------------------------- + // implementation of (DateTimeValidator's) virtual interface + // ----------------------------------------------------------------------- + virtual XMLDateTime* parse(const XMLCh* const, MemoryManager* const manager); + virtual void parse(XMLDateTime* const); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + YearMonthDatatypeValidator(const YearMonthDatatypeValidator&); + YearMonthDatatypeValidator& operator=(const YearMonthDatatypeValidator&); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file YearMonthDatatypeValidator.hpp + */ + diff --git a/include/xercesc/validators/schema/ComplexTypeInfo.cpp b/include/xercesc/validators/schema/ComplexTypeInfo.cpp new file mode 100644 index 0000000..6876119 --- /dev/null +++ b/include/xercesc/validators/schema/ComplexTypeInfo.cpp @@ -0,0 +1,911 @@ +/* + * 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: ComplexTypeInfo.cpp 901107 2010-01-20 08:45:02Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Static member data +// --------------------------------------------------------------------------- +ComplexTypeInfo* ComplexTypeInfo::fAnyType = 0; + +void XMLInitializer::initializeComplexTypeInfo() +{ + // create type name + XMLCh typeName[128]; + XMLSize_t nsLen = XMLString::stringLen(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + + XMLString::copyString(typeName, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + typeName[nsLen] = chComma; + XMLString::copyString(typeName + nsLen + 1, SchemaSymbols::fgATTVAL_ANYTYPE); + + // Create and initialize 'anyType' + ComplexTypeInfo::fAnyType = new ComplexTypeInfo(); + + ContentSpecNode* term = new ContentSpecNode + ( + new QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , 1 + ) + , false + ); + term->setType(ContentSpecNode::Any_Lax); + term->setMinOccurs(0); + term->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED); + + ContentSpecNode* particle = new ContentSpecNode + ( + ContentSpecNode::ModelGroupSequence + , term + , 0 + ); + + SchemaAttDef* attWildCard = new SchemaAttDef + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , 1 + , XMLAttDef::Any_Any + , XMLAttDef::ProcessContents_Lax + ); + + ComplexTypeInfo::fAnyType->setTypeName(typeName); + ComplexTypeInfo::fAnyType->setBaseComplexTypeInfo(ComplexTypeInfo::fAnyType); + ComplexTypeInfo::fAnyType->setDerivedBy(SchemaSymbols::XSD_RESTRICTION); + ComplexTypeInfo::fAnyType->setContentType(SchemaElementDecl::Mixed_Complex); + ComplexTypeInfo::fAnyType->setContentSpec(particle); + ComplexTypeInfo::fAnyType->setAttWildCard(attWildCard); +} + +void XMLInitializer::terminateComplexTypeInfo() +{ + delete ComplexTypeInfo::fAnyType; + ComplexTypeInfo::fAnyType = 0; +} + +ComplexTypeInfo* ComplexTypeInfo::getAnyType(unsigned int /*emptyNSId*/) +{ + return fAnyType; +} + + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +ComplexTypeInfo::ComplexTypeInfo(MemoryManager* const manager) + : fAnonymous(false) + , fAbstract(false) + , fAdoptContentSpec(true) + , fAttWithTypeId(false) + , fPreprocessed(false) + , fDerivedBy(0) + , fBlockSet(0) + , fFinalSet(0) + , fScopeDefined(Grammar::TOP_LEVEL_SCOPE) + , fContentType(SchemaElementDecl::Empty) + , fElementId(XMLElementDecl::fgInvalidElemId) + , fUniqueURI(0) + , fContentSpecOrgURISize(16) + , fTypeName(0) + , fTypeLocalName(0) + , fTypeUri(0) + , fBaseDatatypeValidator(0) + , fDatatypeValidator(0) + , fBaseComplexTypeInfo(0) + , fContentSpec(0) + , fAttWildCard(0) + , fAttList(0) + , fElements(0) + , fAttDefs(0) + , fContentModel(0) + , fFormattedModel(0) + , fContentSpecOrgURI(0) + , fLocator(0) + , fMemoryManager(manager) +{ + fAttDefs = new (fMemoryManager) RefHash2KeysTableOf(29, true, fMemoryManager); + fAttList = new (fMemoryManager) SchemaAttDefList(fAttDefs,fMemoryManager); +} + + +ComplexTypeInfo::~ComplexTypeInfo() +{ + fMemoryManager->deallocate(fTypeName); //delete [] fTypeName; + fMemoryManager->deallocate(fTypeLocalName); //delete [] fTypeLocalName; + fMemoryManager->deallocate(fTypeUri); //delete [] fTypeUri; + + if (fAdoptContentSpec) { + delete fContentSpec; + } + + delete fAttWildCard; + delete fAttDefs; + delete fAttList; + delete fElements; + delete fLocator; + + delete fContentModel; + fMemoryManager->deallocate(fFormattedModel); //delete [] fFormattedModel; + fMemoryManager->deallocate(fContentSpecOrgURI); //delete [] fContentSpecOrgURI; + +} + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Setter methods +// --------------------------------------------------------------------------- +void ComplexTypeInfo::addAttDef(SchemaAttDef* const toAdd) { + + // Tell this guy the element id of its parent (us) + toAdd->setElemId(getElementId()); + + fAttDefs->put((void*)(toAdd->getAttName()->getLocalPart()), + toAdd->getAttName()->getURI(), toAdd); + // update and/or create fAttList + fAttList->addAttDef(toAdd); +} + +void ComplexTypeInfo::setContentSpec(ContentSpecNode* const toAdopt) { + + if (fContentSpec && fAdoptContentSpec) { + delete fContentSpec; + } + + fContentSpec = toAdopt; +} + +void ComplexTypeInfo::setLocator(XSDLocator* const aLocator) { + + if (fLocator) + delete fLocator; + + fLocator = aLocator; +} + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Getter methods +// --------------------------------------------------------------------------- +XMLAttDefList& ComplexTypeInfo::getAttDefList() const +{ + // NOTE: if users plan on using nextElement() to access attributes + // they need to call Reset() explicitly (i.e attList.Reset()). + // It's better to get the attribute count and use an index to + // access attributes (especially if same grammar is used in + // multiple threads). + return *fAttList; +} + +const XMLCh* +ComplexTypeInfo::getFormattedContentModel() const +{ + // + // If its not already built, then call the protected virtual method + // to allow the derived class to build it (since only it knows.) + // Otherwise, just return the previously formatted methods. + // + // Since we are faulting this in, within a const getter, we have to + // cast off the const-ness. + // + if (!fFormattedModel) + ((ComplexTypeInfo*)this)->fFormattedModel = formatContentModel(); + + return fFormattedModel; +} + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Helper methods +// --------------------------------------------------------------------------- +void ComplexTypeInfo::checkUniqueParticleAttribution (SchemaGrammar* const pGrammar, + GrammarResolver* const pGrammarResolver, + XMLStringPool* const pStringPool, + XMLValidator* const pValidator) +{ + if (fContentSpec && !fContentModel) + { + fContentModel = makeContentModel(true); + if (fContentModel) { + fContentModel->checkUniqueParticleAttribution(pGrammar, pGrammarResolver, pStringPool, pValidator, fContentSpecOrgURI, fTypeLocalName); + } + } +} + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Private Helper methods +// --------------------------------------------------------------------------- +void ComplexTypeInfo::faultInAttDefList() const +{ + // Use a hash modulus of 29 and tell it owns its elements + ((ComplexTypeInfo*)this)->fAttDefs = + new (fMemoryManager) RefHash2KeysTableOf(29, true, fMemoryManager); +} + +XMLCh* ComplexTypeInfo::formatContentModel() const +{ + XMLCh* newValue = 0; + if (fContentType == SchemaElementDecl::Any) + { + newValue = XMLString::replicate(XMLUni::fgAnyString, fMemoryManager); + } + else if (fContentType == SchemaElementDecl::Empty || + fContentType == SchemaElementDecl::ElementOnlyEmpty) + { + newValue = XMLString::replicate(XMLUni::fgEmptyString, fMemoryManager); + } + else + { + // + // Use a temp XML buffer to format into. Content models could be + // pretty long, but very few will be longer than one K. The buffer + // will expand to handle the more pathological ones. + // + const ContentSpecNode* specNode = fContentSpec; + + if (specNode) { + XMLBuffer bufFmt(1023, fMemoryManager); + + specNode->formatSpec(bufFmt); + newValue = XMLString::replicate + ( + bufFmt.getRawBuffer() + , fMemoryManager + ); + } + } + return newValue; +} + +bool ComplexTypeInfo::useRepeatingLeafNodes(ContentSpecNode* particle) +{ + int maxOccurs = particle->getMaxOccurs(); + int minOccurs = particle->getMinOccurs(); + ContentSpecNode::NodeTypes type = particle->getType(); + + if (((type & 0x0f) == ContentSpecNode::Choice) || ((type & 0x0f) == ContentSpecNode::Sequence)) + { + if (minOccurs != 1 || maxOccurs != 1) { + if(particle->getFirst()!=0 && particle->getSecond()==0) + { + ContentSpecNode* particle2 = particle->getFirst(); + ContentSpecNode::NodeTypes type2 = particle2->getType(); + return (((type2 == ContentSpecNode::Leaf) || + ((type2 & 0x0f) == ContentSpecNode::Any) || + ((type2 & 0x0f) == ContentSpecNode::Any_Other) || + ((type2 & 0x0f) == ContentSpecNode::Any_NS)) && + particle2->getMinOccurs() == 1 && + particle2->getMaxOccurs() == 1); + } + return (particle->getFirst()==0 && particle->getSecond()==0); + } + if(particle->getFirst()!=0 && !useRepeatingLeafNodes(particle->getFirst())) + return false; + if(particle->getSecond()!=0 && !useRepeatingLeafNodes(particle->getSecond())) + return false; + } + return true; +} + +XMLContentModel* ComplexTypeInfo::makeContentModel(bool checkUPA) +{ + ContentSpecNode* aSpecNode = new (fMemoryManager) ContentSpecNode(*fContentSpec); + + if (checkUPA) { + fContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate + ( + fContentSpecOrgURISize * sizeof(unsigned int) + ); //new unsigned int[fContentSpecOrgURISize]; + } + + aSpecNode = convertContentSpecTree(aSpecNode, checkUPA, useRepeatingLeafNodes(aSpecNode)); + + Janitor janSpecNode(aSpecNode); + + XMLContentModel* cmRet = 0; + if (fContentType == SchemaElementDecl::Simple || + fContentType == SchemaElementDecl::ElementOnlyEmpty) { + // just return nothing + } + else if (fContentType == SchemaElementDecl::Mixed_Simple) + { + // + // Just create a mixel content model object. This type of + // content model is optimized for mixed content validation. + // + cmRet = new (fMemoryManager) MixedContentModel(false, aSpecNode, false, fMemoryManager); + } + else if (fContentType == SchemaElementDecl::Mixed_Complex || + fContentType == SchemaElementDecl::Children) + { + bool isMixed = (fContentType == SchemaElementDecl::Mixed_Complex); + + // + // This method will create an optimal model for the complexity + // of the element's defined model. If its simple, it will create + // a SimpleContentModel object. If its a simple list, it will + // create a SimpleListContentModel object. If its complex, it + // will create a DFAContentModel object. + // + if(!aSpecNode) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager); + + ContentSpecNode::NodeTypes specType = aSpecNode->getType(); + // + // Do a sanity check that the node is does not have a PCDATA id. Since, + // if it was, it should have already gotten taken by the Mixed model. + // + if (aSpecNode->getElement() && aSpecNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoPCDATAHere, fMemoryManager); + + // + // According to the type of node, we will create the correct type of + // content model. + // + if (((specType & 0x0f) == ContentSpecNode::Any) || + ((specType & 0x0f) == ContentSpecNode::Any_Other) || + ((specType & 0x0f) == ContentSpecNode::Any_NS) || + specType == ContentSpecNode::Loop) { + // let fall through to build a DFAContentModel + } + else if (isMixed) + { + if (specType == ContentSpecNode::All) { + // All the nodes under an ALL must be additional ALL nodes and + // ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.) + // We collapse the ELEMENTs into a single vector. + cmRet = new (fMemoryManager) AllContentModel(aSpecNode, true, fMemoryManager); + } + else if (specType == ContentSpecNode::ZeroOrOne) { + // An ALL node can appear under a ZERO_OR_ONE node. + if (aSpecNode->getFirst()->getType() == ContentSpecNode::All) { + cmRet = new (fMemoryManager) AllContentModel(aSpecNode->getFirst(), true, fMemoryManager); + } + } + + // otherwise, let fall through to build a DFAContentModel + } + else if (specType == ContentSpecNode::Leaf) + { + // Create a simple content model + cmRet = new (fMemoryManager) SimpleContentModel + ( + false + , aSpecNode->getElement() + , 0 + , ContentSpecNode::Leaf + , fMemoryManager + ); + } + else if (((specType & 0x0f) == ContentSpecNode::Choice) + || ((specType & 0x0f) == ContentSpecNode::Sequence)) + { + // + // Lets see if both of the children are leafs. If so, then it has to + // be a simple content model + // + if ((aSpecNode->getFirst()->getType() == ContentSpecNode::Leaf) + && (aSpecNode->getSecond()) + && (aSpecNode->getSecond()->getType() == ContentSpecNode::Leaf)) + { + cmRet = new (fMemoryManager) SimpleContentModel + ( + false + , aSpecNode->getFirst()->getElement() + , aSpecNode->getSecond()->getElement() + , specType + , fMemoryManager + ); + } + } + else if ((specType == ContentSpecNode::OneOrMore) + || (specType == ContentSpecNode::ZeroOrMore) + || (specType == ContentSpecNode::ZeroOrOne)) + { + // + // Its a repetition, so see if its one child is a leaf. If so its a + // repetition of a single element, so we can do a simple content + // model for that. + // + if (aSpecNode->getFirst()->getType() == ContentSpecNode::Leaf) + { + cmRet = new (fMemoryManager) SimpleContentModel + ( + false + , aSpecNode->getFirst()->getElement() + , 0 + , specType + , fMemoryManager + ); + } + else if (aSpecNode->getFirst()->getType() == ContentSpecNode::All) + cmRet = new (fMemoryManager) AllContentModel(aSpecNode->getFirst(), false, fMemoryManager); + + } + else if (specType == ContentSpecNode::All) + cmRet = new (fMemoryManager) AllContentModel(aSpecNode, false, fMemoryManager); + else + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager); + } + + // Its not any simple type of content, so create a DFA based content model + if(cmRet==0) + cmRet = new (fMemoryManager) DFAContentModel(false, aSpecNode, isMixed, fMemoryManager); + } + else + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren, fMemoryManager); + } + + return cmRet; +} + +// --------------------------------------------------------------------------- +// SchemaElementDecl: Private helper methods +// --------------------------------------------------------------------------- + +ContentSpecNode* +ComplexTypeInfo::convertContentSpecTree(ContentSpecNode* const curNode, + bool checkUPA, + bool bAllowCompactSyntax) { + + if (!curNode) + return 0; + + const ContentSpecNode::NodeTypes curType = curNode->getType(); + + // When checking Unique Particle Attribution, rename leaf elements + if (checkUPA) { + if (curNode->getElement()) { + if (fUniqueURI == fContentSpecOrgURISize) { + resizeContentSpecOrgURI(); + } + + fContentSpecOrgURI[fUniqueURI] = curNode->getElement()->getURI(); + curNode->getElement()->setURI(fUniqueURI); + fUniqueURI++; + } + } + + // Get the spec type of the passed node + int minOccurs = curNode->getMinOccurs(); + int maxOccurs = curNode->getMaxOccurs(); + ContentSpecNode* retNode = curNode; + + if ((curType & 0x0f) == ContentSpecNode::Any + || (curType & 0x0f) == ContentSpecNode::Any_Other + || (curType & 0x0f) == ContentSpecNode::Any_NS + || curType == ContentSpecNode::Leaf) + { + retNode = expandContentModel(curNode, minOccurs, maxOccurs, bAllowCompactSyntax); + } + else if (((curType & 0x0f) == ContentSpecNode::Choice) + || (curType == ContentSpecNode::All) + || ((curType & 0x0f) == ContentSpecNode::Sequence)) + { + ContentSpecNode* childNode = curNode->getFirst(); + ContentSpecNode* leftNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax); + ContentSpecNode* rightNode = curNode->getSecond(); + + if (!rightNode) { + + retNode = expandContentModel(leftNode, minOccurs, maxOccurs, bAllowCompactSyntax); + curNode->setAdoptFirst(false); + delete curNode; + return retNode; + } + + if (leftNode != childNode) { + + curNode->setAdoptFirst(false); + curNode->setFirst(leftNode); + curNode->setAdoptFirst(true); + } + + childNode = rightNode; + rightNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax); + + if (rightNode != childNode) { + + curNode->setAdoptSecond(false); + curNode->setSecond(rightNode); + curNode->setAdoptSecond(true); + } + + retNode = expandContentModel(curNode, minOccurs, maxOccurs, bAllowCompactSyntax); + } + + return retNode; +} + +ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const specNode, + int minOccurs, + int maxOccurs, + bool bAllowCompactSyntax) +{ + if (!specNode) { + return 0; + } + + ContentSpecNode* saveNode = specNode; + ContentSpecNode* retNode = specNode; + + if (minOccurs == 1 && maxOccurs == 1) { + } + else if (minOccurs == 0 && maxOccurs == 1) { + + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::ZeroOrOne + , retNode + , 0 + , true + , true + , fMemoryManager + ); + } + else if (minOccurs == 0 && maxOccurs == -1) { + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::ZeroOrMore + , retNode + , 0 + , true + , true + , fMemoryManager + ); + } + else if (minOccurs == 1 && maxOccurs == -1) { + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::OneOrMore + , retNode + , 0 + , true + , true + , fMemoryManager + ); + } + // if what is being repeated is a leaf avoid expanding the tree + else if(bAllowCompactSyntax && + (saveNode->getType()==ContentSpecNode::Leaf || + (saveNode->getType() & 0x0f)==ContentSpecNode::Any || + (saveNode->getType() & 0x0f)==ContentSpecNode::Any_Other || + (saveNode->getType() & 0x0f)==ContentSpecNode::Any_NS)) + { + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Loop + , retNode + , 0 + , true + , true + , fMemoryManager + ); + retNode->setMinOccurs(minOccurs); + retNode->setMaxOccurs(maxOccurs); + + if(minOccurs==0) + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::ZeroOrMore + , retNode + , 0 + , true + , true + , fMemoryManager + ); + else + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::OneOrMore + , retNode + , 0 + , true + , true + , fMemoryManager + ); + + } + else if (maxOccurs == -1) { + + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::OneOrMore + , retNode + , 0 + , true + , true + , fMemoryManager + ); + + for (int i=0; i < (minOccurs-1); i++) { + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Sequence + , saveNode + , retNode + , false + , true + , fMemoryManager + ); + } + } + else { + + if (minOccurs == 0) { + + ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::ZeroOrOne + , saveNode + , 0 + , true + , true + , fMemoryManager + ); + + retNode = optional; + + for (int i=0; i < (maxOccurs-1); i++) { + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Sequence + , retNode + , optional + , true + , false + , fMemoryManager + ); + } + } + else { + + if (minOccurs > 1) { + + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Sequence + , retNode + , saveNode + , true + , false + , fMemoryManager + ); + + for (int i=1; i < (minOccurs-1); i++) { + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Sequence + , retNode + , saveNode + , true + , false + , fMemoryManager + ); + } + } + + int counter = maxOccurs-minOccurs; + + if (counter > 0) { + + ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::ZeroOrOne + , saveNode + , 0 + , false + , true + , fMemoryManager + ); + + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Sequence + , retNode + , optional + , true + , true + , fMemoryManager + ); + + for (int j=1; j < counter; j++) { + + retNode = new (fMemoryManager) ContentSpecNode + ( + ContentSpecNode::Sequence + , retNode + , optional + , true + , false + , fMemoryManager + ); + } + } + } + } + + return retNode; +} + +void ComplexTypeInfo::resizeContentSpecOrgURI() { + + unsigned int newSize = fContentSpecOrgURISize * 2; + unsigned int* newContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate + ( + newSize * sizeof(unsigned int) + ); //new unsigned int[newSize]; + + // Copy the existing values + unsigned int index = 0; + for (; index < fContentSpecOrgURISize; index++) + newContentSpecOrgURI[index] = fContentSpecOrgURI[index]; + + for (; index < newSize; index++) + newContentSpecOrgURI[index] = 0; + + // Delete the old array and udpate our members + fMemoryManager->deallocate(fContentSpecOrgURI); //delete [] fContentSpecOrgURI; + fContentSpecOrgURI = newContentSpecOrgURI; + fContentSpecOrgURISize = newSize; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(ComplexTypeInfo) + +void ComplexTypeInfo::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<* fElements; + * Serialize RefHash2KeysTableOf* fAttDefs; + ***/ + XTemplateSerializer::storeObject(fElements, serEng); + XTemplateSerializer::storeObject(fAttDefs, serEng); + + /*** + * Don't serialize + * + * fContentModel; + * fFormattedModel; + * fLocator; + * + * fContentSpecOrgURI: start of the array + * fContentSpecOrgURISize: size of the array + * fUniqueURI: the current last element in the array + ***/ + } + else + { + serEng>>fAnonymous; + serEng>>fAbstract; + serEng>>fAdoptContentSpec; + serEng>>fAttWithTypeId; + serEng>>fPreprocessed; + serEng>>fDerivedBy; + serEng>>fBlockSet; + serEng>>fFinalSet; + serEng>>fScopeDefined; + serEng>>fContentType; + + serEng>>fElementId; + + serEng.readString(fTypeName); + serEng.readString(fTypeLocalName); + serEng.readString(fTypeUri); + + fBaseDatatypeValidator = DatatypeValidator::loadDV(serEng); + fDatatypeValidator = DatatypeValidator::loadDV(serEng); + + serEng>>fBaseComplexTypeInfo; + serEng>>fContentSpec; + serEng>>fAttWildCard; + delete fAttList; // will recreate it next... + serEng>>fAttList; + + /*** + * + * Deserialize RefVectorOf* fElements; + * Deserialize RefHash2KeysTableOf* fAttDefs; + ***/ + XTemplateSerializer::loadObject(&fElements, 8, false, serEng); + delete fAttDefs; // will recreate it next... + XTemplateSerializer::loadObject(&fAttDefs, 29, true, serEng); + + /*** + * Don't deserialize + * + * fFormattedModel; + * fLocator; + * + * fContentSpecOrgURI: start of the array + * fContentSpecOrgURISize: size of the array + * fUniqueURI: the current last element in the array + ***/ + + fFormattedModel = 0; + fLocator = 0; + fContentSpecOrgURI = 0; + fContentSpecOrgURISize = 0; + fUniqueURI = 0; + + // Create the content model by calling getContentModel(). This + // will ensure the grammar can be used concurrently by multiple + // parsers. + // Don't bother to do check unique particle attribution, since + // this will already have been done when the grammar was first + // created (if full schema checking was enabled). + getContentModel(false); + } +} + + +XERCES_CPP_NAMESPACE_END + +/** + * End of file ComplexTypeInfo.cpp + */ diff --git a/include/xercesc/validators/schema/ComplexTypeInfo.hpp b/include/xercesc/validators/schema/ComplexTypeInfo.hpp new file mode 100644 index 0000000..7ed611c --- /dev/null +++ b/include/xercesc/validators/schema/ComplexTypeInfo.hpp @@ -0,0 +1,531 @@ +/* + * 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: ComplexTypeInfo.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_COMPLEXTYPEINFO_HPP) +#define XERCESC_INCLUDE_GUARD_COMPLEXTYPEINFO_HPP + + +/** + * The class act as a place holder to store complex type information. + * + * The class is intended for internal use. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class DatatypeValidator; +class ContentSpecNode; +class SchemaAttDefList; +class SchemaElementDecl; +class XSDLocator; + + +class VALIDATORS_EXPORT ComplexTypeInfo : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Public Constructors/Destructor + // ----------------------------------------------------------------------- + ComplexTypeInfo(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~ComplexTypeInfo(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getAbstract() const; + bool getAdoptContentSpec() const; + bool containsAttWithTypeId() const; + bool getPreprocessed() const; + int getDerivedBy() const; + int getBlockSet() const; + int getFinalSet() const; + unsigned int getScopeDefined() const; + unsigned int getElementId() const; + int getContentType() const; + XMLSize_t elementCount() const; + XMLCh* getTypeName() const; + DatatypeValidator* getBaseDatatypeValidator() const; + DatatypeValidator* getDatatypeValidator() const; + ComplexTypeInfo* getBaseComplexTypeInfo() const; + ContentSpecNode* getContentSpec() const; + const SchemaAttDef* getAttWildCard() const; + SchemaAttDef* getAttWildCard(); + const SchemaAttDef* getAttDef(const XMLCh* const baseName, + const int uriId) const; + SchemaAttDef* getAttDef(const XMLCh* const baseName, + const int uriId); + XMLAttDefList& getAttDefList() const; + const SchemaElementDecl* elementAt(const XMLSize_t index) const; + SchemaElementDecl* elementAt(const XMLSize_t index); + XMLContentModel* getContentModel(const bool checkUPA = false); + const XMLCh* getFormattedContentModel () const; + XSDLocator* getLocator() const; + const XMLCh* getTypeLocalName() const; + const XMLCh* getTypeUri() const; + + /** + * returns true if this type is anonymous + **/ + bool getAnonymous() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setAbstract(const bool isAbstract); + void setAdoptContentSpec(const bool toAdopt); + void setAttWithTypeId(const bool value); + void setPreprocessed(const bool aValue = true); + void setDerivedBy(const int derivedBy); + void setBlockSet(const int blockSet); + void setFinalSet(const int finalSet); + void setScopeDefined(const unsigned int scopeDefined); + void setElementId(const unsigned int elemId); + void setTypeName(const XMLCh* const typeName); + void setContentType(const int contentType); + void setBaseDatatypeValidator(DatatypeValidator* const baseValidator); + void setDatatypeValidator(DatatypeValidator* const validator); + void setBaseComplexTypeInfo(ComplexTypeInfo* const typeInfo); + void setContentSpec(ContentSpecNode* const toAdopt); + void setAttWildCard(SchemaAttDef* const toAdopt); + void addAttDef(SchemaAttDef* const toAdd); + void addElement(SchemaElementDecl* const toAdd); + void setLocator(XSDLocator* const aLocator); + + /** + * sets this type to be anonymous + **/ + void setAnonymous(); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + bool hasAttDefs() const; + bool contains(const XMLCh* const attName); + void checkUniqueParticleAttribution + ( + SchemaGrammar* const pGrammar + , GrammarResolver* const pGrammarResolver + , XMLStringPool* const pStringPool + , XMLValidator* const pValidator + ) ; + + /** + * Return a singleton that represents 'anyType' + * + * @param emptyNSId the uri id of the empty namespace + */ + static ComplexTypeInfo* getAnyType(unsigned int emptyNSId); + + /** + * Notification that lazy data has been deleted + */ + static void reinitAnyType(); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(ComplexTypeInfo) + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ComplexTypeInfo(const ComplexTypeInfo& elemInfo); + ComplexTypeInfo& operator= (const ComplexTypeInfo& other); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void faultInAttDefList() const; + bool useRepeatingLeafNodes(ContentSpecNode* particle); + XMLContentModel* makeContentModel(bool checkUPA = false); + XMLCh* formatContentModel () const ; + ContentSpecNode* expandContentModel(ContentSpecNode* const curNode, int minOccurs, int maxOccurs, bool bAllowCompactSyntax); + ContentSpecNode* convertContentSpecTree(ContentSpecNode* const curNode, bool checkUPA, bool bAllowCompactSyntax); + void resizeContentSpecOrgURI(); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fAnonymous; + bool fAbstract; + bool fAdoptContentSpec; + bool fAttWithTypeId; + bool fPreprocessed; + int fDerivedBy; + int fBlockSet; + int fFinalSet; + unsigned int fScopeDefined; + int fContentType; + + unsigned int fElementId; + unsigned int fUniqueURI; + unsigned int fContentSpecOrgURISize; + + XMLCh* fTypeName; + XMLCh* fTypeLocalName; + XMLCh* fTypeUri; + DatatypeValidator* fBaseDatatypeValidator; + DatatypeValidator* fDatatypeValidator; + ComplexTypeInfo* fBaseComplexTypeInfo; + ContentSpecNode* fContentSpec; + SchemaAttDef* fAttWildCard; + SchemaAttDefList* fAttList; + RefVectorOf* fElements; + RefHash2KeysTableOf* fAttDefs; + XMLContentModel* fContentModel; + XMLCh* fFormattedModel; + unsigned int* fContentSpecOrgURI; + XSDLocator* fLocator; + MemoryManager* fMemoryManager; + + static ComplexTypeInfo* fAnyType; + + friend class XMLInitializer; +}; + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Getter methods +// --------------------------------------------------------------------------- +inline bool ComplexTypeInfo::getAbstract() const { + + return fAbstract; +} + +inline bool ComplexTypeInfo::getAdoptContentSpec() const { + + return fAdoptContentSpec; +} + +inline bool ComplexTypeInfo::containsAttWithTypeId() const { + + return fAttWithTypeId; +} + +inline bool ComplexTypeInfo::getPreprocessed() const { + + return fPreprocessed; +} + +inline int ComplexTypeInfo::getDerivedBy() const { + + return fDerivedBy; +} + +inline int ComplexTypeInfo::getBlockSet() const { + + return fBlockSet; +} + +inline int ComplexTypeInfo::getFinalSet() const { + + return fFinalSet; +} + +inline unsigned int ComplexTypeInfo::getScopeDefined() const { + + return fScopeDefined; +} + +inline unsigned int ComplexTypeInfo::getElementId() const { + + return fElementId; +} + +inline int ComplexTypeInfo::getContentType() const { + + return fContentType; +} + +inline XMLSize_t ComplexTypeInfo::elementCount() const { + + if (fElements) { + return fElements->size(); + } + + return 0; +} + +inline XMLCh* ComplexTypeInfo::getTypeName() const { + return fTypeName; +} + +inline DatatypeValidator* ComplexTypeInfo::getBaseDatatypeValidator() const { + + return fBaseDatatypeValidator; +} + +inline DatatypeValidator* ComplexTypeInfo::getDatatypeValidator() const { + + return fDatatypeValidator; +} + +inline ComplexTypeInfo* ComplexTypeInfo::getBaseComplexTypeInfo() const { + + return fBaseComplexTypeInfo; +} + +inline ContentSpecNode* ComplexTypeInfo::getContentSpec() const { + + return fContentSpec; +} + +inline const SchemaAttDef* ComplexTypeInfo::getAttWildCard() const { + + return fAttWildCard; +} + +inline SchemaAttDef* ComplexTypeInfo::getAttWildCard() { + + return fAttWildCard; +} + +inline const SchemaAttDef* ComplexTypeInfo::getAttDef(const XMLCh* const baseName, + const int uriId) const { + + return fAttDefs->get(baseName, uriId); +} + +inline SchemaAttDef* ComplexTypeInfo::getAttDef(const XMLCh* const baseName, + const int uriId) +{ + return fAttDefs->get(baseName, uriId); +} + +inline SchemaElementDecl* +ComplexTypeInfo::elementAt(const XMLSize_t index) { + + if (!fElements) { + return 0; // REVISIT - need to throw an exception + } + + return fElements->elementAt(index); +} + +inline const SchemaElementDecl* +ComplexTypeInfo::elementAt(const XMLSize_t index) const { + + if (!fElements) { + return 0; // REVISIT - need to throw an exception + } + + return fElements->elementAt(index); +} + +inline XMLContentModel* ComplexTypeInfo::getContentModel(const bool checkUPA) +{ + if (!fContentModel && fContentSpec) + fContentModel = makeContentModel(checkUPA); + + return fContentModel; +} + +inline XSDLocator* ComplexTypeInfo::getLocator() const +{ + return fLocator; +} + +inline bool ComplexTypeInfo::getAnonymous() const { + return fAnonymous; +} + +inline const XMLCh* ComplexTypeInfo::getTypeLocalName() const +{ + return fTypeLocalName; +} + +inline const XMLCh* ComplexTypeInfo::getTypeUri() const +{ + return fTypeUri; +} + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Setter methods +// --------------------------------------------------------------------------- +inline void ComplexTypeInfo::setAbstract(const bool isAbstract) { + + fAbstract = isAbstract; +} + +inline void ComplexTypeInfo::setAdoptContentSpec(const bool toAdopt) { + + fAdoptContentSpec = toAdopt; +} + +inline void ComplexTypeInfo::setAttWithTypeId(const bool value) { + + fAttWithTypeId = value; +} + +inline void ComplexTypeInfo::setPreprocessed(const bool aValue) { + + fPreprocessed = aValue; +} + +inline void ComplexTypeInfo::setDerivedBy(const int derivedBy) { + + fDerivedBy = derivedBy; +} + +inline void ComplexTypeInfo::setBlockSet(const int blockSet) { + + fBlockSet = blockSet; +} + +inline void ComplexTypeInfo::setFinalSet(const int finalSet) { + + fFinalSet = finalSet; +} + +inline void ComplexTypeInfo::setScopeDefined(const unsigned int scopeDefined) { + + fScopeDefined = scopeDefined; +} + +inline void ComplexTypeInfo::setElementId(const unsigned int elemId) { + + fElementId = elemId; +} + +inline void +ComplexTypeInfo::setContentType(const int contentType) { + + fContentType = contentType; +} + +inline void ComplexTypeInfo::setTypeName(const XMLCh* const typeName) { + + fMemoryManager->deallocate(fTypeName);//delete [] fTypeName; + fMemoryManager->deallocate(fTypeLocalName);//delete [] fTypeLocalName; + fMemoryManager->deallocate(fTypeUri);//delete [] fTypeUri; + + if (typeName) + { + fTypeName = XMLString::replicate(typeName, fMemoryManager); + + int index = XMLString::indexOf(fTypeName, chComma); + XMLSize_t length = XMLString::stringLen(fTypeName); + fTypeLocalName = (XMLCh*) fMemoryManager->allocate + ( + (length - index + 1) * sizeof(XMLCh) + ); //new XMLCh[length - index + 1]; + XMLString::subString(fTypeLocalName, fTypeName, index + 1, length, fMemoryManager); + + fTypeUri = (XMLCh*) fMemoryManager->allocate + ( + (index + 1) * sizeof(XMLCh) + ); //new XMLCh[index + 1]; + XMLString::subString(fTypeUri, fTypeName, 0, index, fMemoryManager); + } + else + { + fTypeName = fTypeLocalName = fTypeUri = 0; + } +} + +inline void +ComplexTypeInfo::setBaseDatatypeValidator(DatatypeValidator* const validator) { + + fBaseDatatypeValidator = validator; +} + +inline void +ComplexTypeInfo::setDatatypeValidator(DatatypeValidator* const validator) { + + fDatatypeValidator = validator; +} + +inline void +ComplexTypeInfo::setBaseComplexTypeInfo(ComplexTypeInfo* const typeInfo) { + + fBaseComplexTypeInfo = typeInfo; +} + +inline void ComplexTypeInfo::addElement(SchemaElementDecl* const elem) { + + if (!fElements) { + fElements = new (fMemoryManager) RefVectorOf(8, false, fMemoryManager); + } + else if (fElements->containsElement(elem)) { + return; + } + + fElements->addElement(elem); +} + +inline void ComplexTypeInfo::setAttWildCard(SchemaAttDef* const toAdopt) { + + if (fAttWildCard) { + delete fAttWildCard; + } + + fAttWildCard = toAdopt; +} + +inline void ComplexTypeInfo::setAnonymous() { + fAnonymous = true; +} + +// --------------------------------------------------------------------------- +// ComplexTypeInfo: Helper methods +// --------------------------------------------------------------------------- +inline bool ComplexTypeInfo::hasAttDefs() const +{ + return !fAttDefs->isEmpty(); +} + +inline bool ComplexTypeInfo::contains(const XMLCh* const attName) { + + RefHash2KeysTableOfEnumerator enumDefs(fAttDefs, false, fMemoryManager); + + while (enumDefs.hasMoreElements()) { + + if (XMLString::equals(attName, enumDefs.nextElement().getAttName()->getLocalPart())) { + return true; + } + } + + return false; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file ComplexTypeInfo.hpp + */ + diff --git a/include/xercesc/validators/schema/GeneralAttributeCheck.cpp b/include/xercesc/validators/schema/GeneralAttributeCheck.cpp new file mode 100644 index 0000000..657526f --- /dev/null +++ b/include/xercesc/validators/schema/GeneralAttributeCheck.cpp @@ -0,0 +1,798 @@ +/* + * 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. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local const data +// --------------------------------------------------------------------------- +static const XMLCh fgValueZero[] = +{ + chDigit_0, chNull +}; + +static const XMLCh fgValueOne[] = +{ + chDigit_1, chNull +}; + +static const XMLCh fgUnbounded[] = +{ + chLatin_u, chLatin_n, chLatin_b, chLatin_o, chLatin_u, chLatin_n, chLatin_d, + chLatin_e, chLatin_d, chNull +}; + +// --------------------------------------------------------------------------- +// Static member data initialization +// --------------------------------------------------------------------------- +ValueHashTableOf* GeneralAttributeCheck::fAttMap = 0; +ValueHashTableOf* GeneralAttributeCheck::fFacetsMap = 0; +DatatypeValidator* GeneralAttributeCheck::fNonNegIntDV = 0; +DatatypeValidator* GeneralAttributeCheck::fBooleanDV = 0; +DatatypeValidator* GeneralAttributeCheck::fAnyURIDV = 0; + +void XMLInitializer::initializeGeneralAttributeCheck() +{ + GeneralAttributeCheck::initialize (); +} + +void XMLInitializer::terminateGeneralAttributeCheck() +{ + delete GeneralAttributeCheck::fFacetsMap; + delete GeneralAttributeCheck::fAttMap; + + GeneralAttributeCheck::fAttMap = 0; + GeneralAttributeCheck::fFacetsMap = 0; + + GeneralAttributeCheck::fNonNegIntDV = 0; + GeneralAttributeCheck::fBooleanDV = 0; + GeneralAttributeCheck::fAnyURIDV = 0; +} + +void GeneralAttributeCheck::initialize() +{ + // Set up validators. + // + DatatypeValidatorFactory dvFactory; + + fNonNegIntDV = dvFactory.getDatatypeValidator(SchemaSymbols::fgDT_NONNEGATIVEINTEGER); + fBooleanDV = dvFactory.getDatatypeValidator(SchemaSymbols::fgDT_BOOLEAN); + fAnyURIDV = dvFactory.getDatatypeValidator(SchemaSymbols::fgDT_ANYURI); + + // TODO - add remaining valdiators + + // Map attributes. + // + fAttMap = new ValueHashTableOf(A_Count); + + fAttMap->put((void*)SchemaSymbols::fgATT_ABSTRACT, A_Abstract); + fAttMap->put((void*)SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT, A_AttributeFormDefault); + fAttMap->put((void*)SchemaSymbols::fgATT_BASE, A_Base); + fAttMap->put((void*)SchemaSymbols::fgATT_BLOCK, A_Block); + fAttMap->put((void*)SchemaSymbols::fgATT_BLOCKDEFAULT, A_BlockDefault); + fAttMap->put((void*)SchemaSymbols::fgATT_DEFAULT, A_Default); + fAttMap->put((void*)SchemaSymbols::fgATT_ELEMENTFORMDEFAULT, A_ElementFormDefault); + fAttMap->put((void*)SchemaSymbols::fgATT_FINAL, A_Final); + fAttMap->put((void*)SchemaSymbols::fgATT_FINALDEFAULT, A_FinalDefault); + fAttMap->put((void*)SchemaSymbols::fgATT_FIXED, A_Fixed); + fAttMap->put((void*)SchemaSymbols::fgATT_FORM, A_Form); + fAttMap->put((void*)SchemaSymbols::fgATT_ID, A_ID); + fAttMap->put((void*)SchemaSymbols::fgATT_ITEMTYPE, A_ItemType); + fAttMap->put((void*)SchemaSymbols::fgATT_MAXOCCURS, A_MaxOccurs); + fAttMap->put((void*)SchemaSymbols::fgATT_MEMBERTYPES, A_MemberTypes); + fAttMap->put((void*)SchemaSymbols::fgATT_MINOCCURS, A_MinOccurs); + fAttMap->put((void*)SchemaSymbols::fgATT_MIXED, A_Mixed); + fAttMap->put((void*)SchemaSymbols::fgATT_NAME, A_Name); + fAttMap->put((void*)SchemaSymbols::fgATT_NAMESPACE, A_Namespace); + fAttMap->put((void*)SchemaSymbols::fgATT_NILLABLE, A_Nillable); + fAttMap->put((void*)SchemaSymbols::fgATT_PROCESSCONTENTS, A_ProcessContents); + fAttMap->put((void*)SchemaSymbols::fgATT_PUBLIC, A_Public); + fAttMap->put((void*)SchemaSymbols::fgATT_REF, A_Ref); + fAttMap->put((void*)SchemaSymbols::fgATT_REFER, A_Refer); + fAttMap->put((void*)SchemaSymbols::fgATT_SCHEMALOCATION, A_SchemaLocation); + fAttMap->put((void*)SchemaSymbols::fgATT_SOURCE, A_Source); + fAttMap->put((void*)SchemaSymbols::fgATT_SUBSTITUTIONGROUP, A_SubstitutionGroup); + fAttMap->put((void*)SchemaSymbols::fgATT_SYSTEM, A_System); + fAttMap->put((void*)SchemaSymbols::fgATT_TARGETNAMESPACE, A_TargetNamespace); + fAttMap->put((void*)SchemaSymbols::fgATT_TYPE, A_Type); + fAttMap->put((void*)SchemaSymbols::fgATT_USE, A_Use); + fAttMap->put((void*)SchemaSymbols::fgATT_VALUE, A_Value); + fAttMap->put((void*)SchemaSymbols::fgATT_VERSION, A_Version); + fAttMap->put((void*)SchemaSymbols::fgATT_XPATH, A_XPath); + + fFacetsMap = new ValueHashTableOf(13); + + fFacetsMap->put((void*) SchemaSymbols::fgELT_MINEXCLUSIVE, E_MinExclusive); + fFacetsMap->put((void*) SchemaSymbols::fgELT_MININCLUSIVE, E_MinInclusive); + fFacetsMap->put((void*) SchemaSymbols::fgELT_MAXEXCLUSIVE, E_MaxExclusive); + fFacetsMap->put((void*) SchemaSymbols::fgELT_MAXINCLUSIVE, E_MaxInclusive); + fFacetsMap->put((void*) SchemaSymbols::fgELT_TOTALDIGITS, E_TotalDigits); + fFacetsMap->put((void*) SchemaSymbols::fgELT_FRACTIONDIGITS, E_FractionDigits); + fFacetsMap->put((void*) SchemaSymbols::fgELT_LENGTH, E_Length); + fFacetsMap->put((void*) SchemaSymbols::fgELT_MINLENGTH, E_MinLength); + fFacetsMap->put((void*) SchemaSymbols::fgELT_MAXLENGTH, E_MaxLength); + fFacetsMap->put((void*) SchemaSymbols::fgELT_ENUMERATION, E_Enumeration); + fFacetsMap->put((void*) SchemaSymbols::fgELT_WHITESPACE, E_WhiteSpace); + fFacetsMap->put((void*) SchemaSymbols::fgELT_PATTERN, E_Pattern); +} + +// --------------------------------------------------------------------------- +// GeneralAttributeCheck: Constructors and Destructor +// --------------------------------------------------------------------------- +GeneralAttributeCheck::GeneralAttributeCheck(MemoryManager* const manager) + : fMemoryManager(manager) + , fIDValidator(manager) +{ +} + +GeneralAttributeCheck::~GeneralAttributeCheck() +{ +} + +// --------------------------------------------------------------------------- +// GeneralAttributeCheck: Validation methods +// --------------------------------------------------------------------------- +void +GeneralAttributeCheck::checkAttributes(const DOMElement* const elem, + const unsigned short elemContext, + TraverseSchema* const schema, + const bool isTopLevel, + ValueVectorOf* const nonXSAttList) +{ + if (nonXSAttList) + nonXSAttList->removeAllElements(); + + if (elem == 0 || !fAttMap || elemContext>=E_Count) + return; + + const XMLCh* elemName = elem->getLocalName(); + if (!XMLString::equals(SchemaSymbols::fgURI_SCHEMAFORSCHEMA, elem->getNamespaceURI())) { + schema->reportSchemaError + ( + elem + , XMLUni::fgXMLErrDomain + , XMLErrs::ELTSchemaNS + , elemName + ); + } + + DOMNamedNodeMap* eltAttrs = elem->getAttributes(); + const XMLSize_t attrCount = eltAttrs->getLength(); + XMLByte attList[A_Count]; + + memset(attList, 0, sizeof(attList)); + + for (XMLSize_t i = 0; i < attrCount; i++) { + + DOMNode* attribute = eltAttrs->item(i); + const XMLCh* attName = attribute->getNodeName(); + + // skip namespace declarations + if (XMLString::equals(attName, XMLUni::fgXMLNSString) + || XMLString::startsWith(attName, XMLUni::fgXMLNSColonString)) + continue; + + // Bypass attributes that start with xml + // add this to the list of "non-schema" attributes + if ((*attName == chLatin_X || *attName == chLatin_x) + && (*(attName+1) == chLatin_M || *(attName+1) == chLatin_m) + && (*(attName+2) == chLatin_L || *(attName+2) == chLatin_l)) { + + if (nonXSAttList) + nonXSAttList->addElement(attribute); + + continue; + } + + // for attributes with namespace prefix + const XMLCh* attrURI = attribute->getNamespaceURI(); + + if (attrURI != 0 && *attrURI) { + + // attributes with schema namespace are not allowed + // and not allowed on "documentation" and "appInfo" + if (XMLString::equals(attrURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) || + XMLString::equals(elemName, SchemaSymbols::fgELT_APPINFO) || + XMLString::equals(elemName, SchemaSymbols::fgELT_DOCUMENTATION)) { + + schema->reportSchemaError(elem, XMLUni::fgXMLErrDomain, + isTopLevel?XMLErrs::AttributeDisallowedGlobal:XMLErrs::AttributeDisallowedLocal, + attName, elemName); + } + else if (nonXSAttList) + { + nonXSAttList->addElement(attribute); + } + + continue; + } + + int attNameId = A_Invalid; + attName = attribute->getLocalName(); + + bool bContinue=false; // workaround for Borland bug with 'continue' in 'catch' + try { + attNameId= fAttMap->get(attName, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + + schema->reportSchemaError(elem, XMLUni::fgXMLErrDomain, + isTopLevel?XMLErrs::AttributeDisallowedGlobal:XMLErrs::AttributeDisallowedLocal, + attName, elemName); + bContinue=true; + } + if(bContinue) + continue; + + if (fgElemAttTable[elemContext][attNameId] & Att_Mask) { + + attList[attNameId] = 1; + validate + ( + elem + , attName + , attribute->getNodeValue() + , fgElemAttTable[elemContext][attNameId] & DV_Mask + , schema + ); + } + else { + schema->reportSchemaError(elem, XMLUni::fgXMLErrDomain, + isTopLevel?XMLErrs::AttributeDisallowedGlobal:XMLErrs::AttributeDisallowedLocal, + attName, elemName); + } + } + + // ------------------------------------------------------------------ + // Check for required attributes + // ------------------------------------------------------------------ + for (unsigned int j=0; j < A_Count; j++) { + + if ((fgElemAttTable[elemContext][j] & Att_Required) && attList[j] == 0) { + schema->reportSchemaError(elem, XMLUni::fgXMLErrDomain, + isTopLevel?XMLErrs::AttributeRequiredGlobal:XMLErrs::AttributeRequiredLocal, + fAttNames[j], elemName); + } + } +} + + +void GeneralAttributeCheck::validate(const DOMElement* const elem, + const XMLCh* const attName, + const XMLCh* const attValue, + const short dvIndex, + TraverseSchema* const schema) +{ + bool isInvalid = false; + DatatypeValidator* dv = 0; + + ValidationContext* fValidationContext = schema->fSchemaInfo->getValidationContext(); + switch (dvIndex) { + case DV_Form: + if (!XMLString::equals(attValue, SchemaSymbols::fgATTVAL_QUALIFIED) + && !XMLString::equals(attValue, SchemaSymbols::fgATTVAL_UNQUALIFIED)) { + isInvalid = true; + } + break; + case DV_MaxOccurs: + // maxOccurs = (nonNegativeInteger | unbounded) + if (!XMLString::equals(attValue, fgUnbounded)) { + dv = fNonNegIntDV; + } + break; + case DV_MaxOccurs1: + if (!XMLString::equals(attValue, fgValueOne)) { + isInvalid = true; + } + break; + case DV_MinOccurs1: + if (!XMLString::equals(attValue, fgValueZero) + && !XMLString::equals(attValue, fgValueOne)) { + isInvalid = true; + } + break; + case DV_ProcessContents: + if (!XMLString::equals(attValue, SchemaSymbols::fgATTVAL_SKIP) + && !XMLString::equals(attValue, SchemaSymbols::fgATTVAL_LAX) + && !XMLString::equals(attValue, SchemaSymbols::fgATTVAL_STRICT)) { + isInvalid = true; + } + break; + case DV_Use: + if (!XMLString::equals(attValue, SchemaSymbols::fgATTVAL_OPTIONAL) + && !XMLString::equals(attValue, SchemaSymbols::fgATTVAL_PROHIBITED) + && !XMLString::equals(attValue, SchemaSymbols::fgATTVAL_REQUIRED)) { + isInvalid = true; + } + break; + case DV_WhiteSpace: + if (!XMLString::equals(attValue, SchemaSymbols::fgWS_PRESERVE) + && !XMLString::equals(attValue, SchemaSymbols::fgWS_REPLACE) + && !XMLString::equals(attValue, SchemaSymbols::fgWS_COLLAPSE)) { + isInvalid = true; + } + break; + case DV_Boolean: + dv = fBooleanDV; + break; + case DV_NonNegInt: + dv = fNonNegIntDV; + break; + case DV_AnyURI: + dv = fAnyURIDV; + break; + case DV_ID: + if (fValidationContext) + { + dv = &fIDValidator; + } + break; + } + + if (dv) { + try { + dv->validate(attValue, fValidationContext, fMemoryManager); + } + catch(const XMLException& excep) { + schema->reportSchemaError(elem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + isInvalid = true; + } + } + + if (isInvalid) { + schema->reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttValue, + attValue, attName); + } +} + + +// --------------------------------------------------------------------------- +// Conditional methods for building the table +// --------------------------------------------------------------------------- + +// +// This code will set up the character flags table. Its defined out since +// this table is now written out and hard coded (at the bottom of this +// file) into the code itself. This code is retained in case there is +// any need to recreate it later. +// + +#if defined(NEED_TO_GEN_ELEM_ATT_MAP_TABLE) + +#include + +void GeneralAttributeCheck::initCharFlagTable() +{ + unsigned short attList[E_Count][A_Count]; + + for (unsigned int i=0; i < E_Count; i++) { + for (unsigned int j=0; j < A_Count; j++) { + attList[i][j] = 0; + } + } + + // + // Write it out to a temp file to be read back into this source later. + // + FILE* outFl = fopen("ea_table.out", "wt+"); + fprintf(outFl, "unsigned short GeneralAttributeCheck::fgElemAttTable[GeneralAttributeCheck::E_Count][GeneralAttributeCheck::A_Count] =\n{\n {"); + + //"all" + attList[E_All][A_ID] = Att_Optional | DV_ID; + attList[E_All][A_MaxOccurs] = Att_Optional | DV_MaxOccurs1; + attList[E_All][A_MinOccurs] = Att_Optional | DV_MinOccurs1; + + // "annotation" + attList[E_Annotation][A_ID] = Att_Optional | DV_ID; + + // "any" + attList[E_Any][A_ID] = Att_Optional | DV_ID; + attList[E_Any][A_MaxOccurs] = Att_Optional | DV_MaxOccurs; + attList[E_Any][A_MinOccurs] = Att_Optional | DV_NonNegInt; + attList[E_Any][A_Namespace] = Att_Optional; + attList[E_Any][A_ProcessContents] = Att_Optional | DV_ProcessContents; + + // "anyAttribute" + attList[E_AnyAttribute][A_ID] = Att_Optional | DV_ID; + attList[E_AnyAttribute][A_Namespace] = Att_Optional; + attList[E_AnyAttribute][A_ProcessContents] = Att_Optional | DV_ProcessContents; + + // "appinfo" + attList[E_Appinfo][A_Source]= Att_Optional | DV_AnyURI; + + // attribute - global" + attList[E_AttributeGlobal][A_Default] = Att_Optional; + attList[E_AttributeGlobal][A_Fixed] = Att_Optional; + attList[E_AttributeGlobal][A_ID] = Att_Optional | DV_ID; + attList[E_AttributeGlobal][A_Name] = Att_Required; + attList[E_AttributeGlobal][A_Type] = Att_Optional; + + // "attribute - local" + attList[E_AttributeLocal][A_Default] = Att_Optional; + attList[E_AttributeLocal][A_Fixed] = Att_Optional; + attList[E_AttributeLocal][A_Form]= Att_Optional | DV_Form; + attList[E_AttributeLocal][A_ID] = Att_Optional | DV_ID; + attList[E_AttributeLocal][A_Name] = Att_Required; + attList[E_AttributeLocal][A_Type] = Att_Optional; + attList[E_AttributeLocal][A_Use] = Att_Optional | DV_Use; + + // "attribute - ref" + attList[E_AttributeRef][A_Default] = Att_Optional; + attList[E_AttributeRef][A_Fixed] = Att_Optional; + attList[E_AttributeRef][A_ID] = Att_Optional | DV_ID; + attList[E_AttributeRef][A_Ref]= Att_Required; + attList[E_AttributeRef][A_Use] = Att_Optional | DV_Use; + + // "attributeGroup - global" + attList[E_AttributeGroupGlobal][A_ID] = Att_Optional | DV_ID; + attList[E_AttributeGroupGlobal][A_Name] = Att_Required; + + // "attributeGroup - ref" + attList[E_AttributeGroupRef][A_ID] = Att_Optional | DV_ID; + attList[E_AttributeGroupRef][A_Ref]= Att_Required; + + // "choice" + attList[E_Choice][A_ID] = Att_Optional | DV_ID; + attList[E_Choice][A_MaxOccurs] = Att_Optional | DV_MaxOccurs; + attList[E_Choice][A_MinOccurs] = Att_Optional | DV_NonNegInt; + + // "complexContent" + attList[E_ComplexContent][A_ID] = Att_Optional | DV_ID; + attList[E_ComplexContent][A_Mixed] = Att_Optional | DV_Boolean; + + // "complexType - global" + attList[E_ComplexTypeGlobal][A_Abstract] = Att_Optional | DV_Boolean; + attList[E_ComplexTypeGlobal][A_Block] = Att_Optional; + attList[E_ComplexTypeGlobal][A_Final] = Att_Optional; + attList[E_ComplexTypeGlobal][A_ID] = Att_Optional | DV_ID; + attList[E_ComplexTypeGlobal][A_Mixed] = Att_Optional | DV_Boolean; + attList[E_ComplexTypeGlobal][A_Name] = Att_Required; + + // "complexType - local" + attList[E_ComplexTypeLocal][A_ID] = Att_Optional | DV_ID; + attList[E_ComplexTypeLocal][A_Mixed] = Att_Optional | DV_Boolean; + + // "documentation" + attList[E_Documentation][A_Source] = Att_Optional | DV_AnyURI; + + // "element - global" + attList[E_ElementGlobal][A_Abstract] = Att_Optional | DV_Boolean; + attList[E_ElementGlobal][A_Block] = Att_Optional; + attList[E_ElementGlobal][A_Default] = Att_Optional; + attList[E_ElementGlobal][A_Final] = Att_Optional; + attList[E_ElementGlobal][A_Fixed] = Att_Optional; + attList[E_ElementGlobal][A_ID] = Att_Optional | DV_ID; + attList[E_ElementGlobal][A_Name] = Att_Required; + attList[E_ElementGlobal][A_Nillable] = Att_Optional | DV_Boolean; + attList[E_ElementGlobal][A_SubstitutionGroup] = Att_Optional; + attList[E_ElementGlobal][A_Type] = Att_Optional; + + // "element - local" + attList[E_ElementLocal][A_Block]= Att_Optional; + attList[E_ElementLocal][A_Default] = Att_Optional; + attList[E_ElementLocal][A_Fixed] = Att_Optional; + attList[E_ElementLocal][A_Form] = Att_Optional | DV_Form; + attList[E_ElementLocal][A_ID] = Att_Optional | DV_ID; + attList[E_ElementLocal][A_MaxOccurs] = Att_Optional | DV_MaxOccurs; + attList[E_ElementLocal][A_MinOccurs] = Att_Optional | DV_NonNegInt; + attList[E_ElementLocal][A_Name] = Att_Required; + attList[E_ElementLocal][A_Nillable] = Att_Optional | DV_Boolean; + attList[E_ElementLocal][A_Type] = Att_Optional; + + //"element - ref" + attList[E_ElementRef][A_ID] = Att_Optional | DV_ID; + attList[E_ElementRef][A_MaxOccurs] = Att_Optional | DV_MaxOccurs; + attList[E_ElementRef][A_MinOccurs] = Att_Optional | DV_NonNegInt; + attList[E_ElementRef][A_Ref] = Att_Required; + + // "enumeration" + attList[E_Enumeration][A_ID] = Att_Optional | DV_ID; + attList[E_Enumeration][A_Value] = Att_Optional; + + // "extension" + attList[E_Extension][A_Base] = Att_Required; + attList[E_Extension][A_ID] = Att_Optional | DV_ID; + + //"field" + attList[E_Field][A_ID] = Att_Optional | DV_ID; + attList[E_Field][A_XPath] = Att_Required; + + // "fractionDigits" + attList[E_FractionDigits][A_ID] = Att_Optional | DV_ID; + attList[E_FractionDigits][A_Value] = Att_Optional | DV_NonNegInt; + attList[E_FractionDigits][A_Fixed] = Att_Optional | DV_Boolean; + + // "group - global" + attList[E_GroupGlobal][A_ID] = Att_Optional | DV_ID; + attList[E_GroupGlobal][A_Name] = Att_Required; + + // "group - ref" + attList[E_GroupRef][A_ID] = Att_Optional | DV_ID; + attList[E_GroupRef][A_MaxOccurs] = Att_Optional | DV_MaxOccurs; + attList[E_GroupRef][A_MinOccurs] = Att_Optional | DV_NonNegInt; + attList[E_GroupRef][A_Ref] = Att_Required; + + // "import" + attList[E_Import][A_ID] = Att_Optional | DV_ID; + attList[E_Import][A_Namespace] = Att_Optional; + attList[E_Import][A_SchemaLocation] = Att_Optional; + + // "include" + attList[E_Include][A_ID] = Att_Optional | DV_ID; + attList[E_Include][A_SchemaLocation] = Att_Required; + + // "key" + attList[E_Key][A_ID] = Att_Optional | DV_ID; + attList[E_Key][A_Name] = Att_Required; + + // "keyref" + attList[E_KeyRef][A_ID] = Att_Optional | DV_ID; + attList[E_KeyRef][A_Name] = Att_Required; + attList[E_KeyRef][A_Refer] = Att_Required; + + // "length" + attList[E_Length][A_ID] = Att_Optional | DV_ID; + attList[E_Length][A_Value] = Att_Optional | DV_NonNegInt; + attList[E_Length][A_Fixed] = Att_Optional | DV_Boolean; + + // "list" + attList[E_List][A_ID] = Att_Optional | DV_ID; + attList[E_List][A_ItemType] = Att_Optional; + + // "maxExclusive" + attList[E_MaxExclusive][A_ID] = Att_Optional | DV_ID; + attList[E_MaxExclusive][A_Value] = Att_Optional; + attList[E_MaxExclusive][A_Fixed] = Att_Optional | DV_Boolean; + + // "maxInclusive" + attList[E_MaxInclusive][A_ID] = Att_Optional | DV_ID; + attList[E_MaxInclusive][A_Value] = Att_Optional; + attList[E_MaxInclusive][A_Fixed] = Att_Optional | DV_Boolean; + + // "maxLength" + attList[E_MaxLength][A_ID] = Att_Optional | DV_ID; + attList[E_MaxLength][A_Value] = Att_Optional | DV_NonNegInt; + attList[E_MaxLength][A_Fixed] = Att_Optional | DV_Boolean; + + // "minExclusive" + attList[E_MinExclusive][A_ID] = Att_Optional | DV_ID; + attList[E_MinExclusive][A_Value] = Att_Optional; + attList[E_MinExclusive][A_Fixed] = Att_Optional | DV_Boolean; + + // "minInclusive" + attList[E_MinInclusive][A_ID] = Att_Optional | DV_ID; + attList[E_MinInclusive][A_Value] = Att_Optional; + attList[E_MinInclusive][A_Fixed] = Att_Optional | DV_Boolean; + + // "minLength" + attList[E_MinLength][A_ID] = Att_Optional | DV_ID; + attList[E_MinLength][A_Value] = Att_Optional | DV_NonNegInt; + attList[E_MinLength][A_Fixed] = Att_Optional | DV_Boolean; + + // "notation" + attList[E_Notation][A_ID] = Att_Optional | DV_ID; + attList[E_Notation][A_Name] = Att_Required; + attList[E_Notation][A_Public] = Att_Optional; + attList[E_Notation][A_System] = Att_Optional | DV_AnyURI; + + // "pattern" + attList[E_Pattern][A_ID] = Att_Optional; + attList[E_Pattern][A_Value] = Att_Optional; + + // "redefine" + attList[E_Redefine][A_ID] = Att_Optional | DV_ID; + attList[E_Redefine][A_SchemaLocation] = Att_Required; + + // "restriction" + attList[E_Restriction][A_Base] = Att_Optional; + attList[E_Restriction][A_ID] = Att_Optional | DV_ID; + + // "schema" + attList[E_Schema][A_AttributeFormDefault] = Att_Optional | DV_Form; + attList[E_Schema][A_BlockDefault] = Att_Optional; + attList[E_Schema][A_ElementFormDefault] = Att_Optional | DV_Form; + attList[E_Schema][A_FinalDefault] = Att_Optional; + attList[E_Schema][A_ID] = Att_Optional | DV_ID; + attList[E_Schema][A_TargetNamespace] = Att_Optional; + attList[E_Schema][A_Version] = Att_Optional; + + // "selector" + attList[E_Selector][A_ID] = Att_Optional | DV_ID; + attList[E_Selector][A_XPath] = Att_Required; + + // "sequence" + attList[E_Sequence][A_ID] = Att_Optional | DV_ID; + attList[E_Sequence][A_MaxOccurs] = Att_Optional | DV_MaxOccurs; + attList[E_Sequence][A_MinOccurs] = Att_Optional | DV_NonNegInt; + + // "simpleContent" + attList[E_SimpleContent][A_ID] = Att_Optional | DV_ID; + + // "simpleType - global" + attList[E_SimpleTypeGlobal][A_Final] = Att_Optional; + attList[E_SimpleTypeGlobal][A_ID] = Att_Optional | DV_ID; + attList[E_SimpleTypeGlobal][A_Name] = Att_Required; + + // "simpleType - local" + attList[E_SimpleTypeLocal][A_Final] = Att_Optional; + attList[E_SimpleTypeLocal][A_ID] = Att_Optional | DV_ID; + + // "totalDigits" + attList[E_TotalDigits][A_ID] = Att_Optional | DV_ID; + attList[E_TotalDigits][A_Value] = Att_Optional | DV_NonNegInt; + attList[E_TotalDigits][A_Fixed] = Att_Optional | DV_Boolean; + + // "union" + attList[E_Union][A_ID] = Att_Optional | DV_ID; + attList[E_Union][A_MemberTypes] = Att_Optional; + + // "unique" + attList[E_Unique][A_ID] = Att_Optional | DV_ID; + attList[E_Unique][A_Name] = Att_Required; + + // "whitespace" + attList[E_WhiteSpace][A_ID] = Att_Optional | DV_ID; + attList[E_WhiteSpace][A_Value] = Att_Optional | DV_WhiteSpace; + attList[E_WhiteSpace][A_Fixed] = Att_Optional | DV_Boolean; + + for (unsigned int j=0; j < E_Count; j++) { + + for (unsigned int index = 0; index < A_Count-1; index++) + { + fprintf(outFl, " %d,", attList[j][index]); + } + + fprintf(outFl, " %d", attList[j][A_Count - 1]); + + if (j + 1 == E_Count) + fprintf(outFl, "}\n};"); + else + fprintf(outFl, "},\n {"); + } + + fclose(outFl); +} + +#endif + + +unsigned short GeneralAttributeCheck::fgElemAttTable[GeneralAttributeCheck::E_Count][GeneralAttributeCheck::A_Count] = +{ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 258, 0, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 130, 0, 10, 0, 0, 2, 0, 1026, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 2, 0, 1026, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 66, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2050, 0, 0, 0}, + { 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2050, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 130, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 34, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0}, + { 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 66, 34, 0, 130, 0, 10, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 130, 0, 10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, + { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 130, 0, 10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 66, 0, 0, 2, 0, 66, 0, 2, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 130, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4098, 0, 0} +}; + +const XMLCh* GeneralAttributeCheck::fAttNames[GeneralAttributeCheck::A_Count] = +{ + SchemaSymbols::fgATT_ABSTRACT, + SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT, + SchemaSymbols::fgATT_BASE, + SchemaSymbols::fgATT_BLOCK, + SchemaSymbols::fgATT_BLOCKDEFAULT, + SchemaSymbols::fgATT_DEFAULT, + SchemaSymbols::fgATT_ELEMENTFORMDEFAULT, + SchemaSymbols::fgATT_FINAL, + SchemaSymbols::fgATT_FINALDEFAULT, + SchemaSymbols::fgATT_FIXED, + SchemaSymbols::fgATT_FORM, + SchemaSymbols::fgATT_ID, + SchemaSymbols::fgATT_ITEMTYPE, + SchemaSymbols::fgATT_MAXOCCURS, + SchemaSymbols::fgATT_MEMBERTYPES, + SchemaSymbols::fgATT_MINOCCURS, + SchemaSymbols::fgATT_MIXED, + SchemaSymbols::fgATT_NAME, + SchemaSymbols::fgATT_NAMESPACE, + SchemaSymbols::fgATT_NILLABLE, + SchemaSymbols::fgATT_PROCESSCONTENTS, + SchemaSymbols::fgATT_PUBLIC, + SchemaSymbols::fgATT_REF, + SchemaSymbols::fgATT_REFER, + SchemaSymbols::fgATT_SCHEMALOCATION, + SchemaSymbols::fgATT_SOURCE, + SchemaSymbols::fgATT_SUBSTITUTIONGROUP, + SchemaSymbols::fgATT_SYSTEM, + SchemaSymbols::fgATT_TARGETNAMESPACE, + SchemaSymbols::fgATT_TYPE, + SchemaSymbols::fgATT_USE, + SchemaSymbols::fgATT_VALUE, + SchemaSymbols::fgATT_VERSION, + SchemaSymbols::fgATT_XPATH, +}; + +XERCES_CPP_NAMESPACE_END + +/** + * End of file GeneralAttributeCheck.cpp + */ + + diff --git a/include/xercesc/validators/schema/GeneralAttributeCheck.hpp b/include/xercesc/validators/schema/GeneralAttributeCheck.hpp new file mode 100644 index 0000000..792678a --- /dev/null +++ b/include/xercesc/validators/schema/GeneralAttributeCheck.hpp @@ -0,0 +1,258 @@ +/* + * 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: GeneralAttributeCheck.hpp 729944 2008-12-29 17:03:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_GENERALATTRIBUTECHECK_HPP) +#define XERCESC_INCLUDE_GUARD_GENERALATTRIBUTECHECK_HPP + +/** + * A general purpose class to check for valid values of attributes, as well + * as check for proper association with corresponding schema elements. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward declaration +// --------------------------------------------------------------------------- +class TraverseSchema; +class DOMElement; +class DOMNode; + +class VALIDATORS_EXPORT GeneralAttributeCheck : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constants + // ----------------------------------------------------------------------- + //Elements + enum + { + E_All, + E_Annotation, + E_Any, + E_AnyAttribute, + E_Appinfo, + E_AttributeGlobal, + E_AttributeLocal, + E_AttributeRef, + E_AttributeGroupGlobal, + E_AttributeGroupRef, + E_Choice, + E_ComplexContent, + E_ComplexTypeGlobal, + E_ComplexTypeLocal, + E_Documentation, + E_ElementGlobal, + E_ElementLocal, + E_ElementRef, + E_Enumeration, + E_Extension, + E_Field, + E_FractionDigits, + E_GroupGlobal, + E_GroupRef, + E_Import, + E_Include, + E_Key, + E_KeyRef, + E_Length, + E_List, + E_MaxExclusive, + E_MaxInclusive, + E_MaxLength, + E_MinExclusive, + E_MinInclusive, + E_MinLength, + E_Notation, + E_Pattern, + E_Redefine, + E_Restriction, + E_Schema, + E_Selector, + E_Sequence, + E_SimpleContent, + E_SimpleTypeGlobal, + E_SimpleTypeLocal, + E_TotalDigits, + E_Union, + E_Unique, + E_WhiteSpace, + + E_Count, + E_Invalid = -1 + }; + + //Attributes + enum + { + A_Abstract, + A_AttributeFormDefault, + A_Base, + A_Block, + A_BlockDefault, + A_Default, + A_ElementFormDefault, + A_Final, + A_FinalDefault, + A_Fixed, + A_Form, + A_ID, + A_ItemType, + A_MaxOccurs, + A_MemberTypes, + A_MinOccurs, + A_Mixed, + A_Name, + A_Namespace, + A_Nillable, + A_ProcessContents, + A_Public, + A_Ref, + A_Refer, + A_SchemaLocation, + A_Source, + A_SubstitutionGroup, + A_System, + A_TargetNamespace, + A_Type, + A_Use, + A_Value, + A_Version, + A_XPath, + + A_Count, + A_Invalid = -1 + }; + + //Validators + enum { + + DV_String = 0, + DV_AnyURI = 4, + DV_NonNegInt = 8, + DV_Boolean = 16, + DV_ID = 32, + DV_Form = 64, + DV_MaxOccurs = 128, + DV_MaxOccurs1 = 256, + DV_MinOccurs1 = 512, + DV_ProcessContents = 1024, + DV_Use = 2048, + DV_WhiteSpace = 4096, + + DV_Mask = (DV_AnyURI | DV_NonNegInt | DV_Boolean | DV_ID | DV_Form | + DV_MaxOccurs | DV_MaxOccurs1 | DV_MinOccurs1 | + DV_ProcessContents | DV_Use | DV_WhiteSpace) + }; + + // generate element-attributes map table +#if defined(NEED_TO_GEN_ELEM_ATT_MAP_TABLE) + static void initCharFlagTable(); +#endif + + // ----------------------------------------------------------------------- + // Constructor/Destructor + // ----------------------------------------------------------------------- + GeneralAttributeCheck(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~GeneralAttributeCheck(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + unsigned short getFacetId(const XMLCh* const facetName, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + void checkAttributes(const DOMElement* const elem, + const unsigned short elemContext, + TraverseSchema* const schema, + const bool isTopLevel = false, + ValueVectorOf* const nonXSAttList = 0); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + GeneralAttributeCheck(const GeneralAttributeCheck&); + GeneralAttributeCheck& operator=(const GeneralAttributeCheck&); + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + void validate(const DOMElement* const elem, const XMLCh* const attName, const XMLCh* const attValue, + const short dvIndex, TraverseSchema* const schema); + + // ----------------------------------------------------------------------- + // Private Constants + // ----------------------------------------------------------------------- + // optional vs. required attribute + enum { + Att_Required = 1, + Att_Optional = 2, + Att_Mask = 3 + }; + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + static ValueHashTableOf* fAttMap; + static ValueHashTableOf* fFacetsMap; + static DatatypeValidator* fNonNegIntDV; + static DatatypeValidator* fBooleanDV; + static DatatypeValidator* fAnyURIDV; + static unsigned short fgElemAttTable[E_Count][A_Count]; + static const XMLCh* fAttNames[A_Count]; + MemoryManager* fMemoryManager; + IDDatatypeValidator fIDValidator; + +private: + static void initialize(); + + friend class XMLInitializer; +}; + + +// --------------------------------------------------------------------------- +// GeneralAttributeCheck: Getter methods +// --------------------------------------------------------------------------- +inline unsigned short +GeneralAttributeCheck::getFacetId(const XMLCh* const facetName, MemoryManager* const manager) { + + return fFacetsMap->get(facetName, manager); +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file GeneralAttributeCheck.hpp + */ + diff --git a/include/xercesc/validators/schema/NamespaceScope.cpp b/include/xercesc/validators/schema/NamespaceScope.cpp new file mode 100644 index 0000000..4ce4007 --- /dev/null +++ b/include/xercesc/validators/schema/NamespaceScope.cpp @@ -0,0 +1,317 @@ +/* + * 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: NamespaceScope.cpp 729944 2008-12-29 17:03:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// NamespaceScope: Constructors and Destructor +// --------------------------------------------------------------------------- +NamespaceScope::NamespaceScope(MemoryManager* const manager /*= XMLPlatformUtils::fgMemoryManager*/) : + fEmptyNamespaceId(0) + , fStackCapacity(8) + , fStackTop(0) + , fPrefixPool(109, manager) + , fStack(0) + , fMemoryManager(manager) +{ + // Do an initial allocation of the stack and zero it out + fStack = (StackElem**) fMemoryManager->allocate + ( + fStackCapacity * sizeof(StackElem*) + );//new StackElem*[fStackCapacity]; + memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); +} + +NamespaceScope::NamespaceScope(const NamespaceScope* const initialize, MemoryManager* const manager /*= XMLPlatformUtils::fgMemoryManager*/) : + fEmptyNamespaceId(0) + , fStackCapacity(8) + , fStackTop(0) + , fPrefixPool(109, manager) + , fStack(0) + , fMemoryManager(manager) +{ + // Do an initial allocation of the stack and zero it out + fStack = (StackElem**) fMemoryManager->allocate + ( + fStackCapacity * sizeof(StackElem*) + );//new StackElem*[fStackCapacity]; + memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); + + if(initialize) + { + reset(initialize->fEmptyNamespaceId); + + // copy the existing bindings + for (unsigned int index = initialize->fStackTop; index > 0; index--) + { + // Get a convenience pointer to the current element + StackElem* curRow = initialize->fStack[index-1]; + + // If no prefixes mapped at this level, then go the next one + if (!curRow->fMapCount) + continue; + + for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) + { + // go from the id to the prefix + const XMLCh* prefix = initialize->fPrefixPool.getValueForId(curRow->fMap[mapIndex].fPrefId); + + // if the prefix is not already known, add it + if(getNamespaceForPrefix(prefix)==fEmptyNamespaceId) + addPrefix(prefix, curRow->fMap[mapIndex].fURIId); + } + } + } +} + +NamespaceScope::~NamespaceScope() +{ + // + // Start working from the bottom of the stack and clear it out as we + // go up. Once we hit an uninitialized one, we can break out. + // + for (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++) + { + // If this entry has been set, then lets clean it up + if (!fStack[stackInd]) + break; + + // Delete the row for this entry, then delete the row structure + fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap; + delete fStack[stackInd]; + } + + // Delete the stack array itself now + fMemoryManager->deallocate(fStack);//delete [] fStack; +} + + +// --------------------------------------------------------------------------- +// NamespaceScope: Stack access +// --------------------------------------------------------------------------- +unsigned int NamespaceScope::increaseDepth() +{ + // See if we need to expand the stack + if (fStackTop == fStackCapacity) + expandStack(); + + // If this element has not been initialized yet, then initialize it + if (!fStack[fStackTop]) + { + fStack[fStackTop] = new (fMemoryManager) StackElem; + fStack[fStackTop]->fMapCapacity = 0; + fStack[fStackTop]->fMap = 0; + } + + // Set up the new top row + fStack[fStackTop]->fMapCount = 0; + + // Bump the top of stack + fStackTop++; + + return fStackTop-1; +} + +unsigned int NamespaceScope::decreaseDepth() +{ + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); + + fStackTop--; + + return fStackTop; +} + + +// --------------------------------------------------------------------------- +// NamespaceScope: Prefix map methods +// --------------------------------------------------------------------------- +void NamespaceScope::addPrefix(const XMLCh* const prefixToAdd, + const unsigned int uriId) { + + if (!fStackTop) + ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); + + // Get a convenience pointer to the stack top row + StackElem* curRow = fStack[fStackTop - 1]; + + // Map the prefix to its unique id + const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); + + // Search the map at this level for the passed prefix + for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) + { + if (curRow->fMap[mapIndex].fPrefId == prefId) + { + curRow->fMap[mapIndex].fURIId = uriId; + return; + } + } + + // + // Add a new element to the prefix map for this element. If its full, + // then expand it out. + // + if (curRow->fMapCount == curRow->fMapCapacity) + expandMap(curRow); + + // + // And now add a new element for this prefix. + // + curRow->fMap[curRow->fMapCount].fPrefId = prefId; + curRow->fMap[curRow->fMapCount].fURIId = uriId; + + // Bump the map count now + curRow->fMapCount++; +} + +unsigned int +NamespaceScope::getNamespaceForPrefix(const XMLCh* const prefixToMap) const { + + // + // Map the prefix to its unique id, from the prefix string pool. If its + // not a valid prefix, then its a failure. + // + unsigned int prefixId = fPrefixPool.getId(prefixToMap); + + if (!prefixId){ + return fEmptyNamespaceId; + } + + // + // Start at the stack top and work backwards until we come to some + // element that mapped this prefix. + // + for (unsigned int index = fStackTop; index > 0; index--) + { + // Get a convenience pointer to the current element + StackElem* curRow = fStack[index-1]; + + // If no prefixes mapped at this level, then go the next one + if (!curRow->fMapCount) + continue; + + // Search the map at this level for the passed prefix + for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) + { + if (curRow->fMap[mapIndex].fPrefId == prefixId) + return curRow->fMap[mapIndex].fURIId; + } + } + + return fEmptyNamespaceId; +} + + +// --------------------------------------------------------------------------- +// NamespaceScope: Miscellaneous methods +// --------------------------------------------------------------------------- +void NamespaceScope::reset(const unsigned int emptyId) +{ + // Flush the prefix pool and put back in the standard prefixes + fPrefixPool.flushAll(); + + // Reset the stack top to clear the stack + fStackTop = 0; + + // And store the new special URI ids + fEmptyNamespaceId = emptyId; + + // add the first storage + increaseDepth(); +} + + +// --------------------------------------------------------------------------- +// Namespace: Private helpers +// --------------------------------------------------------------------------- +void NamespaceScope::expandMap(StackElem* const toExpand) +{ + // For convenience get the old map size + const unsigned int oldCap = toExpand->fMapCapacity; + + // + // Expand the capacity by 25%, or initialize it to 16 if its currently + // empty. Then allocate a new temp buffer. + // + const unsigned int newCapacity = oldCap ? + (unsigned int)(oldCap * 1.25) : 16; + PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate + ( + newCapacity * sizeof(PrefMapElem) + );//new PrefMapElem[newCapacity]; + + // + // Copy over the old stuff. We DON'T have to zero out the new stuff + // since this is a by value map and the current map index controls what + // is relevant. + // + memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem)); + + // Delete the old map and store the new stuff + fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap; + toExpand->fMap = newMap; + toExpand->fMapCapacity = newCapacity; +} + +void NamespaceScope::expandStack() +{ + // Expand the capacity by 25% and allocate a new buffer + const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25); + StackElem** newStack = (StackElem**) fMemoryManager->allocate + ( + newCapacity * sizeof(StackElem*) + );//new StackElem*[newCapacity]; + + // Copy over the old stuff + memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); + + // + // And zero out the new stuff. Though we use a stack top, we reuse old + // stack contents so we need to know if elements have been initially + // allocated or not as we push new stuff onto the stack. + // + memset + ( + &newStack[fStackCapacity] + , 0 + , (newCapacity - fStackCapacity) * sizeof(StackElem*) + ); + + // Delete the old array and update our members + fMemoryManager->deallocate(fStack);//delete [] fStack; + fStack = newStack; + fStackCapacity = newCapacity; +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file NamespaceScope.cpp + */ + diff --git a/include/xercesc/validators/schema/NamespaceScope.hpp b/include/xercesc/validators/schema/NamespaceScope.hpp new file mode 100644 index 0000000..2a83bcd --- /dev/null +++ b/include/xercesc/validators/schema/NamespaceScope.hpp @@ -0,0 +1,169 @@ +/* + * 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: NamespaceScope.hpp 729944 2008-12-29 17:03:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_NAMESPACESCOPE_HPP) +#define XERCESC_INCLUDE_GUARD_NAMESPACESCOPE_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// Define a pure interface to allow XercesXPath to work on both NamespaceScope and DOMXPathNSResolver +class VALIDATORS_EXPORT XercesNamespaceResolver +{ +public: + virtual unsigned int getNamespaceForPrefix(const XMLCh* const prefix) const = 0; +}; + +// +// NamespaceScope provides a data structure for mapping namespace prefixes +// to their URI's. The mapping accurately reflects the scoping of namespaces +// at a particular instant in time. +// + +class VALIDATORS_EXPORT NamespaceScope : public XMemory, + public XercesNamespaceResolver +{ +public : + // ----------------------------------------------------------------------- + // Class specific data types + // + // These really should be private, but some of the compilers we have to + // support are too dumb to deal with that. + // + // PrefMapElem + // fURIId is the id of the URI from the validator's URI map. The + // fPrefId is the id of the prefix from our own prefix pool. The + // namespace stack consists of these elements. + // + // StackElem + // The fMapCapacity is how large fMap has grown so far. fMapCount + // is how many of them are valid right now. + // ----------------------------------------------------------------------- + struct PrefMapElem : public XMemory + { + unsigned int fPrefId; + unsigned int fURIId; + }; + + struct StackElem : public XMemory + { + PrefMapElem* fMap; + unsigned int fMapCapacity; + unsigned int fMapCount; + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + NamespaceScope(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + NamespaceScope(const NamespaceScope* const initialize, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~NamespaceScope(); + + + // ----------------------------------------------------------------------- + // Stack access + // ----------------------------------------------------------------------- + unsigned int increaseDepth(); + unsigned int decreaseDepth(); + + // ----------------------------------------------------------------------- + // Prefix map methods + // ----------------------------------------------------------------------- + void addPrefix(const XMLCh* const prefixToAdd, + const unsigned int uriId); + + virtual unsigned int getNamespaceForPrefix(const XMLCh* const prefixToMap) const; + + + // ----------------------------------------------------------------------- + // Miscellaneous methods + // ----------------------------------------------------------------------- + bool isEmpty() const; + void reset(const unsigned int emptyId); + unsigned int getEmptyNamespaceId() const; + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + NamespaceScope(const NamespaceScope&); + NamespaceScope& operator=(const NamespaceScope&); + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void expandMap(StackElem* const toExpand); + void expandStack(); + + + // ----------------------------------------------------------------------- + // Data members + // + // fEmptyNamespaceId + // This is the special URI id for the "" namespace, which is magic + // because of the xmlns="" operation. + // + // fPrefixPool + // This is the prefix pool where prefixes are hashed and given unique + // ids. These ids are used to track prefixes in the element stack. + // + // fStack + // fStackCapacity + // fStackTop + // This the stack array. Its an array of pointers to StackElem + // structures. The capacity is the current high water mark of the + // stack. The top is the current top of stack (i.e. the part of it + // being used.) + // ----------------------------------------------------------------------- + unsigned int fEmptyNamespaceId; + unsigned int fStackCapacity; + unsigned int fStackTop; + XMLStringPool fPrefixPool; + StackElem** fStack; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// NamespaceScope: Miscellaneous methods +// --------------------------------------------------------------------------- +inline bool NamespaceScope::isEmpty() const +{ + return (fStackTop == 0); +} + +inline unsigned int NamespaceScope::getEmptyNamespaceId() const +{ + return fEmptyNamespaceId; +} + + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file NameSpaceScope.hpp + */ + diff --git a/include/xercesc/validators/schema/PSVIDefs.hpp b/include/xercesc/validators/schema/PSVIDefs.hpp new file mode 100644 index 0000000..6e1c461 --- /dev/null +++ b/include/xercesc/validators/schema/PSVIDefs.hpp @@ -0,0 +1,40 @@ +/* + * 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: PSVIDefs.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_PSVIDEFS_HPP) +#define XERCESC_INCLUDE_GUARD_PSVIDEFS_HPP + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT PSVIDefs +{ +public: + enum PSVIScope + { + SCP_ABSENT // declared in group/attribute group + , SCP_GLOBAL // global declaration or ref + , SCP_LOCAL // local declaration + }; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/SchemaAttDef.cpp b/include/xercesc/validators/schema/SchemaAttDef.cpp new file mode 100644 index 0000000..c79da4c --- /dev/null +++ b/include/xercesc/validators/schema/SchemaAttDef.cpp @@ -0,0 +1,178 @@ +/* + * 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: SchemaAttDef.cpp 679359 2008-07-24 11:15:19Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaAttDef: Implementation of the XMLAttDef interface +// --------------------------------------------------------------------------- +const XMLCh* SchemaAttDef::getFullName() const +{ + return fAttName->getRawName(); +} + +// --------------------------------------------------------------------------- +// SchemaAttDef: Constructors and Destructor +// --------------------------------------------------------------------------- +SchemaAttDef::SchemaAttDef(MemoryManager* const manager) : + XMLAttDef(XMLAttDef::CData, XMLAttDef::Implied, manager) + , fElemId(XMLElementDecl::fgInvalidElemId) + , fPSVIScope(PSVIDefs::SCP_ABSENT) + , fAttName(0) + , fDatatypeValidator(0) + , fNamespaceList(0) + , fBaseAttDecl(0) +{ +} + +SchemaAttDef::SchemaAttDef( const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId + , const XMLAttDef::AttTypes type + , const XMLAttDef::DefAttTypes defType + , MemoryManager* const manager) : + XMLAttDef(type, defType, manager) + , fElemId(XMLElementDecl::fgInvalidElemId) + , fPSVIScope(PSVIDefs::SCP_ABSENT) + , fDatatypeValidator(0) + , fNamespaceList(0) + , fBaseAttDecl(0) +{ + fAttName = new (manager) QName(prefix, localPart, uriId, manager); +} + +SchemaAttDef::SchemaAttDef( const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId + , const XMLCh* const attValue + , const XMLAttDef::AttTypes type + , const XMLAttDef::DefAttTypes defType + , const XMLCh* const enumValues + , MemoryManager* const manager) : + + XMLAttDef(attValue, type, defType, enumValues, manager) + , fElemId(XMLElementDecl::fgInvalidElemId) + , fPSVIScope(PSVIDefs::SCP_ABSENT) + , fDatatypeValidator(0) + , fNamespaceList(0) + , fBaseAttDecl(0) +{ + fAttName = new (manager) QName(prefix, localPart, uriId, manager); +} + +SchemaAttDef::SchemaAttDef(const SchemaAttDef* other) : + + XMLAttDef(other->getValue(), other->getType(), + other->getDefaultType(), other->getEnumeration(), + other->getMemoryManager()) + , fElemId(XMLElementDecl::fgInvalidElemId) + , fPSVIScope(other->fPSVIScope) + , fAttName(0) + , fDatatypeValidator(other->fDatatypeValidator) + , fNamespaceList(0) + , fBaseAttDecl(other->fBaseAttDecl) +{ + QName* otherName = other->getAttName(); + fAttName = new (getMemoryManager()) QName(otherName->getPrefix(), + otherName->getLocalPart(), otherName->getURI(), + getMemoryManager()); + + if (other->fNamespaceList && other->fNamespaceList->size()) { + fNamespaceList = new (getMemoryManager()) ValueVectorOf(*(other->fNamespaceList)); + } +} + +SchemaAttDef::~SchemaAttDef() +{ + delete fAttName; + delete fNamespaceList; +} + + +// --------------------------------------------------------------------------- +// SchemaAttDef: Setter methods +// --------------------------------------------------------------------------- +void SchemaAttDef::setAttName(const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId ) +{ + fAttName->setName(prefix, localPart, uriId); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(SchemaAttDef) + +void SchemaAttDef::serialize(XSerializeEngine& serEng) +{ + + XMLAttDef::serialize(serEng); + + if (serEng.isStoring()) + { + serEng.writeSize (fElemId); + serEng<<(int)fPSVIScope; + + serEng< + ***/ + XTemplateSerializer::storeObject(fNamespaceList, serEng); + + serEng<>i; + fPSVIScope = (PSVIDefs::PSVIScope)i; + + serEng>>fAttName; + + fDatatypeValidator = DatatypeValidator::loadDV(serEng); + + /*** + * Deserialize ValueVectorOf + ***/ + XTemplateSerializer::loadObject(&fNamespaceList, 8, false, serEng); + + serEng>>fBaseAttDecl; + } +} + + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/SchemaAttDef.hpp b/include/xercesc/validators/schema/SchemaAttDef.hpp new file mode 100644 index 0000000..40b8079 --- /dev/null +++ b/include/xercesc/validators/schema/SchemaAttDef.hpp @@ -0,0 +1,252 @@ +/* + * 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: SchemaAttDef.hpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMAATTDEF_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMAATTDEF_HPP + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DatatypeValidator; +class QName; +class ComplexTypeInfo; +// +// This class is a derivative of the core XMLAttDef class. This class adds +// any Schema specific data members and provides Schema specific implementations +// of any underlying attribute def virtual methods. +// +class VALIDATORS_EXPORT SchemaAttDef : public XMLAttDef +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructors + // ----------------------------------------------------------------------- + SchemaAttDef(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + SchemaAttDef + ( + const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId + , const XMLAttDef::AttTypes type = CData + , const XMLAttDef::DefAttTypes defType = Implied + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + SchemaAttDef + ( + const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId + , const XMLCh* const attValue + , const XMLAttDef::AttTypes type + , const XMLAttDef::DefAttTypes defType + , const XMLCh* const enumValues = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + SchemaAttDef + ( + const SchemaAttDef* other + ); + virtual ~SchemaAttDef(); + + // ----------------------------------------------------------------------- + // Implementation of the XMLAttDef interface + // ----------------------------------------------------------------------- + virtual const XMLCh* getFullName() const; + virtual void reset(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLSize_t getElemId() const; + QName* getAttName() const; + DatatypeValidator* getDatatypeValidator() const; + ValueVectorOf* getNamespaceList() const; + const SchemaAttDef* getBaseAttDecl() const; + SchemaAttDef* getBaseAttDecl(); + PSVIDefs::PSVIScope getPSVIScope() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setElemId(const XMLSize_t newId); + void setAttName + ( + const XMLCh* const prefix + ,const XMLCh* const localPart + ,const int uriId = -1 + ); + void setDatatypeValidator(DatatypeValidator* newDatatypeValidator); + void setBaseAttDecl(SchemaAttDef* const attDef); + void setPSVIScope(const PSVIDefs::PSVIScope toSet); + + void setNamespaceList(const ValueVectorOf* const toSet); + void resetNamespaceList(); + void setEnclosingCT(ComplexTypeInfo* complexTypeInfo); + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(SchemaAttDef) + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaAttDef(const SchemaAttDef&); + SchemaAttDef& operator=(const SchemaAttDef&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fElemId + // This is the id of the element (the id is into the element decl + // pool) of the element this attribute def said it belonged to. + // This is used later to link back to the element, mostly for + // validation purposes. + // + // fAttName + // This is the name of the attribute. + // + // fDatatypeValidator + // The DatatypeValidator used to validate this attribute type. + // + // fNamespaceList + // The list of namespace values for a wildcard attribute + // + // fBaseAttDecl + // The base attribute declaration that this attribute is based on + // NOTE: we do not have a notion of attribute use, so in the case + // of ref'd attributes and inherited attributes, we make a copy + // of the actual attribute declaration. The fBaseAttDecl stores that + // declaration, and will be helpful when we build the XSModel (i.e + // easy access the XSAnnotation object). + // ----------------------------------------------------------------------- + XMLSize_t fElemId; + + PSVIDefs::PSVIScope fPSVIScope; + + QName* fAttName; + DatatypeValidator* fDatatypeValidator; + ValueVectorOf* fNamespaceList; + SchemaAttDef* fBaseAttDecl; +}; + + +// --------------------------------------------------------------------------- +// SchemaAttDef: Getter methods +// --------------------------------------------------------------------------- +inline XMLSize_t SchemaAttDef::getElemId() const +{ + return fElemId; +} + + +inline QName* SchemaAttDef::getAttName() const +{ + return fAttName; +} + +inline DatatypeValidator* SchemaAttDef::getDatatypeValidator() const +{ + return fDatatypeValidator; +} + +inline ValueVectorOf* +SchemaAttDef::getNamespaceList() const { + return fNamespaceList; +} + +inline SchemaAttDef* SchemaAttDef::getBaseAttDecl() +{ + return fBaseAttDecl; +} + +inline const SchemaAttDef* SchemaAttDef::getBaseAttDecl() const +{ + return fBaseAttDecl; +} + +inline PSVIDefs::PSVIScope SchemaAttDef::getPSVIScope() const +{ + return fPSVIScope; +} + +// --------------------------------------------------------------------------- +// SchemaAttDef: Setter methods +// --------------------------------------------------------------------------- +inline void SchemaAttDef::setElemId(const XMLSize_t newId) +{ + fElemId = newId; +} + +inline void SchemaAttDef::setDatatypeValidator(DatatypeValidator* newDatatypeValidator) +{ + fDatatypeValidator = newDatatypeValidator; +} + +inline void SchemaAttDef::resetNamespaceList() { + + if (fNamespaceList && fNamespaceList->size()) { + fNamespaceList->removeAllElements(); + } +} + +inline void SchemaAttDef::setNamespaceList(const ValueVectorOf* const toSet) { + + if (toSet && toSet->size()) { + + if (fNamespaceList) { + *fNamespaceList = *toSet; + } + else { + fNamespaceList = new (getMemoryManager()) ValueVectorOf(*toSet); + } + } + else { + resetNamespaceList(); + } +} + +inline void SchemaAttDef::reset() { +} + +inline void SchemaAttDef::setEnclosingCT(ComplexTypeInfo*) +{ +} + +inline void SchemaAttDef::setBaseAttDecl(SchemaAttDef* const attDef) +{ + fBaseAttDecl = attDef; +} + +inline void SchemaAttDef::setPSVIScope(const PSVIDefs::PSVIScope toSet) +{ + fPSVIScope = toSet; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/SchemaAttDefList.cpp b/include/xercesc/validators/schema/SchemaAttDefList.cpp new file mode 100644 index 0000000..6e25263 --- /dev/null +++ b/include/xercesc/validators/schema/SchemaAttDefList.cpp @@ -0,0 +1,201 @@ +/* + * 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: SchemaAttDefList.cpp 679359 2008-07-24 11:15:19Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaAttDefList: Constructors and Destructor +// --------------------------------------------------------------------------- +SchemaAttDefList::SchemaAttDefList(RefHash2KeysTableOf* const listToUse, MemoryManager* const manager) +: XMLAttDefList(manager) +,fEnum(0) +,fList(listToUse) +,fArray(0) +,fSize(0) +,fCount(0) +{ + fEnum = new (getMemoryManager()) RefHash2KeysTableOfEnumerator(listToUse, false, getMemoryManager()); + fArray = (SchemaAttDef **)((getMemoryManager())->allocate( sizeof(SchemaAttDef*) << 1)); + fSize = 2; +} + +SchemaAttDefList::~SchemaAttDefList() +{ + delete fEnum; + (getMemoryManager())->deallocate(fArray); +} + + +// --------------------------------------------------------------------------- +// SchemaAttDefList: Implementation of the virtual interface +// --------------------------------------------------------------------------- + +bool SchemaAttDefList::isEmpty() const +{ + return fList->isEmpty(); +} + + +XMLAttDef* SchemaAttDefList::findAttDef(const unsigned int uriID + , const XMLCh* const attName) +{ + const int colonInd = XMLString::indexOf(attName, chColon); + + // An index of 0 is really an error, but the QName class doesn't check for + // that case either... + const XMLCh* const localPart = colonInd >= 0 ? attName + colonInd + 1 : attName; + + return fList->get((void*)localPart, uriID); +} + + +const XMLAttDef* +SchemaAttDefList::findAttDef( const unsigned int uriID + , const XMLCh* const attName) const +{ + const int colonInd = XMLString::indexOf(attName, chColon); + + // An index of 0 is really an error, but the QName class doesn't check for + // that case either... + const XMLCh* const localPart = colonInd >= 0 ? attName + colonInd + 1 : attName; + + return fList->get((void*)localPart, uriID); +} + + +XMLAttDef* SchemaAttDefList::findAttDef( const XMLCh* const + , const XMLCh* const) +{ + //need numeric URI id to locate the attribute, that's how it was stored + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Pool_InvalidId, getMemoryManager()); + return 0; +} + + +const XMLAttDef* +SchemaAttDefList::findAttDef( const XMLCh* const + , const XMLCh* const) const +{ + //need numeric URI id to locate the attribute, that's how it was stored + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Pool_InvalidId, getMemoryManager()); + return 0; +} + +/** + * return total number of attributes in this list + */ +XMLSize_t SchemaAttDefList::getAttDefCount() const +{ + return fCount; +} + +/** + * return attribute at the index-th position in the list. + */ +XMLAttDef &SchemaAttDefList::getAttDef(XMLSize_t index) +{ + if(index >= fCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::AttrList_BadIndex, getMemoryManager()); + return *(fArray[index]); +} + +/** + * return attribute at the index-th position in the list. + */ +const XMLAttDef &SchemaAttDefList::getAttDef(XMLSize_t index) const +{ + if(index >= fCount) + ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::AttrList_BadIndex, getMemoryManager()); + return *(fArray[index]); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(SchemaAttDefList) + +void SchemaAttDefList::serialize(XSerializeEngine& serEng) +{ + + XMLAttDefList::serialize(serEng); + + if (serEng.isStoring()) + { + /*** + * + * Serialize RefHash2KeysTableOf + * + ***/ + XTemplateSerializer::storeObject(fList, serEng); + serEng.writeSize (fCount); + + // do not serialize fEnum + } + else + { + /*** + * + * Deserialize RefHash2KeysTableOf + * + ***/ + XTemplateSerializer::loadObject(&fList, 29, true, serEng); + + // assume empty so we can size fArray just right + serEng.readSize (fSize); + if (!fEnum && fList) + { + fEnum = new (getMemoryManager()) RefHash2KeysTableOfEnumerator(fList, false, getMemoryManager()); + } + if(fSize) + { + (getMemoryManager())->deallocate(fArray); + fArray = (SchemaAttDef **)((getMemoryManager())->allocate( sizeof(SchemaAttDef*) * fSize)); + fCount = 0; + while(fEnum->hasMoreElements()) + { + fArray[fCount++] = &fEnum->nextElement(); + } + } + } + +} + +SchemaAttDefList::SchemaAttDefList(MemoryManager* const manager) +: XMLAttDefList(manager) +,fEnum(0) +,fList(0) +,fArray(0) +,fSize(0) +,fCount(0) +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/SchemaAttDefList.hpp b/include/xercesc/validators/schema/SchemaAttDefList.hpp new file mode 100644 index 0000000..3093855 --- /dev/null +++ b/include/xercesc/validators/schema/SchemaAttDefList.hpp @@ -0,0 +1,181 @@ +/* + * 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: SchemaAttDefList.hpp 673679 2008-07-03 13:50:10Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMAATTDEFLIST_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMAATTDEFLIST_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This is a derivative of the framework abstract class which defines the +// interface to a list of attribute defs that belong to a particular +// element. The scanner needs to be able to get a list of the attributes +// that an element supports, for use during the validation process and for +// fixed/default attribute processing. +// +// For us, we just wrap the RefHash2KeysTableOf collection that the SchemaElementDecl +// class uses to store the attributes that belong to it. +// +// This class does not adopt the hash table, it just references it. The +// hash table is owned by the element decl it is a member of. +// +class VALIDATORS_EXPORT SchemaAttDefList : public XMLAttDefList +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + SchemaAttDefList + ( + RefHash2KeysTableOf* const listToUse, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + ~SchemaAttDefList(); + + + // ----------------------------------------------------------------------- + // Implementation of the virtual interface + // ----------------------------------------------------------------------- + + virtual bool isEmpty() const; + virtual XMLAttDef* findAttDef + ( + const unsigned int uriID + , const XMLCh* const attName + ); + virtual const XMLAttDef* findAttDef + ( + const unsigned int uriID + , const XMLCh* const attName + ) const; + virtual XMLAttDef* findAttDef + ( + const XMLCh* const attURI + , const XMLCh* const attName + ); + virtual const XMLAttDef* findAttDef + ( + const XMLCh* const attURI + , const XMLCh* const attName + ) const; + + XMLAttDef* findAttDefLocalPart + ( + const unsigned int uriID + , const XMLCh* const attLocalPart + ); + + const XMLAttDef* findAttDefLocalPart + ( + const unsigned int uriID + , const XMLCh* const attLocalPart + ) const; + + /** + * return total number of attributes in this list + */ + virtual XMLSize_t getAttDefCount() const ; + + /** + * return attribute at the index-th position in the list. + */ + virtual XMLAttDef &getAttDef(XMLSize_t index) ; + + /** + * return attribute at the index-th position in the list. + */ + virtual const XMLAttDef &getAttDef(XMLSize_t index) const ; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(SchemaAttDefList) + + SchemaAttDefList(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaAttDefList(const SchemaAttDefList&); + SchemaAttDefList& operator=(const SchemaAttDefList&); + + void addAttDef(SchemaAttDef *toAdd); + + // ----------------------------------------------------------------------- + // Private data members + // + // fEnum + // This is an enumerator for the list that we use to do the enumerator + // type methods of this class. + // + // fList + // The list of SchemaAttDef objects that represent the attributes that + // a particular element supports. + // fArray + // vector of pointers to the DTDAttDef objects contained in this list + // fSize + // size of fArray + // fCount + // number of DTDAttDef objects currently stored in this list + // ----------------------------------------------------------------------- + RefHash2KeysTableOfEnumerator* fEnum; + RefHash2KeysTableOf* fList; + SchemaAttDef** fArray; + XMLSize_t fSize; + XMLSize_t fCount; + + friend class ComplexTypeInfo; +}; + +inline void SchemaAttDefList::addAttDef(SchemaAttDef *toAdd) +{ + if(fCount == fSize) + { + // need to grow fArray + fSize <<= 1; + SchemaAttDef** newArray = (SchemaAttDef **)((getMemoryManager())->allocate( sizeof(SchemaAttDef*) * fSize )); + memcpy(newArray, fArray, fCount * sizeof(SchemaAttDef *)); + (getMemoryManager())->deallocate(fArray); + fArray = newArray; + } + fArray[fCount++] = toAdd; +} + +inline XMLAttDef* SchemaAttDefList::findAttDefLocalPart(const unsigned int uriID + , const XMLCh* const attLocalPart) +{ + return fList->get((void*)attLocalPart, uriID); +} + +inline const XMLAttDef* SchemaAttDefList::findAttDefLocalPart(const unsigned int uriID + , const XMLCh* const attLocalPart) const +{ + return fList->get((void*)attLocalPart, uriID); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/SchemaElementDecl.cpp b/include/xercesc/validators/schema/SchemaElementDecl.cpp new file mode 100644 index 0000000..ef4d1fc --- /dev/null +++ b/include/xercesc/validators/schema/SchemaElementDecl.cpp @@ -0,0 +1,277 @@ +/* + * 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: SchemaElementDecl.cpp 609971 2008-01-08 13:30:47Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaElementDecl: Constructors and Destructor +// --------------------------------------------------------------------------- +SchemaElementDecl::SchemaElementDecl(MemoryManager* const manager) : + XMLElementDecl(manager) + , fModelType(Any) + , fPSVIScope(PSVIDefs::SCP_ABSENT) + , fEnclosingScope(Grammar::TOP_LEVEL_SCOPE) + , fFinalSet(0) + , fBlockSet(0) + , fMiscFlags(0) + , fDefaultValue(0) + , fComplexTypeInfo(0) + , fAttDefs(0) + , fIdentityConstraints(0) + , fAttWildCard(0) + , fSubstitutionGroupElem(0) + , fDatatypeValidator(0) +{ +} + +SchemaElementDecl::SchemaElementDecl(const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId + , const SchemaElementDecl::ModelTypes type + , const unsigned int enclosingScope + , MemoryManager* const manager) : + XMLElementDecl(manager) + , fModelType(type) + , fPSVIScope(PSVIDefs::SCP_ABSENT) + , fEnclosingScope(enclosingScope) + , fFinalSet(0) + , fBlockSet(0) + , fMiscFlags(0) + , fDefaultValue(0) + , fComplexTypeInfo(0) + , fAttDefs(0) + , fIdentityConstraints(0) + , fAttWildCard(0) + , fSubstitutionGroupElem(0) + , fDatatypeValidator(0) +{ + setElementName(prefix, localPart, uriId); +} + +SchemaElementDecl::SchemaElementDecl(const QName* const elementName + , const SchemaElementDecl::ModelTypes type + , const unsigned int enclosingScope + , MemoryManager* const manager) : + XMLElementDecl(manager) + , fModelType(type) + , fPSVIScope(PSVIDefs::SCP_ABSENT) + , fEnclosingScope(enclosingScope) + , fFinalSet(0) + , fBlockSet(0) + , fMiscFlags(0) + , fDefaultValue(0) + , fComplexTypeInfo(0) + , fAttDefs(0) + , fIdentityConstraints(0) + , fAttWildCard(0) + , fSubstitutionGroupElem(0) + , fDatatypeValidator(0) +{ + setElementName(elementName); +} + +SchemaElementDecl::~SchemaElementDecl() +{ + getMemoryManager()->deallocate(fDefaultValue);//delete [] fDefaultValue; + delete fAttDefs; + delete fIdentityConstraints; + delete fAttWildCard; +} + + +// --------------------------------------------------------------------------- +// SchemaElementDecl: XMLElementDecl virtual interface implementation +// --------------------------------------------------------------------------- +XMLAttDefList& SchemaElementDecl::getAttDefList() const +{ + if (!fComplexTypeInfo) + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::DV_InvalidOperation, getMemoryManager()); + } + + return fComplexTypeInfo->getAttDefList(); +} + + +XMLElementDecl::CharDataOpts SchemaElementDecl::getCharDataOpts() const +{ + SchemaElementDecl::ModelTypes modelType = fModelType; + + if (fComplexTypeInfo) { + modelType = (SchemaElementDecl::ModelTypes) fComplexTypeInfo->getContentType(); + } + + XMLElementDecl::CharDataOpts retVal; + switch(modelType) + { + case Children : + case ElementOnlyEmpty : + retVal = XMLElementDecl::SpacesOk; + break; + + case Empty : + retVal = XMLElementDecl::NoCharData; + break; + + default : + retVal = XMLElementDecl::AllCharData; + break; + } + return retVal; +} + + +bool SchemaElementDecl::hasAttDefs() const +{ + if (fComplexTypeInfo) { + return fComplexTypeInfo->hasAttDefs(); + } + + // If the collection hasn't been faulted in, then no att defs + return false; + +} + +const XMLCh* +SchemaElementDecl::getFormattedContentModel() const +{ + if (fComplexTypeInfo) { + return fComplexTypeInfo->getFormattedContentModel(); + } + return 0; +} + +// --------------------------------------------------------------------------- +// SchemaElementDecl: Getter methods +// --------------------------------------------------------------------------- +const SchemaAttDef* SchemaElementDecl::getAttDef(const XMLCh* const baseName, const int uriId) const +{ + if (fComplexTypeInfo) { + return fComplexTypeInfo->getAttDef(baseName, uriId); + } + + // If no complex type, then return a null + return 0; + +} + +SchemaAttDef* SchemaElementDecl::getAttDef(const XMLCh* const baseName, const int uriId) +{ + if (fComplexTypeInfo) { + return fComplexTypeInfo->getAttDef(baseName, uriId); + } + + // If no complex type, then return a null + return 0; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(SchemaElementDecl) + +void SchemaElementDecl::serialize(XSerializeEngine& serEng) +{ + + XMLElementDecl::serialize(serEng); + + if (serEng.isStoring()) + { + serEng<<(int)fModelType; + serEng<<(int)fPSVIScope; + + serEng<* fAttDefs; + ***/ + + XTemplateSerializer::storeObject(fAttDefs, serEng); + + /*** + * Serialize RefVectorOf* fIdentityConstraints; + ***/ + XTemplateSerializer::storeObject(fIdentityConstraints, serEng); + + serEng<>i; + fModelType = (ModelTypes)i; + serEng>>i; + fPSVIScope = (PSVIDefs::PSVIScope)i; + + serEng>>fEnclosingScope; + serEng>>fFinalSet; + serEng>>fBlockSet; + serEng>>fMiscFlags; + + serEng.readString(fDefaultValue); + + serEng>>fComplexTypeInfo; + + /*** + * DeSerialize RefHash2KeysTableOf* fAttDefs; + ***/ + XTemplateSerializer::loadObject(&fAttDefs, 29, true, serEng); + + /*** + * DeSerialize RefVectorOf* fIdentityConstraints; + ***/ + XTemplateSerializer::loadObject(&fIdentityConstraints, 16, true, serEng); + + serEng>>fAttWildCard; + serEng>>fSubstitutionGroupElem; + fDatatypeValidator = DatatypeValidator::loadDV(serEng); + } +} + +XMLElementDecl::objectType SchemaElementDecl::getObjectType() const +{ + return Schema; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/SchemaElementDecl.hpp b/include/xercesc/validators/schema/SchemaElementDecl.hpp new file mode 100644 index 0000000..2b79eba --- /dev/null +++ b/include/xercesc/validators/schema/SchemaElementDecl.hpp @@ -0,0 +1,438 @@ +/* + * 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: SchemaElementDecl.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMAELEMENTDECL_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMAELEMENTDECL_HPP + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class ContentSpecNode; +class SchemaAttDefList; + +// +// This class is a derivative of the basic element decl. This one implements +// the virtuals so that they work for a Schema. +// +class VALIDATORS_EXPORT SchemaElementDecl : public XMLElementDecl +{ +public : + + // ----------------------------------------------------------------------- + // Class specific types + // + // ModelTypes + // Indicates the type of content model that an element has. This + // indicates how the content model is represented and validated. + // ----------------------------------------------------------------------- + enum ModelTypes + { + Empty + , Any + , Mixed_Simple + , Mixed_Complex + , Children + , Simple + , ElementOnlyEmpty + , ModelTypes_Count + }; + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + SchemaElementDecl(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + SchemaElementDecl + ( + const XMLCh* const prefix + , const XMLCh* const localPart + , const int uriId + , const ModelTypes modelType = Any + , const unsigned int enclosingScope = Grammar::TOP_LEVEL_SCOPE + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + SchemaElementDecl + ( + const QName* const elementName + , const ModelTypes modelType = Any + , const unsigned int enclosingScope = Grammar::TOP_LEVEL_SCOPE + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + ~SchemaElementDecl(); + + + // ----------------------------------------------------------------------- + // The virtual element decl interface + // ----------------------------------------------------------------------- + virtual XMLAttDefList& getAttDefList() const; + virtual CharDataOpts getCharDataOpts() const; + virtual bool hasAttDefs() const; + virtual const ContentSpecNode* getContentSpec() const; + virtual ContentSpecNode* getContentSpec(); + virtual void setContentSpec(ContentSpecNode* toAdopt); + virtual XMLContentModel* getContentModel(); + virtual void setContentModel(XMLContentModel* const newModelToAdopt); + virtual const XMLCh* getFormattedContentModel () const; + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + const SchemaAttDef* getAttDef(const XMLCh* const baseName, const int uriId) const; + SchemaAttDef* getAttDef(const XMLCh* const baseName, const int uriId); + const SchemaAttDef* getAttWildCard() const; + SchemaAttDef* getAttWildCard(); + ModelTypes getModelType() const; + PSVIDefs::PSVIScope getPSVIScope() const; + DatatypeValidator* getDatatypeValidator() const; + unsigned int getEnclosingScope() const; + int getFinalSet() const; + int getBlockSet() const; + int getMiscFlags() const; + XMLCh* getDefaultValue() const; + ComplexTypeInfo* getComplexTypeInfo() const; + virtual bool isGlobalDecl() const; + SchemaElementDecl* getSubstitutionGroupElem() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setModelType(const SchemaElementDecl::ModelTypes toSet); + void setPSVIScope(const PSVIDefs::PSVIScope toSet); + void setDatatypeValidator(DatatypeValidator* newDatatypeValidator); + void setEnclosingScope(const unsigned int enclosingScope); + void setFinalSet(const int finalSet); + void setBlockSet(const int blockSet); + void setMiscFlags(const int flags); + void setDefaultValue(const XMLCh* const value); + void setComplexTypeInfo(ComplexTypeInfo* const typeInfo); + void setAttWildCard(SchemaAttDef* const attWildCard); + void setSubstitutionGroupElem(SchemaElementDecl* const elemDecl); + + // ----------------------------------------------------------------------- + // IC methods + // ----------------------------------------------------------------------- + void addIdentityConstraint(IdentityConstraint* const ic); + XMLSize_t getIdentityConstraintCount() const; + IdentityConstraint* getIdentityConstraintAt(XMLSize_t index) const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(SchemaElementDecl) + + virtual XMLElementDecl::objectType getObjectType() const; + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaElementDecl(const SchemaElementDecl&); + SchemaElementDecl& operator=(const SchemaElementDecl&); + + // ----------------------------------------------------------------------- + // Private data members + // + // fModelType + // The content model type of this element. This tells us what kind + // of content model to create. + // + // fDatatypeValidator + // The DatatypeValidator used to validate this element type. + // + // fEnclosingScope + // The enclosing scope where this element is declared. + // + // fFinalSet + // The value set of the 'final' attribute. + // + // fBlockSet + // The value set of the 'block' attribute. + // + // fMiscFlags + // Stores 'abstract/nullable' values + // + // fDefaultValue + // The default/fixed value + // + // fComplexTypeInfo + // Stores complex type information + // (no need to delete - handled by schema grammar) + // + // fAttDefs + // The list of attributes that are faulted in for this element + // when ComplexTypeInfo does not exist. We want to keep track + // of these faulted in attributes to avoid duplicate redundant + // error. + // + // fIdentityConstraints + // Store information about an element identity constraints. + // + // fAttWildCard + // Store wildcard attribute in the case of an element with a type of + // 'anyType'. + // + // fSubstitutionGroupElem + // The substitution group element declaration. + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + ModelTypes fModelType; + PSVIDefs::PSVIScope fPSVIScope; + + unsigned int fEnclosingScope; + int fFinalSet; + int fBlockSet; + int fMiscFlags; + XMLCh* fDefaultValue; + ComplexTypeInfo* fComplexTypeInfo; + RefHash2KeysTableOf* fAttDefs; + RefVectorOf* fIdentityConstraints; + SchemaAttDef* fAttWildCard; + SchemaElementDecl* fSubstitutionGroupElem; + DatatypeValidator* fDatatypeValidator; +}; + +// --------------------------------------------------------------------------- +// SchemaElementDecl: XMLElementDecl virtual interface implementation +// --------------------------------------------------------------------------- +inline ContentSpecNode* SchemaElementDecl::getContentSpec() +{ + if (fComplexTypeInfo != 0) { + return fComplexTypeInfo->getContentSpec(); + } + + return 0; +} + +inline const ContentSpecNode* SchemaElementDecl::getContentSpec() const +{ + if (fComplexTypeInfo != 0) { + return fComplexTypeInfo->getContentSpec(); + } + + return 0; +} + +inline void +SchemaElementDecl::setContentSpec(ContentSpecNode*) +{ + //Handled by complexType +} + +inline XMLContentModel* SchemaElementDecl::getContentModel() +{ + if (fComplexTypeInfo != 0) { + return fComplexTypeInfo->getContentModel(); + } + return 0; +} + +inline void +SchemaElementDecl::setContentModel(XMLContentModel* const) +{ + //Handled by complexType +} + + +// --------------------------------------------------------------------------- +// SchemaElementDecl: Getter methods +// --------------------------------------------------------------------------- +inline SchemaElementDecl::ModelTypes SchemaElementDecl::getModelType() const +{ + if (fComplexTypeInfo) { + return (SchemaElementDecl::ModelTypes) fComplexTypeInfo->getContentType(); + } + + return fModelType; +} + +inline PSVIDefs::PSVIScope SchemaElementDecl::getPSVIScope() const +{ + return fPSVIScope; +} + +inline DatatypeValidator* SchemaElementDecl::getDatatypeValidator() const +{ + return fDatatypeValidator; +} + +inline unsigned int SchemaElementDecl::getEnclosingScope() const +{ + return fEnclosingScope; +} + +inline int SchemaElementDecl::getFinalSet() const +{ + return fFinalSet; +} + +inline int SchemaElementDecl::getBlockSet() const +{ + return fBlockSet; +} + +inline int SchemaElementDecl::getMiscFlags() const +{ + return fMiscFlags; +} + +inline XMLCh* SchemaElementDecl::getDefaultValue() const +{ + return fDefaultValue; +} + +inline ComplexTypeInfo* SchemaElementDecl::getComplexTypeInfo() const +{ + return fComplexTypeInfo; +} + +inline const SchemaAttDef* SchemaElementDecl::getAttWildCard() const { + return fAttWildCard; +} + +inline SchemaAttDef* SchemaElementDecl::getAttWildCard() { + return fAttWildCard; +} + +inline bool SchemaElementDecl::isGlobalDecl() const { + + return (fEnclosingScope == Grammar::TOP_LEVEL_SCOPE); +} + +inline SchemaElementDecl* +SchemaElementDecl::getSubstitutionGroupElem() const { + + return fSubstitutionGroupElem; +} + +// --------------------------------------------------------------------------- +// SchemaElementDecl: Setter methods +// --------------------------------------------------------------------------- +inline void +SchemaElementDecl::setModelType(const SchemaElementDecl::ModelTypes toSet) +{ + fModelType = toSet; +} + +inline void +SchemaElementDecl::setPSVIScope(const PSVIDefs::PSVIScope toSet) +{ + fPSVIScope = toSet; +} + +inline void SchemaElementDecl::setDatatypeValidator(DatatypeValidator* newDatatypeValidator) +{ + fDatatypeValidator = newDatatypeValidator; +} + +inline void SchemaElementDecl::setEnclosingScope(const unsigned int newEnclosingScope) +{ + fEnclosingScope = newEnclosingScope; +} + +inline void SchemaElementDecl::setFinalSet(const int finalSet) +{ + fFinalSet = finalSet; +} + +inline void SchemaElementDecl::setBlockSet(const int blockSet) +{ + fBlockSet = blockSet; +} + +inline void SchemaElementDecl::setMiscFlags(const int flags) +{ + fMiscFlags = flags; +} + +inline void SchemaElementDecl::setDefaultValue(const XMLCh* const value) +{ + if (fDefaultValue) { + getMemoryManager()->deallocate(fDefaultValue);//delete[] fDefaultValue; + } + + fDefaultValue = XMLString::replicate(value, getMemoryManager()); +} + +inline void +SchemaElementDecl::setComplexTypeInfo(ComplexTypeInfo* const typeInfo) +{ + fComplexTypeInfo = typeInfo; +} + +inline void +SchemaElementDecl::setAttWildCard(SchemaAttDef* const attWildCard) { + + if (fAttWildCard) + delete fAttWildCard; + + fAttWildCard = attWildCard; +} + +inline void +SchemaElementDecl::setSubstitutionGroupElem(SchemaElementDecl* const elemDecl) { + + fSubstitutionGroupElem = elemDecl; +} + +// --------------------------------------------------------------------------- +// SchemaElementDecl: IC methods +// --------------------------------------------------------------------------- +inline void +SchemaElementDecl::addIdentityConstraint(IdentityConstraint* const ic) { + + if (!fIdentityConstraints) { + fIdentityConstraints = new (getMemoryManager()) RefVectorOf(16, true, getMemoryManager()); + } + + fIdentityConstraints->addElement(ic); +} + +inline XMLSize_t SchemaElementDecl::getIdentityConstraintCount() const { + + if (fIdentityConstraints) { + return fIdentityConstraints->size(); + } + + return 0; +} + +inline IdentityConstraint* +SchemaElementDecl::getIdentityConstraintAt(XMLSize_t index) const { + + if (fIdentityConstraints) { + return fIdentityConstraints->elementAt(index); + } + + return 0; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/SchemaGrammar.cpp b/include/xercesc/validators/schema/SchemaGrammar.cpp new file mode 100644 index 0000000..636b96a --- /dev/null +++ b/include/xercesc/validators/schema/SchemaGrammar.cpp @@ -0,0 +1,369 @@ +/* + * 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: SchemaGrammar.cpp 883376 2009-11-23 15:45:23Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// SchemaGrammar: Constructors and Destructor +// --------------------------------------------------------------------------- +SchemaGrammar::SchemaGrammar(MemoryManager* const manager) : + fTargetNamespace(0) + , fElemDeclPool(0) + , fElemNonDeclPool(0) + , fGroupElemDeclPool(0) + , fNotationDeclPool(0) + , fAttributeDeclRegistry(0) + , fComplexTypeRegistry(0) + , fGroupInfoRegistry(0) + , fAttGroupInfoRegistry(0) + , fValidSubstitutionGroups(0) + , fValidationContext(0) + , fMemoryManager(manager) + , fGramDesc(0) + , fAnnotations(0) + , fValidated(false) + , fDatatypeRegistry(manager) + , fScopeCount (0) + , fAnonTypeCount (0) +{ + CleanupType cleanup(this, &SchemaGrammar::cleanUp); + + // + // Init all the pool members. + // + // Investigate what the optimum values would be for the various + // pools. + // + fElemDeclPool = new (fMemoryManager) RefHash3KeysIdPool(109, true, 128, fMemoryManager); + + try { + // should not be necessary now that grammars, once built, + // are read-only + // fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool(29, true, 128, fMemoryManager); + fGroupElemDeclPool = new (fMemoryManager) RefHash3KeysIdPool(109, false, 128, fMemoryManager); + fNotationDeclPool = new (fMemoryManager) NameIdPool(109, 128, fMemoryManager); + fValidationContext = new (fMemoryManager) ValidationContextImpl(fMemoryManager); + + //REVISIT: use grammarPool to create + fGramDesc = new (fMemoryManager) XMLSchemaDescriptionImpl(XMLUni::fgXMLNSURIName, fMemoryManager); + + // Create annotation table + fAnnotations = new (fMemoryManager) RefHashTableOf + ( + 29, true, fMemoryManager + ); + + // + // Call our own reset method. This lets us have the pool setup stuff + // done in just one place (because this stame setup stuff has to be + // done every time we are reset.) + // + reset(); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +SchemaGrammar::~SchemaGrammar() +{ + cleanUp(); +} + + +// ----------------------------------------------------------------------- +// Virtual methods +// ----------------------------------------------------------------------- +XMLElementDecl* SchemaGrammar::findOrAddElemDecl (const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const prefixName + , const XMLCh* const qName + , unsigned int scope + , bool& wasAdded ) +{ + // See it it exists + SchemaElementDecl* retVal = (SchemaElementDecl*) getElemDecl(uriId, baseName, qName, scope); + + // if not, then add this in + if (!retVal) + { + retVal = new (fMemoryManager) SchemaElementDecl + ( + prefixName + , baseName + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + if(!fElemNonDeclPool) + fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool(29, true, 128, fMemoryManager); + const XMLSize_t elemId = fElemNonDeclPool->put((void*)retVal->getBaseName(), uriId, scope, retVal); + retVal->setId(elemId); + wasAdded = true; + } + else + { + wasAdded = false; + } + return retVal; +} + +XMLElementDecl* SchemaGrammar::putElemDecl (const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const prefixName + , const XMLCh* const + , unsigned int scope + , const bool notDeclared) +{ + SchemaElementDecl* retVal = new (fMemoryManager) SchemaElementDecl + ( + prefixName + , baseName + , uriId + , SchemaElementDecl::Any + , Grammar::TOP_LEVEL_SCOPE + , fMemoryManager + ); + if(notDeclared) + { + if(!fElemNonDeclPool) + fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool(29, true, 128, fMemoryManager); + retVal->setId(fElemNonDeclPool->put((void*)retVal->getBaseName(), uriId, scope, retVal)); + } else + { + retVal->setId(fElemDeclPool->put((void*)retVal->getBaseName(), uriId, scope, retVal)); + } + return retVal; +} + +void SchemaGrammar::reset() +{ + // + // We need to reset all of the pools. + // + fElemDeclPool->removeAll(); + if(fElemNonDeclPool) + fElemNonDeclPool->removeAll(); + fGroupElemDeclPool->removeAll(); + fNotationDeclPool->removeAll(); + fAnnotations->removeAll(); + fValidated = false; +} + + +void SchemaGrammar::cleanUp() +{ + delete fElemDeclPool; + if(fElemNonDeclPool) + delete fElemNonDeclPool; + delete fGroupElemDeclPool; + delete fNotationDeclPool; + fMemoryManager->deallocate(fTargetNamespace);//delete [] fTargetNamespace; + delete fAttributeDeclRegistry; + delete fComplexTypeRegistry; + delete fGroupInfoRegistry; + delete fAttGroupInfoRegistry; + delete fValidSubstitutionGroups; + delete fValidationContext; + delete fGramDesc; + delete fAnnotations; +} + +void SchemaGrammar::setGrammarDescription(XMLGrammarDescription* gramDesc) +{ + if ((!gramDesc) || + (gramDesc->getGrammarType() != Grammar::SchemaGrammarType)) + return; + + if (fGramDesc) + delete fGramDesc; + + //adopt the grammar Description + fGramDesc = (XMLSchemaDescription*) gramDesc; +} + +// --------------------------------------------------------------------------- +// SchemaGrammar: Helper methods +// --------------------------------------------------------------------------- +void SchemaGrammar::putAnnotation(void* key, XSAnnotation* const annotation) +{ + fAnnotations->put(key, annotation); +} + +void SchemaGrammar::addAnnotation(XSAnnotation* const annotation) +{ + XSAnnotation* lAnnot = fAnnotations->get(this); + + if (lAnnot) + lAnnot->setNext(annotation); + else + fAnnotations->put(this, annotation); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(SchemaGrammar) + +void SchemaGrammar::serialize(XSerializeEngine& serEng) +{ + + /*** + * don't serialize ValidationContext* fValidationContext; + * fElemNonDeclPool + ***/ + + Grammar::serialize(serEng); + + if (serEng.isStoring()) + { + //serialize DatatypeValidatorFactory first + fDatatypeRegistry.serialize(serEng); + + /*** + * + * Serialize RefHash3KeysIdPool* fElemDeclPool; + * Serialize RefHash3KeysIdPool* fGroupElemDeclPool; + * + ***/ + XTemplateSerializer::storeObject(fElemDeclPool, serEng); + XTemplateSerializer::storeObject(fGroupElemDeclPool, serEng); + + /*** + * Serialize NameIdPool* fNotationDeclPool; + ***/ + XTemplateSerializer::storeObject(fNotationDeclPool, serEng); + + /*** + * + * Serialize RefHashTableOf* fAttributeDeclRegistry; + * Serialize RefHashTableOf* fComplexTypeRegistry; + * Serialize RefHashTableOf* fGroupInfoRegistry; + * Serialize RefHashTableOf* fAttGroupInfoRegistry; + * Serialize RefHashTableOf* fIDRefList; + * + ***/ + + XTemplateSerializer::storeObject(fAttributeDeclRegistry, serEng); + XTemplateSerializer::storeObject(fComplexTypeRegistry, serEng); + XTemplateSerializer::storeObject(fGroupInfoRegistry, serEng); + XTemplateSerializer::storeObject(fAttGroupInfoRegistry, serEng); + + /*** + * Serialize RefHash2KeysTableOf* fValidSubstitutionGroups; + ***/ + XTemplateSerializer::storeObject(fValidSubstitutionGroups, serEng); + + /*** + * Serialize RefHashTableOf* fAnnotations; + ***/ + XTemplateSerializer::storeObject(fAnnotations, serEng); + + serEng.writeString(fTargetNamespace); + serEng<serialize(serEng); + + } + else + { + fDatatypeRegistry.serialize(serEng); + + /*** + * + * Deserialize RefHash3KeysIdPool* fElemDeclPool; + * Deserialize RefHash3KeysIdPool* fGroupElemDeclPool; + * + ***/ + XTemplateSerializer::loadObject(&fElemDeclPool, 109, true, 128, serEng); + XTemplateSerializer::loadObject(&fGroupElemDeclPool, 109, true, 128, serEng); + + /*** + * Deserialize NameIdPool* fNotationDeclPool; + ***/ + XTemplateSerializer::loadObject(&fNotationDeclPool, 109, 128, serEng); + + /*** + * + * Deserialize RefHashTableOf* fAttributeDeclRegistry; + * Deserialize RefHashTableOf* fComplexTypeRegistry; + * Deserialize RefHashTableOf* fGroupInfoRegistry; + * Deserialize RefHashTableOf* fAttGroupInfoRegistry; + * Deserialize RefHashTableOf* fIDRefList; + * + ***/ + + XTemplateSerializer::loadObject(&fAttributeDeclRegistry, 29, true, serEng); + XTemplateSerializer::loadObject(&fComplexTypeRegistry, 29, true, serEng); + XTemplateSerializer::loadObject(&fGroupInfoRegistry, 13, true, serEng); + XTemplateSerializer::loadObject(&fAttGroupInfoRegistry, 13, true, serEng); + + /*** + * Deserialize RefHash2KeysTableOf* fValidSubstitutionGroups; + ***/ + XTemplateSerializer::loadObject(&fValidSubstitutionGroups, 29, true, serEng); + + /*** + * Deserialize RefHashTableOf* fAnnotations; + ***/ + XTemplateSerializer::loadObject(&fAnnotations, 29, true, serEng); + + serEng.readString(fTargetNamespace); + serEng>>fValidated; + + /*** + * serialize() method shall be used to load object + * which has been created in ctor + ***/ + fGramDesc->serialize(serEng); + + } +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/SchemaGrammar.hpp b/include/xercesc/validators/schema/SchemaGrammar.hpp new file mode 100644 index 0000000..a06062a --- /dev/null +++ b/include/xercesc/validators/schema/SchemaGrammar.hpp @@ -0,0 +1,638 @@ +/* + * 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: SchemaGrammar.hpp 883376 2009-11-23 15:45:23Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMAGRAMMAR_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMAGRAMMAR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// This class stores the Schema information +// NOTE: Schemas are not namespace aware, so we just use regular NameIdPool +// data structures to store element and attribute decls. They are all set +// to be in the global namespace and the full QName is used as the base name +// of the decl. This means that all the URI parameters below are expected +// to be null pointers (and anything else will cause an exception.) +// + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class ComplexTypeInfo; +class XercesGroupInfo; +class XercesAttGroupInfo; +class XSAnnotation; + +// --------------------------------------------------------------------------- +// typedef declaration +// --------------------------------------------------------------------------- +typedef ValueVectorOf ElemVector; + + +class VALIDATORS_EXPORT SchemaGrammar : public Grammar +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + SchemaGrammar(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual ~SchemaGrammar(); + + // ----------------------------------------------------------------------- + // Implementation of Virtual Interface + // ----------------------------------------------------------------------- + virtual Grammar::GrammarType getGrammarType() const; + virtual const XMLCh* getTargetNamespace() const; + + // 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 + ) ; + + virtual XMLSize_t getElemId + ( + const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const qName + , unsigned int scope + ) const ; + + virtual const XMLElementDecl* getElemDecl + ( + const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const qName + , unsigned int scope + ) const ; + + virtual XMLElementDecl* getElemDecl + ( + const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const qName + , unsigned int scope + ); + + virtual const XMLElementDecl* getElemDecl + ( + const unsigned int elemId + ) const; + + virtual XMLElementDecl* getElemDecl + ( + const unsigned int elemId + ); + + virtual const XMLNotationDecl* getNotationDecl + ( + const XMLCh* const notName + ) const; + + virtual XMLNotationDecl* getNotationDecl + ( + const XMLCh* const notName + ); + + virtual bool getValidated() const; + + 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 + ); + + virtual XMLSize_t putElemDecl + ( + XMLElementDecl* const elemDecl + , const bool notDeclared = false + ) ; + + virtual XMLSize_t putNotationDecl + ( + XMLNotationDecl* const notationDecl + ) const; + + virtual void setValidated(const bool newState); + + virtual void reset(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + RefHash3KeysIdPoolEnumerator getElemEnumerator() const; + NameIdPoolEnumerator getNotationEnumerator() const; + RefHashTableOf* getAttributeDeclRegistry() const; + RefHashTableOf* getComplexTypeRegistry() const; + RefHashTableOf* getGroupInfoRegistry() const; + RefHashTableOf* getAttGroupInfoRegistry() const; + DatatypeValidatorFactory* getDatatypeRegistry(); + RefHash2KeysTableOf* getValidSubstitutionGroups() const; + + // @deprecated + ValidationContext* getValidationContext() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setTargetNamespace(const XMLCh* const targetNamespace); + void setAttributeDeclRegistry(RefHashTableOf* const attReg); + void setComplexTypeRegistry(RefHashTableOf* const other); + void setGroupInfoRegistry(RefHashTableOf* const other); + void setAttGroupInfoRegistry(RefHashTableOf* const other); + void setValidSubstitutionGroups(RefHash2KeysTableOf* const); + + virtual void setGrammarDescription( XMLGrammarDescription*); + virtual XMLGrammarDescription* getGrammarDescription() const; + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + XMLSize_t putGroupElemDecl + ( + XMLElementDecl* const elemDecl + ) const; + + // ----------------------------------------------------------------------- + // Annotation management methods + // ----------------------------------------------------------------------- + /** + * Add annotation to the list of annotations for a given key + */ + void putAnnotation(void* key, XSAnnotation* const annotation); + + /** + * Add global annotation + * + * Note: XSAnnotation acts as a linked list + */ + void addAnnotation(XSAnnotation* const annotation); + + /** + * Retrieve the annotation that is associated with the specified key + * + * @param key represents a schema component object (i.e. SchemaGrammar) + * @return XSAnnotation associated with the key object + */ + XSAnnotation* getAnnotation(const void* const key); + + /** + * Retrieve the annotation that is associated with the specified key + * + * @param key represents a schema component object (i.e. SchemaGrammar) + * @return XSAnnotation associated with the key object + */ + const XSAnnotation* getAnnotation(const void* const key) const; + + /** + * Get global annotation + */ + XSAnnotation* getAnnotation(); + const XSAnnotation* getAnnotation() const; + + /** + * Get annotation hash table, to enumerate through them + */ + RefHashTableOf* getAnnotations(); + const RefHashTableOf* getAnnotations() const; + + /** + * Get/set scope count. + */ + unsigned int getScopeCount () const; + void setScopeCount (unsigned int); + + /** + * Get/set anonymous type count. + */ + unsigned int getAnonTypeCount () const; + void setAnonTypeCount (unsigned int); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(SchemaGrammar) + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaGrammar(const SchemaGrammar&); + SchemaGrammar& operator=(const SchemaGrammar&); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Private data members + // + // fElemDeclPool + // This is the element decl pool. It contains all of the elements + // declared in the Schema (and their associated attributes.) + // + // fElemNonDeclPool + // This is the element decl pool that is is populated as new elements + // are seen in the XML document (not declared in the Schema), and they + // are given default characteristics. + // + // fGroupElemDeclPool + // This is the element decl pool for elements in a group that are + // referenced in different scope. It contains all of the elements + // declared in the Schema (and their associated attributes.) + // + // fNotationDeclPool + // This is a pool of NotationDecl objects, which contains all of the + // notations declared in the Schema. + // + // fTargetNamespace + // Target name space for this grammar. + // + // fAttributeDeclRegistry + // Global attribute declarations + // + // fComplexTypeRegistry + // Stores complexType declaration info + // + // fGroupInfoRegistry + // Stores global declaration info + // + // fAttGroupInfoRegistry + // Stores global declaration info + // + // fDatatypeRegistry + // Datatype validator factory + // + // fValidSubstitutionGroups + // Valid list of elements that can substitute a given element + // + // fIDRefList + // List of ids of schema declarations extracted during schema grammar + // traversal + // + // fValidated + // Indicates if the content of the Grammar has been pre-validated + // or not (UPA checking, etc.). When using a cached grammar, no need + // for pre content validation. + // + // fGramDesc: adopted + // + // ----------------------------------------------------------------------- + XMLCh* fTargetNamespace; + RefHash3KeysIdPool* fElemDeclPool; + RefHash3KeysIdPool* fElemNonDeclPool; + RefHash3KeysIdPool* fGroupElemDeclPool; + NameIdPool* fNotationDeclPool; + RefHashTableOf* fAttributeDeclRegistry; + RefHashTableOf* fComplexTypeRegistry; + RefHashTableOf* fGroupInfoRegistry; + RefHashTableOf* fAttGroupInfoRegistry; + RefHash2KeysTableOf* fValidSubstitutionGroups; + // @deprecated + ValidationContext* fValidationContext; + MemoryManager* fMemoryManager; + XMLSchemaDescription* fGramDesc; + RefHashTableOf* fAnnotations; + + bool fValidated; + DatatypeValidatorFactory fDatatypeRegistry; + + unsigned int fScopeCount; + unsigned int fAnonTypeCount; +}; + + +// --------------------------------------------------------------------------- +// SchemaGrammar: Getter methods +// --------------------------------------------------------------------------- +inline RefHash3KeysIdPoolEnumerator +SchemaGrammar::getElemEnumerator() const +{ + return RefHash3KeysIdPoolEnumerator(fElemDeclPool, false, fMemoryManager); +} + +inline NameIdPoolEnumerator +SchemaGrammar::getNotationEnumerator() const +{ + return NameIdPoolEnumerator(fNotationDeclPool, fMemoryManager); +} + +inline RefHashTableOf* SchemaGrammar::getAttributeDeclRegistry() const { + + return fAttributeDeclRegistry; +} + +inline RefHashTableOf* +SchemaGrammar::getComplexTypeRegistry() const { + + return fComplexTypeRegistry; +} + +inline RefHashTableOf* +SchemaGrammar::getGroupInfoRegistry() const { + + return fGroupInfoRegistry; +} + +inline RefHashTableOf* +SchemaGrammar::getAttGroupInfoRegistry() const { + + return fAttGroupInfoRegistry; +} + +inline DatatypeValidatorFactory* SchemaGrammar::getDatatypeRegistry() { + + return &fDatatypeRegistry; +} + +inline RefHash2KeysTableOf* +SchemaGrammar::getValidSubstitutionGroups() const { + + return fValidSubstitutionGroups; +} + +// @deprecated +inline ValidationContext* SchemaGrammar::getValidationContext() const { + + return fValidationContext; +} + +inline XMLGrammarDescription* SchemaGrammar::getGrammarDescription() const +{ + return fGramDesc; +} + +inline XSAnnotation* SchemaGrammar::getAnnotation(const void* const key) +{ + return fAnnotations->get(key); +} + +inline const XSAnnotation* SchemaGrammar::getAnnotation(const void* const key) const +{ + return fAnnotations->get(key); +} + +inline XSAnnotation* SchemaGrammar::getAnnotation() +{ + return fAnnotations->get(this); +} + +inline const XSAnnotation* SchemaGrammar::getAnnotation() const +{ + return fAnnotations->get(this); +} + +inline RefHashTableOf* SchemaGrammar::getAnnotations() +{ + return fAnnotations; +} + +inline const RefHashTableOf* SchemaGrammar::getAnnotations() const +{ + return fAnnotations; +} +// ----------------------------------------------------------------------- +// Setter methods +// ----------------------------------------------------------------------- +inline void SchemaGrammar::setTargetNamespace(const XMLCh* const targetNamespace) +{ + if (fTargetNamespace) + fMemoryManager->deallocate(fTargetNamespace);//delete [] fTargetNamespace; + fTargetNamespace = XMLString::replicate(targetNamespace, fMemoryManager); +} + +inline void +SchemaGrammar::setAttributeDeclRegistry(RefHashTableOf* const attReg) { + + fAttributeDeclRegistry = attReg; +} + +inline void +SchemaGrammar::setComplexTypeRegistry(RefHashTableOf* const other) { + + fComplexTypeRegistry = other; +} + +inline void +SchemaGrammar::setGroupInfoRegistry(RefHashTableOf* const other) { + + fGroupInfoRegistry = other; +} + +inline void +SchemaGrammar::setAttGroupInfoRegistry(RefHashTableOf* const other) { + + fAttGroupInfoRegistry = other; +} + +inline void +SchemaGrammar::setValidSubstitutionGroups(RefHash2KeysTableOf* const other) { + + fValidSubstitutionGroups = other; +} + + +// --------------------------------------------------------------------------- +// SchemaGrammar: Virtual methods +// --------------------------------------------------------------------------- +inline Grammar::GrammarType SchemaGrammar::getGrammarType() const { + return Grammar::SchemaGrammarType; +} + +inline const XMLCh* SchemaGrammar::getTargetNamespace() const { + return fTargetNamespace; +} + +// Element Decl +inline XMLSize_t SchemaGrammar::getElemId (const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const + , unsigned int scope ) const +{ + // + // In this case, we don't return zero to mean 'not found', so we have to + // map it to the official not found value if we don't find it. + // + const SchemaElementDecl* decl = fElemDeclPool->getByKey(baseName, uriId, scope); + if (!decl) { + + decl = fGroupElemDeclPool->getByKey(baseName, uriId, scope); + + if (!decl) + return XMLElementDecl::fgInvalidElemId; + } + return decl->getId(); +} + +inline const XMLElementDecl* SchemaGrammar::getElemDecl( const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const + , unsigned int scope ) const +{ + const SchemaElementDecl* decl = fElemDeclPool->getByKey(baseName, uriId, scope); + + if (!decl) { + + decl = fGroupElemDeclPool->getByKey(baseName, uriId, scope); + + if (!decl && fElemNonDeclPool) + decl = fElemNonDeclPool->getByKey(baseName, uriId, scope); + } + + return decl; +} + +inline XMLElementDecl* SchemaGrammar::getElemDecl (const unsigned int uriId + , const XMLCh* const baseName + , const XMLCh* const + , unsigned int scope ) +{ + SchemaElementDecl* decl = fElemDeclPool->getByKey(baseName, uriId, scope); + + if (!decl) { + + decl = fGroupElemDeclPool->getByKey(baseName, uriId, scope); + + if (!decl && fElemNonDeclPool) + decl = fElemNonDeclPool->getByKey(baseName, uriId, scope); + } + + return decl; +} + +inline const XMLElementDecl* SchemaGrammar::getElemDecl(const unsigned int elemId) const +{ + // Look up this element decl by id + const SchemaElementDecl* decl = fElemDeclPool->getById(elemId); + + if (!decl) + decl = fGroupElemDeclPool->getById(elemId); + + return decl; +} + +inline XMLElementDecl* SchemaGrammar::getElemDecl(const unsigned int elemId) +{ + // Look up this element decl by id + SchemaElementDecl* decl = fElemDeclPool->getById(elemId); + + if (!decl) + decl = fGroupElemDeclPool->getById(elemId); + + return decl; +} + +inline XMLSize_t +SchemaGrammar::putElemDecl(XMLElementDecl* const elemDecl, + const bool notDeclared) +{ + if (notDeclared) + { + if(!fElemNonDeclPool) + fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool(29, true, 128, fMemoryManager); + return fElemNonDeclPool->put(elemDecl->getBaseName(), elemDecl->getURI(), ((SchemaElementDecl* )elemDecl)->getEnclosingScope(), (SchemaElementDecl*) elemDecl); + } + + return fElemDeclPool->put(elemDecl->getBaseName(), elemDecl->getURI(), ((SchemaElementDecl* )elemDecl)->getEnclosingScope(), (SchemaElementDecl*) elemDecl); +} + +inline XMLSize_t SchemaGrammar::putGroupElemDecl (XMLElementDecl* const elemDecl) const +{ + return fGroupElemDeclPool->put(elemDecl->getBaseName(), elemDecl->getURI(), ((SchemaElementDecl* )elemDecl)->getEnclosingScope(), (SchemaElementDecl*) elemDecl); +} + +// Notation Decl +inline const XMLNotationDecl* SchemaGrammar::getNotationDecl(const XMLCh* const notName) const +{ + return fNotationDeclPool->getByKey(notName); +} + +inline XMLNotationDecl* SchemaGrammar::getNotationDecl(const XMLCh* const notName) +{ + return fNotationDeclPool->getByKey(notName); +} + +inline XMLSize_t SchemaGrammar::putNotationDecl(XMLNotationDecl* const notationDecl) const +{ + return fNotationDeclPool->put(notationDecl); +} + +inline bool SchemaGrammar::getValidated() const +{ + return fValidated; +} + +inline void SchemaGrammar::setValidated(const bool newState) +{ + fValidated = newState; +} + +inline unsigned int +SchemaGrammar::getScopeCount () const +{ + return fScopeCount; +} + +inline void +SchemaGrammar::setScopeCount (unsigned int scopeCount) +{ + fScopeCount = scopeCount; +} + +inline unsigned int +SchemaGrammar::getAnonTypeCount () const +{ + return fAnonTypeCount; +} + +inline void +SchemaGrammar::setAnonTypeCount (unsigned int count) +{ + fAnonTypeCount = count; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/SchemaInfo.cpp b/include/xercesc/validators/schema/SchemaInfo.cpp new file mode 100644 index 0000000..cb6feaf --- /dev/null +++ b/include/xercesc/validators/schema/SchemaInfo.cpp @@ -0,0 +1,251 @@ +/* + * 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: SchemaInfo.cpp 925236 2010-03-19 14:29:47Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +SchemaInfo::SchemaInfo(const unsigned short elemAttrDefaultQualified, + const int blockDefault, + const int finalDefault, + const int targetNSURI, + const NamespaceScope* const currNamespaceScope, + const XMLCh* const schemaURL, + const XMLCh* const targetNSURIString, + const DOMElement* const root, + XMLScanner* xmlScanner, + MemoryManager* const manager) + : fAdoptInclude(false) + , fProcessed(false) + , fElemAttrDefaultQualified(elemAttrDefaultQualified) + , fBlockDefault(blockDefault) + , fFinalDefault(finalDefault) + , fTargetNSURI(targetNSURI) + , fNamespaceScope(0) + , fSchemaRootElement(root) + , fIncludeInfoList(0) + , fImportedInfoList(0) + , fImportingInfoList(0) + , fFailedRedefineList(0) + , fRecursingAnonTypes(0) + , fRecursingTypeNames(0) + , fNonXSAttList(0) + , fValidationContext(0) + , fMemoryManager(manager) +{ + fImportingInfoList = new (fMemoryManager) RefVectorOf(4, false, fMemoryManager); + + memset( + fTopLevelComponents, + 0, + sizeof(fTopLevelComponents[0]) * C_Count); + memset( + fLastTopLevelComponent, + 0, + sizeof(fLastTopLevelComponent[0]) * C_Count); + + fNonXSAttList = new (fMemoryManager) ValueVectorOf(2, fMemoryManager); + fValidationContext = new (fMemoryManager) ValidationContextImpl(fMemoryManager); + fNamespaceScope = new (fMemoryManager) NamespaceScope(currNamespaceScope, fMemoryManager); + fCurrentSchemaURL = XMLString::replicate(schemaURL, fMemoryManager); + fTargetNSURIString = XMLString::replicate(targetNSURIString, fMemoryManager); + + fValidationContext->setScanner (xmlScanner); + fValidationContext->setNamespaceScope(fNamespaceScope); +} + + +SchemaInfo::~SchemaInfo() +{ + fMemoryManager->deallocate(fCurrentSchemaURL);//delete [] fCurrentSchemaURL; + fMemoryManager->deallocate(fTargetNSURIString); + delete fImportedInfoList; + + if (fAdoptInclude) + delete fIncludeInfoList; + + delete fImportingInfoList; + delete fFailedRedefineList; + delete fRecursingAnonTypes; + delete fRecursingTypeNames; + + for (unsigned int i = 0; i < C_Count; i++) { + delete fTopLevelComponents[i]; + } + + delete fNonXSAttList; + delete fValidationContext; + delete fNamespaceScope; +} + +// --------------------------------------------------------------------------- +// SchemaInfo: +// --------------------------------------------------------------------------- +DOMElement* +SchemaInfo::getTopLevelComponent(const unsigned short compCategory, + const XMLCh* const compName, + const XMLCh* const name, + SchemaInfo** enclosingSchema) { + + if (fSchemaRootElement == 0) + return 0; + + SchemaInfo* currentInfo = this; + DOMElement* child = getTopLevelComponent(compCategory, compName, name); + + if (child == 0) { + + XMLSize_t listSize = (fIncludeInfoList) ? fIncludeInfoList->size() : 0; + + for (XMLSize_t i=0; i < listSize; i++) { + + currentInfo = fIncludeInfoList->elementAt(i); + + if (currentInfo == this) + continue; + + child = currentInfo->getTopLevelComponent(compCategory, compName, name); + + if (child != 0) { + + *enclosingSchema = currentInfo; + break; + } + } + } + + return child; +} + + +DOMElement* +SchemaInfo::getTopLevelComponent(const unsigned short compCategory, + const XMLCh* const compName, + const XMLCh* const name) { + + if (fSchemaRootElement == 0 || compCategory >= C_Count) + return 0; + + DOMElement* child = XUtil::getFirstChildElement(fSchemaRootElement); + + if (!child) + return 0; + + RefHashTableOf* compList = fTopLevelComponents[compCategory]; + + if (fTopLevelComponents[compCategory] == 0) { + + compList= new (fMemoryManager) RefHashTableOf(17, false, fMemoryManager); + fTopLevelComponents[compCategory] = compList; + } + else { + DOMElement* cachedChild = compList->get(name); + if(cachedChild) + return cachedChild; + + child = fLastTopLevelComponent[compCategory]; + } + + DOMElement* redefParent = (DOMElement*) child->getParentNode(); + + // Parent is not "redefine" + if (!XMLString::equals(redefParent->getLocalName(),SchemaSymbols::fgELT_REDEFINE)) + redefParent = 0; + + while (child != 0) { + + fLastTopLevelComponent[compCategory]=child; + if (XMLString::equals(child->getLocalName(), compName)) { + + const XMLCh* cName=child->getAttribute(SchemaSymbols::fgATT_NAME); + compList->put((void*)cName, child); + + if (XMLString::equals(cName, name)) + return child; + } + else if (XMLString::equals(child->getLocalName(),SchemaSymbols::fgELT_REDEFINE) + && (!fFailedRedefineList || !fFailedRedefineList->containsElement(child))) { // if redefine + + DOMElement* redefineChild = XUtil::getFirstChildElement(child); + + while (redefineChild != 0) { + + fLastTopLevelComponent[compCategory]=redefineChild; + if ((!fFailedRedefineList || !fFailedRedefineList->containsElement(redefineChild)) + && XMLString::equals(redefineChild->getLocalName(), compName)) { + + const XMLCh* rName=redefineChild->getAttribute(SchemaSymbols::fgATT_NAME); + compList->put((void*)rName, redefineChild); + + if (XMLString::equals(rName, name)) + return redefineChild; + } + + redefineChild = XUtil::getNextSiblingElement(redefineChild); + } + } + + child = XUtil::getNextSiblingElement(child); + + if (child == 0 && redefParent) { + + child = XUtil::getNextSiblingElement(redefParent); + redefParent = 0; + } + } + + return child; +} + +void SchemaInfo::updateImportingInfo(SchemaInfo* const importingInfo) { + + if (!fImportingInfoList->containsElement(importingInfo)) { + fImportingInfoList->addElement(importingInfo); + } + + XMLSize_t listSize = importingInfo->fImportingInfoList->size(); + + for (XMLSize_t i=0; i < listSize; i++) { + + SchemaInfo* tmpInfo = importingInfo->fImportingInfoList->elementAt(i); + + if (tmpInfo != this && !fImportingInfoList->containsElement(tmpInfo)) { + fImportingInfoList->addElement(tmpInfo); + } + } +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file SchemaInfo.cpp + */ diff --git a/include/xercesc/validators/schema/SchemaInfo.hpp b/include/xercesc/validators/schema/SchemaInfo.hpp new file mode 100644 index 0000000..9dad859 --- /dev/null +++ b/include/xercesc/validators/schema/SchemaInfo.hpp @@ -0,0 +1,432 @@ +/* + * 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: SchemaInfo.hpp 925236 2010-03-19 14:29:47Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMAINFO_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMAINFO_HPP + + +/** When in a , type definitions being used (and indeed + * refs to 's and 's) may refer to info + * items either in the schema being redefined, in the , + * or else in the schema doing the redefining. Because of this + * latter we have to be prepared sometimes to look for our type + * definitions outside the schema stored in fSchemaRootElement. + * This simple class does this; it's just a linked list that + * lets us look at the 's on the queue; note also that this + * should provide us with a mechanism to handle nested 's. + * It's also a handy way of saving schema info when importing/including. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class XMLScanner; +class ValidationContext; +class NamespaceScope; + +class VALIDATORS_EXPORT SchemaInfo : public XMemory +{ +public: + + enum ListType { + // Redefine is treated as an include + IMPORT = 1, + INCLUDE = 2 + }; + + enum { + C_ComplexType, + C_SimpleType, + C_Group, + C_Attribute, + C_AttributeGroup, + C_Element, + C_Notation, + + C_Count + }; + + // ----------------------------------------------------------------------- + // Constructor/Destructor + // ----------------------------------------------------------------------- + SchemaInfo(const unsigned short fElemAttrDefaultQualified, + const int blockDefault, + const int finalDefault, + const int targetNSURI, + const NamespaceScope* const currNamespaceScope, + const XMLCh* const schemaURL, + const XMLCh* const targetNSURIString, + const DOMElement* const root, + XMLScanner* xmlScanner, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~SchemaInfo(); + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XMLCh* getCurrentSchemaURL() const; + const XMLCh* getTargetNSURIString() const; + const DOMElement* getRoot() const; + bool getProcessed() const; + int getBlockDefault() const; + int getFinalDefault() const; + int getTargetNSURI() const; + NamespaceScope* getNamespaceScope() const; + unsigned short getElemAttrDefaultQualified() const; + BaseRefVectorEnumerator getImportingListEnumerator() const; + ValueVectorOf* getRecursingAnonTypes() const; + ValueVectorOf* getRecursingTypeNames() const; + ValueVectorOf* getNonXSAttList() const; + ValidationContext* getValidationContext() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setProcessed(const bool aValue = true); + void setBlockDefault(const int aValue); + void setFinalDefault(const int aValue); + void setElemAttrDefaultQualified(const unsigned short aValue); + void resetRoot (); + + // ----------------------------------------------------------------------- + // Access methods + // ----------------------------------------------------------------------- + void addSchemaInfo(SchemaInfo* const toAdd, const ListType aListType); + bool containsInfo(const SchemaInfo* const toCheck, const ListType aListType) const; + SchemaInfo* getImportInfo(const unsigned int namespaceURI) const; + DOMElement* getTopLevelComponent(const unsigned short compCategory, + const XMLCh* const compName, + const XMLCh* const name); + DOMElement* getTopLevelComponent(const unsigned short compCategory, + const XMLCh* const compName, + const XMLCh* const name, + SchemaInfo** enclosingSchema); + void updateImportingInfo(SchemaInfo* const importingInfo); + bool circularImportExist(const unsigned int nameSpaceURI); + bool isFailedRedefine(const DOMElement* const anElem); + void addFailedRedefine(const DOMElement* const anElem); + void addRecursingType(const DOMElement* const elem, const XMLCh* const name); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaInfo(const SchemaInfo&); + SchemaInfo& operator=(const SchemaInfo&); + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void clearTopLevelComponents(); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fAdoptInclude; + bool fProcessed; + unsigned short fElemAttrDefaultQualified; + int fBlockDefault; + int fFinalDefault; + int fTargetNSURI; + NamespaceScope* fNamespaceScope; + XMLCh* fCurrentSchemaURL; + XMLCh* fTargetNSURIString; + const DOMElement* fSchemaRootElement; + RefVectorOf* fIncludeInfoList; + RefVectorOf* fImportedInfoList; + RefVectorOf* fImportingInfoList; + ValueVectorOf* fFailedRedefineList; + ValueVectorOf* fRecursingAnonTypes; + ValueVectorOf* fRecursingTypeNames; + RefHashTableOf* fTopLevelComponents[C_Count]; + DOMElement* fLastTopLevelComponent[C_Count]; + ValueVectorOf* fNonXSAttList; + ValidationContext* fValidationContext; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// SchemaInfo: Getter methods +// --------------------------------------------------------------------------- +inline unsigned short SchemaInfo::getElemAttrDefaultQualified() const { + + return fElemAttrDefaultQualified; +} + +inline bool SchemaInfo::getProcessed() const { + + return fProcessed; +} + +inline int SchemaInfo::getBlockDefault() const { + + return fBlockDefault; +} + +inline int SchemaInfo::getFinalDefault() const { + + return fFinalDefault; +} + +inline NamespaceScope* SchemaInfo::getNamespaceScope() const { + return fNamespaceScope; +} + +inline XMLCh* SchemaInfo::getCurrentSchemaURL() const { + + return fCurrentSchemaURL; +} + +inline const XMLCh* SchemaInfo::getTargetNSURIString() const { + + return fTargetNSURIString; +} + +inline const DOMElement* SchemaInfo::getRoot() const { + + return fSchemaRootElement; +} + +inline int SchemaInfo::getTargetNSURI() const { + + return fTargetNSURI; +} + +inline BaseRefVectorEnumerator +SchemaInfo::getImportingListEnumerator() const { + + return BaseRefVectorEnumerator(fImportingInfoList); +} + +inline ValueVectorOf* +SchemaInfo::getRecursingAnonTypes() const { + + return fRecursingAnonTypes; +} + + +inline ValueVectorOf* +SchemaInfo::getRecursingTypeNames() const { + + return fRecursingTypeNames; +} + +inline ValueVectorOf* SchemaInfo::getNonXSAttList() const +{ + return fNonXSAttList; +} + +// --------------------------------------------------------------------------- +// Setter methods +// --------------------------------------------------------------------------- +inline void SchemaInfo::setBlockDefault(const int aValue) { + + fBlockDefault = aValue; +} + +inline void SchemaInfo::setFinalDefault(const int aValue) { + + fFinalDefault = aValue; +} + +inline void SchemaInfo::setElemAttrDefaultQualified(const unsigned short aValue) { + + fElemAttrDefaultQualified = aValue; +} + +inline void SchemaInfo::setProcessed(const bool aValue) { + + fProcessed = aValue; + +/* if (fProcessed && fIncludeInfoList) { + + unsigned int includeListLen = fIncludeInfoList->size()); + for (unsigned int i = 0; i < includeListLen; i++) { + fIncludeInfoList->elementAt(i)->clearTopLevelComponents(); + } + }*/ +} + +inline void SchemaInfo::resetRoot () +{ + fSchemaRootElement = 0; +} + +// --------------------------------------------------------------------------- +// SchemaInfo: Access methods +// --------------------------------------------------------------------------- +inline void SchemaInfo::addSchemaInfo(SchemaInfo* const toAdd, + const ListType aListType) { + + if (aListType == IMPORT) { + + if (!fImportedInfoList) + fImportedInfoList = new (fMemoryManager) RefVectorOf(4, false, fMemoryManager); + + if (!fImportedInfoList->containsElement(toAdd)) { + + fImportedInfoList->addElement(toAdd); + toAdd->updateImportingInfo(this); + } + } + else { + + if (!fIncludeInfoList) { + + fIncludeInfoList = new (fMemoryManager) RefVectorOf(8, false, fMemoryManager); + fAdoptInclude = true; + } + + if (!fIncludeInfoList->containsElement(toAdd)) { + + fIncludeInfoList->addElement(toAdd); + //code was originally: + //toAdd->fIncludeInfoList = fIncludeInfoList; + //however for handling multiple imports this was causing + //to schemaInfo's to have the same fIncludeInfoList which they + //both owned so when it was deleted it crashed. + if (toAdd->fIncludeInfoList) { + if (toAdd->fIncludeInfoList != fIncludeInfoList) { + XMLSize_t size = toAdd->fIncludeInfoList->size(); + for (XMLSize_t i=0; icontainsElement(toAdd->fIncludeInfoList->elementAt(i))) { + fIncludeInfoList->addElement(toAdd->fIncludeInfoList->elementAt(i)); + } + } + size = fIncludeInfoList->size(); + for (XMLSize_t j=0; jfIncludeInfoList->containsElement(fIncludeInfoList->elementAt(j))) { + toAdd->fIncludeInfoList->addElement(fIncludeInfoList->elementAt(j)); + } + } + } + } + else { + toAdd->fIncludeInfoList = fIncludeInfoList; + } + } + } +} + +inline SchemaInfo* SchemaInfo::getImportInfo(const unsigned int namespaceURI) const { + + XMLSize_t importSize = (fImportedInfoList) ? fImportedInfoList->size() : 0; + SchemaInfo* currInfo = 0; + + for (XMLSize_t i=0; i < importSize; i++) { + + currInfo = fImportedInfoList->elementAt(i); + + if (currInfo->getTargetNSURI() == (int) namespaceURI) + return currInfo; + } + + return 0; +} + +inline ValidationContext* SchemaInfo::getValidationContext() const { + + return fValidationContext; +} + +inline bool SchemaInfo::containsInfo(const SchemaInfo* const toCheck, + const ListType aListType) const { + + if ((aListType == INCLUDE) && fIncludeInfoList) { + return fIncludeInfoList->containsElement(toCheck); + } + else if ((aListType == IMPORT) && fImportedInfoList) { + return fImportedInfoList->containsElement(toCheck); + } + + return false; +} + +inline bool SchemaInfo::circularImportExist(const unsigned int namespaceURI) { + + XMLSize_t importSize = fImportingInfoList->size(); + + for (XMLSize_t i=0; i < importSize; i++) { + if (fImportingInfoList->elementAt(i)->getTargetNSURI() == (int) namespaceURI) { + return true; + } + } + + return false; +} + +inline bool SchemaInfo::isFailedRedefine(const DOMElement* const anElem) { + + if (fFailedRedefineList) + return (fFailedRedefineList->containsElement(anElem)); + + return false; +} + +inline void SchemaInfo::addFailedRedefine(const DOMElement* const anElem) { + + if (!fFailedRedefineList) { + fFailedRedefineList = new (fMemoryManager) ValueVectorOf(4, fMemoryManager); + } + + fFailedRedefineList->addElement(anElem); +} + +inline void SchemaInfo::addRecursingType(const DOMElement* const elem, + const XMLCh* const name) { + + if (!fRecursingAnonTypes) { + fRecursingAnonTypes = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + fRecursingTypeNames = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + } + + fRecursingAnonTypes->addElement(elem); + fRecursingTypeNames->addElement(name); +} + +inline void SchemaInfo::clearTopLevelComponents() { + + for (unsigned int i = 0; i < C_Count; i++) { + + delete fTopLevelComponents[i]; + fTopLevelComponents[i] = 0; + fLastTopLevelComponent[i] = 0; + } +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file SchemaInfo.hpp + */ diff --git a/include/xercesc/validators/schema/SchemaSymbols.cpp b/include/xercesc/validators/schema/SchemaSymbols.cpp new file mode 100644 index 0000000..3294c90 --- /dev/null +++ b/include/xercesc/validators/schema/SchemaSymbols.cpp @@ -0,0 +1,1022 @@ +/* + * 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: SchemaSymbols.cpp 802804 2009-08-10 14:21:48Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaSymbols: Static data +// --------------------------------------------------------------------------- +const XMLCh SchemaSymbols::fgURI_XSI[] = +{ + chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, + chForwardSlash, chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, + chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, + chLatin_X, chLatin_M, chLatin_L, chLatin_S, + chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chDash, chLatin_i, + chLatin_n, chLatin_s, chLatin_t, chLatin_a, chLatin_n, chLatin_c, + chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgURI_SCHEMAFORSCHEMA[] = +{ + chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, + chForwardSlash, chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, + chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, + chLatin_X, chLatin_M, chLatin_L, chLatin_S, + chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chNull +}; + +// deprecated (typo) +const XMLCh SchemaSymbols::fgXSI_SCHEMALOCACTION[] = +{ + chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, + chLatin_L, chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, + chLatin_o, chLatin_n, chNull +}; + +// deprecated (typo) +const XMLCh SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCACTION[] = +{ + chLatin_n, chLatin_o, chLatin_N, chLatin_a, chLatin_m, chLatin_e, + chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chLatin_S, + chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chLatin_L, + chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, chLatin_o, + chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgXSI_SCHEMALOCATION[] = +{ + chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, + chLatin_L, chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, + chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION[] = +{ + chLatin_n, chLatin_o, chLatin_N, chLatin_a, chLatin_m, chLatin_e, + chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chLatin_S, + chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chLatin_L, + chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, chLatin_o, + chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgXSI_TYPE[] = +{ + chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ALL[] = +{ + chLatin_a, chLatin_l, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ANNOTATION[] = +{ + chLatin_a, chLatin_n, chLatin_n, chLatin_o, chLatin_t, chLatin_a, + chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ANY[] = +{ + chLatin_a, chLatin_n, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgELT_WILDCARD[] = +{ + chLatin_a, chLatin_n, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ANYATTRIBUTE[] = +{ + chLatin_a, chLatin_n, chLatin_y, chLatin_A, chLatin_t, chLatin_t, + chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_APPINFO[] = +{ + chLatin_a, chLatin_p, chLatin_p, chLatin_i, chLatin_n, chLatin_f, chLatin_o, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ATTRIBUTE[] = +{ + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, + chLatin_u, chLatin_t, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ATTRIBUTEGROUP[] = +{ + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, + chLatin_u, chLatin_t, chLatin_e, chLatin_G, chLatin_r, chLatin_o, + chLatin_u, chLatin_p, chNull +}; + +const XMLCh SchemaSymbols::fgELT_CHOICE[] = +{ + chLatin_c, chLatin_h, chLatin_o, chLatin_i, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_COMPLEXTYPE[] = +{ + chLatin_c, chLatin_o, chLatin_m, chLatin_p, chLatin_l, chLatin_e, + chLatin_x, chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_CONTENT[] = +{ + chLatin_c, chLatin_o, chLatin_n, chLatin_t, chLatin_e, chLatin_n, + chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgELT_DOCUMENTATION[] = +{ + chLatin_d, chLatin_o, chLatin_c, chLatin_u, chLatin_m, chLatin_e, chLatin_n, + chLatin_t, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_DURATION[] = +{ + chLatin_d, chLatin_u, chLatin_r, chLatin_a, chLatin_t, chLatin_i, + chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ELEMENT[] = +{ + chLatin_e, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, + chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ENCODING[] = +{ + chLatin_e, chLatin_n, chLatin_c, chLatin_o, chLatin_d, chLatin_i, + chLatin_n, chLatin_g, chNull +}; + +const XMLCh SchemaSymbols::fgELT_ENUMERATION[] = +{ + chLatin_e, chLatin_n, chLatin_u, chLatin_m, chLatin_e, chLatin_r, + chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_FIELD[] = +{ + chLatin_f, chLatin_i, chLatin_e, chLatin_l, chLatin_d, chNull +}; + + +const XMLCh SchemaSymbols::fgELT_WHITESPACE[] = +{ + chLatin_w, chLatin_h, chLatin_i, chLatin_t, chLatin_e, chLatin_S, + chLatin_p, chLatin_a, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_GROUP[] = +{ + chLatin_g, chLatin_r, chLatin_o, chLatin_u, chLatin_p, chNull +}; + +const XMLCh SchemaSymbols::fgELT_IMPORT[] = +{ + chLatin_i, chLatin_m, chLatin_p, chLatin_o, chLatin_r, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgELT_INCLUDE[] = +{ + chLatin_i, chLatin_n, chLatin_c, chLatin_l, chLatin_u, chLatin_d, + chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_REDEFINE[] = +{ + chLatin_r, chLatin_e, chLatin_d, chLatin_e, chLatin_f, chLatin_i, + chLatin_n, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_KEY[] = +{ + chLatin_k, chLatin_e, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgELT_KEYREF[] = +{ + chLatin_k, chLatin_e, chLatin_y, chLatin_r, chLatin_e, chLatin_f, chNull +}; + +const XMLCh SchemaSymbols::fgELT_LENGTH[] = +{ + chLatin_l, chLatin_e, chLatin_n, chLatin_g, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgELT_MAXEXCLUSIVE[] = +{ + chLatin_m, chLatin_a, chLatin_x, chLatin_E, chLatin_x, chLatin_c, + chLatin_l, chLatin_u, chLatin_s, chLatin_i, chLatin_v, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_MAXINCLUSIVE[] = +{ + chLatin_m, chLatin_a, chLatin_x, chLatin_I, chLatin_n, chLatin_c, + chLatin_l, chLatin_u, chLatin_s, chLatin_i, chLatin_v, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_MAXLENGTH[] = +{ + chLatin_m, chLatin_a, chLatin_x, chLatin_L, chLatin_e, chLatin_n, + chLatin_g, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgELT_MINEXCLUSIVE[] = +{ + chLatin_m, chLatin_i, chLatin_n, chLatin_E, chLatin_x, chLatin_c, + chLatin_l, chLatin_u, chLatin_s, chLatin_i, chLatin_v, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_MININCLUSIVE[] = +{ + chLatin_m, chLatin_i, chLatin_n, chLatin_I, chLatin_n, chLatin_c, + chLatin_l, chLatin_u, chLatin_s, chLatin_i, chLatin_v, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_MINLENGTH[] = +{ + chLatin_m, chLatin_i, chLatin_n, chLatin_L, chLatin_e, chLatin_n, + chLatin_g, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgELT_NOTATION[] = +{ + chLatin_n, chLatin_o, chLatin_t, chLatin_a, chLatin_t, chLatin_i, + chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_PATTERN[] = +{ + chLatin_p, chLatin_a, chLatin_t, chLatin_t, chLatin_e, chLatin_r, + chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_PERIOD[] = +{ + chLatin_p, chLatin_e, chLatin_r, chLatin_i, chLatin_o, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgELT_TOTALDIGITS[] = +{ + chLatin_t, chLatin_o, chLatin_t, chLatin_a, chLatin_l, chLatin_D, + chLatin_i, chLatin_g, chLatin_i, chLatin_t, chLatin_s, chNull +}; + +const XMLCh SchemaSymbols::fgELT_FRACTIONDIGITS[] = +{ + chLatin_f, chLatin_r, chLatin_a, chLatin_c, chLatin_t, chLatin_i, chLatin_o, + chLatin_n, chLatin_D, chLatin_i, chLatin_g, chLatin_i, chLatin_t, chLatin_s, chNull +}; + +const XMLCh SchemaSymbols::fgELT_SCHEMA[] = +{ + chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chNull +}; + +const XMLCh SchemaSymbols::fgELT_SELECTOR[] = +{ + chLatin_s, chLatin_e, chLatin_l, chLatin_e, chLatin_c, chLatin_t, + chLatin_o, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgELT_SEQUENCE[] = +{ + chLatin_s, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_n, + chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_SIMPLETYPE[] = +{ + chLatin_s, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, + chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_UNION[] = +{ + chLatin_u, chLatin_n, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_LIST[] = +{ + chLatin_l, chLatin_i, chLatin_s, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgELT_UNIQUE[] = +{ + chLatin_u, chLatin_n, chLatin_i, chLatin_q, chLatin_u, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgELT_COMPLEXCONTENT[] = +{ + chLatin_c, chLatin_o, chLatin_m, chLatin_p, chLatin_l, chLatin_e, + chLatin_x, chLatin_C, chLatin_o, chLatin_n, chLatin_t, chLatin_e, + chLatin_n, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgELT_SIMPLECONTENT[] = +{ + chLatin_s, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chLatin_C, + chLatin_o, chLatin_n, chLatin_t, chLatin_e, chLatin_n, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgELT_RESTRICTION[] = +{ + chLatin_r, chLatin_e, chLatin_s, chLatin_t, chLatin_r, chLatin_i, + chLatin_c, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgELT_EXTENSION[] = +{ + chLatin_e, chLatin_x, chLatin_t, chLatin_e, chLatin_n, chLatin_s, + chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATT_ABSTRACT[] = +{ + chLatin_a, chLatin_b, chLatin_s, chLatin_t, chLatin_r, chLatin_a, + chLatin_c, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT[] = +{ + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, + chLatin_u, chLatin_t, chLatin_e, chLatin_F, chLatin_o, chLatin_r, + chLatin_m, chLatin_D, chLatin_e, chLatin_f, chLatin_a, chLatin_u, + chLatin_l, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATT_BASE[] = +{ + chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_ITEMTYPE[] = +{ + chLatin_i, chLatin_t, chLatin_e, chLatin_m, chLatin_T, chLatin_y, + chLatin_p, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_MEMBERTYPES[] = +{ + chLatin_m, chLatin_e, chLatin_m, chLatin_b, chLatin_e, chLatin_r, + chLatin_T, chLatin_y, chLatin_p, chLatin_e, chLatin_s, chNull +}; + +const XMLCh SchemaSymbols::fgATT_BLOCK[] = +{ + chLatin_b, chLatin_l, chLatin_o, chLatin_c, chLatin_k, chNull +}; + +const XMLCh SchemaSymbols::fgATT_BLOCKDEFAULT[] = +{ + chLatin_b, chLatin_l, chLatin_o, chLatin_c, chLatin_k, chLatin_D, + chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATT_DEFAULT[] = +{ + chLatin_d, chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATT_ELEMENTFORMDEFAULT[] = +{ + chLatin_e, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, + chLatin_t, chLatin_F, chLatin_o, chLatin_r, chLatin_m, chLatin_D, + chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATT_SUBSTITUTIONGROUP[] = +{ + chLatin_s, chLatin_u, chLatin_b, chLatin_s, chLatin_t, chLatin_i, + chLatin_t, chLatin_u, chLatin_t, chLatin_i, chLatin_o, chLatin_n, + chLatin_G, chLatin_r, chLatin_o, chLatin_u, chLatin_p, chNull +}; + +const XMLCh SchemaSymbols::fgATT_FINAL[] = +{ + chLatin_f, chLatin_i, chLatin_n, chLatin_a, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgATT_FINALDEFAULT[] = +{ + chLatin_f, chLatin_i, chLatin_n, chLatin_a, chLatin_l, chLatin_D, + chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATT_FIXED[] = +{ + chLatin_f, chLatin_i, chLatin_x, chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATT_FORM[] = +{ + chLatin_f, chLatin_o, chLatin_r, chLatin_m, chNull +}; + +const XMLCh SchemaSymbols::fgATT_ID[] = +{ + chLatin_i, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATT_MAXOCCURS[] = +{ + chLatin_m, chLatin_a, chLatin_x, chLatin_O, chLatin_c, chLatin_c, + chLatin_u, chLatin_r, chLatin_s, chNull +}; + +const XMLCh SchemaSymbols::fgATT_MINOCCURS[] = +{ + chLatin_m, chLatin_i, chLatin_n, chLatin_O, chLatin_c, chLatin_c, + chLatin_u, chLatin_r, chLatin_s, chNull +}; + +const XMLCh SchemaSymbols::fgATT_NAME[] = +{ + chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_NAMESPACE[] = +{ + chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, + chLatin_a, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_NILL[] = +{ + chLatin_n, chLatin_i, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgATT_NILLABLE[] = +{ + chLatin_n, chLatin_i, chLatin_l, chLatin_l, chLatin_a, chLatin_b, + chLatin_l, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_PROCESSCONTENTS[] = +{ + chLatin_p, chLatin_r, chLatin_o, chLatin_c, chLatin_e, chLatin_s, + chLatin_s, chLatin_C, chLatin_o, chLatin_n, chLatin_t, chLatin_e, + chLatin_n, chLatin_t, chLatin_s, chNull +}; + +const XMLCh SchemaSymbols::fgATT_REF[] = +{ + chLatin_r, chLatin_e, chLatin_f, chNull +}; + +const XMLCh SchemaSymbols::fgATT_REFER[] = +{ + chLatin_r, chLatin_e, chLatin_f, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgATT_SCHEMALOCATION[] = +{ + chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, + chLatin_L, chLatin_o, chLatin_c, chLatin_a, chLatin_t, chLatin_i, + chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATT_SOURCE[] = +{ + chLatin_s, chLatin_o, chLatin_u, chLatin_r, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_SYSTEM[] = +{ + chLatin_s, chLatin_y, chLatin_s, chLatin_t, chLatin_e, chLatin_m, chNull +}; + +const XMLCh SchemaSymbols::fgATT_PUBLIC[] = +{ + chLatin_p, chLatin_u, chLatin_b, chLatin_l, chLatin_i, chLatin_c, chNull +}; + +const XMLCh SchemaSymbols::fgATT_TARGETNAMESPACE[] = +{ + chLatin_t, chLatin_a, chLatin_r, chLatin_g, chLatin_e, chLatin_t, + chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, + chLatin_a, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_TYPE[] = +{ + chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_USE[] = +{ + chLatin_u, chLatin_s, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_VALUE[] = +{ + chLatin_v, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATT_MIXED[] = +{ + chLatin_m, chLatin_i, chLatin_x, chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATT_VERSION[] = +{ + chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_i, + chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATT_XPATH[] = +{ + chLatin_x, chLatin_p, chLatin_a, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TWOPOUNDANY[] = +{ + chPound, chPound, chLatin_a, chLatin_n, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL[] = +{ + chPound, chPound, chLatin_l, chLatin_o, chLatin_c, chLatin_a, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TWOPOUNDOTHER[] = +{ + chPound, chPound, chLatin_o, chLatin_t, chLatin_h, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE[] = +{ + chPound, chPound, chLatin_t, chLatin_a, chLatin_r, chLatin_g, chLatin_e, + chLatin_t, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, + chLatin_a, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_POUNDALL[] = +{ + chPound, chLatin_a, chLatin_l, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_BASE64[] = +{ + chLatin_b, chLatin_a, chLatin_s, chLatin_e, chDigit_6, chDigit_4, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_BOOLEAN[] = +{ + chLatin_b, chLatin_o, chLatin_o, chLatin_l, chLatin_e, chLatin_a, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_DEFAULT[] = +{ + chLatin_d, chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_ELEMENTONLY[] = +{ + chLatin_e, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, + chLatin_t, chLatin_O, chLatin_n, chLatin_l, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_EMPTY[] = +{ + chLatin_e, chLatin_m, chLatin_p, chLatin_t, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_EXTENSION[] = +{ + chLatin_e, chLatin_x, chLatin_t, chLatin_e, chLatin_n, chLatin_s, + chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_FALSE[] = +{ + chLatin_f, chLatin_a, chLatin_l, chLatin_s, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_FIXED[] = +{ + chLatin_f, chLatin_i, chLatin_x, chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_HEX[] = +{ + chLatin_h, chLatin_e, chLatin_x, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_ID[] = +{ + chLatin_I, chLatin_D, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_LAX[] = +{ + chLatin_l, chLatin_a, chLatin_x, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_MAXLENGTH[] = +{ + chLatin_m, chLatin_a, chLatin_x, chLatin_L, chLatin_e, chLatin_n, + chLatin_g, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_MINLENGTH[] = +{ + chLatin_m, chLatin_i, chLatin_n, chLatin_L, chLatin_e, chLatin_n, + chLatin_g, chLatin_t, chLatin_h, chNull +}; + + +const XMLCh SchemaSymbols::fgATTVAL_MIXED[] = +{ + chLatin_m, chLatin_i, chLatin_x, chLatin_e, chLatin_d, chNull +}; + + +const XMLCh SchemaSymbols::fgATTVAL_NCNAME[] = +{ + chLatin_N, chLatin_C, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_OPTIONAL[] = +{ + chLatin_o, chLatin_p, chLatin_t, chLatin_i, chLatin_o, chLatin_n, + chLatin_a, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_PROHIBITED[] = +{ + chLatin_p, chLatin_r, chLatin_o, chLatin_h, chLatin_i, chLatin_b, + chLatin_i, chLatin_t, chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_QNAME[] = +{ + chLatin_Q, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_QUALIFIED[] = +{ + chLatin_q, chLatin_u, chLatin_a, chLatin_l, chLatin_i, chLatin_f, + chLatin_i, chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_REQUIRED[] = +{ + chLatin_r, chLatin_e, chLatin_q, chLatin_u, chLatin_i, chLatin_r, + chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_RESTRICTION[] = +{ + chLatin_r, chLatin_e, chLatin_s, chLatin_t, chLatin_r, chLatin_i, + chLatin_c, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_SKIP[] = +{ + chLatin_s, chLatin_k, chLatin_i, chLatin_p, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_STRICT[] = +{ + chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_STRING[] = +{ + chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_n, chLatin_g, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TEXTONLY[] = +{ + chLatin_t, chLatin_e, chLatin_x, chLatin_t, chLatin_O, chLatin_n, + chLatin_l, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TIMEDURATION[] = +{ + chLatin_t, chLatin_i, chLatin_m, chLatin_e, chLatin_D, chLatin_u, + chLatin_r, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_TRUE[] = +{ + chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_UNQUALIFIED[] = +{ + chLatin_u, chLatin_n, chLatin_q, chLatin_u, chLatin_a, chLatin_l, + chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_d, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_URI[] = +{ + chLatin_u, chLatin_r, chLatin_i, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_URIREFERENCE[] = +{ + chLatin_u, chLatin_r, chLatin_i, chLatin_R, chLatin_e, chLatin_f, + chLatin_e, chLatin_r, chLatin_e, chLatin_n, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_SUBSTITUTIONGROUP[] = +{ + chLatin_s, chLatin_u, chLatin_b, chLatin_s, chLatin_t, chLatin_i, + chLatin_t, chLatin_u, chLatin_t, chLatin_i, chLatin_o, chLatin_n, + chLatin_G, chLatin_r, chLatin_o, chLatin_u, chLatin_p, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_SUBSTITUTION[] = +{ + chLatin_s, chLatin_u, chLatin_b, chLatin_s, chLatin_t, chLatin_i, + chLatin_t, chLatin_u, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgATTVAL_ANYTYPE[] = +{ + chLatin_a, chLatin_n, chLatin_y, chLatin_T, chLatin_y, chLatin_p, + chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgWS_PRESERVE[] = +{ + chLatin_p, chLatin_r, chLatin_e, chLatin_s, chLatin_e, chLatin_r, + chLatin_v, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgWS_COLLAPSE[] = +{ + chLatin_c, chLatin_o, chLatin_l, chLatin_l, chLatin_a, chLatin_p, + chLatin_s, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgWS_REPLACE[] = +{ + chLatin_r, chLatin_e, chLatin_p, chLatin_l, chLatin_a, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_STRING[] = +{ + chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_n, chLatin_g, chNull +}; + +const XMLCh SchemaSymbols::fgDT_TOKEN[] = +{ + chLatin_t, chLatin_o, chLatin_k, chLatin_e, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgDT_LANGUAGE[] = +{ + chLatin_l, chLatin_a, chLatin_n, chLatin_g, chLatin_u, chLatin_a, + chLatin_g, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_NAME[] = +{ + chLatin_N, chLatin_a, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_NCNAME[] = +{ + chLatin_N, chLatin_C, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_INTEGER[] = +{ + chLatin_i, chLatin_n, chLatin_t, chLatin_e, chLatin_g, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgDT_DECIMAL[] = +{ + chLatin_d, chLatin_e, chLatin_c, chLatin_i, chLatin_m, chLatin_a, chLatin_l, chNull +}; + +const XMLCh SchemaSymbols::fgDT_BOOLEAN[] = +{ + chLatin_b, chLatin_o, chLatin_o, chLatin_l, chLatin_e, chLatin_a, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgDT_NONPOSITIVEINTEGER[] = +{ + chLatin_n, chLatin_o, chLatin_n, chLatin_P, chLatin_o, chLatin_s, + chLatin_i, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chLatin_I, + chLatin_n, chLatin_t, chLatin_e, chLatin_g, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgDT_NEGATIVEINTEGER[] = +{ + chLatin_n, chLatin_e, chLatin_g, chLatin_a, chLatin_t, chLatin_i, + chLatin_v, chLatin_e, chLatin_I, chLatin_n, chLatin_t, chLatin_e, + chLatin_g, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgDT_LONG[] = +{ + chLatin_l, chLatin_o, chLatin_n, chLatin_g, chNull +}; + +const XMLCh SchemaSymbols::fgDT_INT[] = +{ + chLatin_i, chLatin_n, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgDT_SHORT[] = +{ + chLatin_s, chLatin_h, chLatin_o, chLatin_r, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgDT_BYTE[] = +{ + chLatin_b, chLatin_y, chLatin_t, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_NONNEGATIVEINTEGER[] = +{ + chLatin_n, chLatin_o, chLatin_n, chLatin_N, chLatin_e, chLatin_g, + chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chLatin_I, + chLatin_n, chLatin_t, chLatin_e, chLatin_g, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgDT_ULONG[] = +{ + chLatin_u, chLatin_n, chLatin_s, chLatin_i, chLatin_g, chLatin_n, + chLatin_e, chLatin_d, chLatin_L, chLatin_o, chLatin_n, chLatin_g, chNull +}; + +const XMLCh SchemaSymbols::fgDT_UINT[] = +{ + chLatin_u, chLatin_n, chLatin_s, chLatin_i, chLatin_g, chLatin_n, + chLatin_e, chLatin_d, chLatin_I, chLatin_n, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgDT_USHORT[] = +{ + chLatin_u, chLatin_n, chLatin_s, chLatin_i, chLatin_g, chLatin_n, chLatin_e, + chLatin_d, chLatin_S, chLatin_h, chLatin_o, chLatin_r, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgDT_UBYTE[] = +{ + chLatin_u, chLatin_n, chLatin_s, chLatin_i, chLatin_g, chLatin_n, + chLatin_e, chLatin_d, chLatin_B, chLatin_y, chLatin_t, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_POSITIVEINTEGER[] = +{ + chLatin_p, chLatin_o, chLatin_s, chLatin_i, chLatin_t, chLatin_i, + chLatin_v, chLatin_e, chLatin_I, chLatin_n, chLatin_t, chLatin_e, + chLatin_g, chLatin_e, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgDT_DATETIME[] = +{ + chLatin_d, chLatin_a, chLatin_t, chLatin_e, + chLatin_T, chLatin_i, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_DATE[] = +{ + chLatin_d, chLatin_a, chLatin_t, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_TIME[] = +{ + chLatin_t, chLatin_i, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_DURATION[] = +{ + chLatin_d, chLatin_u, chLatin_r, chLatin_a, + chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh SchemaSymbols::fgDT_DAY[] = +{ + chLatin_g, chLatin_D, chLatin_a, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgDT_MONTH[] = +{ + chLatin_g, chLatin_M, chLatin_o, chLatin_n, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgDT_MONTHDAY[] = +{ + chLatin_g, chLatin_M, chLatin_o, chLatin_n, chLatin_t, chLatin_h, + chLatin_D, chLatin_a, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgDT_YEAR[] = +{ + chLatin_g, chLatin_Y, chLatin_e, chLatin_a, chLatin_r, chNull +}; + +const XMLCh SchemaSymbols::fgDT_YEARMONTH[] = +{ + chLatin_g, chLatin_Y, chLatin_e, chLatin_a, chLatin_r, + chLatin_M, chLatin_o, chLatin_n, chLatin_t, chLatin_h, chNull +}; + +const XMLCh SchemaSymbols::fgDT_BASE64BINARY[] = +{ + chLatin_b, chLatin_a, chLatin_s, chLatin_e, chDigit_6, chDigit_4, + chLatin_B, chLatin_i, chLatin_n, chLatin_a, chLatin_r, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgDT_HEXBINARY[] = +{ + chLatin_h, chLatin_e, chLatin_x, + chLatin_B, chLatin_i, chLatin_n, chLatin_a, chLatin_r, chLatin_y, chNull +}; + +const XMLCh SchemaSymbols::fgDT_FLOAT[] = +{ + chLatin_f, chLatin_l, chLatin_o, chLatin_a, chLatin_t, chNull +}; + +const XMLCh SchemaSymbols::fgDT_DOUBLE[] = +{ + chLatin_d, chLatin_o, chLatin_u, chLatin_b, chLatin_l, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_URIREFERENCE[] = +{ + chLatin_u, chLatin_r, chLatin_i, chLatin_R, chLatin_e, chLatin_f, + chLatin_e, chLatin_r, chLatin_e, chLatin_n, chLatin_c, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_ANYURI[] = +{ + chLatin_a, chLatin_n, chLatin_y, chLatin_U, chLatin_R, chLatin_I, chNull +}; + +const XMLCh SchemaSymbols::fgDT_QNAME[] = +{ + chLatin_Q, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgDT_NORMALIZEDSTRING[] = +{ + chLatin_n, chLatin_o, chLatin_r, chLatin_m, chLatin_a, chLatin_l, chLatin_i, + chLatin_z, chLatin_e, chLatin_d, chLatin_S, chLatin_t, chLatin_r, chLatin_i, + chLatin_n, chLatin_g, chNull +}; + +const XMLCh SchemaSymbols::fgDT_ANYSIMPLETYPE[] = +{ + chLatin_a, chLatin_n, chLatin_y, chLatin_S, chLatin_i, chLatin_m, chLatin_p, + chLatin_l, chLatin_e, chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull +}; + +const XMLCh SchemaSymbols::fgRegEx_XOption[] = +{ + chLatin_X, chNull +}; + +const XMLCh SchemaSymbols::fgRedefIdentifier[] = +{ + chUnderscore, chLatin_r, chLatin_d, chLatin_f, chLatin_n, chNull +}; + +const int SchemaSymbols::fgINT_MIN_VALUE = 0x80000000; + +const int SchemaSymbols::fgINT_MAX_VALUE = 0x7fffffff; + +XERCES_CPP_NAMESPACE_END + +/** + * End of file SchemaSymbols.cpp + */ + diff --git a/include/xercesc/validators/schema/SchemaSymbols.hpp b/include/xercesc/validators/schema/SchemaSymbols.hpp new file mode 100644 index 0000000..7e51afb --- /dev/null +++ b/include/xercesc/validators/schema/SchemaSymbols.hpp @@ -0,0 +1,254 @@ +/* + * 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: SchemaSymbols.hpp 802804 2009-08-10 14:21:48Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMASYMBOLS_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMASYMBOLS_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/* + * Collection of symbols used to parse a Schema Grammar + */ + +class VALIDATORS_EXPORT SchemaSymbols +{ +public : + // ----------------------------------------------------------------------- + // Constant data + // ----------------------------------------------------------------------- + static const XMLCh fgURI_XSI[]; + static const XMLCh fgURI_SCHEMAFORSCHEMA[]; + // deprecated (typo) + static const XMLCh fgXSI_SCHEMALOCACTION[]; + // deprecated (typo) + static const XMLCh fgXSI_NONAMESPACESCHEMALOCACTION[]; + static const XMLCh fgXSI_SCHEMALOCATION[]; + static const XMLCh fgXSI_NONAMESPACESCHEMALOCATION[]; + static const XMLCh fgXSI_TYPE[]; + static const XMLCh fgELT_ALL[]; + static const XMLCh fgELT_ANNOTATION[]; + static const XMLCh fgELT_ANY[]; + static const XMLCh fgELT_WILDCARD[]; + static const XMLCh fgELT_ANYATTRIBUTE[]; + static const XMLCh fgELT_APPINFO[]; + static const XMLCh fgELT_ATTRIBUTE[]; + static const XMLCh fgELT_ATTRIBUTEGROUP[]; + static const XMLCh fgELT_CHOICE[]; + static const XMLCh fgELT_COMPLEXTYPE[]; + static const XMLCh fgELT_CONTENT[]; + static const XMLCh fgELT_DOCUMENTATION[]; + static const XMLCh fgELT_DURATION[]; + static const XMLCh fgELT_ELEMENT[]; + static const XMLCh fgELT_ENCODING[]; + static const XMLCh fgELT_ENUMERATION[]; + static const XMLCh fgELT_FIELD[]; + static const XMLCh fgELT_WHITESPACE[]; + static const XMLCh fgELT_GROUP[]; + static const XMLCh fgELT_IMPORT[]; + static const XMLCh fgELT_INCLUDE[]; + static const XMLCh fgELT_REDEFINE[]; + static const XMLCh fgELT_KEY[]; + static const XMLCh fgELT_KEYREF[]; + static const XMLCh fgELT_LENGTH[]; + static const XMLCh fgELT_MAXEXCLUSIVE[]; + static const XMLCh fgELT_MAXINCLUSIVE[]; + static const XMLCh fgELT_MAXLENGTH[]; + static const XMLCh fgELT_MINEXCLUSIVE[]; + static const XMLCh fgELT_MININCLUSIVE[]; + static const XMLCh fgELT_MINLENGTH[]; + static const XMLCh fgELT_NOTATION[]; + static const XMLCh fgELT_PATTERN[]; + static const XMLCh fgELT_PERIOD[]; + static const XMLCh fgELT_TOTALDIGITS[]; + static const XMLCh fgELT_FRACTIONDIGITS[]; + static const XMLCh fgELT_SCHEMA[]; + static const XMLCh fgELT_SELECTOR[]; + static const XMLCh fgELT_SEQUENCE[]; + static const XMLCh fgELT_SIMPLETYPE[]; + static const XMLCh fgELT_UNION[]; + static const XMLCh fgELT_LIST[]; + static const XMLCh fgELT_UNIQUE[]; + static const XMLCh fgELT_COMPLEXCONTENT[]; + static const XMLCh fgELT_SIMPLECONTENT[]; + static const XMLCh fgELT_RESTRICTION[]; + static const XMLCh fgELT_EXTENSION[]; + static const XMLCh fgATT_ABSTRACT[]; + static const XMLCh fgATT_ATTRIBUTEFORMDEFAULT[]; + static const XMLCh fgATT_BASE[]; + static const XMLCh fgATT_ITEMTYPE[]; + static const XMLCh fgATT_MEMBERTYPES[]; + static const XMLCh fgATT_BLOCK[]; + static const XMLCh fgATT_BLOCKDEFAULT[]; + static const XMLCh fgATT_DEFAULT[]; + static const XMLCh fgATT_ELEMENTFORMDEFAULT[]; + static const XMLCh fgATT_SUBSTITUTIONGROUP[]; + static const XMLCh fgATT_FINAL[]; + static const XMLCh fgATT_FINALDEFAULT[]; + static const XMLCh fgATT_FIXED[]; + static const XMLCh fgATT_FORM[]; + static const XMLCh fgATT_ID[]; + static const XMLCh fgATT_MAXOCCURS[]; + static const XMLCh fgATT_MINOCCURS[]; + static const XMLCh fgATT_NAME[]; + static const XMLCh fgATT_NAMESPACE[]; + static const XMLCh fgATT_NILL[]; + static const XMLCh fgATT_NILLABLE[]; + static const XMLCh fgATT_PROCESSCONTENTS[]; + static const XMLCh fgATT_REF[]; + static const XMLCh fgATT_REFER[]; + static const XMLCh fgATT_SCHEMALOCATION[]; + static const XMLCh fgATT_SOURCE[]; + static const XMLCh fgATT_SYSTEM[]; + static const XMLCh fgATT_PUBLIC[]; + static const XMLCh fgATT_TARGETNAMESPACE[]; + static const XMLCh fgATT_TYPE[]; + static const XMLCh fgATT_USE[]; + static const XMLCh fgATT_VALUE[]; + static const XMLCh fgATT_MIXED[]; + static const XMLCh fgATT_VERSION[]; + static const XMLCh fgATT_XPATH[]; + static const XMLCh fgATTVAL_TWOPOUNDANY[]; + static const XMLCh fgATTVAL_TWOPOUNDLOCAL[]; + static const XMLCh fgATTVAL_TWOPOUNDOTHER[]; + static const XMLCh fgATTVAL_TWOPOUNDTRAGETNAMESPACE[]; + static const XMLCh fgATTVAL_POUNDALL[]; + static const XMLCh fgATTVAL_BASE64[]; + static const XMLCh fgATTVAL_BOOLEAN[]; + static const XMLCh fgATTVAL_DEFAULT[]; + static const XMLCh fgATTVAL_ELEMENTONLY[]; + static const XMLCh fgATTVAL_EMPTY[]; + static const XMLCh fgATTVAL_EXTENSION[]; + static const XMLCh fgATTVAL_FALSE[]; + static const XMLCh fgATTVAL_FIXED[]; + static const XMLCh fgATTVAL_HEX[]; + static const XMLCh fgATTVAL_ID[]; + static const XMLCh fgATTVAL_LAX[]; + static const XMLCh fgATTVAL_MAXLENGTH[]; + static const XMLCh fgATTVAL_MINLENGTH[]; + static const XMLCh fgATTVAL_MIXED[]; + static const XMLCh fgATTVAL_NCNAME[]; + static const XMLCh fgATTVAL_OPTIONAL[]; + static const XMLCh fgATTVAL_PROHIBITED[]; + static const XMLCh fgATTVAL_QNAME[]; + static const XMLCh fgATTVAL_QUALIFIED[]; + static const XMLCh fgATTVAL_REQUIRED[]; + static const XMLCh fgATTVAL_RESTRICTION[]; + static const XMLCh fgATTVAL_SKIP[]; + static const XMLCh fgATTVAL_STRICT[]; + static const XMLCh fgATTVAL_STRING[]; + static const XMLCh fgATTVAL_TEXTONLY[]; + static const XMLCh fgATTVAL_TIMEDURATION[]; + static const XMLCh fgATTVAL_TRUE[]; + static const XMLCh fgATTVAL_UNQUALIFIED[]; + static const XMLCh fgATTVAL_URI[]; + static const XMLCh fgATTVAL_URIREFERENCE[]; + static const XMLCh fgATTVAL_SUBSTITUTIONGROUP[]; + static const XMLCh fgATTVAL_SUBSTITUTION[]; + static const XMLCh fgATTVAL_ANYTYPE[]; + static const XMLCh fgWS_PRESERVE[]; + static const XMLCh fgWS_COLLAPSE[]; + static const XMLCh fgWS_REPLACE[]; + static const XMLCh fgDT_STRING[]; + static const XMLCh fgDT_TOKEN[]; + static const XMLCh fgDT_LANGUAGE[]; + static const XMLCh fgDT_NAME[]; + static const XMLCh fgDT_NCNAME[]; + static const XMLCh fgDT_INTEGER[]; + static const XMLCh fgDT_DECIMAL[]; + static const XMLCh fgDT_BOOLEAN[]; + static const XMLCh fgDT_NONPOSITIVEINTEGER[]; + static const XMLCh fgDT_NEGATIVEINTEGER[]; + static const XMLCh fgDT_LONG[]; + static const XMLCh fgDT_INT[]; + static const XMLCh fgDT_SHORT[]; + static const XMLCh fgDT_BYTE[]; + static const XMLCh fgDT_NONNEGATIVEINTEGER[]; + static const XMLCh fgDT_ULONG[]; + static const XMLCh fgDT_UINT[]; + static const XMLCh fgDT_USHORT[]; + static const XMLCh fgDT_UBYTE[]; + static const XMLCh fgDT_POSITIVEINTEGER[]; +//datetime + static const XMLCh fgDT_DATETIME[]; + static const XMLCh fgDT_DATE[]; + static const XMLCh fgDT_TIME[]; + static const XMLCh fgDT_DURATION[]; + static const XMLCh fgDT_DAY[]; + static const XMLCh fgDT_MONTH[]; + static const XMLCh fgDT_MONTHDAY[]; + static const XMLCh fgDT_YEAR[]; + static const XMLCh fgDT_YEARMONTH[]; + + static const XMLCh fgDT_BASE64BINARY[]; + static const XMLCh fgDT_HEXBINARY[]; + static const XMLCh fgDT_FLOAT[]; + static const XMLCh fgDT_DOUBLE[]; + static const XMLCh fgDT_URIREFERENCE[]; + static const XMLCh fgDT_ANYURI[]; + static const XMLCh fgDT_QNAME[]; + static const XMLCh fgDT_NORMALIZEDSTRING[]; + static const XMLCh fgDT_ANYSIMPLETYPE[]; + static const XMLCh fgRegEx_XOption[]; + static const XMLCh fgRedefIdentifier[]; + static const int fgINT_MIN_VALUE; + static const int fgINT_MAX_VALUE; + + enum { + XSD_EMPTYSET = 0, + XSD_SUBSTITUTION = 1, + XSD_EXTENSION = 2, + XSD_RESTRICTION = 4, + XSD_LIST = 8, + XSD_UNION = 16, + XSD_ENUMERATION = 32 + }; + + // group orders + enum { + XSD_CHOICE = 0, + XSD_SEQUENCE= 1, + XSD_ALL = 2 + }; + + enum { + XSD_UNBOUNDED = -1, + XSD_NILLABLE = 1, + XSD_ABSTRACT = 2, + XSD_FIXED = 4 + }; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaSymbols(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file SchemaSymbols.hpp + */ + diff --git a/include/xercesc/validators/schema/SchemaValidator.cpp b/include/xercesc/validators/schema/SchemaValidator.cpp new file mode 100644 index 0000000..95480e5 --- /dev/null +++ b/include/xercesc/validators/schema/SchemaValidator.cpp @@ -0,0 +1,2094 @@ +/* + * 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: SchemaValidator.cpp 806488 2009-08-21 10:36:58Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaValidator: Constructors and Destructor +// --------------------------------------------------------------------------- +SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter + , MemoryManager* const manager) : + + XMLValidator(errReporter) + , fMemoryManager(manager) + , fSchemaGrammar(0) + , fGrammarResolver(0) + , fXsiType(0) + , fNil(false) + , fNilFound(false) + , fCurrentDatatypeValidator(0) + , fNotationBuf(0) + , fDatatypeBuffer(1023, manager) + , fTrailing(false) + , fSeenNonWhiteSpace(false) + , fSeenId(false) + , fTypeStack(0) + , fMostRecentAttrValidator(0) + , fErrorOccurred(false) + , fElemIsSpecified(false) +{ + fTypeStack = new (fMemoryManager) ValueStackOf(8, fMemoryManager); +} + +SchemaValidator::~SchemaValidator() +{ + delete fXsiType; + delete fTypeStack; + + if (fNotationBuf) + delete fNotationBuf; +} + +// --------------------------------------------------------------------------- +// SchemaValidator: Implementation of the XMLValidator interface +// --------------------------------------------------------------------------- +bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl + , QName** const children + , XMLSize_t childCount + , XMLSize_t* indexFailingChild) +{ + fErrorOccurred = false; + fElemIsSpecified = false; + + // + // Look up the element id in our element decl pool. This will get us + // the element decl in our own way of looking at them. + // + if (!elemDecl) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager); + + // + // Get the content spec type of this element. This will tell us what + // to do to validate it. + // + // the top of the type stack always knows best... + ComplexTypeInfo* currType = fTypeStack->pop(); + + const SchemaElementDecl::ModelTypes modelType = (currType) + ? (SchemaElementDecl::ModelTypes)(currType->getContentType()) + : ((SchemaElementDecl*)elemDecl)->getModelType(); + + if (modelType == SchemaElementDecl::Empty || + modelType == SchemaElementDecl::ElementOnlyEmpty) + { + // + // We can do this one here. It cannot have any children. If it does + // we return 0 as the index of the first bad child. + // + if (childCount) { + fErrorOccurred = true; + *indexFailingChild=0; + return false; + } + } + else if ((modelType == SchemaElementDecl::Mixed_Simple) + || (modelType == SchemaElementDecl::Mixed_Complex) + || (modelType == SchemaElementDecl::Children)) + { + // if nillable, it's an error to have value + // XML Schema REC: Validation Rule: Element Locally Valid (Element) + // 3.2.1 The element information item must have no + // character or element information item [children]. + // + if (fNil) { + if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) { + emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName()); + fErrorOccurred = true; + } + } + else { + // Get the element's content model or fault it in + XMLContentModel* elemCM = (currType) + ? currType->getContentModel() + : ((SchemaElementDecl*)elemDecl)->getContentModel(); + + // Ask it to validate and return its return + unsigned int emptyNS = getScanner()->getEmptyNamespaceId(); + bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager()); + if (!result) { + result = elemCM->validateContentSpecial(children + , childCount + , emptyNS + , fGrammarResolver + , fGrammarResolver->getStringPool() + , indexFailingChild + , getScanner()->getMemoryManager()); + } + + if(!result) { + fErrorOccurred = true; + } + + return result; + } + } + else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any) + { + // Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes + // but if there is a fXsiTypeValidator, we need to use it for validation + if (modelType == SchemaElementDecl::Simple && childCount > 0) { + emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName()); + fErrorOccurred = true; + } + else + { + XMLCh* value = fDatatypeBuffer.getRawBuffer(); + XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue(); + + if (fNil) + { + if ((!XMLString::equals(value, XMLUni::fgZeroLenString)) + || elemDefaultValue) + { + emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName()); + fErrorOccurred = true; + } + } + else if (fCurrentDatatypeValidator) + { + DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType(); + bool validateCanonical = false; + if (eleDefDVType == DatatypeValidator::NOTATION) + { + // if notation, need to bind URI to notation first + if (!fNotationBuf) + fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager); + + // Make sure that this value maps to one of the + // notation values in the enumList parameter. We don't have to + // look it up in the notation pool (if a notation) because we + // will look up the enumerated values themselves. If they are in + // the notation pool (after the Grammar is parsed), then obviously + // this value will be legal since it matches one of them. + int colonPos = -1; + unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos); + + const XMLCh* uriText = getScanner()->getURIText(uriId); + if (uriText && *uriText) { + fNotationBuf->set(uriText); + fNotationBuf->append(chColon); + fNotationBuf->append(&value[colonPos + 1]); + value = fNotationBuf->getRawBuffer(); + } + } + + if (elemDefaultValue) + { + if (XMLString::equals(value, XMLUni::fgZeroLenString)) + { + fElemIsSpecified = true; + // if this element didn't specified any value + // use default value + if (getScanner()->getDocHandler()) + getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false); + + // Normally for default value, it has been validated already during TraverseSchema + // But if there was a xsi:type and this validator is fXsiTypeValidator, + // need to validate again + // we determine this if the current content dataype validator + // is neither the one in the element nor the one in the current + // complex type (if any) + if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator()) + && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) { + value = elemDefaultValue; + validateCanonical = true; + } + else + value = 0; + } + else + { + // this element has specified some value + // if the flag is FIXED, then this value must be same as default value + if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0) + { + if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 ) + { + emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName()); + fErrorOccurred = true; + } + } + } + } + + if ((!fErrorOccurred) && value) + { + try { + fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager); + if (validateCanonical) { + XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager); + ArrayJanitor tempCanonical(canonical, fMemoryManager); + fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager); + } + } + catch (XMLException& idve) + { + emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); + fErrorOccurred = true; + } + catch(const OutOfMemoryException&) { + throw; + } + catch (...) + { + emitError(XMLValid::GenericError); + throw; + } + } + } + else if (modelType == SchemaElementDecl::Simple) + { + emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName()); + fErrorOccurred = true; + } + // modelType is any + else if (elemDefaultValue) + { + if (XMLString::equals(value, XMLUni::fgZeroLenString)) + { + fElemIsSpecified = true; + // if this element didn't specified any value + // use default value + if (getScanner()->getDocHandler()) { + getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false); + } + } + } + } + } + else + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager); + } + + // must rely on scanner to clear fDatatypeBuffer + // since it may need to query its contents after this method completes + fNil = false; + fNilFound = false; + fTrailing=false; + fSeenNonWhiteSpace = false; + fCurrentDatatypeValidator = 0; + + // Went ok, so return success + return true; +} + +void SchemaValidator::faultInAttr (XMLAttr& toFill, const XMLAttDef& attDef) const +{ + // + // At this level, we cannot set the URI id. So we just set it to zero + // and leave it at that. The scanner, who called us, will look at the + // prefix we stored (if any), resolve it, and store the URL id if any. + // + SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef; + QName* attName = schemaAttDef->getAttName(); + + toFill.set + ( + attName->getURI() + , attName->getLocalPart() + , attName->getPrefix() + , schemaAttDef->getValue() + , schemaAttDef->getType() + ); +} + +void SchemaValidator::reset() +{ + fTrailing = false; + fSeenNonWhiteSpace = false; + fSeenId = false; + fTypeStack->removeAllElements(); + delete fXsiType; + fXsiType = 0; + fCurrentDatatypeValidator = 0; + fNil = false; + fNilFound = false; + fDatatypeBuffer.reset(); + fErrorOccurred = false; +} + +bool SchemaValidator::requiresNamespaces() const +{ + return true; +} + +void SchemaValidator::validateAttrValue (const XMLAttDef* attDef + , const XMLCh* const attrValue + , bool preValidation + , const XMLElementDecl* elemDecl) +{ + fErrorOccurred = false; + + //turn on IdRefList checking + getScanner()->getValidationContext()->toCheckIdRefList(true); + + // + // Get quick refs to lot of the stuff in the passed objects in + // order to simplify the code below, which will reference them very + // often. + // + XMLAttDef::AttTypes type = attDef->getType(); + const XMLAttDef::DefAttTypes defType = attDef->getDefaultType(); + + // + // If the default type is fixed, then make sure the passed value maps + // to the fixed value. + // + // If during preContentValidation, the value we are validating is the fixed value itself + // so no need to compare. + // Only need to do this for regular attribute value validation + // + if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation) + { + const XMLCh* const valueText = attDef->getValue(); + if (!XMLString::equals(attrValue, valueText)) { + emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText); + fErrorOccurred = true; + } + } + + // An empty string cannot be valid for non_CDATA any of the other types + if (!attrValue[0] && type != XMLAttDef::Simple) + { + emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName()); + // accords with original DOMTypeInfo implementation, but this does not feel right. + fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + fErrorOccurred = true; + return; + } + + DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator(); + if (!attDefDV) { + emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName()); + fErrorOccurred = true; + } + else { + DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType(); + ValidationContext *context = getScanner()->getValidationContext(); + try { + + // first, if notation, need to bind URI to notation first + if (attDefDVType == DatatypeValidator::NOTATION) + { + // + // Make sure that this value maps to one of the + // notation values in the enumList parameter. We don't have to + // look it up in the notation pool (if a notation) because we + // will look up the enumerated values themselves. If they are in + // the notation pool (after the Grammar is parsed), then obviously + // this value will be legal since it matches one of them. + // + XMLBuffer notationBuf(1023, fMemoryManager); + int colonPos = -1; + unsigned int uriId = getScanner()->resolveQName(attrValue, notationBuf, ElemStack::Mode_Element, colonPos); + const XMLCh* uriText = getScanner()->getURIText(uriId); + if (uriText && *uriText) { + notationBuf.set(uriText); + notationBuf.append(chColon); + notationBuf.append(&attrValue[colonPos + 1]); + } + else { + notationBuf.set(attrValue); + } + + attDefDV->validate(notationBuf.getRawBuffer() + , context + , fMemoryManager); + } + else { + attDefDV->validate(attrValue + , context + , fMemoryManager); + } + + } + catch (XMLException& idve) { + fErrorOccurred = true; + emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) { + emitError(XMLValid::GenericError); + fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + fErrorOccurred = true; + throw; + } + fMostRecentAttrValidator = attDefDV; + // now we can look for ID's, entities, ... + + // set up the entitydeclpool in ENTITYDatatypeValidator + // and the idreflist in ID/IDREFDatatypeValidator + + // indicate if this attribute is of type ID + bool thisIsAnId = false; + + if (attDefDVType == DatatypeValidator::List) { + DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV(); + DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType(); + if (itemDTVType == DatatypeValidator::ID) { + thisIsAnId = true; + } + else if (itemDTVType == DatatypeValidator::IDREF) { + // if in prevalidatoin, do not add attDef to IDREFList + if (preValidation) + //todo: when to setIdRefList back to non-null + getScanner()->getValidationContext()->toCheckIdRefList(false); + } + } + else if (attDefDVType == DatatypeValidator::Union) { + DatatypeValidator *memberDTV = context->getValidatingMemberType(); + // actual type for DOMTypeInfo is memberDTV + fMostRecentAttrValidator = memberDTV; + // no member datatype validator if there was an error + if(memberDTV) + { + DatatypeValidator::ValidatorType memberDTVType = memberDTV->getType(); + if (memberDTVType == DatatypeValidator::ID) { + thisIsAnId = true; + } + else if (memberDTVType == DatatypeValidator::IDREF) { + // if in prevalidatoin, do not add attDef to IDREFList + if (preValidation) + getScanner()->getValidationContext()->toCheckIdRefList(false); + } + } + } + else if (attDefDVType == DatatypeValidator::ID) { + thisIsAnId = true; + } + else if (attDefDVType == DatatypeValidator::IDREF) { + // if in prevalidation, do not add attDef to IDREFList + if (preValidation) + getScanner()->getValidationContext()->toCheckIdRefList(false); + } + if (thisIsAnId) { + if (fSeenId) { + emitError + ( + XMLValid::MultipleIdAttrs + , elemDecl->getFullName() + ); + fErrorOccurred = true; + } + else + fSeenId = true; + } + + } + + if(fErrorOccurred) { + fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + fTrailing = false; + fSeenNonWhiteSpace = false; +} + +void SchemaValidator::validateElement(const XMLElementDecl* elemDef) +{ + ComplexTypeInfo* elemTypeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo(); + fTypeStack->push(elemTypeInfo); + fCurrentDatatypeValidator = (elemTypeInfo) + ? elemTypeInfo->getDatatypeValidator() + : ((SchemaElementDecl*)elemDef)->getDatatypeValidator(); + + fErrorOccurred = false; + + if (fXsiType) { + // handle "xsi:type" right here + DatatypeValidator *xsiTypeDV = 0; + unsigned int uri = fXsiType->getURI(); + const XMLCh* localPart = fXsiType->getLocalPart(); + + if (uri != XMLElementDecl::fgInvalidElemId && + uri != XMLElementDecl::fgPCDataElemId && + uri != XMLContentModel::gEpsilonFakeId && + uri != XMLContentModel::gEOCFakeId) { + + // retrieve Grammar for the uri + const XMLCh* uriStr = getScanner()->getURIText(uri); + SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr); + if (!sGrammar) { + + // Check built-in simple types + if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + + xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart); + + if (!xsiTypeDV) { + emitError(XMLValid::BadXsiType, fXsiType->getRawName()); + fErrorOccurred = true; + } + else { + if (elemTypeInfo || (fCurrentDatatypeValidator + && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV))) { + // the type is not derived from ancestor + emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); + fErrorOccurred = true; + } + else if(fCurrentDatatypeValidator != xsiTypeDV) + { + // the type is derived from ancestor + if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) { + emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName()); + fErrorOccurred = true; + } + if (elemDef->hasAttDefs()) { + // if we have an attribute but xsi:type's type is simple, we have a problem... + emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); + fErrorOccurred = true; + } + } + fCurrentDatatypeValidator = xsiTypeDV; + } + } + else { + // Grammar not found + emitError(XMLValid::GrammarNotFound, uriStr); + fErrorOccurred = true; + } + } + else if (sGrammar->getGrammarType() != Grammar::SchemaGrammarType) { + emitError(XMLValid::GrammarNotFound, uriStr); + fErrorOccurred = true; + } + else { + // retrieve complexType registry and DatatypeValidator registry + RefHashTableOf* complexTypeRegistry = sGrammar->getComplexTypeRegistry(); + if (!complexTypeRegistry) { + emitError(XMLValid::BadXsiType, fXsiType->getRawName()); + fErrorOccurred = true; + } + else { + + // retrieve the typeInfo specified in xsi:type + XMLBuffer aBuffer(1023, fMemoryManager); + aBuffer.set(uriStr); + aBuffer.append(chComma); + aBuffer.append(localPart); + ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer()); + + if (typeInfo) { + // typeInfo is found + if (typeInfo->getAbstract()) { + emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer()); + fErrorOccurred = true; + } + else + { + if (elemTypeInfo) + { + ComplexTypeInfo* tempType = typeInfo; + while (tempType) { + if (tempType == elemTypeInfo) + break; + tempType = tempType->getBaseComplexTypeInfo(); + } + + if (!tempType) { + emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); + fErrorOccurred = true; + } + else if(elemTypeInfo != typeInfo) { + // perform the check on the entire inheritance chain + ComplexTypeInfo* tempType = typeInfo; + while (tempType) { + if (tempType == elemTypeInfo) + break; + int derivationMethod = tempType->getDerivedBy(); + if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) { + emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName()); + fErrorOccurred = true; + } + if ((elemTypeInfo->getBlockSet() & derivationMethod) != 0) { + emitError(XMLValid::TypeNoSubforBlock, elemTypeInfo->getTypeName()); + fErrorOccurred = true; + } + tempType = tempType->getBaseComplexTypeInfo(); + } + } + } + else + { + // if the original type is a simple type, check derivation ok. + if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(typeInfo->getDatatypeValidator())) { + // the type is not derived from ancestor + emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); + fErrorOccurred = true; + } + } + + if (!fErrorOccurred) + { + fTypeStack->pop(); + fTypeStack->push(typeInfo); + fCurrentDatatypeValidator = typeInfo->getDatatypeValidator(); + } + } + } + else + { + // typeInfo not found + xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart); + + if (!xsiTypeDV) { + emitError(XMLValid::BadXsiType, fXsiType->getRawName()); + fErrorOccurred = true; + } + else { + if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV)) { + // the type is not derived from ancestor + emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); + fErrorOccurred = true; + } + else if(fCurrentDatatypeValidator != xsiTypeDV) + { + DatatypeValidator::ValidatorType derivedType=xsiTypeDV->getType(); + if((derivedType == DatatypeValidator::List || derivedType == DatatypeValidator::Union) && fCurrentDatatypeValidator==0) + { + // the substitution is always allowed if the type is list or union and the base type was xs:anySimpleType + } + else + { + // the type is derived from ancestor + if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) { + emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName()); + fErrorOccurred = true; + } + if (elemDef->hasAttDefs()) { + // if we have an attribute but xsi:type's type is simple, we have a problem... + emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); + fErrorOccurred = true; + } + } + } + + fCurrentDatatypeValidator = xsiTypeDV; + } + } + } + } + } + + delete fXsiType; + fXsiType = 0; + } + else { + // + // xsi:type was not specified... + // If the corresponding type is abstract, detect an error + // + if (elemTypeInfo && elemTypeInfo->getAbstract()) { + emitError(XMLValid::NoUseAbstractType, elemDef->getFullName()); + fErrorOccurred = true; + } + } + + // + // Check whether this element is abstract. If so, an error + // + int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags(); + if ((miscFlags & SchemaSymbols::XSD_ABSTRACT) != 0) { + emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName()); + fErrorOccurred = true; + } + + // + // Check whether this element allows Nillable + // + if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) { + fNil = false; + fNilFound = false; + emitError(XMLValid::NillNotAllowed, elemDef->getFullName()); + fErrorOccurred = true; + } + + fDatatypeBuffer.reset(); + fTrailing = false; + fSeenNonWhiteSpace = false; + fSeenId = false; +} + +void SchemaValidator::preContentValidation(bool, + bool validateDefAttr) +{ + // Lets go through all the grammar in the GrammarResolver + // and validate those that has not been validated yet + // + // Lets enumerate all of the elements in the element decl pool + // and put out an error for any that did not get declared. + // We also check all of the attributes as well. + // + // And enumerate all the complextype info in the grammar + // and do Unique Particle Attribution Checking + + RefHashTableOfEnumerator grammarEnum = fGrammarResolver->getGrammarEnumerator(); + while (grammarEnum.hasMoreElements()) + { + SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement(); + if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getValidated()) + continue; + + sGrammar.setValidated(true); + + RefHash3KeysIdPoolEnumerator elemEnum = sGrammar.getElemEnumerator(); + + while (elemEnum.hasMoreElements()) + { + SchemaElementDecl& curElem = elemEnum.nextElement(); + + // First check if declared or not + // + // See if this element decl was ever marked as declared. If + // not, then put out an error. In some cases its just + // a warning, such as being referenced in a content model. + // + const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason(); + + if (reason != XMLElementDecl::Declared) + { + if (reason == XMLElementDecl::AttList) + { + getScanner()->emitError + ( + XMLErrs::UndeclaredElemInAttList + , curElem.getFullName() + ); + } + else if (reason == XMLElementDecl::AsRootElem) + { + emitError + ( + XMLValid::UndeclaredElemInDocType + , curElem.getFullName() + ); + } + else if (reason == XMLElementDecl::InContentModel) + { + getScanner()->emitError + ( + XMLErrs::UndeclaredElemInCM + , curElem.getFullName() + ); + } + else + { + } + } + + // + // Then check all of the attributes of the current element. + // We check for: + // + // 1) Multiple ID attributes + // 2) That all of the default values of attributes are + // valid for their type. + // 3) That for any notation types, that their lists + // of possible values refer to declared notations. + // + if (curElem.hasAttDefs()) { + XMLAttDefList& attDefList = curElem.getAttDefList(); + bool seenId = false; + + for(XMLSize_t i=0; i janList(list, fMemoryManager); + + // + // Search forward for a space or a null. If a null, + // we are done. If a space, cap it and look it up. + // + bool breakFlag = false; + XMLCh* listPtr = list; + XMLCh* lastPtr = listPtr; + while (true) + { + while (*listPtr && (*listPtr != chSpace)) + listPtr++; + + // + // If at the end, indicate we need to break after + // this one. Else, cap it off here. + // + if (!*listPtr) + breakFlag = true; + else + *listPtr = chNull; + + if (!sGrammar.getNotationDecl(lastPtr)) + { + emitError + ( + XMLValid::UnknownNotRefAttr + , curAttDef.getFullName() + , lastPtr + ); + } + + // Break out if we hit the end last time + if (breakFlag) + break; + + // Else move upwards and try again + listPtr++; + lastPtr = listPtr; + } + } + + // If it has a default/fixed value, then validate it + if (validateDefAttr && curAttDef.getValue()) + { + validateAttrValue + ( + &curAttDef + , curAttDef.getValue() + , true + , &curElem + ); + } + } + } + } + + // For each complex type info, check the Unique Particle Attribution + if (getScanner()->getValidationSchemaFullChecking()) { + RefHashTableOf* complexTypeRegistry = sGrammar.getComplexTypeRegistry(); + + RefHashTableOfEnumerator complexTypeEnum(complexTypeRegistry, false, fMemoryManager); + while (complexTypeEnum.hasMoreElements()) + { + ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement(); + curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, fGrammarResolver->getStringPool(), this); + checkParticleDerivation(&sGrammar, &curTypeInfo); + checkRefElementConsistency(&sGrammar, &curTypeInfo); + } + + RefHashTableOf* groupInfoRegistry = sGrammar.getGroupInfoRegistry(); + RefHashTableOfEnumerator groupEnum(groupInfoRegistry, false, fMemoryManager); + + while (groupEnum.hasMoreElements()) { + + XercesGroupInfo& curGroup = groupEnum.nextElement(); + XercesGroupInfo* baseGroup = curGroup.getBaseGroup(); + + if (baseGroup) { + try { + checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(), + baseGroup->getContentSpec(), baseGroup->getScope()); + } + catch (const XMLException& excep) { + fSchemaErrorReporter.emitError(excep, curGroup.getLocator()); + } + } + + if (curGroup.getCheckElementConsistency()) + checkRefElementConsistency(&sGrammar, 0, &curGroup); + } + } + } +} + +void SchemaValidator::postParseValidation() +{ + // + // At this time, there is nothing to do here. The scanner itself handles + // ID/IDREF validation, since that is the same no matter what kind of + // validator. + // +} + +// --------------------------------------------------------------------------- +// SchemaValidator: Validator method +// --------------------------------------------------------------------------- +// Do Schema Normalization depends on the WhiteSpace Facet +// preserve : No normalization is done +// replace : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return) +// are replaced with #x20 (space). +// collapse : Subsequent to the replacements specified above under replace, +// contiguous sequences of #x20s are collapsed to a single #x20, +// and initial and/or final #x20s are deleted. +// +void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone /*= false*/) +{ + toFill.reset(); + + //empty string + if (!*value) + return; + + if(bStandalone) + fTrailing = fSeenNonWhiteSpace = false; + + short wsFacet = dV->getWSFacet(); + + // Loop through the chars of the source value and normalize it + // according to the whitespace facet + XMLCh nextCh; + const XMLCh* srcPtr = value; + XMLReader* fCurReader = getReaderMgr()->getCurrentReader(); + + if (wsFacet == DatatypeValidator::REPLACE) + { + while (*srcPtr) + { + nextCh = *srcPtr++; + if (fCurReader->isWhitespace(nextCh)) + nextCh = chSpace; + // Add this char to the target buffer + toFill.append(nextCh); + } + } + else // COLLAPSE + { + enum States + { + InWhitespace + , InContent + }; + + States curState = fTrailing ? InWhitespace : InContent; + while (*srcPtr) + { + nextCh = *srcPtr++; + if (curState == InContent) + { + if (fCurReader->isWhitespace(nextCh)) + { + curState = InWhitespace; + continue; + } + fSeenNonWhiteSpace = true; + } + else if (curState == InWhitespace) + { + if (fCurReader->isWhitespace(nextCh)) + continue; + if (fSeenNonWhiteSpace) + toFill.append(chSpace); + curState = InContent; + fSeenNonWhiteSpace = true; + } + // Add this char to the target buffer + toFill.append(nextCh); + } + + if (fCurReader->isWhitespace(*(srcPtr-1))) + fTrailing = true; + else + fTrailing = false; + } + if(bStandalone) + fTrailing = fSeenNonWhiteSpace = false; +} + + +// --------------------------------------------------------------------------- +// SchemaValidator: Particle Derivation Checking +// --------------------------------------------------------------------------- +void SchemaValidator::checkRefElementConsistency(SchemaGrammar* const currentGrammar, + const ComplexTypeInfo* const curTypeInfo, + const XercesGroupInfo* const curGroup) { + + XMLSize_t elemCount = (curTypeInfo) ? curTypeInfo->elementCount() : curGroup->elementCount(); + int elemScope = (curTypeInfo) ? curTypeInfo->getScopeDefined() : curGroup->getScope(); + XSDLocator* typeInfoLocator = (curTypeInfo) ? curTypeInfo->getLocator() : curGroup->getLocator(); + + for (XMLSize_t i=0; i < elemCount; i++) { + + const SchemaElementDecl* elemDecl = (curTypeInfo) ? curTypeInfo->elementAt(i) : curGroup->elementAt(i); + + if (elemDecl->isGlobalDecl()) { + + unsigned int elemURI = elemDecl->getURI(); + const XMLCh* elemName = elemDecl->getBaseName(); + const SchemaElementDecl* other = (SchemaElementDecl*) + currentGrammar->getElemDecl(elemURI, elemName, 0, elemScope); + + if (other + && (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() || + elemDecl->getDatatypeValidator() != other->getDatatypeValidator())) { + fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration, + XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager); + continue; + } + + RefHash2KeysTableOf* validSubsGroups = currentGrammar->getValidSubstitutionGroups(); + ValueVectorOf* subsElements = validSubsGroups->get(elemName, elemURI); + + if (subsElements) { + + XMLSize_t subsElemSize = subsElements->size(); + + for (XMLSize_t j=0; j < subsElemSize; j++) { + + SchemaElementDecl* subsElem = subsElements->elementAt(j); + const XMLCh* subsElemName = subsElem->getBaseName(); + other = (SchemaElementDecl*) + currentGrammar->getElemDecl(subsElem->getURI(), subsElemName, 0, elemScope); + + if (other + && (subsElem->getComplexTypeInfo() != other->getComplexTypeInfo() + || subsElem->getDatatypeValidator() != other->getDatatypeValidator())) { + fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration, + XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager); + } + } + } + } + } +} + +// --------------------------------------------------------------------------- +// SchemaValidator: Particle Derivation Checking +// --------------------------------------------------------------------------- +void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar, + const ComplexTypeInfo* const curTypeInfo) { + + ComplexTypeInfo* baseTypeInfo = 0; + ContentSpecNode* curSpecNode = 0; + + if (curTypeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION + && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0) + && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) { + + try { + checkParticleDerivationOk(currentGrammar, curSpecNode, + curTypeInfo->getScopeDefined(), + baseTypeInfo->getContentSpec(), + baseTypeInfo->getScopeDefined(), baseTypeInfo); + } + catch (const XMLException& excep) { + fSchemaErrorReporter.emitError(excep, curTypeInfo->getLocator()); + } + } +} + +ContentSpecNode* SchemaValidator::getNonUnaryGroup(ContentSpecNode* const pNode) { + + int pNodeType = (pNode->getType() & 0x0f); + if (pNodeType == ContentSpecNode::Leaf + || pNodeType == ContentSpecNode::Any + || pNodeType == ContentSpecNode::Any_Other + || pNodeType == ContentSpecNode::Any_NS) + return pNode; + + if (pNode->getMinOccurs() == 1 && pNode->getMaxOccurs() == 1 + && pNode->getFirst() && !pNode->getSecond()) + return getNonUnaryGroup(pNode->getFirst()); + + return pNode; +} + +void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar, + ContentSpecNode* const curNode, + const int derivedScope, + ContentSpecNode* const baseNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo, + const bool toCheckOccurence) { + + // Check for pointless occurrences of all, choice, sequence. The result is + // the contentspec which is not pointless. If the result is a non-pointless + // group, Vector is filled in with the children of interest + if (curNode && !baseNode) + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_EmptyBase, fMemoryManager); + + if (!curNode) + return; + + ContentSpecNode* curSpecNode = getNonUnaryGroup(curNode); + ContentSpecNode* baseSpecNode = getNonUnaryGroup(baseNode); + ValueVectorOf curVector(8, fMemoryManager); + ValueVectorOf baseVector(8, fMemoryManager); + ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType(); + ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType(); + + if ((curNodeType & 0x0f) == ContentSpecNode::Sequence || + (curNodeType & 0x0f) == ContentSpecNode::Choice || + curNodeType == ContentSpecNode::All) { + curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector); + } + + if ((baseNodeType & 0x0f) == ContentSpecNode::Sequence || + (baseNodeType & 0x0f) == ContentSpecNode::Choice || + baseNodeType == ContentSpecNode::All) { + baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector); + } + + curNodeType = curSpecNode->getType(); + baseNodeType = baseSpecNode->getType(); + + switch (curNodeType & 0x0f) { + case ContentSpecNode::Leaf: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Leaf: + { + checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo); + return; + } + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSCompat(curSpecNode, baseSpecNode, toCheckOccurence); + return; + } + case ContentSpecNode::Choice: + case ContentSpecNode::Sequence: + case ContentSpecNode::All: + { + checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope, + baseSpecNode, baseScope, &baseVector, baseInfo); + return; + } + default: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); + } + } + } + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSSubset(curSpecNode, baseSpecNode); + return; + } + case ContentSpecNode::Choice: + case ContentSpecNode::Sequence: + case ContentSpecNode::All: + case ContentSpecNode::Leaf: + { + if (baseNodeType == ContentSpecNode::Any_NS_Choice) { + if (checkNSSubsetChoiceRoot(curSpecNode, baseSpecNode)) { + return; + } + } + + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes1, fMemoryManager); + } + default: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); + } + } + } + case ContentSpecNode::All: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence); + return; + } + case ContentSpecNode::All: + { + checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, + baseSpecNode, baseScope, &baseVector, baseInfo); + return; + } + case ContentSpecNode::Choice: + case ContentSpecNode::Sequence: + case ContentSpecNode::Leaf: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes2, fMemoryManager); + } + default: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); + } + } + } + case ContentSpecNode::Choice: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence); + return; + } + case ContentSpecNode::Choice: + { + checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, + baseSpecNode, baseScope, &baseVector, baseInfo, true); + return; + } + case ContentSpecNode::All: + case ContentSpecNode::Sequence: + case ContentSpecNode::Leaf: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes3, fMemoryManager); + } + default: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); + } + } + } + case ContentSpecNode::Sequence: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence); + return; + } + case ContentSpecNode::All: + { + checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope, + baseSpecNode, &baseVector, baseScope, baseInfo); + return; + } + case ContentSpecNode::Sequence: + { + checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, + baseSpecNode, baseScope, &baseVector, baseInfo); + return; + } + case ContentSpecNode::Choice: + { + checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope, + baseSpecNode, &baseVector, baseScope, baseInfo); + return; + } + case ContentSpecNode::Leaf: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes4, fMemoryManager); + } + default: + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); + } + } + } + } +} + +ContentSpecNode* +SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode, + const ContentSpecNode::NodeTypes nodeType, + ValueVectorOf* const nodes) { + + ContentSpecNode* rightNode = specNode->getSecond(); + int min = specNode->getMinOccurs(); + int max = specNode->getMaxOccurs(); + + if (!rightNode) { + + gatherChildren(nodeType, specNode->getFirst(), nodes); + + if (nodes->size() == 1 && min == 1 && max == 1) { + return nodes->elementAt(0); + } + + return specNode; + } + + gatherChildren(nodeType, specNode->getFirst(), nodes); + gatherChildren(nodeType, rightNode, nodes); + + return specNode; +} + +void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, + ContentSpecNode* const specNode, + ValueVectorOf* const nodes) { + + if (!specNode) { + return; + } + + int min = specNode->getMinOccurs(); + int max = specNode->getMaxOccurs(); + ContentSpecNode::NodeTypes nodeType = specNode->getType(); + ContentSpecNode* rightNode = specNode->getSecond(); + + if (nodeType == ContentSpecNode::Leaf || + (nodeType & 0x0f) == ContentSpecNode::Any || + (nodeType & 0x0f) == ContentSpecNode::Any_NS || + (nodeType & 0x0f) == ContentSpecNode::Any_Other) { + nodes->addElement(specNode); + } + else if (min !=1 || max != 1) { + nodes->addElement(specNode); + } + else if (!rightNode) { + gatherChildren(nodeType, specNode->getFirst(), nodes); + } + else if ((parentNodeType & 0x0f) == (nodeType & 0x0f)) { + + gatherChildren(nodeType, specNode->getFirst(), nodes); + gatherChildren(nodeType, rightNode, nodes); + } + else { + nodes->addElement(specNode); + } +} + +void +SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode, + const bool toCheckOccurence) { + + // check Occurrence ranges + if (toCheckOccurence && + !isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, + derivedSpecNode->getElement()->getLocalPart(), fMemoryManager); + } + + // check wildcard subset + if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NSCompat1, + derivedSpecNode->getElement()->getLocalPart(), fMemoryManager); + } +} + +bool +SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, + const unsigned int derivedURI) { + + ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType(); + + if ((nodeType & 0x0f) == ContentSpecNode::Any) { + return true; + } + + unsigned int baseURI = baseSpecNode->getElement()->getURI(); + + if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) { + if (derivedURI == baseURI) { + return true; + } + } + else { // must be ANY_OTHER + if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) { + return true; + } + } + + return false; +} + +void +SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + if (derivedSpecNode->getMaxOccurs() == 0) + return; + + unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); + + // case of mixed complex types with attributes only + if (derivedURI == XMLElementDecl::fgPCDataElemId) { + return; + } + + SchemaGrammar* dGrammar = currentGrammar; + + if (derivedURI != getScanner()->getEmptyNamespaceId()) + { + const XMLCh* dURI = fGrammarResolver->getStringPool()->getValueForId(derivedURI); + dGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(dURI); + } + + if (!dGrammar) { //something is wrong + return; + } + + const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart(); + + SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, dGrammar); + + if (!derivedElemDecl) { + return; + } + + const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart(); + unsigned int baseURI = baseSpecNode->getElement()->getURI(); + bool subsGroup = false; + + if (!XMLString::equals(derivedName, baseName) || derivedURI != baseURI) { + // Check if derived is substitutable for base. + // + SchemaElementDecl* e = derivedElemDecl->getSubstitutionGroupElem (); + + for (; e != 0; e = e->getSubstitutionGroupElem ()) { + if (XMLString::equals(e->getBaseName (), baseName) && e->getURI () == baseURI) { + break; + } + } + + if (e == 0) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NameTypeOK1, fMemoryManager); + } + + subsGroup = true; + } + + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName, fMemoryManager); + } + + // Find the schema grammar for the base element using the base type as + // a reference if it is available (it is unavailable if we are checking + // element group restriction which happens in redefine). + // + SchemaGrammar* bGrammar = dGrammar; + + if (baseInfo) + { + const XMLCh* baseTypeURI = baseInfo->getTypeUri (); + + if (baseTypeURI != 0 && *baseTypeURI != 0) // Non-empty namespace. + bGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(baseTypeURI); + + if (!bGrammar) { //something is wrong + return; + } + } + + SchemaElementDecl* baseElemDecl = + findElement(baseScope, baseURI, baseName, bGrammar, baseInfo); + + if (!baseElemDecl) { + return; + } + + int derivedFlags = derivedElemDecl->getMiscFlags(); + int baseFlags = baseElemDecl->getMiscFlags(); + + if (((baseFlags & SchemaSymbols::XSD_NILLABLE) == 0) && + ((derivedFlags & SchemaSymbols::XSD_NILLABLE) != 0)) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName, fMemoryManager); + } + + const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue(); + const XMLCh* baseDefVal = baseElemDecl->getDefaultValue(); + + if (baseDefVal && (baseFlags & SchemaSymbols::XSD_FIXED) != 0 && + ((derivedFlags & SchemaSymbols::XSD_FIXED) == 0 || + !XMLString::equals(derivedDefVal, baseDefVal))) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName, fMemoryManager); + } + + int derivedBlockSet = derivedElemDecl->getBlockSet(); + int baseBlockSet = baseElemDecl->getBlockSet(); + + if ((derivedBlockSet & baseBlockSet) != baseBlockSet) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName, fMemoryManager); + } + + // check identity constraints + checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName); + + // check that the derived element's type is derived from the base's. + if (!subsGroup) + checkTypesOK(derivedElemDecl, baseElemDecl, derivedName); +} + +SchemaElementDecl* +SchemaValidator::findElement(const int scope, const unsigned int uriIndex, + const XMLCh* const name, + SchemaGrammar* const grammar, + const ComplexTypeInfo* const typeInfo) { + + // check for element at given scope first + SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope); + + // if not found, check at global scope + if (!elemDecl) { + + elemDecl = (SchemaElementDecl*) + grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE); + + // if still not found, and base is specified, look it up there + if (!elemDecl && typeInfo) { + + const ComplexTypeInfo* baseInfo = typeInfo; + + while (baseInfo) { + + elemDecl = (SchemaElementDecl*) + grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined()); + + if (elemDecl) { + break; + } + + baseInfo = baseInfo->getBaseComplexTypeInfo(); + } + } + } + + return elemDecl; +} + +void +SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName, + const XMLCh* const baseElemName) { + + // REVIST - need to get more clarification + XMLSize_t derivedICCount = derivedElemDecl->getIdentityConstraintCount(); + XMLSize_t baseICCount = baseElemDecl->getIdentityConstraintCount(); + + if (derivedICCount > baseICCount) { + ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName, fMemoryManager); + } + + for (XMLSize_t i=0; i < derivedICCount; i++) { + + bool found = false; + IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i); + + for (XMLSize_t j=0; j < baseICCount; j++) { + if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) { + + found = true; + break; + } + } + + if (!found) { + ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName, fMemoryManager); + } + } +} + +void +SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName) { + + SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType(); + + if (baseType == SchemaElementDecl::Any) { + return; + } + + ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo(); + ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo(); + + if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) { + + if (baseType != SchemaElementDecl::Simple) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager); + } + + if (!rInfo) { + + DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator(); + + if (bInfo || bDV == 0 || + !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager); + } + + return; + } + } + + if (rInfo == bInfo) + return; + + for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) { + if (rInfo->getDerivedBy() != SchemaSymbols::XSD_RESTRICTION) { + + rInfo = 0; + break; + } + } + + if (!rInfo) { + ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager); + } +} + +void +SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar, + ContentSpecNode* const derivedSpecNodeIn, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf* const baseNodes, + const ComplexTypeInfo* const baseInfo) { + + ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); + bool toLax = false; + + //Treat the element as if it were in a group of the same variety as base + ContentSpecNode derivedGroupNode(baseType, derivedSpecNodeIn, 0, false, true, fMemoryManager); + const ContentSpecNode* const derivedSpecNode = &derivedGroupNode; + + if ((baseSpecNode->getType() & 0x0f) == ContentSpecNode::Choice) { + toLax = true; + } + + // Instead of calling this routine, inline it + // checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes, + // baseSpecNode, baseScope, baseNodes, baseInfo, toLax); + + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); + } + + // check for mapping of children + XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; + XMLSize_t count2= baseNodes->size(); + XMLSize_t current = 0; + + { + bool matched = false; + + for (XMLSize_t j = current; j < count2; j++) { + + ContentSpecNode* baseNode = baseNodes->elementAt(j); + current++; + + bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' + try { + + checkParticleDerivationOk(currentGrammar, derivedSpecNodeIn, + derivedScope, baseNode, baseScope, baseInfo); + matched = true; + break; + } + catch(const XMLException&) { + if (!toLax && baseNode->getMinTotalRange()) { + bDoBreak=true; + } + } + if(bDoBreak) + break; + } + + // did not find a match + if (!matched) { + codeToThrow = XMLExcepts::PD_Recurse2; + } + } + + // Now, see if there are some elements in the base we didn't match up + // in case of Sequence or All + if (!toLax && codeToThrow == XMLExcepts::NoError) { + for (XMLSize_t j = current; j < count2; j++) { + if (baseNodes->elementAt(j)->getMinTotalRange() * baseSpecNode->getMinOccurs()) { //!emptiable + codeToThrow = XMLExcepts::PD_Recurse2; + break; + } + } + } + + if (codeToThrow != XMLExcepts::NoError) { + ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager); + } +} + +void +SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + ValueVectorOf* const derivedNodes, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf* const baseNodes, + const ComplexTypeInfo* const baseInfo, + const bool toLax) { + + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); + } + + // check for mapping of children + XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; + XMLSize_t count1= derivedNodes->size(); + XMLSize_t count2= baseNodes->size(); + XMLSize_t current = 0; + + for (XMLSize_t i=0; ielementAt(j); + current++; + + bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' + try { + + checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), + derivedScope, baseNode, baseScope, baseInfo); + matched = true; + break; + } + catch(const XMLException&) { + if (!toLax && baseNode->getMinTotalRange()) { + bDoBreak=true; + } + } + if(bDoBreak) + break; + } + + // did not find a match + if (!matched) { + + codeToThrow = XMLExcepts::PD_Recurse2; + break; + } + } + + // Now, see if there are some elements in the base we didn't match up + // in case of Sequence or All + if (!toLax && codeToThrow == XMLExcepts::NoError) { + for (XMLSize_t j = current; j < count2; j++) { + if (baseNodes->elementAt(j)->getMinTotalRange()) { //!emptiable + codeToThrow = XMLExcepts::PD_Recurse2; + break; + } + } + } + + if (codeToThrow != XMLExcepts::NoError) { + ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager); + } +} + +void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset1, fMemoryManager); + } + + if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset2, fMemoryManager); + } +} + +bool SchemaValidator::checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + bool found = false; + + if (baseSpecNode->getType() == ContentSpecNode::Any_NS_Choice) { + const ContentSpecNode* first = baseSpecNode->getFirst(); + const ContentSpecNode* second = baseSpecNode->getSecond(); + + if (first) { + found = checkNSSubsetChoiceRoot(derivedSpecNode, first); + if (found) return true; + } + if (second) { + found = checkNSSubsetChoiceRoot(derivedSpecNode, second); + if (found) return true; + } + } + else { // should be Any_NS + found = checkNSSubsetChoice(derivedSpecNode, baseSpecNode); + } + + return found; +} + +bool SchemaValidator::checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + return false; + } + + if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) { + return false; + } + return true; +} + +bool +SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + + ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); + + if ((baseType & 0x0f) == ContentSpecNode::Any) { + return true; + } + + ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType(); + unsigned int baseURI = baseSpecNode->getElement()->getURI(); + unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); + + // Below we assume that empty string has id 1. + // + if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) && + ((baseType & 0x0f) == ContentSpecNode::Any_Other) && + (baseURI == derivedURI || baseURI == 1)) { + return true; + } + + if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) { + + if (((baseType & 0x0f) == ContentSpecNode::Any_NS) && + baseURI == derivedURI) { + return true; + } + + if (((baseType & 0x0f) == ContentSpecNode::Any_Other) && + (derivedURI == 1 || baseURI != derivedURI)) { + return true; + } + } + + return false; +} + +void +SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + const bool toCheckOccurence) { + + // Implement total range check + int derivedMin = derivedSpecNode->getMinTotalRange(); + int derivedMax = derivedSpecNode->getMaxTotalRange(); + + // check Occurrence ranges + if (toCheckOccurence && + !isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), + baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1, fMemoryManager); + } + + // Check that each member of the group is a valid restriction of the wildcard + XMLSize_t nodesCount = derivedNodes->size(); + + for (XMLSize_t i = 0; i < nodesCount; i++) { + checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1, 0, false); + } +} + +void +SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); + } + + XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; + XMLSize_t derivedCount= derivedNodes->size(); + XMLSize_t baseCount = baseNodes->size(); + bool* foundIt = (bool*) fMemoryManager->allocate + ( + baseCount * sizeof(bool) + );//new bool[baseCount]; + ArrayJanitor janFoundIt(foundIt, fMemoryManager); + + for (XMLSize_t k=0; k < baseCount; k++) { + foundIt[k] = false; + } + + // check for mapping of children + for (XMLSize_t i = 0; i < derivedCount; i++) { + + ContentSpecNode* derivedNode = derivedNodes->elementAt(i); + bool matched = false; + + for (XMLSize_t j = 0; j < baseCount; j++) { + + try { + + checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope, + baseNodes->elementAt(j), baseScope, baseInfo); + + if (foundIt[j]) { + break; + } + + foundIt[j] = true; + matched = true; + break; + } + catch (const XMLException&) { + } + } + + // didn't find a match. + if (!matched) { + + codeToThrow = XMLExcepts::PD_RecurseUnordered; + break; + } + } + + // For all unmapped particles in base, check to see it it's emptiable or not + if (codeToThrow == XMLExcepts::NoError) { + for (XMLSize_t j=0; j < baseCount; j++) { + if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) { + + codeToThrow = XMLExcepts::PD_RecurseUnordered; + break; + } + } + } + + if (codeToThrow != XMLExcepts::NoError) { + ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager); + } +} + +void +SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + // check Occurrence ranges + XMLSize_t derivedCount = derivedNodes->size(); + XMLSize_t baseCount = baseNodes->size(); + int derivedMin = derivedSpecNode->getMinOccurs() * (unsigned int)derivedCount; + int derivedMax = derivedSpecNode->getMaxOccurs(); + + if (derivedMax != SchemaSymbols::XSD_UNBOUNDED) { + derivedMax *= (unsigned int)derivedCount; + } + + if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), + baseSpecNode->getMaxOccurs())) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); + } + + // check for mapping of children + for (XMLSize_t i = 0; i < derivedCount; i++) { + + ContentSpecNode* derivedNode = derivedNodes->elementAt(i); + bool matched = false; + + for (XMLSize_t j = 0; j < baseCount && !matched; j++) { + + try { + + checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope, + baseNodes->elementAt(j), baseScope, baseInfo); + matched = true; + } + catch (const XMLException&) { + } + } + + // didn't find a match. + if (!matched) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_MapAndSum, fMemoryManager); + } + } + +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/SchemaValidator.hpp b/include/xercesc/validators/schema/SchemaValidator.hpp new file mode 100644 index 0000000..e1dda3a --- /dev/null +++ b/include/xercesc/validators/schema/SchemaValidator.hpp @@ -0,0 +1,443 @@ +/* + * 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: SchemaValidator.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SCHEMAVALIDATOR_HPP) +#define XERCESC_INCLUDE_GUARD_SCHEMAVALIDATOR_HPP + +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class GrammarResolver; +class DatatypeValidator; +class SchemaElementDecl; + +// +// This is a derivative of the abstract validator interface. This class +// implements a validator that supports standard XML Schema semantics. +// This class handles scanning the of the schema, and provides +// the standard validation services against the Schema info it found. +// +class VALIDATORS_EXPORT SchemaValidator : public XMLValidator +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + SchemaValidator + ( + XMLErrorReporter* const errReporter = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + virtual ~SchemaValidator(); + + // ----------------------------------------------------------------------- + // Implementation of the XMLValidator interface + // ----------------------------------------------------------------------- + virtual bool checkContent + ( + XMLElementDecl* const elemDecl + , QName** const children + , XMLSize_t childCount + , XMLSize_t* indexFailingChild + ); + + virtual void faultInAttr + ( + XMLAttr& toFill + , const XMLAttDef& attDef + ) const; + + virtual void preContentValidation(bool reuseGrammar, + bool validateDefAttr = false); + + virtual void postParseValidation(); + + virtual void reset(); + + virtual bool requiresNamespaces() const; + + virtual void validateAttrValue + ( + const XMLAttDef* attDef + , const XMLCh* const attrValue + , bool preValidation = false + , const XMLElementDecl* elemDecl = 0 + ); + + virtual void validateElement + ( + const XMLElementDecl* elemDef + ); + + virtual Grammar* getGrammar() const; + virtual void setGrammar(Grammar* aGrammar); + + // ----------------------------------------------------------------------- + // Virtual DTD handler interface. + // ----------------------------------------------------------------------- + virtual bool handlesDTD() const; + + // ----------------------------------------------------------------------- + // Virtual Schema handler interface. handlesSchema() always return false. + // ----------------------------------------------------------------------- + virtual bool handlesSchema() const; + + // ----------------------------------------------------------------------- + // Schema Validator methods + // ----------------------------------------------------------------------- + void normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone = false); + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setGrammarResolver(GrammarResolver* grammarResolver); + + void setXsiType(const XMLCh* const prefix + , const XMLCh* const localPart + , const unsigned int uriId); + + void setNillable(bool isNil); + void resetNillable(); + void setErrorReporter(XMLErrorReporter* const errorReporter); + void setExitOnFirstFatal(const bool newValue); + void setDatatypeBuffer(const XMLCh* const value); + void clearDatatypeBuffer(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + ComplexTypeInfo* getCurrentTypeInfo() const; + DatatypeValidator *getCurrentDatatypeValidator() const; + DatatypeValidator *getMostRecentAttrValidator() const; + bool getErrorOccurred() const; + bool getIsElemSpecified() const; + bool getIsXsiTypeSet() const; + const XMLCh* getNormalizedValue() const; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SchemaValidator(const SchemaValidator&); + SchemaValidator& operator=(const SchemaValidator&); + + // ----------------------------------------------------------------------- + // Element Consistency Checking methods + // ----------------------------------------------------------------------- + void checkRefElementConsistency(SchemaGrammar* const currentGrammar, + const ComplexTypeInfo* const curTypeInfo, + const XercesGroupInfo* const curGroup = 0); + + // ----------------------------------------------------------------------- + // Particle Derivation Checking methods + // ----------------------------------------------------------------------- + void checkParticleDerivation(SchemaGrammar* const currentGrammar, + const ComplexTypeInfo* const typeInfo); + void checkParticleDerivationOk(SchemaGrammar* const currentGrammar, + ContentSpecNode* const curNode, + const int derivedScope, + ContentSpecNode* const baseNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo = 0, + const bool toCheckOccurrence = true); + ContentSpecNode* checkForPointlessOccurrences(ContentSpecNode* const specNode, + const ContentSpecNode::NodeTypes nodeType, + ValueVectorOf* const nodes); + void gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, + ContentSpecNode* const specNode, + ValueVectorOf* const nodes); + bool isOccurrenceRangeOK(const int min1, const int max1, const int min2, const int max2); + void checkNSCompat(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode, + const bool toCheckOccurence); + bool wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, + const unsigned int derivedURI); + void checkNameAndTypeOK(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo = 0); + SchemaElementDecl* findElement(const int scope, + const unsigned int uriIndex, + const XMLCh* const name, + SchemaGrammar* const grammar, + const ComplexTypeInfo* const typeInfo = 0); + void checkICRestriction(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName, + const XMLCh* const baseElemName); + void checkTypesOK(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName); + void checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar, + ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf* const nodes, + const ComplexTypeInfo* const baseInfo); + void checkRecurse(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + ValueVectorOf* const derivedNodes, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf* const baseNodes, + const ComplexTypeInfo* const baseInfo, + const bool toLax = false); + void checkNSSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + bool checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + bool checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + bool isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + void checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + const bool toCheckOccurence); + void checkRecurseUnordered(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo); + void checkMapAndSum(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo); + ContentSpecNode* getNonUnaryGroup(ContentSpecNode* const pNode); + + // ----------------------------------------------------------------------- + // Private data members + // + // ----------------------------------------------------------------------- + // The following comes from or set by the Scanner + // fSchemaGrammar + // The current schema grammar used by the validator + // + // fGrammarResolver + // All the schema grammar stored + // + // fXsiType + // Store the Schema Type Attribute Value if schema type is specified + // + // fNil + // Indicates if a nil value is acceptable + // fNilFound + // Indicates if Nillable has been set + // ----------------------------------------------------------------------- + // The following used internally in the validator + // + // fCurrentDatatypeValidator + // The validator used for validating the content of elements + // with simple types + // + // fDatatypeBuffer + // Buffer for simple type element string content + // + // fTrailing + // Previous chunk had a trailing space + // + // fSeenNonWhiteSpace + // Seen a non-whitespace character in the previous chunk + // + // fSeenId + // Indicate if an attribute of ID type has been seen already, reset per element. + // + // fSchemaErrorReporter + // Report schema process errors + // + // fTypeStack + // Stack of complex type declarations. + // + // fMostRecentAttrValidator + // DatatypeValidator that validated attribute most recently processed + // + // fErrorOccurred + // whether an error occurred in the most recent operation + // ----------------------------------------------------------------------- + MemoryManager* fMemoryManager; + SchemaGrammar* fSchemaGrammar; + GrammarResolver* fGrammarResolver; + QName* fXsiType; + bool fNil; + bool fNilFound; + DatatypeValidator* fCurrentDatatypeValidator; + XMLBuffer* fNotationBuf; + XMLBuffer fDatatypeBuffer; + bool fTrailing; + bool fSeenNonWhiteSpace; + bool fSeenId; + XSDErrorReporter fSchemaErrorReporter; + ValueStackOf* fTypeStack; + DatatypeValidator * fMostRecentAttrValidator; + bool fErrorOccurred; + bool fElemIsSpecified; +}; + + +// --------------------------------------------------------------------------- +// SchemaValidator: Setter methods +// --------------------------------------------------------------------------- +inline void SchemaValidator::setGrammarResolver(GrammarResolver* grammarResolver) { + fGrammarResolver = grammarResolver; +} + +inline void SchemaValidator::setXsiType(const XMLCh* const prefix + , const XMLCh* const localPart + , const unsigned int uriId) +{ + delete fXsiType; + fXsiType = new (fMemoryManager) QName(prefix, localPart, uriId, fMemoryManager); +} + +inline void SchemaValidator::setNillable(bool isNil) { + fNil = isNil; + fNilFound = true; +} + +inline void SchemaValidator::resetNillable() { + fNil = false; + fNilFound = false; +} + +inline void SchemaValidator::setExitOnFirstFatal(const bool newValue) { + + fSchemaErrorReporter.setExitOnFirstFatal(newValue); +} + +inline void SchemaValidator::setDatatypeBuffer(const XMLCh* const value) +{ + fDatatypeBuffer.append(value); +} + +inline void SchemaValidator::clearDatatypeBuffer() +{ + fDatatypeBuffer.reset(); +} + +// --------------------------------------------------------------------------- +// SchemaValidator: Getter methods +// --------------------------------------------------------------------------- +inline ComplexTypeInfo* SchemaValidator::getCurrentTypeInfo() const { + if (fTypeStack->empty()) + return 0; + return fTypeStack->peek(); +} + +inline DatatypeValidator * SchemaValidator::getCurrentDatatypeValidator() const +{ + return fCurrentDatatypeValidator; +} +inline DatatypeValidator *SchemaValidator::getMostRecentAttrValidator() const +{ + return fMostRecentAttrValidator; +} + +// --------------------------------------------------------------------------- +// Virtual interface +// --------------------------------------------------------------------------- +inline Grammar* SchemaValidator::getGrammar() const { + return fSchemaGrammar; +} + +inline void SchemaValidator::setGrammar(Grammar* aGrammar) { + fSchemaGrammar = (SchemaGrammar*) aGrammar; +} + +inline void SchemaValidator::setErrorReporter(XMLErrorReporter* const errorReporter) { + + XMLValidator::setErrorReporter(errorReporter); + fSchemaErrorReporter.setErrorReporter(errorReporter); +} + +// --------------------------------------------------------------------------- +// SchemaValidator: DTD handler interface +// --------------------------------------------------------------------------- +inline bool SchemaValidator::handlesDTD() const +{ + // No DTD scanning + return false; +} + +// --------------------------------------------------------------------------- +// SchemaValidator: Schema handler interface +// --------------------------------------------------------------------------- +inline bool SchemaValidator::handlesSchema() const +{ + return true; +} + +// --------------------------------------------------------------------------- +// SchemaValidator: Particle derivation checking +// --------------------------------------------------------------------------- +inline bool +SchemaValidator::isOccurrenceRangeOK(const int min1, const int max1, + const int min2, const int max2) { + + if (min1 >= min2 && + (max2 == SchemaSymbols::XSD_UNBOUNDED || + (max1 != SchemaSymbols::XSD_UNBOUNDED && max1 <= max2))) { + return true; + } + return false; +} + +inline bool SchemaValidator::getErrorOccurred() const +{ + return fErrorOccurred; +} + +inline bool SchemaValidator::getIsElemSpecified() const +{ + return fElemIsSpecified; +} + +inline const XMLCh* SchemaValidator::getNormalizedValue() const +{ + return fDatatypeBuffer.getRawBuffer(); +} + +inline bool SchemaValidator::getIsXsiTypeSet() const +{ + return (fXsiType!=0); +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/SubstitutionGroupComparator.cpp b/include/xercesc/validators/schema/SubstitutionGroupComparator.cpp new file mode 100644 index 0000000..dbb5d7f --- /dev/null +++ b/include/xercesc/validators/schema/SubstitutionGroupComparator.cpp @@ -0,0 +1,210 @@ +/* + * 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: SubstitutionGroupComparator.cpp 794273 2009-07-15 14:13:07Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +bool SubstitutionGroupComparator::isEquivalentTo(const QName* const anElement + , const QName* const exemplar) +{ + if (!anElement && !exemplar) + return true; + + if ((!anElement && exemplar) || (anElement && !exemplar)) + return false; + + + if (XMLString::equals(anElement->getLocalPart(), exemplar->getLocalPart()) && + (anElement->getURI() == exemplar->getURI())) + return true; // they're the same! + + if (!fGrammarResolver || !fStringPool ) + { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::SubGrpComparator_NGR, anElement->getMemoryManager()); + } + + unsigned int uriId = anElement->getURI(); + if (uriId == XMLContentModel::gEOCFakeId || + uriId == XMLContentModel::gEpsilonFakeId || + uriId == XMLElementDecl::fgPCDataElemId || + uriId == XMLElementDecl::fgInvalidElemId) + return false; + + const XMLCh* uri = fStringPool->getValueForId(uriId); + const XMLCh* localpart = anElement->getLocalPart(); + + // In addition to simply trying to find a chain between anElement and exemplar, + // we need to make sure that no steps in the chain are blocked. + // That is, at every step, we need to make sure that the element + // being substituted for will permit being substituted + // for, and whether the type of the element will permit derivations in + // instance documents of this sort. + + if (!uri) + return false; + + SchemaGrammar *sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uri); + if (!sGrammar || sGrammar->getGrammarType() == Grammar::DTDGrammarType) + return false; + + SchemaElementDecl* anElementDecl = (SchemaElementDecl*) sGrammar->getElemDecl(uriId, localpart, 0, Grammar::TOP_LEVEL_SCOPE); + if (!anElementDecl) + return false; + + SchemaElementDecl* pElemDecl = anElementDecl->getSubstitutionGroupElem(); + bool foundIt = false; + + while (pElemDecl) //(substitutionGroupFullName) + { + if (XMLString::equals(pElemDecl->getBaseName(), exemplar->getLocalPart()) && + (pElemDecl->getURI() == exemplar->getURI())) + { + // time to check for block value on element + if((pElemDecl->getBlockSet() & SchemaSymbols::XSD_SUBSTITUTION) != 0) + return false; + + foundIt = true; + break; + } + + pElemDecl = pElemDecl->getSubstitutionGroupElem(); + }//while + + if (!foundIt) + return false; + + // this will contain anElement's complexType information. + ComplexTypeInfo *aComplexType = anElementDecl->getComplexTypeInfo(); + int exemplarBlockSet = pElemDecl->getBlockSet(); + + if(!aComplexType) + { + // check on simpleType case + DatatypeValidator *anElementDV = anElementDecl->getDatatypeValidator(); + DatatypeValidator *exemplarDV = pElemDecl->getDatatypeValidator(); + + return((anElementDV == 0) || + ((anElementDV == exemplarDV) || + ((exemplarBlockSet & SchemaSymbols::XSD_RESTRICTION) == 0))); + } + + // 2.3 The set of all {derivation method}s involved in the derivation of D's {type definition} from C's {type definition} does not intersect with the union of the blocking constraint, C's {prohibited substitutions} (if C is complex, otherwise the empty set) and the {prohibited substitutions} (respectively the empty set) of any intermediate {type definition}s in the derivation of D's {type definition} from C's {type definition}. + // prepare the combination of {derivation method} and + // {disallowed substitution} + int devMethod = 0; + int blockConstraint = exemplarBlockSet; + + ComplexTypeInfo *exemplarComplexType = pElemDecl->getComplexTypeInfo(); + ComplexTypeInfo *tempType = aComplexType;; + + while (tempType != 0 && + tempType != exemplarComplexType) + { + devMethod |= tempType->getDerivedBy(); + tempType = tempType->getBaseComplexTypeInfo(); + if (tempType) { + blockConstraint |= tempType->getBlockSet(); + } + } + if (tempType != exemplarComplexType) { + return false; + } + if ((devMethod & blockConstraint) != 0) { + return false; + } + + return true; +} + + +bool SubstitutionGroupComparator::isAllowedByWildcard(SchemaGrammar* const pGrammar, + QName* const element, + unsigned int wuri, bool wother) +{ + // whether the uri is allowed directly by the wildcard + unsigned int uriId = element->getURI(); + + // Here we assume that empty string has id 1. + // + if ((!wother && uriId == wuri) || + (wother && + uriId != 1 && + uriId != wuri && + uriId != XMLContentModel::gEOCFakeId && + uriId != XMLContentModel::gEpsilonFakeId && + uriId != XMLElementDecl::fgPCDataElemId && + uriId != XMLElementDecl::fgInvalidElemId)) + { + return true; + } + + // get all elements that can substitute the current element + RefHash2KeysTableOf* theValidSubstitutionGroups = pGrammar->getValidSubstitutionGroups(); + + if (!theValidSubstitutionGroups) + return false; + + ValueVectorOf* subsElements = theValidSubstitutionGroups->get(element->getLocalPart(), uriId); + + if (!subsElements) + return false; + + // then check whether there exists one element that is allowed by the wildcard + XMLSize_t size = subsElements->size(); + + for (XMLSize_t i = 0; i < size; i++) + { + unsigned int subUriId = subsElements->elementAt(i)->getElementName()->getURI(); + + // Here we assume that empty string has id 1. + // + if ((!wother && subUriId == wuri) || + (wother && + subUriId != 1 && + subUriId != wuri && + subUriId != XMLContentModel::gEOCFakeId && + subUriId != XMLContentModel::gEpsilonFakeId && + subUriId != XMLElementDecl::fgPCDataElemId && + subUriId != XMLElementDecl::fgInvalidElemId)) + { + return true; + } + } + return false; +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file SubstitutionGroupComparator.cpp + */ diff --git a/include/xercesc/validators/schema/SubstitutionGroupComparator.hpp b/include/xercesc/validators/schema/SubstitutionGroupComparator.hpp new file mode 100644 index 0000000..c5ab8ff --- /dev/null +++ b/include/xercesc/validators/schema/SubstitutionGroupComparator.hpp @@ -0,0 +1,126 @@ +/* + * 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: SubstitutionGroupComparator.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_SUBSTITUTIONGROUPCOMPARATOR_HPP) +#define XERCESC_INCLUDE_GUARD_SUBSTITUTIONGROUPCOMPARATOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class SchemaGrammar; + +class VALIDATORS_EXPORT SubstitutionGroupComparator : public XMemory +{ +public: + + // ----------------------------------------------------------------------- + // Public Constructor + // ----------------------------------------------------------------------- + /** @name Constructor. */ + //@{ + + SubstitutionGroupComparator(GrammarResolver* const pGrammarResolver + , XMLStringPool* const pStringPool); + + + //@} + + // ----------------------------------------------------------------------- + // Public Destructor + // ----------------------------------------------------------------------- + /** @name Destructor. */ + //@{ + + ~SubstitutionGroupComparator(); + + //@} + + // ----------------------------------------------------------------------- + // Validation methods + // ----------------------------------------------------------------------- + /** @name Validation Function */ + //@{ + + /** + * Checks that the "anElement" is within the substitution group. + * + * @param anElement QName of the element + * + * @param exemplar QName of the head element in the group + */ + bool isEquivalentTo(const QName* const anElement + , const QName* const exemplar); + //@} + + /* + * check whether one element or any element in its substitution group + * is allowed by a given wildcard uri + * + * @param pGrammar the grammar where the wildcard is declared + * @param element the QName of a given element + * @param wuri the uri of the wildcard + * @param wother whether the uri is from ##other, so wuri is excluded + * + * @return whether the element is allowed by the wildcard + */ + bool isAllowedByWildcard(SchemaGrammar* const pGrammar, QName* const element, unsigned int wuri, bool wother); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SubstitutionGroupComparator(); + SubstitutionGroupComparator(const SubstitutionGroupComparator&); + SubstitutionGroupComparator& operator=(const SubstitutionGroupComparator&); + + // ----------------------------------------------------------------------- + // Private data members + // + // + // ----------------------------------------------------------------------- + GrammarResolver *fGrammarResolver; + XMLStringPool *fStringPool; +}; + + +// --------------------------------------------------------------------------- +// SubstitutionGroupComparator: Getters +// --------------------------------------------------------------------------- +inline SubstitutionGroupComparator::SubstitutionGroupComparator(GrammarResolver* const pGrammarResolver + , XMLStringPool* const pStringPool) +:fGrammarResolver(pGrammarResolver) +,fStringPool(pStringPool) +{} + +inline SubstitutionGroupComparator::~SubstitutionGroupComparator() +{} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file SubstitutionGroupComparator.hpp + */ + diff --git a/include/xercesc/validators/schema/TraverseSchema.cpp b/include/xercesc/validators/schema/TraverseSchema.cpp new file mode 100644 index 0000000..b11053a --- /dev/null +++ b/include/xercesc/validators/schema/TraverseSchema.cpp @@ -0,0 +1,9466 @@ +/* + * 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: TraverseSchema.cpp 1141162 2011-06-29 16:48:30Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// TraverseSchema: Local declaration +// --------------------------------------------------------------------------- + +// This helper class will handle the parsing of namespace prefixes for a given DOMElement, and its winding back +class NamespaceScopeManager +{ +public: + NamespaceScopeManager(const DOMElement* const node, SchemaInfo* info, TraverseSchema* traverser) + { + fScopeAdded=node?traverser->retrieveNamespaceMapping(node):false; + fSchemaInfo=info; + } + ~NamespaceScopeManager() + { + if(fScopeAdded) + fSchemaInfo->getNamespaceScope()->decreaseDepth(); + + } +protected: + bool fScopeAdded; + SchemaInfo* fSchemaInfo; +}; + +// --------------------------------------------------------------------------- +// TraverseSchema: Static member data +// --------------------------------------------------------------------------- + + +// --------------------------------------------------------------------------- +// TraverseSchema: Local const data +// --------------------------------------------------------------------------- +static const XMLCh fgAnonSNamePrefix[] = +{ + chUnderscore, chUnderscore, chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_S, chNull +}; + +static const XMLCh fgAnonCNamePrefix[] = +{ + chUnderscore, chUnderscore, chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_C, chNull +}; + +static const XMLCh fgUnbounded[] = +{ + chLatin_u, chLatin_n, chLatin_b, chLatin_o, chLatin_u, chLatin_n, chLatin_d, + chLatin_e, chLatin_d, chNull +}; + +static const XMLCh fgValueOne[] = +{ + chDigit_1, chNull +}; + +static const XMLCh fgValueZero[] = +{ + chDigit_0, chNull +}; + +static const XMLCh* fgIdentityConstraints[] = +{ + SchemaSymbols::fgELT_UNIQUE, + SchemaSymbols::fgELT_KEY, + SchemaSymbols::fgELT_KEYREF +}; + +static const XMLCh fgSynthetic_Annotation[] = +{ + chLatin_S, chLatin_y, chLatin_n, chLatin_t, chLatin_h, chLatin_e, chLatin_t + , chLatin_i, chLatin_c, chUnderscore + , chLatin_A, chLatin_n, chLatin_n, chLatin_o, chLatin_t, chLatin_a, chLatin_t + , chLatin_i, chLatin_o, chLatin_n, chNull +}; + + +// Flags for global declaration +enum { + ENUM_ELT_SIMPLETYPE, + ENUM_ELT_COMPLEXTYPE, + ENUM_ELT_ELEMENT, + ENUM_ELT_ATTRIBUTE, + ENUM_ELT_ATTRIBUTEGROUP, + ENUM_ELT_GROUP, + ENUM_ELT_SIZE +}; + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// TraverseSchema: Constructors and Destructor +// --------------------------------------------------------------------------- +TraverseSchema::TraverseSchema( DOMElement* const schemaRoot + , XMLStringPool* const uriStringPool + , SchemaGrammar* const schemaGrammar + , GrammarResolver* const grammarResolver + , RefHash2KeysTableOf* cachedSchemaInfoList + , RefHash2KeysTableOf* schemaInfoList + , XMLScanner* const xmlScanner + , const XMLCh* const schemaURL + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errorReporter + , MemoryManager* const manager + , bool multipleImport) + : fFullConstraintChecking(false) + , fTargetNSURI(-1) + , fEmptyNamespaceURI(-1) + , fCurrentScope(Grammar::TOP_LEVEL_SCOPE) + , fScopeCount(schemaGrammar->getScopeCount ()) + , fAnonXSTypeCount(schemaGrammar->getAnonTypeCount ()) + , fCircularCheckIndex(0) + , fTargetNSURIString(0) + , fDatatypeRegistry(0) + , fGrammarResolver(grammarResolver) + , fSchemaGrammar(schemaGrammar) + , fEntityHandler(entityHandler) + , fErrorReporter(errorReporter) + , fURIStringPool(uriStringPool) + , fStringPool(0) + , fBuffer(1023, manager) + , fScanner(xmlScanner) + , fAttributeDeclRegistry(0) + , fComplexTypeRegistry(0) + , fGroupRegistry(0) + , fAttGroupRegistry(0) + , fIC_ElementsNS(0) + , fPreprocessedNodes(0) + , fSchemaInfo(0) + , fCurrentGroupInfo(0) + , fCurrentAttGroupInfo(0) + , fCurrentComplexType(0) + , fCurrentTypeNameStack(0) + , fCurrentGroupStack(0) + , fIC_Elements(0) + , fDeclStack(0) + , fGlobalDeclarations(0) + , fNonXSAttList(0) + , fImportedNSList(0) + , fIC_NodeListNS(0) + , fNotationRegistry(0) + , fRedefineComponents(0) + , fIdentityConstraintNames(0) + , fValidSubstitutionGroups(0) + , fSchemaInfoList(schemaInfoList) + , fCachedSchemaInfoList (cachedSchemaInfoList) + , fParser(0) + , fLocator(0) + , fMemoryManager(manager) + , fGrammarPoolMemoryManager(fGrammarResolver->getGrammarPoolMemoryManager()) + , fAnnotation(0) + , fAttributeCheck(manager) +{ + CleanupType cleanup(this, &TraverseSchema::cleanUp); + + try { + + if (fGrammarResolver && schemaRoot && fURIStringPool) { + + init(); + + if (multipleImport) + { + // If we are working on an existing schema, do some + // intitialization that is otherwise done by preprocessSchema. + // + fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry(); + fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry(); + fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry(); + fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry(); + fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups(); + } + + preprocessSchema(schemaRoot, schemaURL, multipleImport); + doTraverseSchema(schemaRoot); + + // Store the scope and anon type counts in case we need to add + // more to this grammar (multi-import case). schemaGrammar and + // fSchemaGrammar should be the same here. + // + fSchemaGrammar->setScopeCount (fScopeCount); + fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount); + } + + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +TraverseSchema::~TraverseSchema() +{ + cleanUp(); +} + + +// --------------------------------------------------------------------------- +// TraverseSchema: Traversal methods +// --------------------------------------------------------------------------- +void TraverseSchema::doTraverseSchema(const DOMElement* const schemaRoot) { + + // process children nodes + processChildren(schemaRoot); + + // Handle identity constraints - keyref + if (fIC_ElementsNS && fIC_ElementsNS->containsKey(fTargetNSURIString)) { + + fIC_Elements = fIC_ElementsNS->get(fTargetNSURIString); + + XMLSize_t icListSize = fIC_Elements->size(); + + for (XMLSize_t i=0; i < icListSize; i++) { + + SchemaElementDecl* curElem = fIC_Elements->elementAt(i); + ValueVectorOf* icNodes = fIC_NodeListNS->get(curElem); + XMLSize_t icNodesSize = icNodes->size(); + + for (XMLSize_t j = 0; j < icNodesSize; j++) { + traverseKeyRef(icNodes->elementAt(j), curElem); + } + } + } + + if (fScanner->getValidateAnnotations() && !fSchemaGrammar->getAnnotations()->isEmpty()) + { + validateAnnotations(); + } + fSchemaInfo->setProcessed(); +} + +void TraverseSchema::preprocessSchema(DOMElement* const schemaRoot, + const XMLCh* const schemaURL, + bool multipleImport) { + if (!multipleImport) { + // Make sure namespace binding is defaulted + const XMLCh* rootPrefix = schemaRoot->getPrefix(); + + if (rootPrefix == 0 || !*rootPrefix) { + + const XMLCh* xmlnsStr = schemaRoot->getAttribute(XMLUni::fgXMLNSString); + + if (!xmlnsStr || !*xmlnsStr) { + schemaRoot->setAttribute(XMLUni::fgXMLNSString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + } + } + + // Set schemaGrammar data and add it to GrammarResolver + // For complex type registry, attribute decl registry , group/attGroup + // and namespace mapping, needs to check whether the passed in + // Grammar was a newly instantiated one. + fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry(); + + if (fComplexTypeRegistry == 0 ) { + + fComplexTypeRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(29, fGrammarPoolMemoryManager); + fSchemaGrammar->setComplexTypeRegistry(fComplexTypeRegistry); + } + + fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry(); + + if (fGroupRegistry == 0 ) { + + fGroupRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(13, fGrammarPoolMemoryManager); + fSchemaGrammar->setGroupInfoRegistry(fGroupRegistry); + } + + fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry(); + + if (fAttGroupRegistry == 0 ) { + + fAttGroupRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(13, fGrammarPoolMemoryManager); + fSchemaGrammar->setAttGroupInfoRegistry(fAttGroupRegistry); + } + + fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry(); + + if (fAttributeDeclRegistry == 0) { + + fAttributeDeclRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(29, fGrammarPoolMemoryManager); + fSchemaGrammar->setAttributeDeclRegistry(fAttributeDeclRegistry); + } + + fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups(); + + if (!fValidSubstitutionGroups) { + + fValidSubstitutionGroups = new (fGrammarPoolMemoryManager) RefHash2KeysTableOf(29, fGrammarPoolMemoryManager); + fSchemaGrammar->setValidSubstitutionGroups(fValidSubstitutionGroups); + } + + //Retrieve the targetnamespace URI information + const XMLCh* targetNSURIStr = schemaRoot->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + fSchemaGrammar->setTargetNamespace(targetNSURIStr); + + fCurrentScope = Grammar::TOP_LEVEL_SCOPE; + fTargetNSURIString = fSchemaGrammar->getTargetNamespace(); + fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString); + + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) fSchemaGrammar->getGrammarDescription(); + gramDesc->setTargetNamespace(fTargetNSURIString); + + fGrammarResolver->putGrammar(fSchemaGrammar); + } + else { + fCurrentScope = Grammar::TOP_LEVEL_SCOPE; + + fTargetNSURIString = fSchemaGrammar->getTargetNamespace(); + fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString); + } + + SchemaInfo* currInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, + 0, + schemaURL, + fTargetNSURIString, schemaRoot, + fScanner, + fGrammarPoolMemoryManager); + + currInfo->getNamespaceScope()->reset(fEmptyNamespaceURI); + // Add mapping for the xml prefix + currInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName)); + + if (fSchemaInfo) + fSchemaInfo->addSchemaInfo(currInfo, SchemaInfo::IMPORT); + + addImportedNS(currInfo->getTargetNSURI()); + + fSchemaInfo = currInfo; + fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo); + fSchemaInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE); + traverseSchemaHeader(schemaRoot); + + // preprocess chidren + preprocessChildren(schemaRoot); +} + + +void TraverseSchema::traverseSchemaHeader(const DOMElement* const schemaRoot) { + + // Make sure that the root element is + if (!XMLString::equals(schemaRoot->getLocalName(), SchemaSymbols::fgELT_SCHEMA)) { + reportSchemaError(schemaRoot, XMLUni::fgXMLErrDomain, XMLErrs::InvalidXMLSchemaRoot); + } + + // Make sure that the targetNamespace value is not empty string + checkForEmptyTargetNamespace(schemaRoot); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + schemaRoot, GeneralAttributeCheck::E_Schema, this + , true, fSchemaInfo->getNonXSAttList() + ); + + retrieveNamespaceMapping(schemaRoot); + // Add mapping for the default namespace + if ((!fTargetNSURIString || !*fTargetNSURIString) && schemaRoot->getAttributeNode(XMLUni::fgXMLNSString)==NULL) + fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgZeroLenString, fEmptyNamespaceURI); + + unsigned short elemAttrDefaultQualified = 0; + + if (XMLString::equals(schemaRoot->getAttribute(SchemaSymbols::fgATT_ELEMENTFORMDEFAULT), + SchemaSymbols::fgATTVAL_QUALIFIED)) { + elemAttrDefaultQualified |= Elem_Def_Qualified; + } + + if (XMLString::equals(schemaRoot->getAttribute(SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT), + SchemaSymbols::fgATTVAL_QUALIFIED)) { + elemAttrDefaultQualified |= Attr_Def_Qualified; + } + + fSchemaInfo->setElemAttrDefaultQualified(elemAttrDefaultQualified); + fSchemaInfo->setBlockDefault(parseBlockSet(schemaRoot, ES_Block, true)); + fSchemaInfo->setFinalDefault(parseFinalSet(schemaRoot, ECS_Final, true)); +} + + +XSAnnotation* +TraverseSchema::traverseAnnotationDecl(const DOMElement* const annotationElem, + ValueVectorOf* const nonXSAttList, + const bool topLevel) { + + NamespaceScopeManager nsMgr(annotationElem, fSchemaInfo, this); + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + annotationElem, GeneralAttributeCheck::E_Annotation, this, topLevel + ); + + const XMLCh* contents = 0; + DOMElement* child = XUtil::getFirstChildElement(annotationElem); + if (child) { + for (; + child != 0; + child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* name = child->getLocalName(); + + if (XMLString::equals(name, SchemaSymbols::fgELT_APPINFO)) { + + DOMNode* textContent = child->getFirstChild(); + if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE) + contents = ((DOMText*) textContent)->getData(); + + fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Appinfo, this); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_DOCUMENTATION)) { + + DOMNode* textContent = child->getFirstChild(); + if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE) + contents = ((DOMText*) textContent)->getData(); + + fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Documentation, this); + } + else { + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAnnotationContent); + } + } + } + else + { + // If the Annotation has no children, get the text directly + DOMNode* textContent = annotationElem->getFirstChild(); + if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE) + contents = ((DOMText*) textContent)->getData(); + } + + if (contents && !fScanner->getIgnoreAnnotations()) + { + XSAnnotation* theAnnotation = 0; + + XMLSize_t nonXSAttSize = nonXSAttList->size(); + + if (nonXSAttSize) + { + int annotTokenStart = XMLString::patternMatch( + contents, SchemaSymbols::fgELT_ANNOTATION); + + if (annotTokenStart == -1) // something is wrong + return 0; + + // set annotation element + fBuffer.set(contents, annotTokenStart + 10); + + for (XMLSize_t i=0; ielementAt(i); + + if (!XMLString::equals( + annotationElem->getAttributeNS( + attNode->getNamespaceURI(), attNode->getLocalName()) + , XMLUni::fgZeroLenString) + ) + { + continue; + } + + fBuffer.append(chSpace); + fBuffer.append(attNode->getNodeName()); + fBuffer.append(chEqual); + fBuffer.append(chDoubleQuote); + processAttValue(attNode->getNodeValue(), fBuffer); + fBuffer.append(chDoubleQuote); + } + + // add remaining annotation content + fBuffer.append(contents + annotTokenStart + 10); + + theAnnotation = new (fGrammarPoolMemoryManager) XSAnnotation(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager); + } + else + { + theAnnotation = new (fGrammarPoolMemoryManager) XSAnnotation(contents, fGrammarPoolMemoryManager); + } + + /*** + * set line, col and systemId info + ***/ + theAnnotation->setLineCol( + ((XSDElementNSImpl*)annotationElem)->getLineNo() + , ((XSDElementNSImpl*)annotationElem)->getColumnNo() + ); + theAnnotation->setSystemId(fSchemaInfo->getCurrentSchemaURL()); + + return theAnnotation; + } + + return 0; +} + + +/** + * Traverse include + * + * + * Content: (annotation?) + * + */ +void TraverseSchema::preprocessInclude(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Include, this, true, fNonXSAttList); + + // ----------------------------------------------------------------------- + // First, handle any ANNOTATION declaration + // ----------------------------------------------------------------------- + if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + + if (fAnnotation) + fSchemaGrammar->addAnnotation(fAnnotation); + else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + fSchemaGrammar->addAnnotation(fAnnotation); + } + + // ----------------------------------------------------------------------- + // Get 'schemaLocation' attribute + // ----------------------------------------------------------------------- + const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI); + + if (!schemaLocation || !*schemaLocation) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNoSchemaLocation, SchemaSymbols::fgELT_INCLUDE); + return; + } + + // ------------------------------------------------------------------ + // Resolve schema location + // ------------------------------------------------------------------ + fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, + ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + InputSource* srcToFill = resolveSchemaLocation(schemaLocation, + XMLResourceIdentifier::SchemaInclude); + Janitor janSrc(srcToFill); + + // Nothing to do + if (!srcToFill) { + return; + } + + const XMLCh* includeURL = srcToFill->getSystemId(); + SchemaInfo* includeSchemaInfo = fCachedSchemaInfoList->get(includeURL, fTargetNSURI); + + if (!includeSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList) + includeSchemaInfo = fSchemaInfoList->get(includeURL, fTargetNSURI); + + if (includeSchemaInfo) { + + fSchemaInfo->addSchemaInfo(includeSchemaInfo, SchemaInfo::INCLUDE); + return; + } + + // ------------------------------------------------------------------ + // Parse input source + // ------------------------------------------------------------------ + if (!fParser) + fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0, fGrammarPoolMemoryManager, 0); + + fParser->setValidationScheme(XercesDOMParser::Val_Never); + fParser->setDoNamespaces(true); + fParser->setUserEntityHandler(fEntityHandler); + fParser->setUserErrorReporter(fErrorReporter); + + // Should just issue warning if the schema is not found + bool flag = srcToFill->getIssueFatalErrorIfNotFound(); + srcToFill->setIssueFatalErrorIfNotFound(false); + + fParser->parse(*srcToFill); + + // Reset the InputSource + srcToFill->setIssueFatalErrorIfNotFound(flag); + + if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal()) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError); + + // ------------------------------------------------------------------ + // Get root element + // ------------------------------------------------------------------ + DOMDocument* document = fParser->getDocument(); + + if (document) { + + DOMElement* root = document->getDocumentElement(); + + if (root) { + + const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + + // check to see if targetNameSpace is right + if (*targetNSURIString + && !XMLString::equals(targetNSURIString,fTargetNSURIString)){ + reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::IncludeNamespaceDifference, + schemaLocation, targetNSURIString); + return; + } + + // if targetNamespace is empty, change it to includ'g schema + // targetNamespace + if (!*targetNSURIString && root->getAttributeNode(XMLUni::fgXMLNSString) == 0 + && fTargetNSURI != fEmptyNamespaceURI) { + root->setAttribute(XMLUni::fgXMLNSString, fTargetNSURIString); + } + + // -------------------------------------------------------- + // Update schema information with included schema + // -------------------------------------------------------- + SchemaInfo* saveInfo = fSchemaInfo; + + fSchemaInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, + 0, + includeURL, + fTargetNSURIString, root, + fScanner, + fGrammarPoolMemoryManager); + + fSchemaInfo->getNamespaceScope()->reset(fEmptyNamespaceURI); + // Add mapping for the xml prefix + fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName)); + + fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), + fSchemaInfo->getTargetNSURI(), fSchemaInfo); + fPreprocessedNodes->put((void*) elem, fSchemaInfo); + saveInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE); + traverseSchemaHeader(root); + preprocessChildren(root); + fSchemaInfo = saveInfo; + } + } +} + + +void TraverseSchema::traverseInclude(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + SchemaInfo* includeInfo = fPreprocessedNodes->get(elem); + + if (includeInfo) { + + SchemaInfo* saveInfo = fSchemaInfo; + + fSchemaInfo = includeInfo; + processChildren(includeInfo->getRoot()); + fSchemaInfo = saveInfo; + } +} + + +/** + * Traverse import + * + * + * Content: (annotation?) + * + */ +void TraverseSchema::preprocessImport(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Import, this, true, fNonXSAttList); + + // ----------------------------------------------------------------------- + // First, handle any ANNOTATION declaration + // ----------------------------------------------------------------------- + if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + + if (fAnnotation) + fSchemaGrammar->addAnnotation(fAnnotation); + else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + fSchemaGrammar->addAnnotation(fAnnotation); + } + // ----------------------------------------------------------------------- + // Handle 'namespace' attribute + // ----------------------------------------------------------------------- + const XMLCh* nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE, DatatypeValidator::AnyURI); + const XMLCh* nameSpaceValue = nameSpace ? nameSpace : XMLUni::fgZeroLenString; + + if (XMLString::equals(nameSpaceValue, fTargetNSURIString)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_1); + return; + } + + if (!*nameSpaceValue && fTargetNSURI == fEmptyNamespaceURI) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_2); + return; + } + + // ------------------------------------------------------------------ + // Get 'schemaLocation' attribute + // ------------------------------------------------------------------ + const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI); + + // ------------------------------------------------------------------ + // Resolve namespace to a grammar + // ------------------------------------------------------------------ + Grammar* aGrammar = 0; + + { + XMLSchemaDescription* gramDesc =fGrammarResolver->getGrammarPool()->createSchemaDescription(nameSpaceValue); + Janitor janName(gramDesc); + gramDesc->setContextType(XMLSchemaDescription::CONTEXT_IMPORT); + gramDesc->setLocationHints(schemaLocation); + aGrammar = fGrammarResolver->getGrammar(gramDesc); + } + + bool grammarFound = (aGrammar && (aGrammar->getGrammarType() == Grammar::SchemaGrammarType)); + + if (grammarFound) { + addImportedNS(fURIStringPool->addOrFind(nameSpaceValue)); + } + + // a bare doesn't load anything + if(!schemaLocation && !nameSpace) + return; + + // ------------------------------------------------------------------ + // Resolve schema location + // ------------------------------------------------------------------ + fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, + ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + InputSource* srcToFill = resolveSchemaLocation(schemaLocation, + XMLResourceIdentifier::SchemaImport, nameSpace); + + // Nothing to do + if (!srcToFill) { + if (!grammarFound) { + addImportedNS(fURIStringPool->addOrFind(nameSpaceValue)); + } + + return; + } + + Janitor janSrc(srcToFill); + const XMLCh* importURL = srcToFill->getSystemId(); + unsigned int nameSpaceId = nameSpace ? fURIStringPool->addOrFind(nameSpace) : fEmptyNamespaceURI; + + SchemaInfo* importSchemaInfo = fCachedSchemaInfoList->get(importURL, nameSpaceId); + + if (!importSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList) + importSchemaInfo = fSchemaInfoList->get(importURL, nameSpaceId); + + if (importSchemaInfo) { + fSchemaInfo->addSchemaInfo(importSchemaInfo, SchemaInfo::IMPORT); + addImportedNS(importSchemaInfo->getTargetNSURI()); + return; + } + + if (grammarFound) { + if (!fScanner->getHandleMultipleImports()) + return; + } + + // ------------------------------------------------------------------ + // Parse input source + // ------------------------------------------------------------------ + if (!fParser) + fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0, fGrammarPoolMemoryManager, 0); + + fParser->setValidationScheme(XercesDOMParser::Val_Never); + fParser->setDoNamespaces(true); + fParser->setUserEntityHandler(fEntityHandler); + fParser->setUserErrorReporter(fErrorReporter); + + // Should just issue warning if the schema is not found + bool flag = srcToFill->getIssueFatalErrorIfNotFound(); + srcToFill->setIssueFatalErrorIfNotFound(false); + + fParser->parse(*srcToFill) ; + + // Reset the InputSource + srcToFill->setIssueFatalErrorIfNotFound(flag); + + if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal()) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError); + + // ------------------------------------------------------------------ + // Get root element + // ------------------------------------------------------------------ + DOMDocument* document = fParser->getDocument(); + + if (document) { + + DOMElement* root = document->getDocumentElement(); + + if (!root) { + return; + } + + const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + + if (!XMLString::equals(targetNSURIString, nameSpaceValue)) { + reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::ImportNamespaceDifference, + schemaLocation, targetNSURIString, nameSpaceValue); + } + else { + + // -------------------------------------------------------- + // Preprocess new schema + // -------------------------------------------------------- + SchemaInfo* saveInfo = fSchemaInfo; + fSchemaGrammar->setScopeCount (fScopeCount); + fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount); + if (grammarFound) { + fSchemaGrammar = (SchemaGrammar*) aGrammar; + } + else { + fSchemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); + } + fScopeCount = fSchemaGrammar->getScopeCount (); + fAnonXSTypeCount = fSchemaGrammar->getAnonTypeCount (); + + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) fSchemaGrammar->getGrammarDescription(); + gramDesc->setContextType(XMLSchemaDescription::CONTEXT_IMPORT); + gramDesc->setLocationHints(importURL); + + preprocessSchema(root, importURL, grammarFound); + fPreprocessedNodes->put((void*) elem, fSchemaInfo); + + // -------------------------------------------------------- + // Restore old schema information + // -------------------------------------------------------- + restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT); + } + } +} + + +void TraverseSchema::traverseImport(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + SchemaInfo* importInfo = fPreprocessedNodes->get(elem); + + if (importInfo) { + + // -------------------------------------------------------- + // Traverse new schema + // -------------------------------------------------------- + SchemaInfo* saveInfo = fSchemaInfo; + + restoreSchemaInfo(importInfo, SchemaInfo::IMPORT); + doTraverseSchema(importInfo->getRoot()); + + // -------------------------------------------------------- + // Restore old schema information + // -------------------------------------------------------- + restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT); + } +} + + +/** + * Traverse redefine declaration + * + * + * schemaLocation = uriReference + * {any attributes with non-schema namespace . . .}> + * Content: (annotation | ( + * attributeGroup | complexType | group | simpleType))* + * + */ +void TraverseSchema::preprocessRedefine(const DOMElement* const redefineElem) { + + NamespaceScopeManager nsMgr(redefineElem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + redefineElem, GeneralAttributeCheck::E_Redefine, this, true + ); + + // First, we look through the children of redefineElem. Each one will + // correspond to an element of the redefined schema that we need to + // redefine. To do this, we rename the element of the redefined schema, + // and rework the base or ref tag of the kid we're working on to refer to + // the renamed group or derive the renamed type. Once we've done this, we + // actually go through the schema being redefined and convert it to a + // grammar. Only then do we run through redefineDecl's kids and put them + // in the grammar. + SchemaInfo* redefiningInfo = fSchemaInfo; + + if (!openRedefinedSchema(redefineElem)) { + + redefiningInfo->addFailedRedefine(redefineElem); + return; + } + + if (!fRedefineComponents) { + fRedefineComponents = new (fMemoryManager) RefHash2KeysTableOf(13, (bool) false, fMemoryManager); + } + + SchemaInfo* redefinedInfo = fSchemaInfo; + renameRedefinedComponents(redefineElem, redefiningInfo, redefinedInfo); + + // Now we have to preprocess our nicely-renamed schemas. + if (fPreprocessedNodes->containsKey(redefineElem)) { + + fSchemaInfo = redefinedInfo; + preprocessChildren(fSchemaInfo->getRoot()); + } + + fSchemaInfo = redefiningInfo; +} + +void TraverseSchema::traverseRedefine(const DOMElement* const redefineElem) { + + NamespaceScopeManager nsMgr(redefineElem, fSchemaInfo, this); + + SchemaInfo* saveInfo = fSchemaInfo; + SchemaInfo* redefinedInfo = fPreprocessedNodes->get(redefineElem); + + if (redefinedInfo) { + + // Now we have to march through our nicely-renamed schemas. When + // we do these traversals other 's may perhaps be + // encountered; we leave recursion to sort this out. + fSchemaInfo = redefinedInfo; + processChildren(fSchemaInfo->getRoot()); + fSchemaInfo = saveInfo; + + // Now traverse our own + processChildren(redefineElem); + } +} + + +/** + * Traverse the Choice, Sequence declaration + * + * + */ +ContentSpecNode* +TraverseSchema::traverseChoiceSequence(const DOMElement* const elem, + const int modelGroupType, + bool& hasChildren) +{ + hasChildren = false; + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Sequence, this, false, fNonXSAttList + ); + + // ----------------------------------------------------------------------- + // Process contents + // ----------------------------------------------------------------------- + DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + Janitor left(0); + Janitor right(0); + + bool hadContent = false; + + Janitor contentSpecNode(0); + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + hasChildren = true; + contentSpecNode.release(); + bool seeParticle = false; + bool wasAny = false; + const XMLCh* childName = child->getLocalName(); + + if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) { + + SchemaElementDecl* elemDecl = traverseElementDecl(child); + + if (!elemDecl ) + continue; + + contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode + ( + elemDecl + , fGrammarPoolMemoryManager + )); + seeParticle = true; + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_GROUP)) { + + XercesGroupInfo* grpInfo = traverseGroupDecl(child, false); + + if (!grpInfo) { + continue; + } + + ContentSpecNode* grpContentSpecNode = grpInfo->getContentSpec(); + + if (!grpContentSpecNode) { + continue; + } + + if (grpContentSpecNode->hasAllContent()) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentLimited); + continue; + } + + contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*grpContentSpecNode)); + seeParticle = true; + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) { + bool hasChild; + contentSpecNode.reset(traverseChoiceSequence(child,ContentSpecNode::Choice, hasChild)); + seeParticle = true; + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) { + bool hasChild; + contentSpecNode.reset(traverseChoiceSequence(child,ContentSpecNode::Sequence, hasChild)); + seeParticle = true; + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANY)) { + + contentSpecNode.reset(traverseAny(child)); + seeParticle = true; + wasAny = true; + } + else { + reportSchemaError(child, XMLUni::fgValidityDomain, XMLValid::GroupContentRestricted, + childName, + ((ContentSpecNode::NodeTypes) modelGroupType) == ContentSpecNode::Choice?SchemaSymbols::fgELT_CHOICE:SchemaSymbols::fgELT_SEQUENCE); + } + + if (seeParticle) { + checkMinMax(contentSpecNode.get(), child, Not_All_Context); + if (wasAny && contentSpecNode.get()->getMaxOccurs() == 0) { + contentSpecNode.reset(0); + } + } + + if (contentSpecNode.get()) { + hadContent = true; + } + + if (left.get() == 0) { + left.reset(contentSpecNode.release()); + } + else if (right.get() == 0) { + right.reset(contentSpecNode.release()); + } + else { + ContentSpecNode* newNode = + new (fGrammarPoolMemoryManager) ContentSpecNode + ( + (ContentSpecNode::NodeTypes) modelGroupType + , left.get() + , right.get() + , true + , true + , fGrammarPoolMemoryManager + ); + + left.release(); + right.release(); + + left.reset(newNode); + right.reset(contentSpecNode.release()); + } + } + contentSpecNode.release(); + + if (hadContent) + { + ContentSpecNode* newNode = + new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ((ContentSpecNode::NodeTypes) modelGroupType) == ContentSpecNode::Choice + ? ContentSpecNode::ModelGroupChoice : ContentSpecNode::ModelGroupSequence + , left.get() + , right.get() + , true + , true + , fGrammarPoolMemoryManager + ); + + left.release(); + + left.reset(newNode); + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(left.get(), janAnnot.release()); + } + + right.release(); + return left.release(); +} + +/** + * Traverse SimpleType declaration: + * + * Content: (annotation? , ((list | restriction | union))) + * + * + * traverse || + */ +DatatypeValidator* +TraverseSchema::traverseSimpleTypeDecl(const DOMElement* const childElem, + const bool topLevel, int baseRefContext) +{ + NamespaceScopeManager nsMgr(childElem, fSchemaInfo, this); + + // ------------------------------------------------------------------ + // Process contents + // ------------------------------------------------------------------ + const XMLCh* name = getElementAttValue(childElem,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + bool nameEmpty = (!name || !*name); + + if (topLevel && nameEmpty) { + reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, + SchemaSymbols::fgELT_SIMPLETYPE); + return 0; + } + else if(!topLevel && !nameEmpty) { + reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDisallowedLocal, + SchemaSymbols::fgATT_NAME, childElem->getLocalName()); + return 0; + } + + if (nameEmpty) { // anonymous simpleType + name = genAnonTypeName(fgAnonSNamePrefix); + } + else if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) { + + reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_SIMPLETYPE, name); + return 0; + } + + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(name); + + unsigned int fullTypeNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); + const XMLCh* fullName = fStringPool->getValueForId(fullTypeNameId); + + //check if we have already traversed the same simpleType decl + DatatypeValidator* dv = fDatatypeRegistry->getDatatypeValidator(fullName); + + if (!dv) { + + // ------------------------------------------------------------------- + // Check attributes + // ------------------------------------------------------------------- + unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_SimpleTypeGlobal + : GeneralAttributeCheck::E_SimpleTypeLocal; + + fAttributeCheck.checkAttributes( + childElem, scope, this, topLevel, fNonXSAttList + ); + + // Circular constraint checking + if (fCurrentTypeNameStack->containsElement(fullTypeNameId)) { + + reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name); + return 0; + } + + fCurrentTypeNameStack->addElement(fullTypeNameId); + + // Get 'final' values + int finalSet = parseFinalSet(childElem, S_Final); + + // annotation?,(list|restriction|union) + DOMElement* content= checkContent( + childElem, XUtil::getFirstChildElement(childElem), false); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(childElem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + if (content == 0) { + + reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent); + popCurrentTypeNameStack(); + return 0; + } + + const XMLCh* varietyName = content->getLocalName(); + + // Remark: some code will be repeated in list|restriction| union but it + // is cleaner that way + if (XMLString::equals(varietyName, SchemaSymbols::fgELT_LIST)) { //traverse List + if ((baseRefContext & SchemaSymbols::XSD_LIST) != 0) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType); + popCurrentTypeNameStack(); + return 0; + } + + dv = traverseByList(childElem, content, name, fullName, finalSet, &janAnnot); + } + else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_RESTRICTION)) { //traverse Restriction + dv = traverseByRestriction(childElem, content, name, fullName, finalSet, &janAnnot); + } + else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_UNION)) { //traverse union + dv = traverseByUnion(childElem, content, name, fullName, finalSet, baseRefContext, &janAnnot); + } + else { + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::FeatureUnsupported, varietyName); + popCurrentTypeNameStack(); + } + + if (dv) { + if (nameEmpty) + dv->setAnonymous(); + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(dv, janAnnot.release()); + } + } + + return dv; +} + +/** + * Traverse ComplexType Declaration - CR Implementation. + * + * + * Content: (annotation? , (simpleContent | complexContent | + * ( (group | all | choice | sequence)? , + * ( (attribute | attributeGroup)* , anyAttribute?)))) + * + */ +int TraverseSchema::traverseComplexTypeDecl(const DOMElement* const elem, + const bool topLevel, + const XMLCh* const recursingTypeName) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // Get the attributes of the complexType + const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + bool isAnonymous = false; + + if (!name || !*name) { + + if (topLevel) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameComplexType); + return -1; + } + + if (recursingTypeName) + name = recursingTypeName; + else { + name = genAnonTypeName(fgAnonCNamePrefix); + isAnonymous = true; + } + } + + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) { + + //REVISIT - Should we return or continue and save type with wrong name? + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_COMPLEXTYPE, name); + return -1; + } + + // ------------------------------------------------------------------ + // Check if the type has already been registered + // ------------------------------------------------------------------ + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(name); + + int typeNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); + const XMLCh* fullName = fStringPool->getValueForId(typeNameIndex); + ComplexTypeInfo* typeInfo = 0; + + if (topLevel || recursingTypeName) { + + typeInfo = fComplexTypeRegistry->get(fullName); + + if (typeInfo && !typeInfo->getPreprocessed()) { + return typeNameIndex; + } + } + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + bool preProcessFlag = (typeInfo) ? typeInfo->getPreprocessed() : false; + if (!preProcessFlag) { + fAttributeCheck.checkAttributes( + elem, (topLevel) ? GeneralAttributeCheck::E_ComplexTypeGlobal + : GeneralAttributeCheck::E_ComplexTypeLocal + , this, topLevel, fNonXSAttList + ); + } + + // ----------------------------------------------------------------------- + // Create a new instance + // ----------------------------------------------------------------------- + XMLSize_t previousCircularCheckIndex = fCircularCheckIndex; + unsigned int previousScope = fCurrentScope; + + if (preProcessFlag) { + + fCurrentScope = typeInfo->getScopeDefined(); + typeInfo->setPreprocessed(false); + } + else { + + // ------------------------------------------------------------------ + // Register the type + // ------------------------------------------------------------------ + typeInfo = new (fGrammarPoolMemoryManager) ComplexTypeInfo(fGrammarPoolMemoryManager); + if(isAnonymous) { + typeInfo->setAnonymous(); + } + + fCurrentScope = fScopeCount++; + fComplexTypeRegistry->put((void*) fullName, typeInfo); + typeInfo->setTypeName(fullName); + typeInfo->setScopeDefined(fCurrentScope); + + if (fFullConstraintChecking) { + + XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator(); + aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())), + 0, ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + typeInfo->setLocator(aLocator); + } + } + + fCurrentTypeNameStack->addElement(typeNameIndex); + ComplexTypeInfo* saveTypeInfo = fCurrentComplexType; + fCurrentComplexType = typeInfo; + + // ------------------------------------------------------------------ + // First, handle any ANNOTATION declaration and get next child + // ------------------------------------------------------------------ + DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true, !preProcessFlag); + + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + + // ------------------------------------------------------------------ + // Process the content of the complex type declaration + // ------------------------------------------------------------------ + try { + + const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED, DatatypeValidator::Boolean); + bool isMixed = false; + + if ((mixedVal && *mixedVal) + && (XMLString::equals(SchemaSymbols::fgATTVAL_TRUE, mixedVal) + || XMLString::equals(fgValueOne, mixedVal))) { + isMixed = true; + } + + if (child == 0) { + // EMPTY complexType with complexContent + processComplexContent(elem, name, child, typeInfo, 0, isMixed); + } + else { + + const XMLCh* childName = child->getLocalName(); + + if (XMLString::equals(childName, SchemaSymbols::fgELT_SIMPLECONTENT)) { + + // SIMPLE CONTENT element + traverseSimpleContentDecl(name, fullName, child, typeInfo, &janAnnot); + + if (XUtil::getNextSiblingElement(child) != 0) { + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingSimpleContent); + } + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_COMPLEXCONTENT)) { + + // COMPLEX CONTENT element + traverseComplexContentDecl(name, child, typeInfo, isMixed, &janAnnot); + + if (XUtil::getNextSiblingElement(child) != 0) { + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingConplexContent); + } + } + else if (fCurrentGroupInfo) { + typeInfo->setPreprocessed(true); + } + else { + // We must have .... + // GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes + // Note that it's possible that only attributes are specified. + processComplexContent(elem, name, child, typeInfo, 0, isMixed); + } + } + } + catch(const TraverseSchema::ExceptionCodes aCode) { + if (aCode == TraverseSchema::InvalidComplexTypeInfo) + defaultComplexTypeInfo(typeInfo); + else if (aCode == TraverseSchema::RecursingElement) + typeInfo->setPreprocessed(); + } + + // ------------------------------------------------------------------ + // Finish the setup of the typeInfo + // ------------------------------------------------------------------ + if (!preProcessFlag) { + + const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT, DatatypeValidator::Boolean); + int blockSet = parseBlockSet(elem, C_Block); + int finalSet = parseFinalSet(elem, EC_Final); + + typeInfo->setBlockSet(blockSet); + typeInfo->setFinalSet(finalSet); + + if ((abstractAttVal && *abstractAttVal) + && (XMLString::equals(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE) + || XMLString::equals(abstractAttVal, fgValueOne))) { + typeInfo->setAbstract(true); + } + else { + typeInfo->setAbstract(false); + } + } + + // Store Annotation + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(typeInfo, janAnnot.release()); + + // ------------------------------------------------------------------ + // Before exiting, restore the scope, mainly for nested anonymous types + // ------------------------------------------------------------------ + popCurrentTypeNameStack(); + fCircularCheckIndex = previousCircularCheckIndex; + fCurrentScope = previousScope; + fCurrentComplexType = saveTypeInfo; + + return typeNameIndex; +} + +/** + * Traverse Group Declaration. + * + * + * Content: (annotation? , (all | choice | sequence)?) + * + * + */ +XercesGroupInfo* +TraverseSchema::traverseGroupDecl(const DOMElement* const elem, + const bool topLevel) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); + bool nameEmpty = (!name || !*name); + bool refEmpty = (!ref || !*ref); + + if (nameEmpty && topLevel) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, + SchemaSymbols::fgELT_GROUP); + return 0; + } + + if (nameEmpty && refEmpty) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefGroup); + return 0; + } + + // ------------------------------------------------------------------ + // Check attributes + // ------------------------------------------------------------------ + unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_GroupGlobal + : GeneralAttributeCheck::E_GroupRef; + fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); + + // ------------------------------------------------------------------ + // Handle "ref=" + // ------------------------------------------------------------------ + if (!topLevel) { + + if (refEmpty) { + return 0; + } + + return processGroupRef(elem, ref); + } + + // name must be a valid NCName + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_GROUP, name); + return 0; + } + + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(name); + + unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); + const XMLCh* fullName = fStringPool->getValueForId(nameIndex); + XercesGroupInfo* groupInfo = fGroupRegistry->get(fullName); + + if (groupInfo) { + return groupInfo; + } + + // ------------------------------------------------------------------ + // Check for annotations + // ------------------------------------------------------------------ + DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + // ------------------------------------------------------------------ + // Process contents of global groups + // ------------------------------------------------------------------ + unsigned int saveScope = fCurrentScope; + Janitor specNode(0); + XercesGroupInfo* saveGroupInfo = fCurrentGroupInfo; + + Janitor newGroupInfoJan(new (fGrammarPoolMemoryManager) XercesGroupInfo( + fStringPool->addOrFind(name), fTargetNSURI, fGrammarPoolMemoryManager)); + fCurrentGroupStack->addElement(nameIndex); + XercesGroupInfo* const newGroupInfo = newGroupInfoJan.get(); + fCurrentGroupInfo = newGroupInfo; + + fCurrentScope = fScopeCount++; + fCurrentGroupInfo->setScope(fCurrentScope); + + if (content == 0) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name); + } + else { + + if (content->getAttributeNode(SchemaSymbols::fgATT_MINOCCURS) != 0 + || content->getAttributeNode(SchemaSymbols::fgATT_MAXOCCURS) != 0) { + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::MinMaxOnGroupChild); + } + + bool illegalChild = false; + const XMLCh* childName = content->getLocalName(); + bool hasChild; + + + if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) { + specNode.reset(traverseChoiceSequence(content, ContentSpecNode::Sequence, hasChild)); + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) { + specNode.reset(traverseChoiceSequence(content, ContentSpecNode::Choice, hasChild)); + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_ALL)) { + specNode.reset(traverseAll(content, hasChild)); + } + else { + illegalChild = true; + } + + if (illegalChild || XUtil::getNextSiblingElement(content) != 0) { + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name); + } + + // copy local elements to complex type if it exists + if (fCurrentComplexType) + processElements(elem, fCurrentGroupInfo, fCurrentComplexType); + } + + // ------------------------------------------------------------------ + // Set groupInfo and pop group name from stack + // ------------------------------------------------------------------ + XMLSize_t stackSize = fCurrentGroupStack->size(); + + if (stackSize != 0) { + fCurrentGroupStack->removeElementAt(stackSize - 1); + } + + fCurrentGroupInfo->setContentSpec(specNode.release()); + fGroupRegistry->put((void*) fullName, fCurrentGroupInfo); + newGroupInfoJan.release(); + fCurrentGroupInfo = saveGroupInfo; + fCurrentScope = saveScope; + + // Store Annotation + if (!janAnnot.isDataNull()) { + fSchemaGrammar->putAnnotation(newGroupInfo, janAnnot.release()); + } + + if (fFullConstraintChecking) { + + XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator(); + + newGroupInfo->setLocator(aLocator); + aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())), + 0, ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + + if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_GROUP, nameIndex)) + { + + fBuffer.set(fullName); + fBuffer.append(SchemaSymbols::fgRedefIdentifier); + unsigned int rdfNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); + + if (fCurrentGroupStack->containsElement(rdfNameIndex)) + { + reportSchemaError(aLocator, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name); + } + else + { + XercesGroupInfo* baseGroup = fGroupRegistry->get(fBuffer.getRawBuffer()); + if (baseGroup) + { + newGroupInfo->setBaseGroup(baseGroup); + } + else + { + fBuffer.set(name); + fBuffer.append(SchemaSymbols::fgRedefIdentifier); + SchemaInfo* saveInfo = fSchemaInfo; + DOMElement* groupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Group, + SchemaSymbols::fgELT_GROUP, fBuffer.getRawBuffer(), &fSchemaInfo); + + if (groupElem != 0) { + baseGroup = traverseGroupDecl(groupElem); + newGroupInfo->setBaseGroup(baseGroup); + fSchemaInfo = saveInfo; + } + else + { + reportSchemaError(aLocator, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, + SchemaSymbols::fgELT_GROUP, fTargetNSURIString, fBuffer.getRawBuffer()); + } + } + } + } + } + + return newGroupInfo; +} + + +/** + * Traverse attributeGroup Declaration. + * + * + * Content: (annotation? , (attribute|attributeGroup)*, anyAttribute?) + * + * + */ +XercesAttGroupInfo* +TraverseSchema::traverseAttributeGroupDecl(const DOMElement* const elem, + ComplexTypeInfo* const typeInfo, + const bool topLevel) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); + bool nameEmpty = (!name || !*name) ? true : false; + bool refEmpty = (!ref || !*ref) ? true : false; + + if (nameEmpty && topLevel) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, + SchemaSymbols::fgELT_ATTRIBUTEGROUP); + return 0; + } + + if (nameEmpty && refEmpty) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttGroup); + return 0; + } + + // ------------------------------------------------------------------ + // Check attributes + // ------------------------------------------------------------------ + unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_AttributeGroupGlobal + : GeneralAttributeCheck::E_AttributeGroupRef; + fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); + + // ------------------------------------------------------------------ + // Handle "ref=" + // ------------------------------------------------------------------ + XercesAttGroupInfo* attGroupInfo; + Janitor janAttGroupInfo(0); + if (!topLevel) { + + if (refEmpty) { + return 0; + } + + attGroupInfo = processAttributeGroupRef(elem, ref, typeInfo); + } + else + { + // name must be a valid NCName + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_ATTRIBUTEGROUP, name); + return 0; + } + + // Check for annotations + DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + + // Process contents of global attributeGroups + XercesAttGroupInfo* saveAttGroupInfo = fCurrentAttGroupInfo; + janAttGroupInfo.reset(new (fGrammarPoolMemoryManager) XercesAttGroupInfo( + fStringPool->addOrFind(name), fTargetNSURI, fGrammarPoolMemoryManager)); + + fDeclStack->addElement(elem); + fCurrentAttGroupInfo = janAttGroupInfo.get(); + + for (; content !=0; content = XUtil::getNextSiblingElement(content)) { + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ATTRIBUTE)) { + traverseAttributeDecl(content, typeInfo); + } + else if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { + traverseAttributeGroupDecl(content, typeInfo); + } + else { + break; + } + } + + if (content != 0) { + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANYATTRIBUTE)) { + + SchemaAttDef* anyAtt = traverseAnyAttribute(content); + + if (anyAtt) { + fCurrentAttGroupInfo->addAnyAttDef(anyAtt); + } + + if (XUtil::getNextSiblingElement(content) != 0) { + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name); + } + } + else { + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name); + } + } + + // Pop declaration + fDeclStack->removeElementAt(fDeclStack->size() - 1); + + fAttGroupRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), janAttGroupInfo.get()); + // Restore old attGroupInfo + attGroupInfo = janAttGroupInfo.release(); + fCurrentAttGroupInfo = saveAttGroupInfo; + + // Check Attribute Derivation Restriction OK + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(name); + + unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); + + if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_ATTRIBUTEGROUP, nameIndex)) { + + fBuffer.set(name); + fBuffer.append(SchemaSymbols::fgRedefIdentifier); + XercesAttGroupInfo* baseAttGroupInfo = fAttGroupRegistry->get(fBuffer.getRawBuffer()); + + if (baseAttGroupInfo) + checkAttDerivationOK(elem, baseAttGroupInfo, attGroupInfo); + } + + // Store annotation + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(attGroupInfo, janAnnot.release()); + } + + // calculate complete wildcard if necessary + if (attGroupInfo) + { + XMLSize_t anyAttCount = attGroupInfo->anyAttributeCount(); + if (anyAttCount && !attGroupInfo->getCompleteWildCard()) + { + SchemaAttDef* attGroupWildCard = new (fGrammarPoolMemoryManager) + SchemaAttDef(attGroupInfo->anyAttributeAt(0)); + + for (XMLSize_t k= 1; k < anyAttCount; k++) + attWildCardIntersection(attGroupWildCard, attGroupInfo->anyAttributeAt(k)); + + attGroupInfo->setCompleteWildCard(attGroupWildCard); + } + } + + return attGroupInfo; +} + + +inline XercesAttGroupInfo* +TraverseSchema::traverseAttributeGroupDeclNS(const DOMElement* const elem, + const XMLCh* const uriStr, + const XMLCh* const name) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ------------------------------------------------------------------ + // Get grammar information + // ------------------------------------------------------------------ + Grammar* aGrammar = fGrammarResolver->getGrammar(uriStr); + + if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { + + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); + return 0; + } + + XercesAttGroupInfo* attGroupInfo = ((SchemaGrammar*)aGrammar)->getAttGroupInfoRegistry()->get(name); + + return attGroupInfo; +} + +/** + * Traverse Any declaration + * + * + * Content: (annotation?) + * + */ +ContentSpecNode* +TraverseSchema::traverseAny(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Any, this, false, fNonXSAttList + ); + + // ------------------------------------------------------------------ + // First, handle any ANNOTATION declaration + // ------------------------------------------------------------------ + if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + + // ------------------------------------------------------------------ + // Get attributes + // ------------------------------------------------------------------ + const XMLCh* const processContents = getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS); + const XMLCh* const nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE); + + // ------------------------------------------------------------------ + // Set default node type based on 'processContents' value + // ------------------------------------------------------------------ + ContentSpecNode::NodeTypes anyType = ContentSpecNode::Any; + ContentSpecNode::NodeTypes anyLocalType = ContentSpecNode::Any_NS; + ContentSpecNode::NodeTypes anyOtherType = ContentSpecNode::Any_Other; + + if ((processContents && *processContents) + && !XMLString::equals(processContents, SchemaSymbols::fgATTVAL_STRICT)) { + + if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_LAX)) { + + anyType = ContentSpecNode::Any_Lax; + anyOtherType = ContentSpecNode::Any_Other_Lax; + anyLocalType = ContentSpecNode::Any_NS_Lax; + } + else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_SKIP)) { + + anyType = ContentSpecNode::Any_Skip; + anyOtherType = ContentSpecNode::Any_Other_Skip; + anyLocalType = ContentSpecNode::Any_NS_Skip; + } + } + + // ------------------------------------------------------------------ + // Process 'namespace' attribute + // ------------------------------------------------------------------ + ContentSpecNode* retSpecNode = 0; + + if ((!nameSpace || !*nameSpace) + || XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY)) { + retSpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + new (fGrammarPoolMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , fEmptyNamespaceURI + , fGrammarPoolMemoryManager + ) + , false + , fGrammarPoolMemoryManager + ); + retSpecNode->setType(anyType); + } + else if (XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) { + retSpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + new (fGrammarPoolMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , fTargetNSURI, fGrammarPoolMemoryManager + ) + , false + , fGrammarPoolMemoryManager + ); + retSpecNode->setType(anyOtherType); + } + else { + + XMLStringTokenizer nameSpaceTokens(nameSpace, fMemoryManager); + ValueVectorOf uriList(8, fGrammarPoolMemoryManager); + Janitor firstNode(0); + Janitor secondNode(0); + DatatypeValidator* anyURIDV = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYURI); + + while (nameSpaceTokens.hasMoreTokens()) { + + const XMLCh* tokenElem = nameSpaceTokens.nextToken(); + int uriIndex = fEmptyNamespaceURI; + + if (!XMLString::equals(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL)) { // not ##local + + if (XMLString::equals(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE)) { + uriIndex = fTargetNSURI; + } + else { + try { + anyURIDV->validate(tokenElem + , fSchemaInfo->getValidationContext() + , fMemoryManager); + } + catch(const XMLException& excep) { + reportSchemaError(elem, excep); + } + uriIndex = fURIStringPool->addOrFind(tokenElem); + } + } + + if (uriList.containsElement(uriIndex)) { + continue; + } + + uriList.addElement(uriIndex); + + firstNode.release(); + firstNode.reset( new (fGrammarPoolMemoryManager) ContentSpecNode + ( + new (fGrammarPoolMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , uriIndex, fGrammarPoolMemoryManager + ) + , false + , fGrammarPoolMemoryManager + )); + firstNode.get()->setType(anyLocalType); + + if (secondNode.get() == 0) { + secondNode.reset(firstNode.release()); + } + else { + ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::Any_NS_Choice + , secondNode.get() + , firstNode.get() + , true + , true + , fGrammarPoolMemoryManager + ); + secondNode.release(); + secondNode.reset(newNode); + firstNode.release(); + } + } + firstNode.release(); + retSpecNode = secondNode.release(); + } + + // Store annotation + if (retSpecNode && !janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(retSpecNode, janAnnot.release()); + + return retSpecNode; +} + + +/** + * Traverse all + * + * + * Content: (annotation?, element*) + * + */ +ContentSpecNode* +TraverseSchema::traverseAll(const DOMElement* const elem, bool& hasChildren) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + hasChildren = false; + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_All, this, false, fNonXSAttList + ); + + // ----------------------------------------------------------------------- + // Process contents + // ----------------------------------------------------------------------- + DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + + if (child == 0) { + return 0; + } + + Janitor left(0); + Janitor right(0); + Janitor contentSpecNode(0); + bool hadContent = false; + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + hasChildren = true; + contentSpecNode.release(); + const XMLCh* childName = child->getLocalName(); + + if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) { + + SchemaElementDecl* elemDecl = traverseElementDecl(child); + + if (!elemDecl) + continue; + + contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode + ( + elemDecl + , fGrammarPoolMemoryManager + )); + checkMinMax(contentSpecNode.get(), child, All_Element); + } + else { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentError, childName); + continue; + } + + hadContent = true; + + if (!left.get()) { + left.reset(contentSpecNode.release()); + } + else if (!right.get()) { + right.reset(contentSpecNode.release()); + } + else { + ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::All + , left.get() + , right.get() + , true + , true + , fGrammarPoolMemoryManager + ); + left.release(); + left.reset(newNode); + right.release(); + right.reset(contentSpecNode.release()); + } + } + contentSpecNode.release(); + + if (hadContent) { + ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::All + , left.get() + , right.get() + , true + , true + , fGrammarPoolMemoryManager + ); + + left.release(); + left.reset(newNode); + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(left.get(), janAnnot.release()); + } + right.release(); + return left.release(); +} + +/** + * Traverses Schema attribute declaration. + * + * + * Content: (annotation? , simpleType?) + * + * + * @param elem: the declaration of the attribute under consideration + * + * @param typeInfo: Contains the complex type info of the element to which + * the attribute declaration is attached. + * + */ +void TraverseSchema::traverseAttributeDecl(const DOMElement* const elem, + ComplexTypeInfo* const typeInfo, + const bool topLevel) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); + bool nameEmpty = (!name || !*name); + bool refEmpty = (!ref || !*ref); + + if (nameEmpty && refEmpty) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttribute); + return; + } + + if (topLevel && nameEmpty) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameAttribute); + return; + } + + // ------------------------------------------------------------------ + // Check attributes + // ------------------------------------------------------------------ + unsigned short scope = (topLevel) + ? GeneralAttributeCheck::E_AttributeGlobal + : (refEmpty) ? GeneralAttributeCheck::E_AttributeLocal + : GeneralAttributeCheck::E_AttributeRef; + + fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); + + const XMLCh* defaultVal = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT); + const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED); + const XMLCh* useVal = getElementAttValue(elem, SchemaSymbols::fgATT_USE); + const XMLCh* attForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM); + const XMLCh* dvType = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName); + DOMElement* simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true); + Janitor janAnnot(fAnnotation); + bool badContent = false; + + while (simpleType != 0) { + + const XMLCh* contentName = simpleType->getLocalName(); + + if (XMLString::equals(SchemaSymbols::fgELT_SIMPLETYPE, contentName)) { + + if (XUtil::getNextSiblingElement(simpleType) != 0) { + badContent = true; + } + break; + } + + badContent = true; + simpleType = XUtil::getNextSiblingElement(simpleType); + } + + if (badContent) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttributeContent, + (name) ? name : ref); + } + + if (defaultVal) { + + if (fixedVal) { + + fixedVal = 0; + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue, + (name) ? name : ref); + } + + if ((useVal && *useVal) + && !XMLString::equals(useVal, SchemaSymbols::fgATTVAL_OPTIONAL)) { + + useVal = 0; + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue, + (name) ? name : ref); + } + } + + // processing ref + if (!refEmpty && !topLevel) { + + // Check ref representation OK - 3.2.3::3.2 + if (attForm || dvType || (simpleType != 0)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeRefContentError, + (name) ? name : ref); + } + + processAttributeDeclRef(elem, typeInfo, ref, useVal, defaultVal, fixedVal); + return; + } + + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + janAnnot.reset(fAnnotation); + } + + // processing 'name' + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) + || XMLString::equals(name, XMLUni::fgXMLNSString)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ATTRIBUTE, name); + return; + } + + // Check for duplicate declaration + const XMLCh* qualified = SchemaSymbols::fgATTVAL_QUALIFIED; + int uriIndex = fEmptyNamespaceURI; + + if ((fTargetNSURIString && *fTargetNSURIString) + && (topLevel || XMLString::equals(attForm, qualified) + || ((fSchemaInfo->getElemAttrDefaultQualified() & Attr_Def_Qualified) + && (!attForm || !*attForm)))) { + uriIndex = fTargetNSURI; + } + + // make sure that attribute namespace is not xsi uri + if (XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_XSI)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttTNS, name); + return; + } + + if (typeInfo && typeInfo->getAttDef(name, uriIndex) != 0) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name); + return; + } + else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(name, uriIndex)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name); + return; + } + + DatatypeValidator* dv = 0; + XMLAttDef::AttTypes attType = XMLAttDef::Simple; + SchemaInfo* saveInfo = fSchemaInfo; + + if (simpleType != 0) { + + if (dvType && *dvType) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithTypeAndSimpleType, name); + } + + dv = traverseSimpleTypeDecl(simpleType, false); + } + else if (!dvType || !*dvType) { + dv = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYSIMPLETYPE); + } + else { + + checkEnumerationRequiredNotation(elem, name, dvType); + + const XMLCh* localPart = getLocalPart(dvType); + const XMLCh* prefix = getPrefix(dvType); + const XMLCh* typeURI = resolvePrefixToURI(elem, prefix); + DatatypeValidator* dvBack = 0; + + if (XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + dv = fDatatypeRegistry->getDatatypeValidator(localPart); + dvBack = dv; + } + else { //isn't of the schema for schemas namespace... + + dv = getAttrDatatypeValidatorNS(elem, localPart, typeURI); + dvBack = dv; + + while(dv != 0 && !XMLString::equals(dv->getTypeUri(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + dv = dv->getBaseValidator(); + } + + if(dv) + localPart = dv->getTypeLocalName(); + } + + if(dv) { + if (XMLString::equals(localPart,XMLUni::fgIDString)) { + attType = XMLAttDef::ID; + } + else if (XMLString::equals(localPart,XMLUni::fgIDRefString)) { + attType = XMLAttDef::IDRef; + } + else if (XMLString::equals(localPart,XMLUni::fgIDRefsString)) { + attType = XMLAttDef::IDRefs; + } + else if (XMLString::equals(localPart,XMLUni::fgEntityString)) { + attType = XMLAttDef::Entity; + } + else if (XMLString::equals(localPart,XMLUni::fgEntitiesString)) { + attType = XMLAttDef::Entities; + } + else if (XMLString::equals(localPart,XMLUni::fgNmTokenString)) { + attType = XMLAttDef::NmToken; + } + else if (XMLString::equals(localPart,XMLUni::fgNmTokensString)) { + attType = XMLAttDef::NmTokens; + } + else if (XMLString::equals(localPart,XMLUni::fgNotationString)) { + attType = XMLAttDef::Notation; + } + else { + attType = XMLAttDef::Simple; + } + } + else + attType = XMLAttDef::Simple; + + dv = dvBack; + + if (!dv) { + reportSchemaError + ( + elem + , XMLUni::fgXMLErrDomain + , XMLErrs::AttributeSimpleTypeNotFound + , typeURI + , localPart + , name + ); + } + } + + // restore schema information, if necessary + fSchemaInfo = saveInfo; + + bool required = false; + bool prohibited = false; + + if (useVal && *useVal) { + + if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_REQUIRED)) { + required = true; + } + else if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_PROHIBITED)) { + prohibited = true; + } + } + + // validate fixed/default values + const XMLCh* valueToCheck = defaultVal ? defaultVal : fixedVal; + bool ofTypeID = (dv && dv->getType() == DatatypeValidator::ID); + + if (attType == XMLAttDef::Simple && dv && valueToCheck) { + + short wsFacet = dv->getWSFacet(); + if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(valueToCheck)) || + (wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(valueToCheck))) + { + XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager); + ArrayJanitor tempURIName(normalizedValue, fMemoryManager); + if(wsFacet == DatatypeValidator::REPLACE) + XMLString::replaceWS(normalizedValue, fMemoryManager); + else if(wsFacet == DatatypeValidator::COLLAPSE) + XMLString::collapseWS(normalizedValue, fMemoryManager); + valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); + } + try { + dv->validate(valueToCheck + , fSchemaInfo->getValidationContext() + , fMemoryManager); + } + catch (const XMLException& excep) { + reportSchemaError(elem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueToCheck); + } + } + else if((attType == XMLAttDef::NmTokens || attType==XMLAttDef::IDRefs || attType==XMLAttDef::Entities) && + valueToCheck && !XMLString::isWSCollapsed(valueToCheck)) + { + XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager); + ArrayJanitor tempURIName(normalizedValue, fMemoryManager); + XMLString::collapseWS(normalizedValue, fMemoryManager); + valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); + } + + if (ofTypeID && valueToCheck) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, name); + } + + // check for multiple attributes with type derived from ID + if (!topLevel && ofTypeID) { + + if (fCurrentAttGroupInfo) { + + if (fCurrentAttGroupInfo->containsTypeWithId()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, name); + return; + } + + fCurrentAttGroupInfo->setTypeWithId(true); + } + else { + + if (typeInfo->containsAttWithTypeId()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, name); + return; + } + + typeInfo->setAttWithTypeId(true); + } + } + + // create SchemaAttDef + SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef + ( + XMLUni::fgZeroLenString + , name + , uriIndex + , attType + , XMLAttDef::Implied + , fGrammarPoolMemoryManager + ); + + attDef->setDatatypeValidator(dv); + + if (prohibited) { + attDef->setDefaultType(XMLAttDef::Prohibited); + } + else if (required) { + + if (fixedVal) { + attDef->setDefaultType(XMLAttDef::Required_And_Fixed); + } + else { + attDef->setDefaultType(XMLAttDef::Required); + } + } + else { + + if (fixedVal) { + attDef->setDefaultType(XMLAttDef::Fixed); + } + else if (defaultVal) { + attDef->setDefaultType(XMLAttDef::Default); + } + } + + if (valueToCheck) { + attDef->setValue(valueToCheck); + } + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(attDef, janAnnot.release()); + + if (topLevel) + { + fAttributeDeclRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), attDef); + attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL); + } + else + { + if (typeInfo) + { + typeInfo->addAttDef(attDef); + if (!fCurrentAttGroupInfo) + attDef->setPSVIScope(PSVIDefs::SCP_LOCAL); + } + + if (fCurrentAttGroupInfo) { + fCurrentAttGroupInfo->addAttDef(attDef, (typeInfo != 0)); + } + } +} + + +/** + * Traverses Schema element declaration. + * + * + * + * @param elem: the declaration of the element under consideration + */ +SchemaElementDecl* +TraverseSchema::traverseElementDecl(const DOMElement* const elem, + const bool topLevel) +{ + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // if local element and ref attribute exists + if (!topLevel) + { + const XMLCh* refName = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); + if (refName) + return processElementDeclRef(elem, refName); + } + + // check for empty name + const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + if (!name || !*name) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefElement); + return 0; + } + + // make sure that name is a valid NCName + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, + XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ELEMENT, name); + return 0; + } + + // if element already exists, just return --- revisit, it should not happen + if (topLevel) + { + SchemaElementDecl* retDecl = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(fTargetNSURI, name, 0, Grammar::TOP_LEVEL_SCOPE); + if (retDecl) + return retDecl; + } + + // Check attributes + unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_ElementGlobal + : GeneralAttributeCheck::E_ElementLocal; + + fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); + + // check annotation + const DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); + // Put annotations on all elements for the situation where there is a group of + // elements and not all have annotations. + //if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + if (!fAnnotation && fScanner->getGenerateSyntheticAnnotations()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + + // Create element decl + bool isDuplicate = false; + const XMLCh* valueConstraint = 0; + SchemaElementDecl* elemDecl = + createSchemaElementDecl(elem, name, isDuplicate, valueConstraint, topLevel); + + if (!isDuplicate) { + + fSchemaGrammar->putElemDecl(elemDecl); + + if (valueConstraint) + elemDecl->setDefaultValue(valueConstraint); + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(elemDecl, janAnnot.release()); + + if (fCurrentComplexType && + elemDecl->getEnclosingScope() == fCurrentComplexType->getScopeDefined()) { + fCurrentComplexType->addElement(elemDecl); + elemDecl->setPSVIScope(PSVIDefs::SCP_LOCAL); + } + + if (fCurrentGroupInfo && + elemDecl->getEnclosingScope() == fCurrentGroupInfo->getScope()) { + fCurrentGroupInfo->addElement(elemDecl); + elemDecl->setPSVIScope(PSVIDefs::SCP_ABSENT); + } + } + else { + if (fAnnotation) { + XSAnnotation* xsAnnot = fSchemaGrammar->getAnnotation(elemDecl); + if (!xsAnnot) { + fSchemaGrammar->putAnnotation(elemDecl, janAnnot.release()); + } + else { + xsAnnot->setNext(janAnnot.release()); + } + } + } + + // Process children + bool anonymousType = false; + ComplexTypeInfo* typeInfo = 0; + DatatypeValidator* validator = 0; + + if (content != 0) + { + const XMLCh* contentName = content->getLocalName(); + + if (XMLString::equals(contentName, SchemaSymbols::fgELT_COMPLEXTYPE)) + { + const XMLCh* temp = content->getAttribute(SchemaSymbols::fgATT_NAME); + + if (temp && *temp) + { + // REVISIT - we are bypassing the complex type declaration. + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnonComplexTypeWithName, name); + } + else + { + typeInfo = checkForComplexTypeInfo(content); + + if (typeInfo) + { + validator = typeInfo->getDatatypeValidator(); + + if (!isDuplicate) { + + //Recursing element + if (typeInfo->getPreprocessed()) { + + const XMLCh* typeInfoName = typeInfo->getTypeName(); + fSchemaInfo->addRecursingType(content, typeInfoName + XMLString::indexOf(typeInfoName, chComma) + 1); + } + } + } + } + + anonymousType = true; + content = XUtil::getNextSiblingElement(content); + } + else if (XMLString::equals(contentName, SchemaSymbols::fgELT_SIMPLETYPE)) + { + const XMLCh* temp = content->getAttribute(SchemaSymbols::fgATT_NAME); + if (temp && *temp) + // REVISIT - we are bypassing the simple type declaration. + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnonSimpleTypeWithName, name); + else + validator = checkForSimpleTypeValidator(content); + + anonymousType = true; + content = XUtil::getNextSiblingElement(content); + } + + // Check for identity constraints + if (content != 0) + { + content = checkIdentityConstraintContent(content); + if (content != 0) + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementContent); + } + } + + // Handle 'type' attribute + const XMLCh* typeStr = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName); + if (typeStr) + { + if (anonymousType) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithTypeAndAnonType, name); + } + else if (*typeStr) + { + const XMLCh* typeLocalPart = getLocalPart(typeStr); + const XMLCh* typePrefix = getPrefix(typeStr); + const XMLCh* typeURI = resolvePrefixToURI(elem, typePrefix); + + if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + || !XMLString::equals(typeLocalPart, SchemaSymbols::fgATTVAL_ANYTYPE)) + { + checkEnumerationRequiredNotation(elem, name, typeStr); + + bool noErrorFound = true; + const XMLCh* anotherSchemaURI = checkTypeFromAnotherSchema(elem, typeStr); + + // get complex type info + typeInfo = getElementComplexTypeInfo(elem, typeStr, anotherSchemaURI); + + // get simple type validtor - if not a complex type + if (typeInfo) + validator = typeInfo->getDatatypeValidator(); + else + validator = getElementTypeValidator(elem, typeStr, noErrorFound, anotherSchemaURI); + } + } + } + + // check for duplicate elements with different types. + if (isDuplicate) + { + DatatypeValidator* eltDV = elemDecl->getDatatypeValidator(); + ComplexTypeInfo* eltTypeInfo = elemDecl->getComplexTypeInfo(); + + if ( (eltTypeInfo != typeInfo) || (eltDV != validator)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, name); + } + } + // Set element declararion type information + else + { + elemDecl->setDatatypeValidator(validator); + elemDecl->setComplexTypeInfo(typeInfo); + + if (validator) + elemDecl->setModelType(SchemaElementDecl::Simple); + else if (typeInfo) + elemDecl->setModelType((SchemaElementDecl::ModelTypes)typeInfo->getContentType()); + + if (topLevel) { + + // Handle the substitutionGroup + const XMLCh* subsGroupName = getElementAttValue(elem, SchemaSymbols::fgATT_SUBSTITUTIONGROUP, DatatypeValidator::QName); + if (subsGroupName && *subsGroupName) + processSubstitutionGroup(elem, elemDecl, typeInfo, validator, subsGroupName); + } + + // process identity constraints + DOMElement* ic = XUtil::getFirstChildElementNS( + elem, fgIdentityConstraints, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3); + + if (ic) + processElemDeclIC(ic, elemDecl); + } + + if (!typeInfo && !validator) + { + if (!isDuplicate) + { + elemDecl->setModelType(SchemaElementDecl::Any); + elemDecl->setAttWildCard( + new (fGrammarPoolMemoryManager) SchemaAttDef( + XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, + fEmptyNamespaceURI, XMLAttDef::Any_Any, + XMLAttDef::ProcessContents_Lax, fGrammarPoolMemoryManager + ) + ); + } + } + else if (valueConstraint) + { + if (!checkElemDeclValueConstraint(elem, elemDecl, valueConstraint, typeInfo, validator) + && !isDuplicate) + { + int miscFlags = elemDecl->getMiscFlags(); + miscFlags &= ~ SchemaSymbols::XSD_FIXED; + elemDecl->setDefaultValue(0); + elemDecl->setMiscFlags(miscFlags); + } + } + + return elemDecl; +} + +/** + * Traverses Schema notation declaration. + * + * + * Content: (annotation?) + * + * + * @param elem: the declaration of the element under consideration + */ +const XMLCh* TraverseSchema::traverseNotationDecl(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Notation, this, true, fNonXSAttList + ); + + // ----------------------------------------------------------------------- + // Process notation attributes/elements + // ----------------------------------------------------------------------- + const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + bool nameEmpty = (!name || !*name) ? true : false; + + if (nameEmpty) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, + SchemaSymbols::fgELT_NOTATION); + return 0; + } + + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_NOTATION, name); + return 0; + } + + if (fNotationRegistry->containsKey(name, fTargetNSURI)) { + return name; + } + + if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + + const XMLCh* publicId = getElementAttValue(elem, SchemaSymbols::fgATT_PUBLIC); + const XMLCh* systemId = getElementAttValue(elem, SchemaSymbols::fgATT_SYSTEM, DatatypeValidator::AnyURI); + + fNotationRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), + fTargetNSURI, 0); + + // for PSVI we need to store the notational decl + XMLNotationDecl* decl = new (fGrammarPoolMemoryManager) XMLNotationDecl + ( + name, + publicId, + systemId, + 0, + fGrammarPoolMemoryManager + ); + decl->setNameSpaceId(fTargetNSURI); + fSchemaGrammar->putNotationDecl(decl); + + if (fAnnotation) + fSchemaGrammar->putAnnotation(decl, fAnnotation); + else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + fSchemaGrammar->putAnnotation(decl, fAnnotation); + } + return name; +} + +const XMLCh* TraverseSchema::traverseNotationDecl(const DOMElement* const elem, + const XMLCh* const name, + const XMLCh* const uriStr) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + SchemaInfo* saveInfo = fSchemaInfo; + + if (fTargetNSURI != (int) uriId) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); + return 0; + } + + Grammar* grammar = fGrammarResolver->getGrammar(uriStr); + + if (grammar == 0 || grammar->getGrammarType() != Grammar::SchemaGrammarType) { + + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); + return 0; + } + + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); + + if (!impInfo || impInfo->getProcessed()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, name); + return 0; + } + + fSchemaInfo = impInfo; + fTargetNSURI = fSchemaInfo->getTargetNSURI(); + } + + DOMElement* notationElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Notation, + SchemaSymbols::fgELT_NOTATION, name, &fSchemaInfo); + + if (notationElem == 0) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Notation_DeclNotFound, uriStr, name); + return 0; + } + + const XMLCh* notationName = traverseNotationDecl(notationElem); + + fSchemaInfo = saveInfo; + fTargetNSURI = fSchemaInfo->getTargetNSURI(); + + return notationName; +} + +/** + * Traverses Schema list simple type declaration. + * + * + * Content: (annotation?, simpleType?) + * + * + */ +DatatypeValidator* +TraverseSchema::traverseByList(const DOMElement* const rootElem, + const DOMElement* const contentElem, + const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const int finalSet, + Janitor* const janAnnot) { + + NamespaceScopeManager nsMgr(contentElem, fSchemaInfo, this); + + DatatypeValidator* baseValidator = 0; + const XMLCh* baseTypeName = getElementAttValue(contentElem, SchemaSymbols::fgATT_ITEMTYPE, DatatypeValidator::QName); + + fAttributeCheck.checkAttributes( + contentElem, GeneralAttributeCheck::E_List, this, false, fNonXSAttList + ); + + const DOMElement* tempEl = XUtil::getNextSiblingElement(contentElem); + if (tempEl != 0) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError, tempEl->getLocalName()); + } + + DOMElement* content = 0; + + if (!baseTypeName || !*baseTypeName) { // must 'see' + + content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), false); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + if (!content) { + + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInList, typeName); + popCurrentTypeNameStack(); + return 0; + } + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { + baseValidator = checkForSimpleTypeValidator(content, SchemaSymbols::XSD_LIST); + } + else { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); + popCurrentTypeNameStack(); + return 0; + } + + content = XUtil::getNextSiblingElement(content); + } + else { // base was provided - get proper validator + + baseValidator = findDTValidator(contentElem, typeName, baseTypeName, SchemaSymbols::XSD_LIST); + content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + } + + DatatypeValidator* newDV = 0; + + if (baseValidator) { + + if (!baseValidator->isAtomic()) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType, baseTypeName); + } + else { + + // 'content' should be empty + // If an annotation was encountered we have already traversed it in + // checkContent in the case of a base provided (only allowed child is + // an annotation). + if (content != 0) { // report an error and continue + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeDerivationByListError, typeName); + } + + // create & register validator for "generated" type + try { + newDV = fDatatypeRegistry->createDatatypeValidator( + qualifiedName, baseValidator, 0, 0, true, finalSet, true, fGrammarPoolMemoryManager); + } + catch (const XMLException& excep) { + reportSchemaError(contentElem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, + XMLErrs::DatatypeValidatorCreationError, typeName); + } + } + } + + popCurrentTypeNameStack(); + return newDV; +} + +/** + * Traverses Schema restriction simple type declaration. + * + * + * Content: (annotation?, (simpleType?, + * (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)) + * + * + */ +DatatypeValidator* +TraverseSchema::traverseByRestriction(const DOMElement* const rootElem, + const DOMElement* const contentElem, + const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const int finalSet, + Janitor* const janAnnot) { + + NamespaceScopeManager nsMgr(contentElem, fSchemaInfo, this); + + DatatypeValidator* baseValidator = 0; + DatatypeValidator* newDV = 0; + const XMLCh* baseTypeName = getElementAttValue(contentElem, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); + + fAttributeCheck.checkAttributes( + contentElem, GeneralAttributeCheck::E_Restriction, this, false, fNonXSAttList + ); + + const DOMElement* tempEl = XUtil::getNextSiblingElement(contentElem); + if (tempEl != 0) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError, tempEl->getLocalName()); + } + + DOMElement* content = 0; + + if (!baseTypeName || !*baseTypeName) { // must 'see' + + content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), false); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + if (content == 0) { + + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInRestriction); + popCurrentTypeNameStack(); + return 0; + } + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { + baseValidator = checkForSimpleTypeValidator(content); + } + else { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); + popCurrentTypeNameStack(); + return 0; + } + + // Check for facets + content = XUtil::getNextSiblingElement(content); + } + else { // base was provided - get proper validator + + baseValidator = findDTValidator(contentElem, typeName, baseTypeName, SchemaSymbols::XSD_RESTRICTION); + content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + } + + if (baseValidator) { + + // Get facets if any existing + typedef RefHashTableOf KVRefHash; + Janitor janFacets(0); + //RefHashTableOf* facets = 0; + typedef RefArrayVectorOf XMLChRefArray; + Janitor enums(0); + //RefArrayVectorOf* enums = 0; + XMLBuffer pattern(128, fGrammarPoolMemoryManager); + Janitor janEnumAnnot(0); + Janitor janPatternAnnot(0); + XMLCh fixedFlagStr[16]; + unsigned int fixedFlag = 0; + unsigned short scope = 0; + bool isFirstPattern = true; + bool sawPattern = false; + + + while (content != 0) { + + if (content->getNodeType() == DOMNode::ELEMENT_NODE) { + + NamespaceScopeManager nsMgr(content, fSchemaInfo, this); + + const XMLCh* facetName = content->getLocalName(); + + bool bContinue=false; // workaround for Borland bug with 'continue' in 'catch' + try { + scope = fAttributeCheck.getFacetId(facetName, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidFacetName, facetName); + content = XUtil::getNextSiblingElement(content); + bContinue=true; + } + if(bContinue) + continue; + + fAttributeCheck.checkAttributes( + content, scope, this, false, fNonXSAttList + ); + if (checkContent(rootElem, XUtil::getFirstChildElement(content), true) != 0) + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + + const XMLCh* attValue = content->getAttribute(SchemaSymbols::fgATT_VALUE); + if (janFacets.get() == 0) { + janFacets.reset(new (fGrammarPoolMemoryManager) RefHashTableOf(29, true, fGrammarPoolMemoryManager)); + + } + + if (XMLString::equals(facetName, SchemaSymbols::fgELT_ENUMERATION)) { + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(content, fNonXSAttList); + } + if (fAnnotation) { + if (janEnumAnnot.isDataNull()) + janEnumAnnot.reset(fAnnotation); + else + janEnumAnnot.get()->setNext(fAnnotation); + } + + // REVISIT + // if validator is a notation datatype validator, we need + // to get the qualified name first before adding it to the + // enum buffer + if (!enums.get()) { + enums.reset(new (fGrammarPoolMemoryManager) RefArrayVectorOf(8, true, fGrammarPoolMemoryManager)); + } + + if (baseValidator->getType() == DatatypeValidator::NOTATION) { + + const XMLCh* localPart = getLocalPart(attValue); + const XMLCh* prefix = getPrefix(attValue); + const XMLCh* uriStr = (prefix && *prefix) ? resolvePrefixToURI(content, prefix) : fTargetNSURIString; + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + + if (!fNotationRegistry->containsKey(localPart, uriId)) { + traverseNotationDecl(content, localPart, uriStr); + } + + if (uriStr && *uriStr) { + fBuffer.set(uriStr); + fBuffer.append(chColon); + fBuffer.append(localPart); + enums.get()->addElement(XMLString::replicate(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager)); + } + else { + enums.get()->addElement(XMLString::replicate(localPart, fGrammarPoolMemoryManager)); + } + + } + else if (baseValidator->getType() == DatatypeValidator::QName) { + // We need the URI string for the prefix to determine + // if that matches the value in the instance document. + // Code was just comparing the string of prefix:localname + // and if the schema and instance document had different + // prefixes with the same URI string then we were giving an error. + const XMLCh* prefix = getPrefix(attValue); + const XMLCh* uriStr = (prefix && *prefix) ? resolvePrefixToURI(content, prefix) : fTargetNSURIString; + + enums.get()->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager)); + enums.get()->addElement(XMLString::replicate(uriStr, fGrammarPoolMemoryManager)); + } + else { + enums.get()->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager)); + } + } + else if (XMLString::equals(facetName, SchemaSymbols::fgELT_PATTERN)) { + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(content, fNonXSAttList); + } + if (fAnnotation) { + if (janPatternAnnot.isDataNull()) + janPatternAnnot.reset(fAnnotation); + else + janPatternAnnot.get()->setNext(fAnnotation); + } + sawPattern = true; + if (isFirstPattern) { // fBuffer.isEmpty() - overhead call + + isFirstPattern = false; + pattern.set(attValue); + } + else { //datatypes: 5.2.4 pattern + + pattern.append(chPipe); + pattern.append(attValue); + } + } + else { + + if (janFacets.get()->containsKey(facetName)) { + + if (fAnnotation) + delete fAnnotation; + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName); + } + else { + + if (XMLString::equals(facetName, SchemaSymbols::fgELT_WHITESPACE) + && baseValidator->getType() != DatatypeValidator::String + && !XMLString::equals(attValue, SchemaSymbols::fgWS_COLLAPSE)) { + + if (fAnnotation) + delete fAnnotation; + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::WS_CollapseExpected, attValue); + } + else { + + const XMLCh* facetStr = fStringPool->getValueForId(fStringPool->addOrFind(facetName)); + KVStringPair* kv = new (fGrammarPoolMemoryManager) KVStringPair(facetStr, attValue, fGrammarPoolMemoryManager); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(content, fNonXSAttList); + } + if (fAnnotation) + fSchemaGrammar->putAnnotation(kv, fAnnotation); + + janFacets.get()->put((void*) facetStr, kv); + checkFixedFacet(content, facetStr, baseValidator, fixedFlag); + } + } + } + } + + content = XUtil::getNextSiblingElement(content); + } // end while + + if (sawPattern) { + + KVStringPair* kv = new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgELT_PATTERN, pattern.getRawBuffer(), pattern.getLen(), fGrammarPoolMemoryManager); + if (!janPatternAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(kv, janPatternAnnot.release()); + janFacets.get()->put((void*) SchemaSymbols::fgELT_PATTERN, kv); + } + + if (fixedFlag) { + + XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10, fGrammarPoolMemoryManager); + janFacets.get()->put((void*) SchemaSymbols::fgATT_FIXED, + new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr, fGrammarPoolMemoryManager)); + } + + if (enums.get() && !janEnumAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(enums.get(), janEnumAnnot.release()); + + try { + newDV = fDatatypeRegistry->createDatatypeValidator(qualifiedName, baseValidator, janFacets.release(), enums.release(), false, finalSet, true, fGrammarPoolMemoryManager); + } + catch (const XMLException& excep) { + reportSchemaError(contentElem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, + XMLErrs::DatatypeValidatorCreationError, typeName); + } + } + popCurrentTypeNameStack(); + return newDV; +} + +/** + * Traverses Schema union simple type declaration. + * + * + * Content: (annotation?, simpleType*) + * + * + */ +DatatypeValidator* +TraverseSchema::traverseByUnion(const DOMElement* const rootElem, + const DOMElement* const contentElem, + const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const int finalSet, + int baseRefContext, + Janitor* const janAnnot) { + + NamespaceScopeManager nsMgr(contentElem, fSchemaInfo, this); + + fAttributeCheck.checkAttributes( + contentElem, GeneralAttributeCheck::E_Union, this, false, fNonXSAttList + ); + + const DOMElement* tempEl = XUtil::getNextSiblingElement(contentElem); + if (tempEl != 0) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError, tempEl->getLocalName()); + } + + const XMLCh* baseTypeName = getElementAttValue(contentElem, SchemaSymbols::fgATT_MEMBERTYPES); + DatatypeValidator* baseValidator = 0; + RefVectorOf* validators = new (fGrammarPoolMemoryManager) RefVectorOf(4, false, fGrammarPoolMemoryManager); + Janitor > janValidators(validators); + DOMElement* content = 0; + + if (baseTypeName && *baseTypeName) { //base was provided - get proper validator. + + XMLStringTokenizer unionMembers(baseTypeName, fGrammarPoolMemoryManager); + int tokCount = unionMembers.countTokens(); + + for (int i = 0; i < tokCount; i++) { + + const XMLCh* memberTypeName = unionMembers.nextToken(); + + baseValidator = findDTValidator(contentElem, typeName, memberTypeName, SchemaSymbols::XSD_UNION); + + if (baseValidator == 0) { + + popCurrentTypeNameStack(); + return 0; + } + + validators->addElement(baseValidator); + } + + content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), true); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + } + else { // must 'see' + + content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), false); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + if (content == 0) { + + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInUnion, typeName); + popCurrentTypeNameStack(); + return 0; + } + + if (!XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); + popCurrentTypeNameStack(); + return 0; + } + } + + // process union content of simpleType children if any + while (content != 0) { + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { + + baseValidator = checkForSimpleTypeValidator(content, baseRefContext | SchemaSymbols::XSD_UNION); + + if (baseValidator == 0) { + + popCurrentTypeNameStack(); + return 0; + } + + validators->addElement(baseValidator); + } + else { + // REVISIT - should we break. For now, we will continue and move to + // the next sibling + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); + } + + content = XUtil::getNextSiblingElement(content); + } // end while + + DatatypeValidator* newDV = 0; + janValidators.orphan(); + + try { + newDV = fDatatypeRegistry->createDatatypeValidator(qualifiedName, validators, finalSet, true, fGrammarPoolMemoryManager); + } + catch (const XMLException& excep) { + reportSchemaError(contentElem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, + XMLErrs::DatatypeValidatorCreationError, typeName); + } + + popCurrentTypeNameStack(); + return newDV; +} + + +/** + * Traverse SimpleContent Declaration + * + * + * + * Content: (annotation? , (restriction | extension)) + * + * + * + * + * Content: (annotation?, (simpleType?, (minExclusive | minInclusive + * | maxExclusive | maxInclusive | totalDigits | fractionDigits + * | length | minLength | maxLength | enumeration | pattern + * | whiteSpace)*)?, ((attribute | attributeGroup)* , anyAttribute?)) + * + * + * + * Content: (annotation? , ((attribute | attributeGroup)* , anyAttribute?)) + * + * + */ +void TraverseSchema::traverseSimpleContentDecl(const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const DOMElement* const contentDecl, + ComplexTypeInfo* const typeInfo, + Janitor* const janAnnot) +{ + NamespaceScopeManager nsMgr(contentDecl, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + bool preProcessFlag = typeInfo->getPreprocessed(); + + if (!preProcessFlag) { + fAttributeCheck.checkAttributes( + contentDecl, GeneralAttributeCheck::E_SimpleContent + , this, false, fNonXSAttList + ); + } + + // ----------------------------------------------------------------------- + // Set the content type to be simple, and initialize content spec handle + // ----------------------------------------------------------------------- + typeInfo->setContentType(SchemaElementDecl::Simple); + + // ----------------------------------------------------------------------- + // Process annotation if any + // ----------------------------------------------------------------------- + DOMElement* simpleContent = checkContent(contentDecl, XUtil::getFirstChildElement(contentDecl), false, !preProcessFlag); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentDecl, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + // If there are no children, return + if (simpleContent == 0) { + + reportSchemaError(contentDecl, XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + NamespaceScopeManager nsMgr2(simpleContent, fSchemaInfo, this); + // ----------------------------------------------------------------------- + // The content should be either "restriction" or "extension" + // ----------------------------------------------------------------------- + if (!preProcessFlag) { + const XMLCh* const contentName = simpleContent->getLocalName(); + + if (XMLString::equals(contentName, SchemaSymbols::fgATTVAL_RESTRICTION)) { + + fAttributeCheck.checkAttributes( + simpleContent, GeneralAttributeCheck::E_Restriction + , this, false, fNonXSAttList + ); + typeInfo->setDerivedBy(SchemaSymbols::XSD_RESTRICTION); + } + else if (XMLString::equals(contentName, SchemaSymbols::fgATTVAL_EXTENSION)) { + + fAttributeCheck.checkAttributes( + simpleContent, GeneralAttributeCheck::E_Extension + , this, false, fNonXSAttList + ); + typeInfo->setDerivedBy(SchemaSymbols::XSD_EXTENSION); + } + else { + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContent); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + + //Skip over any annotations in the restriction or extension elements + DOMElement* content = checkContent(simpleContent, XUtil::getFirstChildElement(simpleContent), true, !preProcessFlag); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(simpleContent, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + // ----------------------------------------------------------------------- + // Handle the base type name + // ----------------------------------------------------------------------- + const XMLCh* baseName = getElementAttValue(simpleContent, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); + + if (!baseName || !*baseName) { + + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + const XMLCh* prefix = getPrefix(baseName); + const XMLCh* localPart = getLocalPart(baseName); + const XMLCh* uri = resolvePrefixToURI(simpleContent, prefix); + + // check for 'anyType' + if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + && XMLString::equals(localPart, SchemaSymbols::fgATTVAL_ANYTYPE)) { + + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + processBaseTypeInfo(simpleContent, baseName, localPart, uri, typeInfo); + + ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); + DatatypeValidator* baseValidator = typeInfo->getBaseDatatypeValidator(); + + if (baseValidator != 0 && baseTypeInfo == 0) { + + // check that the simpleType does not preclude derivation by extension + if ((baseValidator->getFinalSet() & SchemaSymbols::XSD_EXTENSION) == typeInfo->getDerivedBy()) { + + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::DisallowedSimpleTypeExtension, + baseName, typeName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + //Schema Spec: 5.11: Complex Type Definition Properties Correct: 2 + if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION) { + + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeBase, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + + // check that the base isn't a complex type with complex content + // and that derivation method is not included in 'final' + bool simpleTypeRequired = false; + + if (baseTypeInfo) { + + if (baseTypeInfo->getContentType() != SchemaElementDecl::Simple) { + + // Schema Errata: E1-27 + if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION + && ((baseTypeInfo->getContentType() == SchemaElementDecl::Mixed_Simple + || baseTypeInfo->getContentType() == SchemaElementDecl::Mixed_Complex) + && emptiableParticle(baseTypeInfo->getContentSpec()))) { + simpleTypeRequired = true; + } + else { + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + + if ((baseTypeInfo->getFinalSet() & typeInfo->getDerivedBy()) != 0) { + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivation, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + + // ----------------------------------------------------------------------- + // Process the content of the derivation + // ----------------------------------------------------------------------- + if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION) { + + if(baseTypeInfo) + typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator()); + + if (content != 0) { + + // --------------------------------------------------------------- + // There may be a simple type definition in the restriction + // element. The data type validator will be based on it, if + // specified + // --------------------------------------------------------------- + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { + + DatatypeValidator* simpleTypeDV = traverseSimpleTypeDecl(content, false); + + if (simpleTypeDV) { + + // Check that the simpleType validator is validly derived + // from base + DatatypeValidator* baseDV = typeInfo->getBaseDatatypeValidator(); + + if (baseDV && !baseDV->isSubstitutableBy(simpleTypeDV)) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidContentRestriction); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + typeInfo->setBaseDatatypeValidator(simpleTypeDV); + content = XUtil::getNextSiblingElement(content); + } + else { + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + // Schema Errata E1-27 + // Complex Type Definition Restriction OK: 2.2 + else if (simpleTypeRequired) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::CT_SimpleTypeChildRequired); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + // --------------------------------------------------------------- + // Build up the facet info + // --------------------------------------------------------------- + RefHashTableOf* facets = 0; + RefArrayVectorOf* enums = 0; + XMLBuffer pattern(128, fGrammarPoolMemoryManager); + XMLCh fixedFlagStr[16]; + unsigned int fixedFlag = 0; + unsigned short scope = 0; + bool isFirstPattern = true; + + while (content != 0) { + + const XMLCh* facetName = content->getLocalName(); + + bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' + // if not a valid facet, break from the loop + try { + scope = fAttributeCheck.getFacetId(facetName, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + bDoBreak=true; + } + if(bDoBreak) + break; + + if (content->getNodeType() == DOMNode::ELEMENT_NODE) { + + fAttributeCheck.checkAttributes(content, scope, this); + + const XMLCh* attValue = content->getAttribute(SchemaSymbols::fgATT_VALUE); + + if (facets == 0) { + facets = new (fGrammarPoolMemoryManager) RefHashTableOf(29, true, fGrammarPoolMemoryManager); + } + + if (XMLString::equals(facetName, SchemaSymbols::fgELT_ENUMERATION)) { + + if (!enums) { + enums = new (fGrammarPoolMemoryManager) RefArrayVectorOf(8, true, fGrammarPoolMemoryManager); + } + + enums->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager)); + } + else if (XMLString::equals(facetName, SchemaSymbols::fgELT_PATTERN)) { + + if (isFirstPattern) { // fBuffer.isEmpty() - overhead call + + isFirstPattern = false; + pattern.set(attValue); + } + else { //datatypes: 5.2.4 pattern + + pattern.append(chPipe); + pattern.append(attValue); + } + } + else { + + if (facets->containsKey(facetName)) { + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName); + } + else { + + const XMLCh* facetNameStr = + fStringPool->getValueForId(fStringPool->addOrFind(facetName)); + + facets->put((void*) facetNameStr, new (fGrammarPoolMemoryManager) KVStringPair(facetNameStr, attValue, fGrammarPoolMemoryManager)); + checkFixedFacet(content, facetNameStr, typeInfo->getBaseDatatypeValidator(), fixedFlag); + } + } + } + + content = XUtil::getNextSiblingElement(content); + } + + if (facets) { + + if (!pattern.isEmpty()) { + facets->put + ( + (void*) SchemaSymbols::fgELT_PATTERN, + new (fGrammarPoolMemoryManager) KVStringPair + ( + SchemaSymbols::fgELT_PATTERN + , pattern.getRawBuffer() + , pattern.getLen() + , fGrammarPoolMemoryManager + ) + ); + } + + if (fixedFlag) { + + XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10, fGrammarPoolMemoryManager); + facets->put((void*) SchemaSymbols::fgATT_FIXED, + new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr, fGrammarPoolMemoryManager)); + } + + try { + + DatatypeValidator* simpleDV = + fDatatypeRegistry->createDatatypeValidator + ( + qualifiedName, + typeInfo->getBaseDatatypeValidator(), + facets, enums, false, 0, true, fGrammarPoolMemoryManager + ); + simpleDV->setAnonymous(); + typeInfo->setDatatypeValidator(simpleDV); + } + catch (const XMLException& excep) { + reportSchemaError(simpleContent, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) { + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidatorCreationError, typeName); + } + } + else { + typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator()); + } + } + else { + + // Schema Errata E1-27 + // Complex Type Definition Restriction OK: 2.2 + if (simpleTypeRequired) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::CT_SimpleTypeChildRequired); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator()); + } + } // end RESTRICTION + else { // EXTENSION + + ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); + + if (baseTypeInfo!= 0) { + + typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator()); + } + + typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator()); + } + + // ----------------------------------------------------------------------- + // Process attributes if any + // ----------------------------------------------------------------------- + processAttributes(simpleContent, content, typeInfo); + + if (XUtil::getNextSiblingElement(simpleContent) != 0) { + reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInSimpleContent); + } + +} // End of function traverseSimpleContentDecl + +/** + * Traverse complexContent Declaration + * + * + * + * Content: (annotation? , (restriction | extension)) + * + * + * + * + * Content: (annotation? , (group | all | choice | sequence)?, + * ((attribute | attributeGroup)* , anyAttribute?)) + * + * + * + * Content: (annotation? , (group | all | choice | sequence)?, + * ((attribute | attributeGroup)* , anyAttribute?)) + * + */ +void TraverseSchema::traverseComplexContentDecl(const XMLCh* const typeName, + const DOMElement* const contentDecl, + ComplexTypeInfo* const typeInfo, + const bool isMixed, + Janitor* const janAnnot) +{ + NamespaceScopeManager nsMgr(contentDecl, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check attributes + // ----------------------------------------------------------------------- + bool preProcessFlag = typeInfo->getPreprocessed(); + + if (!preProcessFlag) { + fAttributeCheck.checkAttributes( + contentDecl, GeneralAttributeCheck::E_ComplexContent + , this, false, fNonXSAttList + ); + } + + // ----------------------------------------------------------------------- + // Determine whether the content is mixed, or element-only + // Setting here overrides any setting on the complex type decl + // ----------------------------------------------------------------------- + const XMLCh* const mixed = getElementAttValue(contentDecl, SchemaSymbols::fgATT_MIXED, DatatypeValidator::Boolean); + bool mixedContent = isMixed; + + if (mixed) { + if (XMLString::equals(mixed, SchemaSymbols::fgATTVAL_TRUE) + || XMLString::equals(mixed, fgValueOne)) { + mixedContent = true; + } + else if (XMLString::equals(mixed, SchemaSymbols::fgATTVAL_FALSE) + || XMLString::equals(mixed, fgValueZero)) { + mixedContent = false; + } + } + + // ----------------------------------------------------------------------- + // Since the type must have complex content, set the simple type validators + // to null + // ----------------------------------------------------------------------- + typeInfo->setDatatypeValidator(0); + typeInfo->setBaseDatatypeValidator(0); + + DOMElement* complexContent = checkContent(contentDecl,XUtil::getFirstChildElement(contentDecl),false, !preProcessFlag); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(contentDecl, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + // If there are no children, return + if (complexContent == 0) { + throw TraverseSchema::InvalidComplexTypeInfo; + } + + NamespaceScopeManager nsMgr2(complexContent, fSchemaInfo, this); + // ----------------------------------------------------------------------- + // The content should be either "restriction" or "extension" + // ----------------------------------------------------------------------- + const XMLCh* const complexContentName = complexContent->getLocalName(); + + if (XMLString::equals(complexContentName, SchemaSymbols::fgELT_RESTRICTION)) { + typeInfo->setDerivedBy(SchemaSymbols::XSD_RESTRICTION); + } + else if (XMLString::equals(complexContentName, SchemaSymbols::fgELT_EXTENSION)) { + typeInfo->setDerivedBy(SchemaSymbols::XSD_EXTENSION); + } + else { + + reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexContent); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + // ----------------------------------------------------------------------- + // Handle the base type name + // ----------------------------------------------------------------------- + const XMLCh* baseName = getElementAttValue(complexContent, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); + + if (!baseName || !*baseName) { + + reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + const XMLCh* prefix = getPrefix(baseName); + const XMLCh* localPart = getLocalPart(baseName); + const XMLCh* uri = resolvePrefixToURI(complexContent, prefix); + bool isBaseAnyType = false; + + // ------------------------------------------------------------- + // check if the base is "anyType" + // ------------------------------------------------------------- + if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && + XMLString::equals(localPart, SchemaSymbols::fgATTVAL_ANYTYPE)) { + isBaseAnyType = true; + } + else { + + processBaseTypeInfo(complexContent, baseName, localPart, uri, typeInfo); + + //Check that the base is a complex type + if (typeInfo->getBaseComplexTypeInfo() == 0) { + + reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::BaseNotComplexType); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + + if (fCurrentGroupInfo) // defer processing until later + throw TraverseSchema::RecursingElement; + + // ----------------------------------------------------------------------- + // Process the content of the derivation + // ----------------------------------------------------------------------- + //Skip over any annotations in the restriction or extension elements + DOMElement* content = checkContent(complexContent, XUtil::getFirstChildElement(complexContent), true); + if (fAnnotation) + { + if (janAnnot->isDataNull()) + janAnnot->reset(fAnnotation); + else + janAnnot->get()->setNext(fAnnotation); + } + + processComplexContent(complexContent, typeName, content, typeInfo, localPart, + mixedContent, isBaseAnyType); + + if (XUtil::getNextSiblingElement(complexContent) != 0) { + reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexContent); + } +} + + +/** + * + * processContents = (lax | skip | strict) : strict + * Content: (annotation?) + * + */ +SchemaAttDef* TraverseSchema::traverseAnyAttribute(const DOMElement* const elem) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_AnyAttribute, this, false, fNonXSAttList + ); + + // ------------------------------------------------------------------ + // First, handle any ANNOTATION declaration + // ------------------------------------------------------------------ + if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeContentError); + } + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + // ------------------------------------------------------------------ + // Get attributes + // ------------------------------------------------------------------ + const XMLCh* const processContents = getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS); + const XMLCh* const nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE); + + // ------------------------------------------------------------------ + // Set default att type based on 'processContents' value + // ------------------------------------------------------------------ + XMLAttDef::DefAttTypes attDefType = XMLAttDef::ProcessContents_Strict; + + if ((!processContents || !*processContents) + || XMLString::equals(processContents, SchemaSymbols::fgATTVAL_STRICT)) { + // Do nothing - defaulted already + } + else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_SKIP)) { + attDefType = XMLAttDef::ProcessContents_Skip; + } + else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_LAX)) { + attDefType = XMLAttDef::ProcessContents_Lax; + } + + // ------------------------------------------------------------------ + // Process 'namespace' attribute + // ------------------------------------------------------------------ + int uriIndex = fEmptyNamespaceURI; + XMLAttDef::AttTypes attType = XMLAttDef::Any_Any; + ValueVectorOf namespaceList(8, fGrammarPoolMemoryManager); + + if ((!nameSpace || !*nameSpace) + || XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY)) { + // Do nothing - defaulted already + } + else if (XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) { + + attType = XMLAttDef::Any_Other; + uriIndex = fTargetNSURI; + } + else { + + XMLStringTokenizer tokenizer(nameSpace, fGrammarPoolMemoryManager); + DatatypeValidator* anyURIDV = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYURI); + + attType = XMLAttDef::Any_List; + + while (tokenizer.hasMoreTokens()) { + + const XMLCh* token = tokenizer.nextToken(); + + if (XMLString::equals(token, SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL)) { + uriIndex = fEmptyNamespaceURI; + } + else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE)) { + uriIndex = fTargetNSURI; + } + else { + + try { + anyURIDV->validate(token + , fSchemaInfo->getValidationContext() + , fMemoryManager); + } + catch(const XMLException& excep) { + reportSchemaError(elem, excep); + } + uriIndex = fURIStringPool->addOrFind(token); + } + + if (!namespaceList.containsElement(uriIndex)) { + namespaceList.addElement(uriIndex); + } + } + + uriIndex = fEmptyNamespaceURI; + } + + // ------------------------------------------------------------------ + // Create wildcard attribute + // ------------------------------------------------------------------ + SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef(XMLUni::fgZeroLenString, + XMLUni::fgZeroLenString, + uriIndex, attType, attDefType, + fGrammarPoolMemoryManager); + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(attDef, janAnnot.release()); + + if (namespaceList.size()) { + attDef->setNamespaceList(&namespaceList); + } + + return attDef; +} + +/** + * + */ +void TraverseSchema::traverseKey(const DOMElement* const icElem, + SchemaElementDecl* const elemDecl) { + + NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + icElem, GeneralAttributeCheck::E_Key, this, false, fNonXSAttList + ); + + // ----------------------------------------------------------------------- + // Create identity constraint + // ----------------------------------------------------------------------- + const XMLCh* name = getElementAttValue(icElem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_KEY, name); + return; + } + + + if (!fIdentityConstraintNames) { + fIdentityConstraintNames = new (fMemoryManager) RefHash2KeysTableOf(29, (bool) false, fMemoryManager); + } + else if (fIdentityConstraintNames->containsKey(name, fTargetNSURI)) { + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_DuplicateDecl, name); + return; + } + + IC_Key* icKey = new (fGrammarPoolMemoryManager) IC_Key(name, elemDecl->getBaseName(), fGrammarPoolMemoryManager); + Janitor janKey(icKey); + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, icKey); + + // ----------------------------------------------------------------------- + // Get selector and fields + // ----------------------------------------------------------------------- + if (!traverseIdentityConstraint(icKey, icElem)) { + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); + return; + } + + // ----------------------------------------------------------------------- + // Add key to element declaration + // ----------------------------------------------------------------------- + elemDecl->addIdentityConstraint(icKey); + icKey->setNamespaceURI(fTargetNSURI); + janKey.orphan(); +} + +/** + * + */ +void TraverseSchema::traverseUnique(const DOMElement* const icElem, + SchemaElementDecl* const elemDecl) { + + NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + icElem, GeneralAttributeCheck::E_Unique, this, false, fNonXSAttList + ); + + // ----------------------------------------------------------------------- + // Create identity constraint + // ----------------------------------------------------------------------- + const XMLCh* name = getElementAttValue(icElem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_UNIQUE, name); + return; + } + + if (!fIdentityConstraintNames) { + fIdentityConstraintNames = new (fGrammarPoolMemoryManager) RefHash2KeysTableOf(29, (bool) false, fGrammarPoolMemoryManager); + } + else if (fIdentityConstraintNames->containsKey(name, fTargetNSURI)) { + + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_DuplicateDecl, name); + return; + } + + IC_Unique* icUnique = new (fGrammarPoolMemoryManager) IC_Unique(name, elemDecl->getBaseName(), fGrammarPoolMemoryManager); + Janitor janUnique(icUnique); + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, icUnique); + + // ----------------------------------------------------------------------- + // Get selector and fields + // ----------------------------------------------------------------------- + if (!traverseIdentityConstraint(icUnique, icElem)) { + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); + return; + } + + // ----------------------------------------------------------------------- + // Add identity cosntraints to element declaration + // ----------------------------------------------------------------------- + elemDecl->addIdentityConstraint(icUnique); + icUnique->setNamespaceURI(fTargetNSURI); + janUnique.orphan(); +} + +/** + * + */ +void TraverseSchema::traverseKeyRef(const DOMElement* const icElem, + SchemaElementDecl* const elemDecl) { + + NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); + + // ----------------------------------------------------------------------- + // Check Attributes + // ----------------------------------------------------------------------- + fAttributeCheck.checkAttributes( + icElem, GeneralAttributeCheck::E_KeyRef, this, false, fNonXSAttList + ); + + // ----------------------------------------------------------------------- + // Verify that key reference "refer" attribute is valid + // ----------------------------------------------------------------------- + const XMLCh* name = getElementAttValue(icElem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + const XMLCh* refer = getElementAttValue(icElem, SchemaSymbols::fgATT_REFER, DatatypeValidator::QName); + + if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, + SchemaSymbols::fgELT_KEYREF, name); + return; + } + + const XMLCh* prefix = getPrefix(refer); + const XMLCh* localPart = getLocalPart(refer); + + // we use the DOM API, as the NamespaceScope is now pointing to a different place + const XMLCh* uriStr = icElem->lookupNamespaceURI(*prefix==0?NULL:prefix); + if ((!uriStr || !*uriStr) && (prefix && *prefix)) + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::UnresolvedPrefix, prefix); + if(!uriStr) + uriStr=XMLUni::fgZeroLenString; + + IdentityConstraint* icKey = (fIdentityConstraintNames) + ? fIdentityConstraintNames->get(localPart, fURIStringPool->addOrFind(uriStr)) : 0; + + if (!icKey) { + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_KeyRefReferNotFound, name, localPart); + return; + } + + // ----------------------------------------------------------------------- + // Create identity constraint + // ----------------------------------------------------------------------- + if(fIdentityConstraintNames->containsKey(name, fTargetNSURI)) { + + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_DuplicateDecl, name); + return; + } + + IC_KeyRef* icKeyRef = new (fGrammarPoolMemoryManager) IC_KeyRef(name, elemDecl->getBaseName(), icKey, fGrammarPoolMemoryManager); + Janitor janKeyRef(icKeyRef); + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, icKeyRef); + + // ----------------------------------------------------------------------- + // Get selector and fields + // ----------------------------------------------------------------------- + if (!traverseIdentityConstraint(icKeyRef, icElem)) { + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); + return; + } + + // ----------------------------------------------------------------------- + // Add key reference to element decl + // ----------------------------------------------------------------------- + if (icKeyRef->getFieldCount() != icKey->getFieldCount()) { + + fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_KeyRefCardinality, + name, icKey->getIdentityConstraintName()); + } + else { + + elemDecl->addIdentityConstraint(icKeyRef); + icKeyRef->setNamespaceURI(fTargetNSURI); + janKeyRef.orphan(); + } +} + + +bool TraverseSchema::traverseIdentityConstraint(IdentityConstraint* const ic, + const DOMElement* const icElem) { + + NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); + + // ------------------------------------------------------------------ + // First, handle any ANNOTATION declaration + // ------------------------------------------------------------------ + DOMElement* elem = checkContent(icElem, XUtil::getFirstChildElement(icElem), false); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(icElem, fNonXSAttList); + } + Janitor janAnnot(fAnnotation); + + // ------------------------------------------------------------------ + // Get selector + // ------------------------------------------------------------------ + if (elem == 0) { + +// reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); + return false; + } + + if (!XMLString::equals(elem->getLocalName(), SchemaSymbols::fgELT_SELECTOR)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); + return false; + } + + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Selector, this, false, fNonXSAttList + ); + if (checkContent(icElem, XUtil::getFirstChildElement(elem), true) != 0) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot.isDataNull()) + janAnnot.reset(fAnnotation); + else + janAnnot.get()->setNext(fAnnotation); + } + + // ------------------------------------------------------------------ + // Get xpath attribute + // ------------------------------------------------------------------ + const XMLCh* xpathExpr = getElementAttValue(elem, SchemaSymbols::fgATT_XPATH); + XMLSize_t xpathLen = XMLString::stringLen(xpathExpr); + + if (!xpathExpr || !xpathLen) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_XPathExprMissing); + return false; + } + + // ------------------------------------------------------------------ + // Parse xpath expression + // ------------------------------------------------------------------ + try { + + XercesXPath* sXPath = new (fGrammarPoolMemoryManager) XercesXPath(xpathExpr, fStringPool, fSchemaInfo->getNamespaceScope(), fEmptyNamespaceURI, true, fGrammarPoolMemoryManager); + IC_Selector* icSelector = new (fGrammarPoolMemoryManager) IC_Selector(sXPath, ic); + ic->setSelector(icSelector); + } + catch (const XPathException& e) { + + reportSchemaError(elem, e); + return false; + } + + // ------------------------------------------------------------------ + // Get fields + // ------------------------------------------------------------------ + elem = XUtil::getNextSiblingElement(elem); + + if (elem == 0) { + + reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); + return false; + } + + while (elem != 0) { + + if (!XMLString::equals(elem->getLocalName(), SchemaSymbols::fgELT_FIELD)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); + } + else { + // General Attribute Checking + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_Field, this, false, fNonXSAttList + ); + if (checkContent(icElem, XUtil::getFirstChildElement(elem), true) != 0) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); + if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) + { + fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); + } + if (fAnnotation) + { + if (janAnnot.isDataNull()) + janAnnot.reset(fAnnotation); + else + janAnnot.get()->setNext(fAnnotation); + } + + // xpath expression parsing + xpathExpr = getElementAttValue(elem, SchemaSymbols::fgATT_XPATH); + + if (!xpathExpr || !*xpathExpr) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_XPathExprMissing); + return false; + } + + try { + + XercesXPath* fieldXPath = new (fGrammarPoolMemoryManager) XercesXPath + ( + xpathExpr + , fStringPool + , fSchemaInfo->getNamespaceScope() + , fEmptyNamespaceURI + , false + , fGrammarPoolMemoryManager + ); + IC_Field* icField = new (fGrammarPoolMemoryManager) IC_Field(fieldXPath, ic); + ic->addField(icField); + } + catch (const XPathException& e) { + + reportSchemaError(elem, e); + return false; + } + } + + elem = XUtil::getNextSiblingElement(elem); + } + + if (!janAnnot.isDataNull()) + fSchemaGrammar->putAnnotation(ic, janAnnot.release()); + + if (ic->getFieldCount() == 0) { + return false; + } + + return true; +} + +// --------------------------------------------------------------------------- +// TraverseSchema: Helper methods +// --------------------------------------------------------------------------- +bool TraverseSchema::retrieveNamespaceMapping(const DOMElement* const elem) { + + DOMNamedNodeMap* eltAttrs = elem->getAttributes(); + bool seenNS=false; + const XMLSize_t attrCount = eltAttrs->getLength(); + + for (XMLSize_t i = 0; i < attrCount; i++) { + + DOMNode* attribute = eltAttrs->item(i); + + if (!attribute) { + break; + } + + const XMLCh* attName = attribute->getNodeName(); + + // starts with 'xmlns:' + if (XMLString::startsWith(attName, XMLUni::fgXMLNSColonString)) { + if(!seenNS) + fSchemaInfo->getNamespaceScope()->increaseDepth(); + seenNS=true; + + int offsetIndex = XMLString::indexOf(attName, chColon); + const XMLCh* attValue = attribute->getNodeValue(); + + fSchemaInfo->getNamespaceScope()->addPrefix(attName + offsetIndex + 1, fURIStringPool->addOrFind(attValue)); + } + else if (XMLString::equals(attName, XMLUni::fgXMLNSString)) { // == 'xmlns' + if(!seenNS) + fSchemaInfo->getNamespaceScope()->increaseDepth(); + seenNS=true; + + const XMLCh* attValue = attribute->getNodeValue(); + fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgZeroLenString, fURIStringPool->addOrFind(attValue)); + } + } // end for + return seenNS; +} + +void TraverseSchema::processChildren(const DOMElement* const root) { + + NamespaceScopeManager nsMgr(root, fSchemaInfo, this); + + bool sawAnnotation = false; + // process , and info items. + DOMElement* child = XUtil::getFirstChildElement(root); + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* name = child->getLocalName(); + + if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { + XSAnnotation* annot = traverseAnnotationDecl( + child, fSchemaInfo->getNonXSAttList(), true); + if (annot) { + fSchemaGrammar->addAnnotation(annot); + sawAnnotation = true; + } + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_INCLUDE)) { + traverseInclude(child); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_IMPORT)) { + traverseImport(child); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_REDEFINE)) { + traverseRedefine(child); + } + else + break; + } + + // child refers to the first info item which is not or + // one of the schema inclusion/importation declarations. + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* name = child->getLocalName(); + const XMLCh* typeName = getElementAttValue(child, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + int fullNameId = 0; + + if (typeName) { + + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(typeName); + fullNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); + } + + if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { + XSAnnotation* annot = traverseAnnotationDecl( + child, fSchemaInfo->getNonXSAttList(), true); + if (annot) { + fSchemaGrammar->addAnnotation(annot); + sawAnnotation = true; + } + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_SIMPLETYPE)) { + + if (typeName && *typeName) { + if (fGlobalDeclarations[ENUM_ELT_SIMPLETYPE]->containsElement(fullNameId) + || fGlobalDeclarations[ENUM_ELT_COMPLEXTYPE]->containsElement(fullNameId)) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalType, + SchemaSymbols::fgELT_SIMPLETYPE, typeName, SchemaSymbols::fgELT_COMPLEXTYPE); + continue; + } + else { + fGlobalDeclarations[ENUM_ELT_SIMPLETYPE]->addElement(fullNameId); + } + } + + traverseSimpleTypeDecl(child); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_COMPLEXTYPE)) { + + if (typeName && *typeName) { + if (fGlobalDeclarations[ENUM_ELT_SIMPLETYPE]->containsElement(fullNameId) + || fGlobalDeclarations[ENUM_ELT_COMPLEXTYPE]->containsElement(fullNameId)) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalType, + SchemaSymbols::fgELT_COMPLEXTYPE, typeName, SchemaSymbols::fgELT_SIMPLETYPE); + continue; + } + else { + fGlobalDeclarations[ENUM_ELT_COMPLEXTYPE]->addElement(fullNameId); + } + } + + traverseComplexTypeDecl(child); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_ELEMENT)) { + + if (typeName && *typeName) { + if (fGlobalDeclarations[ENUM_ELT_ELEMENT]->containsElement(fullNameId)) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalDeclaration, + SchemaSymbols::fgELT_ELEMENT, typeName); + continue; + } + else { + fGlobalDeclarations[ENUM_ELT_ELEMENT]->addElement(fullNameId); + } + } + + traverseElementDecl(child, true); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { + + if (typeName && *typeName) { + if (fGlobalDeclarations[ENUM_ELT_ATTRIBUTEGROUP]->containsElement(fullNameId)) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalDeclaration, + SchemaSymbols::fgELT_ATTRIBUTEGROUP, typeName); + continue; + } + else { + fGlobalDeclarations[ENUM_ELT_ATTRIBUTEGROUP]->addElement(fullNameId); + } + } + + if (!typeName || !fAttGroupRegistry->containsKey(typeName)) { + traverseAttributeGroupDecl(child, 0, true); + } + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_ATTRIBUTE)) { + + if (typeName && *typeName) { + if (fGlobalDeclarations[ENUM_ELT_ATTRIBUTE]->containsElement(fullNameId)) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, typeName); + continue; + } + else { + fGlobalDeclarations[ENUM_ELT_ATTRIBUTE]->addElement(fullNameId); + } + } + + if (!typeName || !fAttributeDeclRegistry->containsKey(typeName)) { + traverseAttributeDecl( child, 0, true); + } + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_GROUP)) { + + if (typeName && *typeName) { + if (fGlobalDeclarations[ENUM_ELT_GROUP]->containsElement(fullNameId)) { + + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalDeclaration, + SchemaSymbols::fgELT_GROUP, typeName); + continue; + } + else { + fGlobalDeclarations[ENUM_ELT_GROUP]->addElement(fullNameId); + } + } + + if (!typeName || !fGroupRegistry->containsKey(fBuffer.getRawBuffer())) { + traverseGroupDecl(child); + } + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_NOTATION)) { + traverseNotationDecl(child); + } + else { + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::SchemaElementContentError); + } + } // for each child node + + + if (fScanner->getGenerateSyntheticAnnotations() && fSchemaInfo->getNonXSAttList()->size() && !sawAnnotation) + { + // synthesize a global annotation here. + fSchemaGrammar->addAnnotation( + generateSyntheticAnnotation(root, fSchemaInfo->getNonXSAttList()) + ); + } + + // Handle recursing elements - if any + ValueVectorOf* recursingAnonTypes = fSchemaInfo->getRecursingAnonTypes(); + + if (recursingAnonTypes) { + + ValueVectorOf* recursingTypeNames = fSchemaInfo->getRecursingTypeNames(); + XMLSize_t recurseSize = recursingAnonTypes->size(); + + for (XMLSize_t i=0; i < recurseSize; i++) { + traverseComplexTypeDecl(recursingAnonTypes->elementAt(i), false, + recursingTypeNames->elementAt(i)); + } + + recursingAnonTypes->removeAllElements(); + recursingTypeNames->removeAllElements(); + } +} + +void TraverseSchema::preprocessChildren(const DOMElement* const root) { + + NamespaceScopeManager nsMgr(root, fSchemaInfo, this); + + // process , and info items. + DOMElement* child = XUtil::getFirstChildElement(root); + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* name = child->getLocalName(); + + if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { + continue; + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_INCLUDE)) { + preprocessInclude(child); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_IMPORT)) { + preprocessImport(child); + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_REDEFINE)) { + preprocessRedefine(child); + } + else + break; + } +} + +DOMElement* TraverseSchema::checkContent( const DOMElement* const rootElem + , DOMElement* const contentElem + , const bool isEmpty + , const bool processAnnot) +{ + DOMElement* content = contentElem; + const XMLCh* name = getElementAttValue(rootElem,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + + fAnnotation = 0; + Janitor janAnnot(0); + if (!content) { + + if (!isEmpty) { + reportSchemaError(rootElem, XMLUni::fgXMLErrDomain, XMLErrs::ContentError, name); + } + + return 0; + } + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { + + if (processAnnot) { + janAnnot.reset(traverseAnnotationDecl(content, fNonXSAttList)); + } + content = XUtil::getNextSiblingElement(content); + + if (!content) { // must be followed by content + + if (!isEmpty) { + reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ContentError, name); + } + fAnnotation = janAnnot.release(); + return 0; + } + + if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { + + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnnotationError, name); + return 0; + } + fAnnotation = janAnnot.release(); + } + return content; +} + + +DatatypeValidator* +TraverseSchema::getDatatypeValidator(const XMLCh* const uriStr, + const XMLCh* const localPartStr) { + + DatatypeValidator* dv = 0; + + if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + dv = fDatatypeRegistry->getDatatypeValidator(localPartStr); + } + else { + + fBuffer.set(uriStr); + fBuffer.append(chComma); + fBuffer.append(localPartStr); + + if ((uriStr) && !XMLString::equals(uriStr, fTargetNSURIString)) { + + Grammar* grammar = fGrammarResolver->getGrammar(uriStr); + + if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) { + dv = ((SchemaGrammar*) grammar)->getDatatypeRegistry()->getDatatypeValidator(fBuffer.getRawBuffer()); + } + } + else { + dv = fDatatypeRegistry->getDatatypeValidator(fBuffer.getRawBuffer()); + } + } + + return dv; +} + + +DatatypeValidator* +TraverseSchema::checkForSimpleTypeValidator(const DOMElement* const content, + int baseRefContext) { + + DatatypeValidator* baseValidator = traverseSimpleTypeDecl(content, false, baseRefContext); + + if (!baseValidator) { + + const XMLCh* name = getElementAttValue(content,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::UnknownSimpleType, name); + } + + return baseValidator; +} + +ComplexTypeInfo* +TraverseSchema::checkForComplexTypeInfo(const DOMElement* const content) { + + int typeNameIndex = traverseComplexTypeDecl(content, false); + ComplexTypeInfo* baseTypeInfo = 0; + + if (typeNameIndex != -1) { + baseTypeInfo = fComplexTypeRegistry->get(fStringPool->getValueForId(typeNameIndex)); + } + + if (typeNameIndex == -1 || baseTypeInfo == 0) { + + const XMLCh* name = getElementAttValue(content,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::UnknownComplexType, name); + } + + return baseTypeInfo; +} + +DatatypeValidator* +TraverseSchema::findDTValidator(const DOMElement* const elem, + const XMLCh* const derivedTypeName, + const XMLCh* const baseTypeName, + const int baseRefContext) { + + const XMLCh* prefix = getPrefix(baseTypeName); + const XMLCh* localPart = getLocalPart(baseTypeName); + const XMLCh* uri = resolvePrefixToURI(elem, prefix); + DatatypeValidator* baseValidator = getDatatypeValidator(uri, localPart); + + if (baseValidator == 0) { + + // Check if the base is from the schema for schema namespace + // + if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uri, localPart); + return 0; + } + + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + SchemaInfo* saveInfo = fSchemaInfo; + unsigned int saveScope = fCurrentScope; + + if (!XMLString::equals(uri, fTargetNSURIString) && (uri && *uri)) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(uri); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uri); + return 0; + } + + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); + + if (!impInfo || impInfo->getProcessed()) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uri, localPart); + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + + DOMElement* baseTypeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_SimpleType, + SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo); + + if (baseTypeNode != 0) { + + baseValidator = traverseSimpleTypeDecl(baseTypeNode); + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + } + } + + if (baseValidator == 0) { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::UnknownBaseDatatype, baseTypeName, derivedTypeName); + } + else if ((baseValidator->getFinalSet() & baseRefContext) != 0) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DisallowedBaseDerivation, baseTypeName); + return 0; + } + + return baseValidator; +} + + +const XMLCh* TraverseSchema::resolvePrefixToURI(const DOMElement* const elem, + const XMLCh* const prefix) { + + unsigned int nameSpaceIndex = fSchemaInfo->getNamespaceScope()->getNamespaceForPrefix(prefix); + const XMLCh* uriStr = fURIStringPool->getValueForId(nameSpaceIndex); + + if ((!uriStr || !*uriStr) && (prefix && *prefix)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::UnresolvedPrefix, prefix); + return XMLUni::fgZeroLenString; + } + + return uriStr; +} + +SchemaElementDecl* +TraverseSchema::processElementDeclRef(const DOMElement* const elem, + const XMLCh* const refName) +{ + // check attributes + fAttributeCheck.checkAttributes( + elem, GeneralAttributeCheck::E_ElementRef, this, false, fNonXSAttList + ); + + // handle annotation + DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); + Janitor janAnnot(fAnnotation); + + // do not generate synthetic annotation for element reference... + + if (content != 0) + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::NoContentForRef, SchemaSymbols::fgELT_ELEMENT); + + SchemaElementDecl* refElemDecl = getGlobalElemDecl(elem, refName); + + if (!refElemDecl) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::RefElementNotFound, refName); + } + else + { + if (fCurrentComplexType) + fCurrentComplexType->addElement(refElemDecl); + + if (fCurrentGroupInfo) + fCurrentGroupInfo->addElement(refElemDecl); + } + + return refElemDecl; +} + +int TraverseSchema::parseBlockSet(const DOMElement* const elem, + const int blockType, const bool isRoot) { + + const XMLCh* blockVal = (isRoot) ? getElementAttValue(elem, SchemaSymbols::fgATT_BLOCKDEFAULT) + : getElementAttValue(elem, SchemaSymbols::fgATT_BLOCK); + + // blockVal == 0 means 'block attribute is missing'; *blockVal == 0 means 'block="" found' + if (blockVal == 0) + return fSchemaInfo->getBlockDefault(); + + int blockSet = 0; + + if (XMLString::equals(blockVal, SchemaSymbols::fgATTVAL_POUNDALL)) { + + blockSet = SchemaSymbols::XSD_EXTENSION + SchemaSymbols::XSD_RESTRICTION + SchemaSymbols::XSD_SUBSTITUTION; + return blockSet; + } + + XMLStringTokenizer tokenizer(blockVal, fGrammarPoolMemoryManager); + + while (tokenizer.hasMoreTokens()) { + + XMLCh* token = tokenizer.nextToken(); + + if (XMLString::equals(token, SchemaSymbols::fgATTVAL_SUBSTITUTION) + && blockType == ES_Block) { + + if ((blockSet & SchemaSymbols::XSD_SUBSTITUTION) == 0 ) { + blockSet += SchemaSymbols::XSD_SUBSTITUTION; + } + } + else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_EXTENSION)) { + + if ((blockSet & SchemaSymbols::XSD_EXTENSION) == 0) { + blockSet += SchemaSymbols::XSD_EXTENSION; + } + } + else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_RESTRICTION)) { + + if ((blockSet & SchemaSymbols::XSD_RESTRICTION) == 0 ) { + blockSet += SchemaSymbols::XSD_RESTRICTION; + } + } + else { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidBlockValue, blockVal); + } + } //end while + + return blockSet; +} + +int TraverseSchema::parseFinalSet(const DOMElement* const elem, + const int finalType, const bool isRoot) { + + const XMLCh* finalVal = (isRoot) ? getElementAttValue(elem, SchemaSymbols::fgATT_FINALDEFAULT) + : getElementAttValue(elem, SchemaSymbols::fgATT_FINAL); + + // finalVal == 0 means 'final attribute is missing'; *finalVal == 0 means 'final="" found' + if (finalVal == 0) + return fSchemaInfo->getFinalDefault(); + + int finalSet = 0; + + if (XMLString::equals(finalVal, SchemaSymbols::fgATTVAL_POUNDALL)) { + + finalSet = SchemaSymbols::XSD_RESTRICTION + SchemaSymbols::XSD_LIST + + SchemaSymbols::XSD_UNION + SchemaSymbols::XSD_EXTENSION; + return finalSet; + } + + XMLStringTokenizer tokenizer(finalVal, fGrammarPoolMemoryManager); + + while (tokenizer.hasMoreTokens()) { + + XMLCh* token = tokenizer.nextToken(); + + if (XMLString::equals(token, SchemaSymbols::fgELT_UNION) + && (finalType == S_Final || finalType == ECS_Final)) { + + if ((finalSet & SchemaSymbols::XSD_UNION) == 0) { + finalSet += SchemaSymbols::XSD_UNION; + } + } + else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_EXTENSION) + && (finalType == EC_Final || finalType == ECS_Final)) { + + if ((finalSet & SchemaSymbols::XSD_EXTENSION) == 0) { + finalSet += SchemaSymbols::XSD_EXTENSION; + } + } + else if (XMLString::equals(token, SchemaSymbols::fgELT_LIST) + && (finalType == S_Final || finalType == ECS_Final)) { + + if ((finalSet & SchemaSymbols::XSD_LIST) == 0 ) { + finalSet += SchemaSymbols::XSD_LIST; + } + } + else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_RESTRICTION)) { + + if ((finalSet & SchemaSymbols::XSD_RESTRICTION) == 0 ) { + finalSet += SchemaSymbols::XSD_RESTRICTION; + } + } + else { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidFinalValue, finalVal); + } + } //end while + + return finalSet; +} + + +const DOMElement* +TraverseSchema::checkIdentityConstraintContent(const DOMElement* const content) { + + const DOMElement* child = content; + + if (child != 0) { + + do { + + if (!isIdentityConstraintName(child->getLocalName())) { + break; + } + + child = XUtil::getNextSiblingElement(child); + + } while (child != 0); + } + + return child; +} + +bool TraverseSchema::isIdentityConstraintName(const XMLCh* const name) { + + return (XMLString::equals(name, SchemaSymbols::fgELT_KEY) + || XMLString::equals(name, SchemaSymbols::fgELT_KEYREF) + || XMLString::equals(name, SchemaSymbols::fgELT_UNIQUE)); +} + +const XMLCh* +TraverseSchema::checkTypeFromAnotherSchema(const DOMElement* const elem, + const XMLCh* const typeStr) { + + const XMLCh* prefix = getPrefix(typeStr); + const XMLCh* typeURI = resolvePrefixToURI(elem, prefix); + + if (!XMLString::equals(typeURI, fTargetNSURIString) + && !XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + ) { + return typeURI; + } + + return 0; +} + +DatatypeValidator* +TraverseSchema::getElementTypeValidator(const DOMElement* const elem, + const XMLCh* const typeStr, + bool& noErrorDetected, + const XMLCh* const otherSchemaURI) +{ + const XMLCh* localPart = getLocalPart(typeStr); + const XMLCh* typeURI = otherSchemaURI; + DatatypeValidator* dv = 0; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + SchemaInfo* saveInfo = fSchemaInfo; + unsigned int saveScope = fCurrentScope; + + if (otherSchemaURI && *otherSchemaURI) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(otherSchemaURI); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, otherSchemaURI); + return 0; + } + + dv = getDatatypeValidator(typeURI, localPart); + + if (dv) { + return dv; + } + + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); + + if (!impInfo || impInfo->getProcessed()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart); + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + else { + const XMLCh* prefix = getPrefix(typeStr); + + typeURI = resolvePrefixToURI(elem, prefix); + dv = getDatatypeValidator(typeURI, localPart); + } + + if (!dv) { + + if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + || XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + + DOMElement* typeElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_SimpleType, + SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo); + + if (typeElem) { + traverseSimpleTypeDecl(typeElem); + dv = getDatatypeValidator(typeURI, localPart); + } + } + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + + if (!dv) { + + noErrorDetected = false; + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart); + } + } + + return dv; +} + + +DatatypeValidator* +TraverseSchema::getAttrDatatypeValidatorNS(const DOMElement* const elem, + const XMLCh* localPart, + const XMLCh* typeURI) +{ + DatatypeValidator* dv = getDatatypeValidator(typeURI, localPart); + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + SchemaInfo* saveInfo = fSchemaInfo; + unsigned int saveScope = fCurrentScope; + + if (!XMLString::equals(typeURI, fTargetNSURIString) + && (typeURI && *typeURI)) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(typeURI); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, typeURI); + return 0; + } + + if (!dv) { + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); + + if (!impInfo || impInfo->getProcessed()) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart); + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + } + + if (!dv) { + + DOMElement* typeElem = fSchemaInfo->getTopLevelComponent + ( + SchemaInfo::C_SimpleType + , SchemaSymbols::fgELT_SIMPLETYPE + , localPart + , &fSchemaInfo + ); + + if (typeElem) + dv = traverseSimpleTypeDecl(typeElem); + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + } + + return dv; +} + +ComplexTypeInfo* +TraverseSchema::getElementComplexTypeInfo(const DOMElement* const elem, + const XMLCh* const typeStr, + const XMLCh* const otherSchemaURI) +{ + const XMLCh* localPart = getLocalPart(typeStr); + const XMLCh* prefix = getPrefix(typeStr); + const XMLCh* typeURI = (otherSchemaURI) ? otherSchemaURI : resolvePrefixToURI(elem, prefix); + ComplexTypeInfo* typeInfo = 0; + SchemaInfo* saveInfo = fSchemaInfo; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + unsigned int saveScope = fCurrentScope; + + fBuffer.set(typeURI); + fBuffer.append(chComma); + fBuffer.append(localPart); + + if (otherSchemaURI != 0) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(typeURI); + + if (!isImportingNS(uriId)) + return 0; + + Grammar* aGrammar = fGrammarResolver->getGrammar(typeURI); + + if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { + return 0; + } + + typeInfo = ((SchemaGrammar*)aGrammar)->getComplexTypeRegistry()->get(fBuffer.getRawBuffer()); + + if (typeInfo) { + return typeInfo; + } + + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); + + if (!impInfo || impInfo->getProcessed()) { + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + else { + typeInfo = fComplexTypeRegistry->get(fBuffer.getRawBuffer()); + } + + if (!typeInfo) { + if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) || + XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + + DOMElement* typeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_ComplexType, + SchemaSymbols::fgELT_COMPLEXTYPE, localPart, &fSchemaInfo); + + if (typeNode) { + // fBuffer is reused by traverseComplexTypeDecl, so we have to store its current value + XMLBuffer buffCopy(fBuffer.getLen()+1, fMemoryManager); + buffCopy.set(fBuffer.getRawBuffer()); + traverseComplexTypeDecl(typeNode); + typeInfo = fComplexTypeRegistry->get(buffCopy.getRawBuffer()); + } + } + } + + // restore schema information + restoreSchemaInfo(saveInfo, infoType, saveScope); + return typeInfo; +} + + +SchemaElementDecl* +TraverseSchema::getGlobalElemDecl(const DOMElement* const elem, + const XMLCh* const qName) +{ + const XMLCh* nameURI = resolvePrefixToURI(elem, getPrefix(qName)); + const XMLCh* localPart = getLocalPart(qName); + SchemaElementDecl* elemDecl = 0; + SchemaInfo* saveInfo = fSchemaInfo; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + unsigned int saveScope = fCurrentScope; + unsigned int uriId = fURIStringPool->addOrFind(nameURI); + + if (fSchemaInfo->getTargetNSURI() != (int) uriId) + { + //if (!XMLString::equals(nameURI, fTargetNSURIString)) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + if (!isImportingNS(uriId)) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, nameURI); + return 0; + } + + Grammar* grammar = fGrammarResolver->getGrammar(nameURI); + + if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) + { + elemDecl = (SchemaElementDecl*) grammar->getElemDecl( + uriId, localPart, 0, Grammar::TOP_LEVEL_SCOPE); + } + else + { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, nameURI); + return 0; + } + + if (!elemDecl) + { + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); + if (!impInfo || impInfo->getProcessed()) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, nameURI, localPart); + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + } + else + { + elemDecl = (SchemaElementDecl*) + fSchemaGrammar->getElemDecl(fTargetNSURI, localPart, 0, Grammar::TOP_LEVEL_SCOPE); + } + + if (!elemDecl) + { + DOMElement* subsGroupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Element, + SchemaSymbols::fgELT_ELEMENT,localPart, &fSchemaInfo); + + if (subsGroupElem) + elemDecl = traverseElementDecl(subsGroupElem, true); + + if (!elemDecl) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, nameURI, localPart); + } + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + + return elemDecl; +} + +bool +TraverseSchema::isSubstitutionGroupValid(const DOMElement* const elem, + const SchemaElementDecl* const subsElemDecl, + const ComplexTypeInfo* const typeInfo, + const DatatypeValidator* const validator, + const XMLCh* const elemName, + const bool toEmit) { + + // here we must do two things: + // 1. Make sure there actually *is* a relation between the types of + // the element being nominated and the element doing the nominating; + // (see PR 3.3.6 point #3 in the first tableau, for instance; this + // and the corresponding tableaux from 3.4.6 and 3.14.6 rule out the nominated + // element having an anonymous type declaration. + // 2. Make sure the nominated element allows itself to be nominated by + // an element with the given type-relation. + // Note: we assume that (complex|simple)Type processing checks + // whether the type in question allows itself to + // be modified as this element desires. + + // if substitution element has any as content model type, return true + bool subsRestricted = false; + if (subsElemDecl->getModelType() == SchemaElementDecl::Any) { + + if ((subsElemDecl->getFinalSet() & SchemaSymbols::XSD_RESTRICTION) == 0 + || (typeInfo == 0 && validator == 0)) + return true; + else + subsRestricted = true; + } + // Check for type relationship; + // that is, make sure that the type we're deriving has some relatoinship + // to substitutionGroupElt's type. + else if (typeInfo) { // do complexType case ...need testing + + ComplexTypeInfo* subsTypeInfo = subsElemDecl->getComplexTypeInfo(); + + if (subsTypeInfo == typeInfo) + return true; + + int derivationMethod = typeInfo->getDerivedBy(); + + if (subsTypeInfo == 0) { // take care of complexType based on simpleType case... + + DatatypeValidator* elemDV = typeInfo->getDatatypeValidator(); + DatatypeValidator* subsValidator = subsElemDecl->getDatatypeValidator(); + + if (elemDV == subsValidator) { + return true; + } + else if (subsValidator && subsValidator->isSubstitutableBy(elemDV)) { + if ((subsElemDecl->getFinalSet() & derivationMethod) == 0) { + return true; + } + else { + subsRestricted = true; + } + } + } + else { // complex content + + const ComplexTypeInfo* elemTypeInfo = typeInfo; + + for (; elemTypeInfo && elemTypeInfo != subsTypeInfo; + elemTypeInfo = elemTypeInfo->getBaseComplexTypeInfo()) { + } + + if (elemTypeInfo) { + if ((subsElemDecl->getFinalSet() & derivationMethod) == 0) { + return true; + } + else { + subsRestricted = true; + } + } + } + } + else if (validator) { // do simpleType case... + + if (!subsElemDecl->getComplexTypeInfo()) { + // first, check for type relation. + DatatypeValidator* subsValidator = subsElemDecl->getDatatypeValidator(); + + if (subsValidator == validator) { + return true; + } + else if (subsValidator && subsValidator->isSubstitutableBy(validator) + && ((subsElemDecl->getFinalSet() & SchemaSymbols::XSD_RESTRICTION) == 0)) { + return true; + } + } + } + else // validator==0 && typeInfo==0 -- no checking + return true; + + if (toEmit) { + if (subsRestricted) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSubstitutionGroupElement, + elemName, subsElemDecl->getBaseName()); + } + else { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SubstitutionGroupTypeMismatch, elemName); + } + } + + return false; +} + + +SchemaElementDecl* +TraverseSchema::createSchemaElementDecl(const DOMElement* const elem, + const XMLCh* const name, + bool& isDuplicate, + const XMLCh*& valConstraint, + const bool topLevel) +{ + unsigned int enclosingScope = fCurrentScope; + int uriIndex = fEmptyNamespaceURI; + + if (topLevel) { + + uriIndex = fTargetNSURI; + enclosingScope = Grammar::TOP_LEVEL_SCOPE; + } + else + { + const XMLCh* elemForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM); + + if (((!elemForm || !*elemForm) && + (fSchemaInfo->getElemAttrDefaultQualified() & Elem_Def_Qualified)) + || XMLString::equals(elemForm,SchemaSymbols::fgATTVAL_QUALIFIED)) + uriIndex = fTargetNSURI; + + // Check for duplicate elements + SchemaElementDecl* other = (SchemaElementDecl*) + fSchemaGrammar->getElemDecl(uriIndex, name, 0, enclosingScope); + + if (other != 0) + { + isDuplicate = true; + return other; + } + } + + // create element decl and add it to the grammar + Janitor elemDecl(new (fGrammarPoolMemoryManager) SchemaElementDecl( + XMLUni::fgZeroLenString , name, uriIndex , SchemaElementDecl::Any + , enclosingScope , fGrammarPoolMemoryManager + )); + + elemDecl->setCreateReason(XMLElementDecl::Declared); + + if (topLevel) + elemDecl->setPSVIScope(PSVIDefs::SCP_GLOBAL); + + // process attributes + processElemDeclAttrs(elem, elemDecl.get(), valConstraint, topLevel); + + return elemDecl.release(); +} + + +void TraverseSchema::processAttributeDeclRef(const DOMElement* const elem, + ComplexTypeInfo* const typeInfo, + const XMLCh* const refName, + const XMLCh* const useAttr, + const XMLCh* const defaultVal, + const XMLCh* const fixedVal) { + + if (!typeInfo && !fCurrentAttGroupInfo) { + return; + } + + const XMLCh* prefix = getPrefix(refName); + const XMLCh* localPart = getLocalPart(refName); + const XMLCh* uriStr = resolvePrefixToURI(elem, prefix); + unsigned int attURI = fURIStringPool->addOrFind(uriStr); + + // Check for duplicate references + if (typeInfo && typeInfo->getAttDef(localPart, attURI)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart); + return; + } + else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(localPart, attURI)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart); + return; + } + + // check for different namespace + SchemaInfo* saveInfo = fSchemaInfo; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + SchemaAttDef* refAttDef = 0; + unsigned int saveScope = fCurrentScope; + + if (!XMLString::equals(uriStr, fTargetNSURIString)) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); + return; + } + + Grammar* grammar = fGrammarResolver->getGrammar(uriStr); + + if (grammar == 0 || grammar->getGrammarType() != Grammar::SchemaGrammarType) { + + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); + return; + } + + refAttDef = (SchemaAttDef*) ((SchemaGrammar*) grammar)->getAttributeDeclRegistry()->get(localPart); + + if (!refAttDef) { + + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(attURI); + + if (!impInfo || impInfo->getProcessed()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName); + return; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + } + + // if Global attribute registry does not contain the ref attribute, get + // the referred attribute declaration and traverse it. + if (!refAttDef) { + + if (fAttributeDeclRegistry->containsKey(localPart) == false) { + + DOMElement* referredAttribute = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Attribute, + SchemaSymbols::fgELT_ATTRIBUTE, localPart, &fSchemaInfo); + + if (referredAttribute != 0) { + traverseAttributeDecl(referredAttribute, 0, true); + } + } + + refAttDef = (SchemaAttDef*) fAttributeDeclRegistry->get(localPart); + } + + // restore schema information, if necessary + if (fSchemaInfo != saveInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + + if (!refAttDef) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName); + return; + } + + XMLAttDef::DefAttTypes refAttDefType = refAttDef->getDefaultType(); + const XMLCh* refAttValue = refAttDef->getValue(); + bool invalidAttUse = false; + + if (refAttDefType == XMLAttDef::Fixed && + (defaultVal || (fixedVal && !XMLString::equals(fixedVal, refAttValue)))) { + + invalidAttUse = true; + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttUseCorrect, refName); + } + + DatatypeValidator* attDV = refAttDef->getDatatypeValidator(); + + //check for multiple attributes with type derived from ID + if (attDV && attDV->getType() == DatatypeValidator::ID) { + + if (fCurrentAttGroupInfo) { + + if (fCurrentAttGroupInfo->containsTypeWithId()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, refName); + return; + } + + fCurrentAttGroupInfo->setTypeWithId(true); + } + else { + + if (typeInfo->containsAttWithTypeId()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, refName); + return; + } + + typeInfo->setAttWithTypeId(true); + } + } + + bool required = XMLString::equals(useAttr,SchemaSymbols::fgATTVAL_REQUIRED); + bool prohibited = XMLString::equals(useAttr,SchemaSymbols::fgATTVAL_PROHIBITED); + QName* attQName = refAttDef->getAttName(); + SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attQName->getPrefix(), + attQName->getLocalPart(), + attQName->getURI(), + refAttValue, + refAttDef->getType(), + refAttDefType, + 0, fGrammarPoolMemoryManager); + + attDef->setBaseAttDecl(refAttDef); + attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL); + + if (refAttDefType == XMLAttDef::Fixed) { + if (required && !invalidAttUse) { + attDef->setDefaultType(XMLAttDef::Required_And_Fixed); + } + } + else { + + if (prohibited) { + attDef->setDefaultType(XMLAttDef::Prohibited); + } + else { + + const XMLCh* valueConstraint = defaultVal; + + if (required){ + + if (fixedVal) { + + attDef->setDefaultType(XMLAttDef::Required_And_Fixed); + valueConstraint = fixedVal; + } + else { + attDef->setDefaultType(XMLAttDef::Required); + } + } + else + { + if (fixedVal) { + attDef->setDefaultType(XMLAttDef::Fixed); + valueConstraint = fixedVal; + } + else if (defaultVal) { + attDef->setDefaultType(XMLAttDef::Default); + } + } + + if (valueConstraint) { + + // validate content of value constraint + if (attDV) { + + if (attDV->getType() == DatatypeValidator::ID) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, refName); + } + else { + try { + attDV->validate(valueConstraint + , fSchemaInfo->getValidationContext() + , fMemoryManager); + } + catch(const XMLException& excep) { + reportSchemaError(elem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch (...) { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueConstraint); + } + } + } + + attDef->setValue(valueConstraint); + } + } + } + + attDef->setDatatypeValidator(attDV); + + bool toClone = false; + + if (typeInfo) { + + toClone = true; + typeInfo->addAttDef(attDef); + } + + if (fCurrentAttGroupInfo) { + fCurrentAttGroupInfo->addAttDef(attDef, toClone); + } +} + + +int TraverseSchema::checkMinMax(ContentSpecNode* const specNode, + const DOMElement* const elem, + const int allContextFlag) { + + int minOccurs = 1; + int maxOccurs = 1; + const XMLCh* minOccursStr = getElementAttValue(elem, SchemaSymbols::fgATT_MINOCCURS, DatatypeValidator::Decimal); + const XMLCh* maxOccursStr = getElementAttValue(elem, SchemaSymbols::fgATT_MAXOCCURS, DatatypeValidator::Decimal); + + if (!minOccursStr || !*minOccursStr) { + if (specNode) + minOccurs = specNode->getMinOccurs(); + } + else { + try { + minOccurs = XMLString::parseInt(minOccursStr, fMemoryManager); + } + catch(const NumberFormatException& e) + { + // REVISIT: report a warning that we replaced a number too big? + if(e.getCode()==XMLExcepts::Str_ConvertOverflow) + minOccurs = 500; + else + minOccurs = 1; + } + catch(const OutOfMemoryException&) + { + throw; + } + + if (specNode) + specNode->setMinOccurs(minOccurs); + } + + bool isMaxUnbounded = XMLString::equals(maxOccursStr, fgUnbounded); + + if (isMaxUnbounded) { + maxOccurs = SchemaSymbols::XSD_UNBOUNDED; + if (specNode) + specNode->setMaxOccurs(maxOccurs); + } + else { + if (!maxOccursStr || !*maxOccursStr) { + if (specNode) + maxOccurs = specNode->getMaxOccurs(); + } + else { + try { + maxOccurs = XMLString::parseInt(maxOccursStr, fMemoryManager); + } + catch(const NumberFormatException& e) + { + // REVISIT: report a warning that we replaced a number too big? + if(e.getCode()==XMLExcepts::Str_ConvertOverflow && minOccurs < 500) + maxOccurs = 500; + else + maxOccurs = minOccurs; + } + catch(const OutOfMemoryException&) + { + throw; + } + + if (specNode) + specNode->setMaxOccurs(maxOccurs); + } + } + + if (minOccurs == 0 && maxOccurs == 0){ + return minOccurs; + } + + // Constraint checking for min/max value + if (!isMaxUnbounded) { + + XMLCh tmpMinStr[128]; + XMLCh tmpMaxStr[128]; + + XMLString::binToText(minOccurs, tmpMinStr, 127, 10, fMemoryManager); + XMLString::binToText(maxOccurs, tmpMaxStr, 127, 10, fMemoryManager); + + if (maxOccurs < 1) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttValue, + tmpMaxStr, SchemaSymbols::fgATT_MAXOCCURS); + if (specNode) + specNode->setMaxOccurs(minOccurs); + } + else if (maxOccurs < minOccurs) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidMin2MaxOccurs, + tmpMinStr, tmpMaxStr); + if (specNode) + specNode->setMaxOccurs(minOccurs); + } + } + + // Constraint checking for 'all' content + bool isAllElement = (allContextFlag == All_Element); + bool isAllGroup = (allContextFlag == All_Group); + bool isGroupRefAll = (allContextFlag == Group_Ref_With_All); + + if (isAllElement || isAllGroup || isGroupRefAll) { + + if (maxOccurs != 1 || minOccurs > 1) { + + // set back correct value in order to carry on + if (specNode) { + + specNode->setMaxOccurs(1); + + if (minOccurs > 1) + specNode->setMinOccurs(1); + } + + if (isAllElement) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadMinMaxAllElem); + } + else { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadMinMaxAllCT); + } + } + } + return minOccurs; +} + + +void TraverseSchema::processComplexContent(const DOMElement* const ctElem, + const XMLCh* const typeName, + const DOMElement* const childElem, + ComplexTypeInfo* const typeInfo, + const XMLCh* const baseLocalPart, + const bool isMixed, + const bool isBaseAnyType) { + + NamespaceScopeManager nsMgr(childElem, fSchemaInfo, this); + + Janitor specNodeJan(0); + ContentSpecNode* specNode = specNodeJan.get(); + const DOMElement* attrNode = 0; + int typeDerivedBy = typeInfo->getDerivedBy(); + ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); + int baseContentType = (baseTypeInfo) ? baseTypeInfo->getContentType() : SchemaElementDecl::Empty; + + if (baseTypeInfo) { + + if (typeDerivedBy == SchemaSymbols::XSD_RESTRICTION) { + + // check to see if the baseType permits derivation by restriction + if((baseTypeInfo->getFinalSet() & typeDerivedBy) != 0) { + + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivationByRestriction, + baseLocalPart); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + else { + + // check to see if the baseType permits derivation by extension + if((baseTypeInfo->getFinalSet() & typeDerivedBy) != 0) { + + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivationByExtension, baseLocalPart); + throw TraverseSchema::InvalidComplexTypeInfo; // REVISIT - should we continue + } + + processElements(ctElem, baseTypeInfo, typeInfo); + } + } + + bool effectiveContent_hasChild = false; + + if (childElem != 0) { + + fCircularCheckIndex = fCurrentTypeNameStack->size(); + + // -------------------------------------------------------------------- + // GROUP, ALL, SEQUENCE or CHOICE, followed by attributes, if specified. + // Note that it's possible that only attributes are specified. + // -------------------------------------------------------------------- + const XMLCh* childName = childElem->getLocalName(); + + if (XMLString::equals(childName, SchemaSymbols::fgELT_GROUP)) { + + XercesGroupInfo* grpInfo = traverseGroupDecl(childElem, false); + + if (grpInfo) { + + ContentSpecNode* const groupSpecNode = grpInfo->getContentSpec(); + + if (groupSpecNode) { + + int contentContext = groupSpecNode->hasAllContent() ? Group_Ref_With_All : Not_All_Context; + specNodeJan.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*groupSpecNode)); + specNode = specNodeJan.get(); + checkMinMax(specNode, childElem, contentContext); + } + } + + attrNode = XUtil::getNextSiblingElement(childElem); + + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) { + + specNodeJan.reset(traverseChoiceSequence(childElem, ContentSpecNode::Sequence, effectiveContent_hasChild)); + specNode = specNodeJan.get(); + checkMinMax(specNode, childElem); + attrNode = XUtil::getNextSiblingElement(childElem); + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) { + + specNodeJan.reset(traverseChoiceSequence(childElem, ContentSpecNode::Choice, effectiveContent_hasChild)); + specNode = specNodeJan.get(); + int minOccurs = checkMinMax(specNode, childElem); + if (!effectiveContent_hasChild && minOccurs != 0) { + effectiveContent_hasChild = true; + } + + attrNode = XUtil::getNextSiblingElement(childElem); + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_ALL)) { + + specNodeJan.reset(traverseAll(childElem, effectiveContent_hasChild)); + specNode = specNodeJan.get(); + checkMinMax(specNode, childElem, All_Group); + attrNode = XUtil::getNextSiblingElement(childElem); + } + else if (isAttrOrAttrGroup(childElem)) { + // reset the contentType + typeInfo->setContentType(SchemaElementDecl::Any); + attrNode = childElem; + } + else { + reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, childName); + } + } + + typeInfo->setContentSpec(specNode); + typeInfo->setAdoptContentSpec(true); + specNodeJan.release(); + bool specNodeWasNull = false; + + // ----------------------------------------------------------------------- + // Merge in information from base, if it exists + // ----------------------------------------------------------------------- + if (baseTypeInfo) { + + ContentSpecNode* baseSpecNode = baseTypeInfo->getContentSpec(); + + if (typeDerivedBy == SchemaSymbols::XSD_RESTRICTION) { + + //check derivation valid - content type is empty (5.2) + if (!typeInfo->getContentSpec()) { + + if (baseContentType != SchemaElementDecl::Empty + && !emptiableParticle(baseSpecNode)) { + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::EmptyComplexRestrictionDerivation); + } + } + + // Delay particle constraint checking (5.3) until we have processed + // the whole schema. + } + else { + + // Compose the final content model by concatenating the base and + // the current in sequence + if (!specNode) { + specNodeWasNull = true; + if (isMixed) { + if (baseSpecNode && baseSpecNode->hasAllContent()) { + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::NotAllContent); + throw TraverseSchema::InvalidComplexTypeInfo; // REVISIT - should we continue + } + } + if (baseSpecNode) { + specNodeJan.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*baseSpecNode)); + specNode = specNodeJan.get(); + typeInfo->setContentSpec(specNode); + typeInfo->setAdoptContentSpec(true); + specNodeJan.release(); + } + } + else if (baseSpecNode) { + + if (specNode->hasAllContent() || baseSpecNode->hasAllContent()) { + + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::NotAllContent); + throw TraverseSchema::InvalidComplexTypeInfo; // REVISIT - should we continue + } + + // Check for derivation valid (extension) - 1.4.3.2.2.1 + if ((isMixed && baseContentType == SchemaElementDecl::Children) + || (!isMixed && baseContentType != SchemaElementDecl::Children)) { + + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::MixedOrElementOnly, baseLocalPart, typeName); + throw TraverseSchema::InvalidComplexTypeInfo; //REVISIT - should we continue + } + + typeInfo->setAdoptContentSpec(false); + typeInfo->setContentSpec + ( + new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::ModelGroupSequence + , new (fGrammarPoolMemoryManager) ContentSpecNode(*baseSpecNode) + , specNode + , true + , true + , fGrammarPoolMemoryManager + ) + ); + typeInfo->setAdoptContentSpec(true); + } + } + } + else { + typeInfo->setDerivedBy(0); + } + + // ------------------------------------------------------------- + // Set the content type + // ------------------------------------------------------------- + if (isBaseAnyType && typeDerivedBy == SchemaSymbols::XSD_EXTENSION) { + + ContentSpecNode* anySpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + new (fGrammarPoolMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , fEmptyNamespaceURI, fGrammarPoolMemoryManager + ) + , false + , fGrammarPoolMemoryManager + ); + + anySpecNode->setType(ContentSpecNode::Any_Lax); + anySpecNode->setMinOccurs(0); + anySpecNode->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED); + + if (!specNode) { + typeInfo->setContentSpec(anySpecNode); + typeInfo->setDerivedBy(typeDerivedBy); + } + else { + + typeInfo->setAdoptContentSpec(false); + typeInfo->setContentSpec + ( + new (fGrammarPoolMemoryManager) ContentSpecNode + ( + ContentSpecNode::ModelGroupSequence + , anySpecNode + , specNode + , true + , true + , fGrammarPoolMemoryManager + ) + ); + typeInfo->setAdoptContentSpec(true); + + if (!isMixed) { + + reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::MixedOrElementOnly, baseLocalPart, typeName); + throw TraverseSchema::InvalidComplexTypeInfo; //REVISIT - should we continue + } + } + + typeInfo->setContentType(SchemaElementDecl::Mixed_Complex); + } + else if (isMixed) { + + if (specNode != 0) { + typeInfo->setContentType(SchemaElementDecl::Mixed_Complex); + } + else { + // add #PCDATA leaf and set its minOccurs to 0 + ContentSpecNode* pcdataNode = new (fGrammarPoolMemoryManager) ContentSpecNode + ( + new (fGrammarPoolMemoryManager) QName + ( + XMLUni::fgZeroLenString + , XMLUni::fgZeroLenString + , XMLElementDecl::fgPCDataElemId + , fGrammarPoolMemoryManager + ) + , false + , fGrammarPoolMemoryManager + ); + + pcdataNode->setMinOccurs(0); + typeInfo->setContentSpec(pcdataNode); + typeInfo->setAdoptContentSpec(true); + typeInfo->setContentType(SchemaElementDecl::Mixed_Simple); + } + } + else if (specNodeWasNull && + (typeDerivedBy == SchemaSymbols::XSD_EXTENSION) && + baseTypeInfo) { + typeInfo->setBaseDatatypeValidator(baseTypeInfo->getBaseDatatypeValidator()); + typeInfo->setDatatypeValidator(baseTypeInfo->getDatatypeValidator()); + typeInfo->setContentType(baseTypeInfo->getContentType()); + } + else if (typeInfo->getContentSpec() == 0) { + if (!effectiveContent_hasChild) { + typeInfo->setContentType(SchemaElementDecl::Empty); + } + else { + typeInfo->setContentType(SchemaElementDecl::ElementOnlyEmpty); + } + } + else { + typeInfo->setContentType(SchemaElementDecl::Children); + } + + // ------------------------------------------------------------- + // Now, check attributes and handle + // ------------------------------------------------------------- + if (attrNode != 0) { + + if (!isAttrOrAttrGroup(attrNode)) { + reportSchemaError(attrNode, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, + attrNode->getLocalName()); + } + else { + processAttributes(ctElem, attrNode, typeInfo, isBaseAnyType); + } + } + else if (baseTypeInfo != 0 || isBaseAnyType) { + processAttributes(ctElem, 0, typeInfo, isBaseAnyType); + } +} + + +void TraverseSchema::processBaseTypeInfo(const DOMElement* const elem, + const XMLCh* const baseName, + const XMLCh* const localPart, + const XMLCh* const uriStr, + ComplexTypeInfo* const typeInfo) { + + SchemaInfo* saveInfo = fSchemaInfo; + ComplexTypeInfo* baseComplexTypeInfo = 0; + DatatypeValidator* baseDTValidator = 0; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + unsigned int saveScope = fCurrentScope; + + // check if the base type is from another schema + if (!XMLString::equals(uriStr, fTargetNSURIString)) { + + // check for datatype validator if it's schema for schema URI + if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + + baseDTValidator = getDatatypeValidator(uriStr, localPart); + + if (!baseDTValidator) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + else { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + baseComplexTypeInfo = getTypeInfoFromNS(elem, uriStr, localPart); + + if (!baseComplexTypeInfo) { + + baseDTValidator = getDatatypeValidator(uriStr, localPart); + + if (!baseDTValidator) + { + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(fURIStringPool->addOrFind(uriStr)); + + if (!impInfo || impInfo->getProcessed()) + { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + } + } + } + else { + + fBuffer.set(uriStr); + fBuffer.append(chComma); + fBuffer.append(localPart); + + // assume the base is a complexType and try to locate the base type first + const XMLCh* fullBaseName = fBuffer.getRawBuffer(); + baseComplexTypeInfo = fComplexTypeRegistry->get(fullBaseName); + + // Circular check + if (baseComplexTypeInfo) { + + if (fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName), fCircularCheckIndex)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, fullBaseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + else if (fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName))) { + + typeInfo->setBaseComplexTypeInfo(baseComplexTypeInfo); + throw TraverseSchema::RecursingElement; + } + else if (baseComplexTypeInfo->getPreprocessed()) { + baseComplexTypeInfo = 0; + } + } + } + + // if not found, 2 possibilities: + // 1: ComplexType in question has not been compiled yet; + // 2: base is SimpleType; + if (!baseComplexTypeInfo && !baseDTValidator) { + + baseDTValidator = getDatatypeValidator(uriStr, localPart); + + if (baseDTValidator == 0) { + + DOMElement* baseTypeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_ComplexType, + SchemaSymbols::fgELT_COMPLEXTYPE, localPart, &fSchemaInfo); + + if (baseTypeNode != 0) { + + int baseTypeSymbol = traverseComplexTypeDecl(baseTypeNode); + baseComplexTypeInfo = fComplexTypeRegistry->get(fStringPool->getValueForId(baseTypeSymbol)); + } + else { + + baseTypeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_SimpleType, + SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo); + + if (baseTypeNode != 0) { + + baseDTValidator = traverseSimpleTypeDecl(baseTypeNode); + + if (baseDTValidator == 0) { + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, localPart, uriStr); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + else { + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + } + } + } // end if + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + + typeInfo->setBaseComplexTypeInfo(baseComplexTypeInfo); + typeInfo->setBaseDatatypeValidator(baseDTValidator); +} + + +ComplexTypeInfo* TraverseSchema::getTypeInfoFromNS(const DOMElement* const elem, + const XMLCh* const uriStr, + const XMLCh* const localPart) +{ + + Grammar* grammar = fGrammarResolver->getGrammar(uriStr); + + if (grammar != 0 && grammar->getGrammarType() == Grammar::SchemaGrammarType) { + + fBuffer.set(uriStr); + fBuffer.append(chComma); + fBuffer.append(localPart); + + ComplexTypeInfo* typeInfo = + ((SchemaGrammar*)grammar)->getComplexTypeRegistry()->get(fBuffer.getRawBuffer()); + + return typeInfo; + } + else { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); + } + + return 0; +} + + +void TraverseSchema::processAttributes(const DOMElement* const elem, + const DOMElement* const attElem, + ComplexTypeInfo* const typeInfo, + const bool isBaseAnyType) { + + // If we do not have a complexTypeInfo, then what is the point of + // processing. + if (typeInfo == 0) { + return; + } + + ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); + if (baseTypeInfo && baseTypeInfo->getPreprocessed()) + throw TraverseSchema::RecursingElement; + + const DOMElement* child = attElem; + SchemaAttDef* attWildCard = 0; + Janitor janAttWildCard(0); + XercesAttGroupInfo* attGroupInfo = 0; + ValueVectorOf attGroupList(4, fGrammarPoolMemoryManager); + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* childName = child->getLocalName(); + + if (XMLString::equals(childName, SchemaSymbols::fgELT_ATTRIBUTE)) { + if(attWildCard) + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeBeforeAttribute); + + traverseAttributeDecl(child, typeInfo); + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { + if(attWildCard) + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeBeforeAttribute); + + attGroupInfo = traverseAttributeGroupDecl(child, typeInfo); + if (attGroupInfo && !attGroupList.containsElement(attGroupInfo)) { + attGroupList.addElement(attGroupInfo); + } + } + else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANYATTRIBUTE) ) { + if(attWildCard) + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAnyAttribute); + + attWildCard = traverseAnyAttribute(child); + janAttWildCard.reset(attWildCard); + } + else { + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, childName); + } + } + + // ------------------------------------------------------------- + // Handle wild card/any attribute + // ------------------------------------------------------------- + int derivedBy = typeInfo->getDerivedBy(); + XMLSize_t attGroupListSize = attGroupList.size(); + + if (attGroupListSize) { + + SchemaAttDef* completeWildCard = 0; + Janitor janCompleteWildCard(0); + XMLAttDef::DefAttTypes defAttType = XMLAttDef::Default; + bool defAttTypeSet = false; + + for (XMLSize_t i=0; i < attGroupListSize; i++) { + + attGroupInfo = attGroupList.elementAt(i); + XMLSize_t anyAttCount = attGroupInfo->anyAttributeCount(); + + if (anyAttCount) { + + if (!defAttTypeSet) { + + defAttType = (attWildCard) ? attWildCard->getDefaultType() + : attGroupInfo->anyAttributeAt(0)->getDefaultType(); + defAttTypeSet = true; + } + + SchemaAttDef* attGroupWildCard = attGroupInfo->getCompleteWildCard(); + if (completeWildCard) { + attWildCardIntersection(completeWildCard, attGroupWildCard); + } + else { + completeWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(attGroupWildCard); + janCompleteWildCard.reset(completeWildCard); + } + } + + } + + if (completeWildCard) { + + if (attWildCard) { + attWildCardIntersection(attWildCard, completeWildCard); + } + else { + + attWildCard = completeWildCard; + janCompleteWildCard.orphan(); + janAttWildCard.reset(attWildCard); + } + + attWildCard->setDefaultType(defAttType); + } + } + + SchemaAttDef* baseAttWildCard = (baseTypeInfo) ? baseTypeInfo->getAttWildCard() : 0; + Janitor janBaseAttWildCard(0); + + if (derivedBy == SchemaSymbols::XSD_EXTENSION) { + + if (isBaseAnyType) { + + baseAttWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(XMLUni::fgZeroLenString, + XMLUni::fgZeroLenString, + fEmptyNamespaceURI, XMLAttDef::Any_Any, + XMLAttDef::ProcessContents_Lax, + fGrammarPoolMemoryManager); + janBaseAttWildCard.reset(baseAttWildCard); + } + + if (baseAttWildCard && attWildCard) { + + XMLAttDef::DefAttTypes saveDefType = attWildCard->getDefaultType(); + attWildCardUnion(attWildCard, baseAttWildCard); + attWildCard->setDefaultType(saveDefType); + } + } + + // ------------------------------------------------------------- + // insert wildcard attribute + // ------------------------------------------------------------- + if (attWildCard) { + + typeInfo->setAttWildCard(attWildCard); + janAttWildCard.orphan(); + + if (attWildCard->getType() == XMLAttDef::AttTypes_Unknown) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotExpressibleWildCardIntersection); + } + } + else if (baseAttWildCard && derivedBy == SchemaSymbols::XSD_EXTENSION) { + + if (isBaseAnyType) { + + typeInfo->setAttWildCard(baseAttWildCard); + janBaseAttWildCard.orphan(); + } + else { + + SchemaAttDef* newWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(baseAttWildCard); + typeInfo->setAttWildCard(newWildCard); + } + } + + // ------------------------------------------------------------- + // Check attributes derivation OK + // ------------------------------------------------------------- + bool baseWithAttributes = (baseTypeInfo && baseTypeInfo->hasAttDefs()); + bool childWithAttributes = (typeInfo->hasAttDefs() || typeInfo->getAttWildCard()); + + if (derivedBy == SchemaSymbols::XSD_RESTRICTION && childWithAttributes) { + + if (!baseWithAttributes && !baseAttWildCard) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_1); + } + else { + checkAttDerivationOK(elem, baseTypeInfo, typeInfo); + } + } + + // ------------------------------------------------------------- + // merge in base type's attribute decls + // ------------------------------------------------------------- + if (baseTypeInfo && baseTypeInfo->hasAttDefs()) { + + SchemaAttDefList& baseAttList = (SchemaAttDefList&) + baseTypeInfo->getAttDefList(); + + for (XMLSize_t i=0; igetLocalPart(); + + // if found a duplicate, then skip the one from the base type + if (typeInfo->getAttDef(localPart, attName->getURI()) != 0) { + + if (derivedBy == SchemaSymbols::XSD_EXTENSION) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttInDerivation, localPart); + } + + continue; + } + + if (attDef.getDefaultType() != XMLAttDef::Prohibited) { + + SchemaAttDef* newAttDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attName->getPrefix(), + attName->getLocalPart(), + attName->getURI(), + attDef.getValue(), + attDef.getType(), + attDef.getDefaultType(), + attDef.getEnumeration(), + fGrammarPoolMemoryManager); + + newAttDef->setDatatypeValidator(attDef.getDatatypeValidator()); + typeInfo->addAttDef(newAttDef); + + if (attDef.getBaseAttDecl()) + newAttDef->setBaseAttDecl(attDef.getBaseAttDecl()); + else + newAttDef->setBaseAttDecl(&attDef); + } + } + } +} + + +void TraverseSchema::defaultComplexTypeInfo(ComplexTypeInfo* const typeInfo) { + + if (typeInfo) { + + typeInfo->setDerivedBy(0); + typeInfo->setContentType(SchemaElementDecl::Any); + typeInfo->setDatatypeValidator(0); + typeInfo->setContentSpec(0); + typeInfo->setBaseComplexTypeInfo(0); + typeInfo->setBaseDatatypeValidator(0); + } +} + + +InputSource* TraverseSchema::resolveSchemaLocation(const XMLCh* const loc, + const XMLResourceIdentifier::ResourceIdentifierType resourceIdentitiferType, + const XMLCh* const nameSpace) { + + // ------------------------------------------------------------------ + // Create an input source + // ------------------------------------------------------------------ + InputSource* srcToFill = 0; + XMLCh* normalizedURI = 0; + if (loc) { + XMLString::removeChar(loc, 0xFFFF, fBuffer); + normalizedURI = fBuffer.getRawBuffer(); + } + + if (fEntityHandler){ + XMLResourceIdentifier resourceIdentifier(resourceIdentitiferType, + normalizedURI, nameSpace, 0, fSchemaInfo->getCurrentSchemaURL(), fLocator); + srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); + } + + // If they didn't create a source via the entity resolver, then we + // have to create one on our own if we have the schemaLocation (with + // the update resolveEntity accepting nameSpace, a schemImport could + // pass a null schemaLocation) + if (!srcToFill && loc) { + if (fScanner->getDisableDefaultEntityResolution()) + return 0; + + XMLURL urlTmp(fMemoryManager); + if ((!urlTmp.setURL(fSchemaInfo->getCurrentSchemaURL(), normalizedURI, urlTmp)) || + (urlTmp.isRelative())) + { + if (!fScanner->getStandardUriConformant()) + { + XMLCh* tempURI = XMLString::replicate(normalizedURI, fMemoryManager); + ArrayJanitor tempURIName(tempURI, fMemoryManager); + XMLUri::normalizeURI(tempURI, fBuffer); + + srcToFill = new (fMemoryManager) LocalFileInputSource + ( fSchemaInfo->getCurrentSchemaURL() + , fBuffer.getRawBuffer() + , fMemoryManager + ); + } + else + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + } + else + { + if (fScanner->getStandardUriConformant() && urlTmp.hasInvalidChar()) + ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); + srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); + } + } + + return srcToFill; +} + + +void TraverseSchema::restoreSchemaInfo(SchemaInfo* const toRestore, + SchemaInfo::ListType const aListType, + const unsigned int saveScope) { + + + if (aListType == SchemaInfo::IMPORT) { // restore grammar info + + int targetNSURI = toRestore->getTargetNSURI(); + + fSchemaGrammar->setScopeCount (fScopeCount); + fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount); + + fSchemaGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(toRestore->getTargetNSURIString()); + fScopeCount = fSchemaGrammar->getScopeCount (); + fAnonXSTypeCount = fSchemaGrammar->getAnonTypeCount (); + + fTargetNSURI = targetNSURI; + fCurrentScope = saveScope; + fDatatypeRegistry = fSchemaGrammar->getDatatypeRegistry(); + fTargetNSURIString = fSchemaGrammar->getTargetNamespace(); + fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry(); + fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry(); + fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry(); + fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry(); + fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups(); + + } + + fSchemaInfo = toRestore; +} + + +bool +TraverseSchema::emptiableParticle(const ContentSpecNode* const specNode) { + + if (!fFullConstraintChecking || !specNode || (specNode->getMinTotalRange() == 0)) { + return true; + } + + return false; +} + +void TraverseSchema::checkFixedFacet(const DOMElement* const elem, + const XMLCh* const facetName, + const DatatypeValidator* const baseDV, + unsigned int& flags) +{ + const XMLCh* fixedFacet = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED); + + if ((fixedFacet && *fixedFacet) && + (XMLString::equals(fixedFacet, SchemaSymbols::fgATTVAL_TRUE) + || XMLString::equals(fixedFacet, fgValueOne))) { + + if (XMLString::equals(SchemaSymbols::fgELT_LENGTH, facetName)) { + flags |= DatatypeValidator::FACET_LENGTH; + } + if (XMLString::equals(SchemaSymbols::fgELT_MINLENGTH, facetName)) { + flags |= DatatypeValidator::FACET_MINLENGTH; + } + else if (XMLString::equals(SchemaSymbols::fgELT_MAXLENGTH, facetName)) { + flags |= DatatypeValidator::FACET_MAXLENGTH; + } + else if (XMLString::equals(SchemaSymbols::fgELT_MAXEXCLUSIVE, facetName)) { + flags |= DatatypeValidator::FACET_MAXEXCLUSIVE; + } + else if (XMLString::equals(SchemaSymbols::fgELT_MAXINCLUSIVE, facetName)) { + flags |= DatatypeValidator::FACET_MAXINCLUSIVE; + } + else if (XMLString::equals(SchemaSymbols::fgELT_MINEXCLUSIVE, facetName)) { + flags |= DatatypeValidator::FACET_MINEXCLUSIVE; + } + else if (XMLString::equals(SchemaSymbols::fgELT_MININCLUSIVE, facetName)) { + flags |= DatatypeValidator::FACET_MININCLUSIVE; + } + else if (XMLString::equals(SchemaSymbols::fgELT_TOTALDIGITS, facetName)) { + flags |= DatatypeValidator::FACET_TOTALDIGITS; + } + else if (XMLString::equals(SchemaSymbols::fgELT_FRACTIONDIGITS, facetName)) { + flags |= DatatypeValidator::FACET_FRACTIONDIGITS; + } + else if ((XMLString::equals(SchemaSymbols::fgELT_WHITESPACE, facetName)) && + baseDV->getType() == DatatypeValidator::String) { + flags |= DatatypeValidator::FACET_WHITESPACE; + } + } +} + +void +TraverseSchema::buildValidSubstitutionListB(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + SchemaElementDecl* const subsElemDecl) { + + SchemaElementDecl* chainElemDecl = subsElemDecl->getSubstitutionGroupElem(); + + while (chainElemDecl) { + + int chainElemURI = chainElemDecl->getURI(); + XMLCh* chainElemName = chainElemDecl->getBaseName(); + ValueVectorOf* validSubsElements = + fValidSubstitutionGroups->get(chainElemName, chainElemURI); + + if (!validSubsElements) { + + if (fTargetNSURI == chainElemURI) { + break; // an error must have occured + } + + SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(fURIStringPool->getValueForId(chainElemURI)); + + if (!aGrammar) + break; + + validSubsElements = aGrammar->getValidSubstitutionGroups()->get(chainElemName, chainElemURI); + + if (!validSubsElements) { + break; + } + + validSubsElements = new (fGrammarPoolMemoryManager) ValueVectorOf(*validSubsElements); + fValidSubstitutionGroups->put((void*) chainElemName, chainElemURI, validSubsElements); + } + + if (validSubsElements->containsElement(elemDecl) || + !isSubstitutionGroupValid(elem, chainElemDecl, elemDecl->getComplexTypeInfo(), + elemDecl->getDatatypeValidator(), 0, false)) { + break; + } + + validSubsElements->addElement(elemDecl); + + // update related subs. info in case of circular import + BaseRefVectorEnumerator importingEnum = fSchemaInfo->getImportingListEnumerator(); + + while (importingEnum.hasMoreElements()) { + + const SchemaInfo& curRef = importingEnum.nextElement(); + SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(curRef.getTargetNSURIString()); + ValueVectorOf* subsElemList = + aGrammar->getValidSubstitutionGroups()->get(chainElemName, chainElemURI); + + if (subsElemList && !subsElemList->containsElement(elemDecl)) { + subsElemList->addElement(elemDecl); + } + } + + chainElemDecl = chainElemDecl->getSubstitutionGroupElem(); + } +} + +void +TraverseSchema::buildValidSubstitutionListF(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + SchemaElementDecl* const subsElemDecl) { + + int elemURI = elemDecl->getURI(); + XMLCh* elemName = elemDecl->getBaseName(); + ValueVectorOf* validSubsElements =fValidSubstitutionGroups->get(elemName, elemURI); + + if (validSubsElements) { + + int subsElemURI = subsElemDecl->getURI(); + XMLCh* subsElemName = subsElemDecl->getBaseName(); + ValueVectorOf* validSubs = fValidSubstitutionGroups->get(subsElemName, subsElemURI); + + if (!validSubs) { + + if (fTargetNSURI == subsElemURI) { + return; // an error must have occured + } + + SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(fURIStringPool->getValueForId(subsElemURI)); + + if (!aGrammar) + return; + + validSubs = aGrammar->getValidSubstitutionGroups()->get(subsElemName, subsElemURI); + + if (!validSubs) { + return; + } + + validSubs = new (fGrammarPoolMemoryManager) ValueVectorOf(*validSubs); + fValidSubstitutionGroups->put((void*) subsElemName, subsElemURI, validSubs); + } + + XMLSize_t elemSize = validSubsElements->size(); + for (XMLSize_t i=0; ielementAt(i); + + if (validSubs->containsElement(chainElem)) { + continue; + } + + if (isSubstitutionGroupValid(elem, subsElemDecl, chainElem->getComplexTypeInfo(), + chainElem->getDatatypeValidator(), 0, false)) { + validSubs->addElement(chainElem); + buildValidSubstitutionListB(elem, chainElem, subsElemDecl); + } + } + } +} + +void TraverseSchema::checkEnumerationRequiredNotation(const DOMElement* const elem, + const XMLCh* const name, + const XMLCh* const type) { + + const XMLCh* localPart = getLocalPart(type); + + if (XMLString::equals(localPart, XMLUni::fgNotationString)) { + const XMLCh* prefix = getPrefix(type); + const XMLCh* typeURI = resolvePrefixToURI(elem, prefix); + + if (XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNotationType, name); + } + } +} + +XercesGroupInfo* TraverseSchema::processGroupRef(const DOMElement* const elem, + const XMLCh* const refName) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); + Janitor janAnnot(fAnnotation); + if (content != 0) { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::NoContentForRef, SchemaSymbols::fgELT_GROUP); + } + + const XMLCh* prefix = getPrefix(refName); + const XMLCh* localPart = getLocalPart(refName); + const XMLCh* uriStr = resolvePrefixToURI(elem, prefix); + + fBuffer.set(uriStr); + fBuffer.append(chComma); + fBuffer.append(localPart); + + unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); + + if (fCurrentGroupStack->containsElement(nameIndex)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, localPart); + return 0; + } + + XercesGroupInfo* groupInfo = 0; + SchemaInfo* saveInfo = fSchemaInfo; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + unsigned int saveScope = fCurrentScope; + + //if from another target namespace + if (!XMLString::equals(uriStr, fTargetNSURIString)) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); + return 0; + } + + Grammar* aGrammar = fGrammarResolver->getGrammar(uriStr); + + if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { + + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); + return 0; + } + + groupInfo = ((SchemaGrammar*)aGrammar)->getGroupInfoRegistry()->get(fStringPool->getValueForId(nameIndex)); + + if (!groupInfo) { + + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(fURIStringPool->addOrFind(uriStr)); + + if (!impInfo || impInfo->getProcessed()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, + SchemaSymbols::fgELT_GROUP, uriStr, localPart); + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + } + else { + groupInfo = fGroupRegistry->get(fStringPool->getValueForId(nameIndex)); + } + + if (!groupInfo) { + + DOMElement* groupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Group, + SchemaSymbols::fgELT_GROUP, localPart, &fSchemaInfo); + + if (groupElem != 0) { + + groupInfo = traverseGroupDecl(groupElem); + + // restore schema information + restoreSchemaInfo(saveInfo, infoType, saveScope); + + if (groupInfo && (fCurrentGroupInfo || infoType == SchemaInfo::IMPORT)) { + copyGroupElements(elem, groupInfo, fCurrentGroupInfo, + (infoType == SchemaInfo::IMPORT) ? fCurrentComplexType : 0); + } + + return groupInfo; + } + else { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, + SchemaSymbols::fgELT_GROUP, uriStr, localPart); + } + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + } + else { + copyGroupElements(elem, groupInfo, fCurrentGroupInfo, fCurrentComplexType); + } + + return groupInfo; +} + + +XercesAttGroupInfo* +TraverseSchema::processAttributeGroupRef(const DOMElement* const elem, + const XMLCh* const refName, + ComplexTypeInfo* const typeInfo) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) { + reportSchemaError(elem ,XMLUni::fgValidityDomain, XMLValid::NoContentForRef, SchemaSymbols::fgELT_ATTRIBUTEGROUP); + } + + Janitor janAnnot(fAnnotation); + const XMLCh* prefix = getPrefix(refName); + const XMLCh* localPart = getLocalPart(refName); + const XMLCh* uriStr = resolvePrefixToURI(elem, prefix); + XercesAttGroupInfo* attGroupInfo = 0; + SchemaInfo* saveInfo = fSchemaInfo; + SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; + unsigned int saveScope = fCurrentScope; + + if (!XMLString::equals(uriStr, fTargetNSURIString)) { + + // Make sure that we have an explicit import statement. + // Clause 4 of Schema Representation Constraint: + // http://www.w3.org/TR/xmlschema-1/#src-resolve + unsigned int uriId = fURIStringPool->addOrFind(uriStr); + + if (!isImportingNS(uriId)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); + return 0; + } + + attGroupInfo = traverseAttributeGroupDeclNS(elem, uriStr, localPart); + + if (!attGroupInfo) { + SchemaInfo* impInfo = fSchemaInfo->getImportInfo(fURIStringPool->addOrFind(uriStr)); + + if (!impInfo || impInfo->getProcessed()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, + SchemaSymbols::fgELT_ATTRIBUTEGROUP, uriStr, localPart); + return 0; + } + + infoType = SchemaInfo::IMPORT; + restoreSchemaInfo(impInfo, infoType); + } + } + else { + + attGroupInfo = fAttGroupRegistry->get(localPart); + } + + if (!attGroupInfo) { + + // traverse top level attributeGroup - if found + DOMElement* attGroupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_AttributeGroup, + SchemaSymbols::fgELT_ATTRIBUTEGROUP, localPart, &fSchemaInfo); + + if (attGroupElem != 0) { + + // circular attribute check + if (fDeclStack->containsElement(attGroupElem)) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, refName); + return 0; + } + + attGroupInfo = traverseAttributeGroupDecl(attGroupElem, typeInfo, true); + + if (attGroupInfo && fCurrentAttGroupInfo) { + copyAttGroupAttributes(elem, attGroupInfo, fCurrentAttGroupInfo, 0); + } + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType, saveScope); + } + + return attGroupInfo; + } + else { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, + SchemaSymbols::fgELT_ATTRIBUTEGROUP, uriStr, localPart); + } + } + + if (attGroupInfo) { + copyAttGroupAttributes(elem, attGroupInfo, fCurrentAttGroupInfo, typeInfo); + } + + // restore schema information, if necessary + if (saveInfo != fSchemaInfo) { + restoreSchemaInfo(saveInfo, infoType); + } + + return attGroupInfo; +} + +void TraverseSchema::processElements(const DOMElement* const elem, + ComplexTypeInfo* const baseTypeInfo, + ComplexTypeInfo* const newTypeInfo) { + + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + XMLSize_t elemCount = baseTypeInfo->elementCount(); + + if (elemCount) { + + int newTypeScope = newTypeInfo->getScopeDefined(); + int schemaURI = fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + + for (XMLSize_t i=0; i < elemCount; i++) { + + SchemaGrammar* aGrammar = fSchemaGrammar; + SchemaElementDecl* elemDecl = baseTypeInfo->elementAt(i); + int elemURI = elemDecl->getURI(); + unsigned int elemScope = elemDecl->getEnclosingScope(); + + if (elemScope != Grammar::TOP_LEVEL_SCOPE) { + + if (elemURI != fTargetNSURI && elemURI != schemaURI && elemURI != fEmptyNamespaceURI) { + Grammar* aGrammar = fGrammarResolver->getGrammar(fURIStringPool->getValueForId(elemURI)); + + if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { + continue; // REVISIT - error message + } + } + + const XMLCh* localPart = elemDecl->getBaseName(); + const SchemaElementDecl* other = (SchemaElementDecl*) + aGrammar->getElemDecl(elemURI, localPart, 0, newTypeScope); + + if (other) { + + if (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() + || elemDecl->getDatatypeValidator() != other->getDatatypeValidator()) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, localPart); + } + + continue; + } + elemDecl->setEnclosingScope(newTypeScope); + ((SchemaGrammar*) aGrammar)->putGroupElemDecl(elemDecl); + elemDecl->setEnclosingScope(elemScope); + } + + newTypeInfo->addElement(elemDecl); + } + } +} + +void TraverseSchema::processElements(const DOMElement* const elem, + XercesGroupInfo* const fromGroup, + ComplexTypeInfo* const typeInfo) +{ + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + XMLSize_t elemCount = fromGroup->elementCount(); + int newScope = typeInfo->getScopeDefined(); + + for (XMLSize_t i = 0; i < elemCount; i++) { + + SchemaElementDecl* elemDecl = fromGroup->elementAt(i); + unsigned int elemScope = elemDecl->getEnclosingScope(); + + if (elemScope != Grammar::TOP_LEVEL_SCOPE) + { + int elemURI = elemDecl->getURI(); + const XMLCh* localPart = elemDecl->getBaseName(); + const SchemaElementDecl* other = (SchemaElementDecl*) + fSchemaGrammar->getElemDecl(elemURI, localPart, 0, newScope); + + if (other) + { + if (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() + || elemDecl->getDatatypeValidator() != other->getDatatypeValidator()) + { + reportSchemaError( + elem, XMLUni::fgXMLErrDomain + , XMLErrs::DuplicateElementDeclaration, localPart); + } + + continue; + } + + elemDecl->setEnclosingScope(newScope); + fSchemaGrammar->putGroupElemDecl(elemDecl); + elemDecl->setEnclosingScope(elemScope); + typeInfo->addElement(elemDecl); + } + } +} + + +void TraverseSchema::copyGroupElements(const DOMElement* const elem, + XercesGroupInfo* const fromGroup, + XercesGroupInfo* const toGroup, + ComplexTypeInfo* const typeInfo) { + + XMLSize_t elemCount = fromGroup->elementCount(); + int newScope = (typeInfo) ? typeInfo->getScopeDefined() : 0; + + if (typeInfo) + fromGroup->setCheckElementConsistency(false); + + for (XMLSize_t i = 0; i < elemCount; i++) { + + SchemaElementDecl* elemDecl = fromGroup->elementAt(i); + + if (typeInfo) { + + unsigned int elemScope = elemDecl->getEnclosingScope(); + + if (elemScope != Grammar::TOP_LEVEL_SCOPE) { + + int elemURI = elemDecl->getURI(); + const XMLCh* localPart = elemDecl->getBaseName(); + const SchemaElementDecl* other = (SchemaElementDecl*) + fSchemaGrammar->getElemDecl(elemURI, localPart, 0, newScope); + + if (other) { + + if (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() + || elemDecl->getDatatypeValidator() != other->getDatatypeValidator()) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, localPart); + } + + continue; + } + + elemDecl->setEnclosingScope(newScope); + fSchemaGrammar->putGroupElemDecl(elemDecl); + elemDecl->setEnclosingScope(elemScope); + } + + typeInfo->addElement(elemDecl); + } + + if (toGroup) { + toGroup->addElement(elemDecl); + } + } +} + +void TraverseSchema::copyAttGroupAttributes(const DOMElement* const elem, + XercesAttGroupInfo* const fromAttGroup, + XercesAttGroupInfo* const toAttGroup, + ComplexTypeInfo* const typeInfo) { + + XMLSize_t attCount = fromAttGroup->attributeCount(); + + for (XMLSize_t i=0; i < attCount; i++) { + + SchemaAttDef* attDef = fromAttGroup->attributeAt(i); + QName* attName = attDef->getAttName(); + const XMLCh* localPart = attName->getLocalPart(); + DatatypeValidator* attDV = attDef->getDatatypeValidator(); + + if (typeInfo) { + + if (typeInfo->getAttDef(localPart, attName->getURI())) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, localPart); + continue; + } + + if (attDV && attDV->getType() == DatatypeValidator::ID) { + + if (typeInfo->containsAttWithTypeId()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, localPart); + continue; + } + + typeInfo->setAttWithTypeId(true); + } + + SchemaAttDef* clonedAttDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attDef); + typeInfo->addAttDef(clonedAttDef); + + if (!clonedAttDef->getBaseAttDecl()) + clonedAttDef->setBaseAttDecl(attDef); + + if (toAttGroup) { + toAttGroup->addAttDef(attDef, true); + } + } + else { + + if (toAttGroup->containsAttribute(localPart, attName->getURI())) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, localPart); + continue; + } + + if (attDV && attDV->getType() == DatatypeValidator::ID) { + + if (toAttGroup->containsTypeWithId()) { + + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, localPart); + continue; + } + + toAttGroup->setTypeWithId(true); + } + + toAttGroup->addAttDef(attDef, true); + } + } + + if (toAttGroup) { + XMLSize_t anyAttCount = fromAttGroup->anyAttributeCount(); + + for (XMLSize_t j=0; j < anyAttCount; j++) { + toAttGroup->addAnyAttDef(fromAttGroup->anyAttributeAt(j), true); + } + } +} + +void +TraverseSchema::attWildCardIntersection(SchemaAttDef* const resultWildCard, + const SchemaAttDef* const compareWildCard) { + + XMLAttDef::AttTypes typeR = resultWildCard->getType(); + XMLAttDef::AttTypes typeC = compareWildCard->getType(); + + //If either O1 or O2 is any, then the other must be the value. + if (typeC == XMLAttDef::Any_Any || + typeR == XMLAttDef::AttTypes_Unknown) { + return; + } + + if (typeR == XMLAttDef::Any_Any || + typeC == XMLAttDef::AttTypes_Unknown) { + + resultWildCard->resetNamespaceList(); + copyWildCardData(compareWildCard, resultWildCard); + return; + } + + // If either O1 or O2 is a pair of not and a namespace name and the other + // is a set, then that set, minus the negated namespace name if it was in + // is the value + if ((typeC == XMLAttDef::Any_Other && typeR == XMLAttDef::Any_List) || + (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_List)) { + + unsigned int compareURI = 0; + ValueVectorOf* nameURIList = 0; + + if (typeC == XMLAttDef::Any_List) { + nameURIList = compareWildCard->getNamespaceList(); + compareURI = resultWildCard->getAttName()->getURI(); + } + else { + nameURIList = resultWildCard->getNamespaceList(); + compareURI = compareWildCard->getAttName()->getURI(); + } + + XMLSize_t listSize = (nameURIList) ? nameURIList->size() : 0; + + if (listSize) { + + bool found = false; + ValueVectorOf tmpURIList(listSize, fGrammarPoolMemoryManager); + + for (XMLSize_t i=0; i < listSize; i++) { + + unsigned int nameURI = nameURIList->elementAt(i); + + if (nameURI != compareURI && + nameURI != (unsigned int) fEmptyNamespaceURI) { + tmpURIList.addElement(nameURI); + } + else { + found = true; + } + } + + if (found || typeC == XMLAttDef::Any_List) { + resultWildCard->setNamespaceList(&tmpURIList); + } + } + + if (typeC == XMLAttDef::Any_List) { + copyWildCardData(compareWildCard, resultWildCard); + } + + return; + } + + // If both O1 and O2 are sets, then the intersection of those sets must be + // the value. + if (typeR == XMLAttDef::Any_List && typeC == XMLAttDef::Any_List) { + + ValueVectorOf* uriListR = resultWildCard->getNamespaceList(); + ValueVectorOf* uriListC = compareWildCard->getNamespaceList(); + XMLSize_t listSize = (uriListC) ? uriListC->size() : 0; + + if (listSize) { + + ValueVectorOf tmpURIList(listSize, fGrammarPoolMemoryManager); + + for (XMLSize_t i=0; i < listSize; i++) { + + unsigned int uriName = uriListC->elementAt(i); + + if (uriListR && uriListR->containsElement(uriName)) { + tmpURIList.addElement(uriName); + } + } + + resultWildCard->setNamespaceList(&tmpURIList); + } + else { + resultWildCard->resetNamespaceList(); + } + + return; + } + + // If the two are negations of different namespace names, then: + // if one is a negation of absent, then result is negation of namespace + // else intersection is not expressible. + if (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_Other) { + + QName* qnameR = resultWildCard->getAttName(); + + if (qnameR->getURI() != compareWildCard->getAttName()->getURI()) { + + if (qnameR->getURI() == (unsigned int)fEmptyNamespaceURI) { + qnameR->setURI(compareWildCard->getAttName()->getURI()); + } + else if (compareWildCard->getAttName()->getURI() != (unsigned int)fEmptyNamespaceURI) { + + qnameR->setURI(fEmptyNamespaceURI); + resultWildCard->setType(XMLAttDef::AttTypes_Unknown); + } + } + } +} + + +void +TraverseSchema::attWildCardUnion(SchemaAttDef* const resultWildCard, + const SchemaAttDef* const compareWildCard) { + + XMLAttDef::AttTypes typeR = resultWildCard->getType(); + XMLAttDef::AttTypes typeC = compareWildCard->getType(); + + //If either O1 or O2 is any, then the other must be the value. + if (typeR == XMLAttDef::Any_Any || + typeR == XMLAttDef::AttTypes_Unknown) { + return; + } + + if (typeC == XMLAttDef::Any_Any || + typeC == XMLAttDef::AttTypes_Unknown) { + + resultWildCard->resetNamespaceList(); + copyWildCardData(compareWildCard, resultWildCard); + return; + } + + // If both O1 and O2 are sets, then the union of those sets must be + // the value. + if (typeR == XMLAttDef::Any_List && typeC == XMLAttDef::Any_List) { + + ValueVectorOf* uriListR = resultWildCard->getNamespaceList(); + ValueVectorOf* uriListC = compareWildCard->getNamespaceList(); + XMLSize_t listSizeC = (uriListC) ? uriListC->size() : 0; + + if (listSizeC) { + + if (!uriListR || !uriListR->size()) { + + resultWildCard->setNamespaceList(uriListC); + return; + } + + ValueVectorOf tmpURIList(*uriListR); + + for (XMLSize_t i = 0; i < listSizeC; i++) { + + unsigned int uriName = uriListC->elementAt(i); + + if (!uriListR->containsElement(uriName)) { + tmpURIList.addElement(uriName); + } + } + + resultWildCard->setNamespaceList(&tmpURIList); + } + + return; + } + + // If the two are negations of different namespace names, then not and + // absent must be the value + if (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_Other) { + + QName* qnameR = resultWildCard->getAttName(); + + if (qnameR->getURI() != compareWildCard->getAttName()->getURI()) { + + qnameR->setURI(fEmptyNamespaceURI); + resultWildCard->setType(XMLAttDef::Any_Other); + } + } + + // 5. If either O1 or O2 is a pair of not and a namespace name and the + // other is a set, then: + // 1. If the set includes both the negated namespace name and absent + // then any must be the value. + // 2. If the set includes the negated namespace name but not absent, + // then a pair of not and absent must be the value. + // 3. If the set includes absent but not the negated namespace name, + // then the union is not expressible. + // 4. If the set does not include either the negated namespace or + // absent, then whichever of O1 or O2 is a pair of not and a + // namespace name. + // + // 6. If either O1 or O2 is a pair of not and absent and the other is a + // set, then: + // 1. If the set includes absent then any must be the value. + // 2. If the set does not include absent, then a pair of not and + // absent. + if ((typeC == XMLAttDef::Any_Other && typeR == XMLAttDef::Any_List) || + (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_List)) { + + ValueVectorOf* nameURIList = 0; + QName* attNameR = resultWildCard->getAttName(); + unsigned int compareURI = 0; + + if (typeC == XMLAttDef::Any_List) { + nameURIList = compareWildCard->getNamespaceList(); + compareURI = attNameR->getURI(); + } + else { + nameURIList = resultWildCard->getNamespaceList(); + compareURI = compareWildCard->getAttName()->getURI(); + } + + // 6. not and absent + if (compareURI == (unsigned int) fEmptyNamespaceURI) { + + if (nameURIList) { + + // 6.1 result is any + if (nameURIList->containsElement(compareURI)) { + + resultWildCard->setType(XMLAttDef::Any_Any); + attNameR->setURI(fEmptyNamespaceURI); + } + // 6.2 result is not and absent + else if (typeR == XMLAttDef::Any_List){ + + resultWildCard->setType(XMLAttDef::Any_Other); + attNameR->setURI(fEmptyNamespaceURI); + } + } + // 6.2 result is not and absent + else if (typeR == XMLAttDef::Any_List) { + + resultWildCard->setType(XMLAttDef::Any_Other); + attNameR->setURI(fEmptyNamespaceURI); + } + } + // 5. not and namespace + else { + + // 5.3 result is not expressible + if (!nameURIList) { + resultWildCard->setType(XMLAttDef::AttTypes_Unknown); + attNameR->setURI(fEmptyNamespaceURI); + } + else { + bool containsAbsent = + nameURIList->containsElement(fEmptyNamespaceURI); + bool containsNamespace = + nameURIList->containsElement(compareURI); + + // 5.1 result is any + if (containsAbsent && containsNamespace) { + + resultWildCard->setType(XMLAttDef::Any_Any); + attNameR->setURI(fEmptyNamespaceURI); + } + // 5.2 result is not and absent + else if (containsNamespace) { + + resultWildCard->setType(XMLAttDef::Any_Other); + attNameR->setURI(fEmptyNamespaceURI); + } + // 5.3 result is not expressible + else if (containsAbsent) { + + resultWildCard->setType(XMLAttDef::AttTypes_Unknown); + attNameR->setURI(fEmptyNamespaceURI); + } + // 5.4. whichever is not and namespace + else if (typeR == XMLAttDef::Any_List) { + + resultWildCard->setType(XMLAttDef::Any_Other); + attNameR->setURI(compareURI); + } + } + } + + resultWildCard->resetNamespaceList(); + } +} + + +void TraverseSchema::checkAttDerivationOK(const DOMElement* const elem, + const ComplexTypeInfo* const baseTypeInfo, + const ComplexTypeInfo* const childTypeInfo) { + + SchemaAttDefList& childAttList = (SchemaAttDefList&) childTypeInfo->getAttDefList(); + const SchemaAttDef* baseAttWildCard = baseTypeInfo->getAttWildCard(); + + for (XMLSize_t i=0; igetLocalPart(); + const SchemaAttDef* baseAttDef = baseTypeInfo->getAttDef(childLocalPart, childAttName->getURI()); + + if (baseAttDef) { + + XMLAttDef::DefAttTypes baseAttDefType = baseAttDef->getDefaultType(); + XMLAttDef::DefAttTypes childAttDefType = childAttDef.getDefaultType(); + + // Constraint 2.1.1 & 3 + check for prohibited base attribute + if (baseAttDefType == XMLAttDef::Prohibited + && childAttDefType != XMLAttDef::Prohibited) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_8, childLocalPart); + } + + if ((baseAttDefType & XMLAttDef::Required) + && !(childAttDefType & XMLAttDef::Required)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_2, childLocalPart); + } + + // if the attribute in the derived type is prohibited, and it didn't try to override a required attribute, + // it's ok and shouldn't be tested for data type or fixed value + if (childAttDefType == XMLAttDef::Prohibited) + continue; + + // Constraint 2.1.2 + DatatypeValidator* baseDV = baseAttDef->getDatatypeValidator(); + DatatypeValidator* childDV = childAttDef.getDatatypeValidator(); + if (!baseDV || !baseDV->isSubstitutableBy(childDV)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_3, childLocalPart); + } + + // Constraint 2.1.3 + if ((baseAttDefType & XMLAttDef::Fixed) && + (!(childAttDefType & XMLAttDef::Fixed) || + !XMLString::equals(baseAttDef->getValue(), childAttDef.getValue()))) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_4, childLocalPart); + } + } + // Constraint 2.2 + else if (!baseAttWildCard || + !wildcardAllowsNamespace(baseAttWildCard, childAttName->getURI())) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_5, childLocalPart); + } + } + + // Constraint 4 + const SchemaAttDef* childAttWildCard = childTypeInfo->getAttWildCard(); + + if (childAttWildCard) { + + if (!baseAttWildCard) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_6); + } + else if (!isWildCardSubset(baseAttWildCard, childAttWildCard)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_7); + } + else if (childAttWildCard->getDefaultType() < baseAttWildCard->getDefaultType()) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_9); + } + } +} + +void TraverseSchema::checkAttDerivationOK(const DOMElement* const elem, + const XercesAttGroupInfo* const baseAttGrpInfo, + const XercesAttGroupInfo* const childAttGrpInfo) { + + XMLSize_t baseAttCount = baseAttGrpInfo->attributeCount(); + XMLSize_t baseAnyAttCount = baseAttGrpInfo->anyAttributeCount(); + XMLSize_t childAttCount = childAttGrpInfo->attributeCount(); + XMLSize_t childAnyAttCount = childAttGrpInfo->anyAttributeCount(); + + if ((childAttCount || childAnyAttCount) && (!baseAttCount && !baseAnyAttCount)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_1); + } + + const SchemaAttDef* baseAttWildCard = (baseAnyAttCount) ? baseAttGrpInfo->anyAttributeAt(0) : 0; + + for (XMLSize_t i=0; iattributeAt(i); + QName* childAttName = childAttDef->getAttName(); + const XMLCh* childLocalPart = childAttName->getLocalPart(); + const SchemaAttDef* baseAttDef = baseAttGrpInfo->getAttDef(childLocalPart, childAttName->getURI()); + + if (baseAttDef) { + + XMLAttDef::DefAttTypes baseAttDefType = baseAttDef->getDefaultType(); + XMLAttDef::DefAttTypes childAttDefType = childAttDef->getDefaultType(); + + // Constraint 2.1.1 & 3 + check for prohibited base attribute + if (baseAttDefType == XMLAttDef::Prohibited + && childAttDefType != XMLAttDef::Prohibited) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_8, childLocalPart); + } + + if ((baseAttDefType & XMLAttDef::Required) + && !(childAttDefType & XMLAttDef::Required)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_2, childLocalPart); + } + + // if the attribute in the derived type is prohibited, and it didn't try to override a required attribute, + // it's ok and shouldn't be tested for data type or fixed value + if (childAttDefType == XMLAttDef::Prohibited) + continue; + + // Constraint 2.1.2 + DatatypeValidator* baseDV = baseAttDef->getDatatypeValidator(); + DatatypeValidator* childDV = childAttDef->getDatatypeValidator(); + if (!baseDV || !baseDV->isSubstitutableBy(childDV)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_3, childLocalPart); + } + + // Constraint 2.1.3 + if ((baseAttDefType & XMLAttDef::Fixed) && + (!(childAttDefType & XMLAttDef::Fixed) || + !XMLString::equals(baseAttDef->getValue(), childAttDef->getValue()))) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_4, childLocalPart); + } + } + // Constraint 2.2 + else if (!baseAttWildCard || + !wildcardAllowsNamespace(baseAttWildCard, childAttName->getURI())) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_5, childLocalPart); + } + } + + // Constraint 4 + const SchemaAttDef* childAttWildCard = (childAnyAttCount) ? childAttGrpInfo->anyAttributeAt(0) : 0; + + if (childAttWildCard) { + + if (!baseAttWildCard) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_6); + } + else if (!isWildCardSubset(baseAttWildCard, childAttWildCard)) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_7); + } + else if (childAttWildCard->getDefaultType() < baseAttWildCard->getDefaultType()) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_9); + } + } +} + +bool TraverseSchema::wildcardAllowsNamespace(const SchemaAttDef* const wildCard, + const unsigned int nameURI) { + + XMLAttDef::AttTypes wildCardType = wildCard->getType(); + + // The constraint must be any + if (wildCardType == XMLAttDef::Any_Any) { + return true; + } + + // All of the following must be true: + // 2.1 The constraint is a pair of not and a namespace name or ·absent + // 2.2 The value must not be identical to the ·namespace test·. + // 2.3 The value must not be ·absent·. + if (wildCardType == XMLAttDef::Any_Other && + ((int) nameURI) != fEmptyNamespaceURI && + wildCard->getAttName()->getURI() != nameURI) { + return true; + } + + // The constraint is a set, and the value is identical to one of the + // members of the set + if (wildCardType == XMLAttDef::Any_List) { + + ValueVectorOf* nameURIList = wildCard->getNamespaceList(); + + if (nameURIList->containsElement(nameURI)) { + return true; + } + } + + return false; +} + +bool TraverseSchema::isWildCardSubset(const SchemaAttDef* const baseAttWildCard, + const SchemaAttDef* const childAttWildCard) { + + XMLAttDef::AttTypes baseWildCardType = baseAttWildCard->getType(); + XMLAttDef::AttTypes childWildCardType = childAttWildCard->getType(); + + if (baseWildCardType == XMLAttDef::AttTypes_Unknown || + childWildCardType == XMLAttDef::AttTypes_Unknown) { + return false; + } + + // 1 super must be any. + if (baseWildCardType == XMLAttDef::Any_Any) { + return true; + } + + // 2 All of the following must be true: + // 2.1 sub must be a pair of not and a namespace name or ·absent·. + // 2.2 super must be a pair of not and the same value. + if (childWildCardType == XMLAttDef::Any_Other && baseWildCardType == XMLAttDef::Any_Other && + childAttWildCard->getAttName()->getURI() == baseAttWildCard->getAttName()->getURI()) { + return true; + } + + // 3 All of the following must be true: + // 3.1 sub must be a set whose members are either namespace names or ·absent·. + // 3.2 One of the following must be true: + // 3.2.1 super must be the same set or a superset thereof. + // 3.2.2 super must be a pair of not and a namespace name or ·absent· and + // that value must not be in sub's set. + if (childWildCardType == XMLAttDef::Any_List) { + + ValueVectorOf* childURIList = childAttWildCard->getNamespaceList(); + + if (baseWildCardType == XMLAttDef::Any_List) { + + ValueVectorOf* baseURIList = baseAttWildCard->getNamespaceList(); + XMLSize_t childListSize = (childURIList) ? childURIList->size() : 0; + + for (XMLSize_t i=0; icontainsElement(childURIList->elementAt(i))) { + return false; + } + } + + return true; + } + else if (baseWildCardType == XMLAttDef::Any_Other) { + if (!childURIList->containsElement(baseAttWildCard->getAttName()->getURI())) { + return true; + } + } + } + + return false; +} + +bool TraverseSchema::openRedefinedSchema(const DOMElement* const redefineElem) { + + if (fPreprocessedNodes->containsKey(redefineElem)) { + + restoreSchemaInfo(fPreprocessedNodes->get(redefineElem)); + return true; + } + + // ------------------------------------------------------------------ + // Get 'schemaLocation' attribute + // ------------------------------------------------------------------ + const XMLCh* schemaLocation = getElementAttValue(redefineElem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI); + + if (!schemaLocation || !*schemaLocation) { + reportSchemaError(redefineElem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNoSchemaLocation, SchemaSymbols::fgELT_REDEFINE); + return false; + } + + // ------------------------------------------------------------------ + // Resolve schema location + // ------------------------------------------------------------------ + fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, + ((XSDElementNSImpl*) redefineElem)->getLineNo(), + ((XSDElementNSImpl*) redefineElem)->getColumnNo()); + InputSource* srcToFill = resolveSchemaLocation(schemaLocation, + XMLResourceIdentifier::SchemaRedefine); + Janitor janSrc(srcToFill); + + // Nothing to do + if (!srcToFill) { + return false; + } + + const XMLCh* includeURL = srcToFill->getSystemId(); + + if (XMLString::equals(includeURL, fSchemaInfo->getCurrentSchemaURL())) { + return false; + } + + SchemaInfo* redefSchemaInfo = fCachedSchemaInfoList->get(includeURL, fTargetNSURI); + + if (!redefSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList) + redefSchemaInfo = fSchemaInfoList->get(includeURL, fTargetNSURI); + + if (redefSchemaInfo) { + + reportSchemaError(redefineElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidRedefine, includeURL); + return false; + } + + // ------------------------------------------------------------------ + // Parse input source + // ------------------------------------------------------------------ + if (!fParser) + fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0,fGrammarPoolMemoryManager, 0); + + fParser->setValidationScheme(XercesDOMParser::Val_Never); + fParser->setDoNamespaces(true); + fParser->setUserEntityHandler(fEntityHandler); + fParser->setUserErrorReporter(fErrorReporter); + + // Should just issue warning if the schema is not found + bool flag = srcToFill->getIssueFatalErrorIfNotFound(); + srcToFill->setIssueFatalErrorIfNotFound(false); + + fParser->parse(*srcToFill) ; + + // Reset the InputSource + srcToFill->setIssueFatalErrorIfNotFound(flag); + + if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal()) + reportSchemaError(redefineElem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError); + + // ------------------------------------------------------------------ + // Get root element + // ------------------------------------------------------------------ + DOMDocument* document = fParser->getDocument(); + + if (!document) { + return false; + } + else { + + DOMElement* root = document->getDocumentElement(); + + if (root == 0) { + return false; + } + + const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); + + // check to see if targetNameSpace is right + if (*targetNSURIString + && !XMLString::equals(targetNSURIString,fTargetNSURIString)){ + reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::RedefineNamespaceDifference, + schemaLocation, targetNSURIString); + return false; + } + + // if targetNamespace is empty, change it to redefin'g schema + // targetNamespace + if (!*targetNSURIString && root->getAttributeNode(XMLUni::fgXMLNSString) == 0 + && fTargetNSURI != fEmptyNamespaceURI) { + root->setAttribute(XMLUni::fgXMLNSString, fTargetNSURIString); + } + + // -------------------------------------------------------- + // Update schema information with redefined schema + // -------------------------------------------------------- + redefSchemaInfo = fSchemaInfo; + Janitor newSchemaInfo(new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, + 0, + includeURL, + fTargetNSURIString, root, + fScanner, + fGrammarPoolMemoryManager)); + fSchemaInfo = newSchemaInfo.get(); + + fSchemaInfo->getNamespaceScope()->reset(fEmptyNamespaceURI); + // Add mapping for the xml prefix + fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName)); + + traverseSchemaHeader(root); + fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo); + newSchemaInfo.release(); + redefSchemaInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE); + fPreprocessedNodes->put((void*) redefineElem, fSchemaInfo); + } + + return true; +} + +void TraverseSchema::renameRedefinedComponents(const DOMElement* const redefineElem, + SchemaInfo* const redefiningSchemaInfo, + SchemaInfo* const redefinedSchemaInfo) { + + DOMElement* child = XUtil::getFirstChildElement(redefineElem); + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* childName = child->getLocalName(); + + if (XMLString::equals(childName, SchemaSymbols::fgELT_ANNOTATION)) { + continue; + } + + // if component already redefined skip + const XMLCh* typeName = getElementAttValue(child, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(typeName); + + if (fRedefineComponents->containsKey(childName, fStringPool->addOrFind(fBuffer.getRawBuffer()))) { + continue; + } + + // Rename + const XMLCh* tmpChildName = fStringPool->getValueForId(fStringPool->addOrFind(childName)); + + if (validateRedefineNameChange(child, tmpChildName, typeName, 1, redefiningSchemaInfo)) { + fixRedefinedSchema(child, redefinedSchemaInfo, tmpChildName, typeName, 1); + } + else { + redefiningSchemaInfo->addFailedRedefine(child); + } + } +} + +bool TraverseSchema::validateRedefineNameChange(const DOMElement* const redefineChildElem, + const XMLCh* const redefineChildComponentName, + const XMLCh* const redefineChildTypeName, + const int redefineNameCounter, + SchemaInfo* const redefiningSchemaInfo) { + + const XMLCh* baseTypeName = 0; + unsigned int typeNameId = fStringPool->addOrFind(redefineChildTypeName); + + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(redefineChildTypeName); + + int fullTypeNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); + const XMLCh* typeNameStr = fStringPool->getValueForId(fullTypeNameId); + + restoreSchemaInfo(redefiningSchemaInfo); + + if (XMLString::equals(redefineChildComponentName,SchemaSymbols::fgELT_SIMPLETYPE)) { + + if (fDatatypeRegistry->getDatatypeValidator(typeNameStr)) { + return false; + } + + DOMElement* grandKid = XUtil::getFirstChildElement(redefineChildElem); + + if (grandKid && XMLString::equals(grandKid->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { + grandKid = XUtil::getNextSiblingElement(grandKid); + } + + if (grandKid == 0) { + + reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidSimpleType); + return false; + } + else if(!XMLString::equals(grandKid->getLocalName(), SchemaSymbols::fgELT_RESTRICTION)) { + + reportSchemaError(grandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidSimpleType); + return false; + } + + baseTypeName = getElementAttValue(grandKid, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); + const XMLCh* prefix = getPrefix(baseTypeName); + const XMLCh* localPart = getLocalPart(baseTypeName); + const XMLCh* uriStr = resolvePrefixToURI(grandKid, prefix); + + if (fTargetNSURI != (int) fURIStringPool->addOrFind(uriStr) + || fStringPool->addOrFind(localPart) != typeNameId) { + reportSchemaError(grandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidSimpleTypeBase); + return false; + } + + // now we have to do the renaming... + getRedefineNewTypeName(baseTypeName, redefineNameCounter, fBuffer); + grandKid->setAttribute(SchemaSymbols::fgATT_BASE, fBuffer.getRawBuffer()); + fRedefineComponents->put((void*) SchemaSymbols::fgELT_SIMPLETYPE, + fullTypeNameId, 0); + } + else if (XMLString::equals(redefineChildComponentName,SchemaSymbols::fgELT_COMPLEXTYPE)) { + + if (fComplexTypeRegistry->containsKey(typeNameStr)) { + return false; + } + + DOMElement* grandKid = XUtil::getFirstChildElement(redefineChildElem); + + if (grandKid && XMLString::equals(grandKid->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { + grandKid = XUtil::getNextSiblingElement(grandKid); + } + + if (grandKid == 0) { + reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexType); + return false; + } else { + + // have to go one more level down; let another pass worry whether complexType is valid. + DOMElement* greatGrandKid = XUtil::getFirstChildElement(grandKid); + + if (greatGrandKid != 0 && + XMLString::equals(greatGrandKid->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { + greatGrandKid = XUtil::getNextSiblingElement(greatGrandKid); + } + + if (greatGrandKid == 0) { + + reportSchemaError(grandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexType); + return false; + } else { + + const XMLCh* greatGrandKidName = greatGrandKid->getLocalName(); + + if (!XMLString::equals(greatGrandKidName, SchemaSymbols::fgELT_RESTRICTION) + && !XMLString::equals(greatGrandKidName, SchemaSymbols::fgELT_EXTENSION)) { + + reportSchemaError(greatGrandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexType); + return false; + } + + baseTypeName = getElementAttValue(greatGrandKid, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); + const XMLCh* prefix = getPrefix(baseTypeName); + const XMLCh* localPart = getLocalPart(baseTypeName); + const XMLCh* uriStr = resolvePrefixToURI(greatGrandKid, prefix); + + if (fTargetNSURI != (int) fURIStringPool->addOrFind(uriStr) + || fStringPool->addOrFind(localPart) != typeNameId) { + reportSchemaError(greatGrandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexTypeBase); + return false; + } + + // now we have to do the renaming... + getRedefineNewTypeName(baseTypeName, redefineNameCounter, fBuffer); + greatGrandKid->setAttribute(SchemaSymbols::fgATT_BASE, fBuffer.getRawBuffer()); + fRedefineComponents->put((void*) SchemaSymbols::fgELT_COMPLEXTYPE, + fullTypeNameId, 0); + } + } + } + else if (XMLString::equals(redefineChildComponentName, SchemaSymbols::fgELT_GROUP)) { + + if (fGroupRegistry->containsKey(typeNameStr)) { + return false; + } + + int groupRefCount = changeRedefineGroup(redefineChildElem, redefineChildComponentName, + redefineChildTypeName, redefineNameCounter); + + if (groupRefCount > 1) { + + reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_GroupRefCount); + return false; + } + else if (groupRefCount == 0) { + // put a dummy value, default is null. + // when processing groups, we will check that table, if a value + // is found, we need to do a particle derivation check. + fRedefineComponents->put((void*) SchemaSymbols::fgELT_GROUP, + fullTypeNameId, fSchemaInfo->getCurrentSchemaURL()); + } + else { + fRedefineComponents->put((void*) SchemaSymbols::fgELT_GROUP, fullTypeNameId, 0); + } + } + else if (XMLString::equals(redefineChildComponentName, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { + + if (fAttGroupRegistry->containsKey(redefineChildTypeName)) { + return false; + } + + int attGroupRefCount = changeRedefineGroup(redefineChildElem, redefineChildComponentName, + redefineChildTypeName, redefineNameCounter); + + if (attGroupRefCount > 1) { + + reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_AttGroupRefCount); + return false; + } + else if (attGroupRefCount == 0) { + // put a dummy value, default is null. + // when processing attributeGroups, we will check that table, if + // a value is found, we need to check for attribute derivation ok + // (by restriction) + fRedefineComponents->put((void*) SchemaSymbols::fgELT_ATTRIBUTEGROUP, + fullTypeNameId, fSchemaInfo->getCurrentSchemaURL()); + } + else { + fRedefineComponents->put((void*) SchemaSymbols::fgELT_ATTRIBUTEGROUP, fullTypeNameId, 0); + } + } + else { + reportSchemaError + ( + redefineChildElem + , XMLUni::fgXMLErrDomain + , XMLErrs::Redefine_InvalidChild + , redefineChildComponentName + ); + return false; + } + + return true; +} + +int TraverseSchema::changeRedefineGroup(const DOMElement* const redefineChildElem, + const XMLCh* const redefineChildComponentName, + const XMLCh* const redefineChildTypeName, + const int redefineNameCounter) { + int result = 0; + DOMElement* child = XUtil::getFirstChildElement(redefineChildElem); + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* name = child->getLocalName(); + + if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { + continue; + } + + if (!XMLString::equals(name, redefineChildComponentName)) { + result += changeRedefineGroup(child, redefineChildComponentName, redefineChildTypeName, redefineNameCounter); + } else { + const XMLCh* refName = getElementAttValue(child, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); + + if (refName && *refName) { + + const XMLCh* prefix = getPrefix(refName); + const XMLCh* localPart = getLocalPart(refName); + const XMLCh* uriStr = resolvePrefixToURI(child, prefix); + + if (fTargetNSURI == (int) fURIStringPool->addOrFind(uriStr) + && fStringPool->addOrFind(localPart) == fStringPool->addOrFind(redefineChildTypeName)) { + + // now we have to do the renaming... + getRedefineNewTypeName(refName, redefineNameCounter, fBuffer); + child->setAttribute(SchemaSymbols::fgATT_REF, fBuffer.getRawBuffer()); + result++; + + if(XMLString::equals(redefineChildComponentName, SchemaSymbols::fgELT_GROUP)) { + + const XMLCh* minOccurs = getElementAttValue(child, SchemaSymbols::fgATT_MINOCCURS, DatatypeValidator::Decimal); + const XMLCh* maxOccurs = getElementAttValue(child, SchemaSymbols::fgATT_MAXOCCURS, DatatypeValidator::Decimal); + + if (((maxOccurs && *maxOccurs) && !XMLString::equals(maxOccurs, fgValueOne)) + || ((minOccurs && *minOccurs) && !XMLString::equals(minOccurs, fgValueOne))) { + reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidGroupMinMax, redefineChildTypeName); + } + } + } + } // if ref was null some other stage of processing will flag the error + } + } + + return result; +} + + +void TraverseSchema::fixRedefinedSchema(const DOMElement* const elem, + SchemaInfo* const redefinedSchemaInfo, + const XMLCh* const redefineChildComponentName, + const XMLCh* const redefineChildTypeName, + const int redefineNameCounter) { + + bool foundIt = false; + DOMElement* child = XUtil::getFirstChildElement(redefinedSchemaInfo->getRoot()); + + restoreSchemaInfo(redefinedSchemaInfo); + + for (; child != 0; child = XUtil::getNextSiblingElement(child)) { + + const XMLCh* name = child->getLocalName(); + + if (XMLString::equals(name, redefineChildComponentName)) { + + const XMLCh* infoItemName = getElementAttValue(child, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + + if(!XMLString::equals(infoItemName, redefineChildTypeName)) { + continue; + } + else { // found it! + + // now we have to do the renaming... + foundIt = true; + getRedefineNewTypeName(infoItemName, redefineNameCounter, fBuffer); + child->setAttribute(SchemaSymbols::fgATT_NAME, fBuffer.getRawBuffer()); + break; + } + } + else if (XMLString::equals(name, SchemaSymbols::fgELT_REDEFINE)) { // need to search the redefine decl... + + for (DOMElement* redefChild = XUtil::getFirstChildElement(child); + redefChild != 0; + redefChild = XUtil::getNextSiblingElement(redefChild)) { + + const XMLCh* redefName = redefChild->getLocalName(); + + if (XMLString::equals(redefName, redefineChildComponentName)) { + + const XMLCh* infoItemName = getElementAttValue(redefChild, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); + + if(!XMLString::equals(infoItemName, redefineChildTypeName)) { + continue; + } + else { // found it! + + if (!openRedefinedSchema(child)) { + + redefinedSchemaInfo->addFailedRedefine(child); + return; + } + + foundIt = true; + + SchemaInfo* reRedefinedSchemaInfo = fSchemaInfo; + + if (validateRedefineNameChange(redefChild, redefineChildComponentName, redefineChildTypeName, redefineNameCounter + 1, redefinedSchemaInfo)) { + + fixRedefinedSchema(redefChild, reRedefinedSchemaInfo, redefineChildComponentName, redefineChildTypeName, redefineNameCounter + 1); + + // now we have to do the renaming... + getRedefineNewTypeName(infoItemName, redefineNameCounter, fBuffer); + const XMLCh* newInfoItemName = fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); + redefChild->setAttribute(SchemaSymbols::fgATT_NAME, newInfoItemName); + + // and we now know we will traverse this, so set fRedefineComponents appropriately... + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(newInfoItemName); + } + else { + + fixRedefinedSchema(redefChild, reRedefinedSchemaInfo, redefineChildComponentName, redefineChildTypeName, redefineNameCounter); + redefinedSchemaInfo->addFailedRedefine(redefChild); + + // and we now know we will traverse this, so set fRedefineComponents appropriately... + fBuffer.set(fTargetNSURIString); + fBuffer.append(chComma); + fBuffer.append(infoItemName); + } + + unsigned int infoItemNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); + + if (!fRedefineComponents->containsKey(redefineChildComponentName, infoItemNameId)) { + fRedefineComponents->put((void*) redefineChildComponentName, infoItemNameId, 0); + } + + break; + } + } + } //for + + if (foundIt) { + break; + } + } + } //for + + if(!foundIt) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_DeclarationNotFound, redefineChildTypeName); + } +} + +bool TraverseSchema::isSubstitutionGroupCircular(SchemaElementDecl* const elemDecl, + SchemaElementDecl* const subsElemDecl) +{ + + if (elemDecl == subsElemDecl) + return true; + + SchemaElementDecl* tmpElemDecl = subsElemDecl->getSubstitutionGroupElem(); + + while (tmpElemDecl) + { + if (tmpElemDecl == elemDecl) + return true; + + tmpElemDecl = tmpElemDecl->getSubstitutionGroupElem(); + } + + return false; +} + +// --------------------------------------------------------------------------- +// TraverseSchema: Error reporting methods +// --------------------------------------------------------------------------- +void TraverseSchema::reportSchemaError(const XSDLocator* const aLocator, + const XMLCh* const msgDomain, + const int errorCode) { + + fXSDErrorReporter.emitError(errorCode, msgDomain, aLocator); +} + +void TraverseSchema::reportSchemaError(const XSDLocator* const aLocator, + const XMLCh* const msgDomain, + const int errorCode, + const XMLCh* const text1, + const XMLCh* const text2, + const XMLCh* const text3, + const XMLCh* const text4) { + + fXSDErrorReporter.emitError(errorCode, msgDomain, aLocator, text1, text2, text3, text4, fMemoryManager); +} + +void TraverseSchema::reportSchemaError(const DOMElement* const elem, + const XMLCh* const msgDomain, + const int errorCode) { + + fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, + ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + + fXSDErrorReporter.emitError(errorCode, msgDomain, fLocator); +} + +void TraverseSchema::reportSchemaError(const DOMElement* const elem, + const XMLCh* const msgDomain, + const int errorCode, + const XMLCh* const text1, + const XMLCh* const text2, + const XMLCh* const text3, + const XMLCh* const text4) { + + fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, + ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + + fXSDErrorReporter.emitError(errorCode, msgDomain, fLocator, text1, text2, text3, text4, fMemoryManager); +} + +void TraverseSchema::reportSchemaError(const DOMElement* const elem, + const XMLException& except) +{ + fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, + ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + + fXSDErrorReporter.emitError(except, fLocator); +} +// --------------------------------------------------------------------------- +// TraverseSchema: Init/CleanUp methods +// --------------------------------------------------------------------------- +void TraverseSchema::init() { + + fXSDErrorReporter.setErrorReporter(fErrorReporter); + fXSDErrorReporter.setExitOnFirstFatal(fScanner->getExitOnFirstFatal()); + + fFullConstraintChecking = fScanner->getValidationSchemaFullChecking(); + + fDatatypeRegistry = fSchemaGrammar->getDatatypeRegistry(); + fStringPool = fGrammarResolver->getStringPool(); + fEmptyNamespaceURI = fScanner->getEmptyNamespaceId(); + fCurrentTypeNameStack = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + fCurrentGroupStack = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + + fGlobalDeclarations = (ValueVectorOf**) fMemoryManager->allocate + ( + ENUM_ELT_SIZE * sizeof(ValueVectorOf*) + );//new ValueVectorOf*[ENUM_ELT_SIZE]; + memset(fGlobalDeclarations, 0, ENUM_ELT_SIZE * sizeof(ValueVectorOf*)); + for(unsigned int i=0; i < ENUM_ELT_SIZE; i++) + fGlobalDeclarations[i] = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + + fNonXSAttList = new (fMemoryManager) ValueVectorOf(4, fMemoryManager); + fNotationRegistry = new (fMemoryManager) RefHash2KeysTableOf(13, (bool) false, fMemoryManager); + fPreprocessedNodes = new (fMemoryManager) RefHashTableOf + ( + 29 + , false + , fMemoryManager + ); + fLocator = new (fMemoryManager) XSDLocator(); + fDeclStack = new (fMemoryManager) ValueVectorOf(16, fMemoryManager); +} + +void TraverseSchema::cleanUp() { + + delete fCurrentTypeNameStack; + delete fCurrentGroupStack; + + if (fGlobalDeclarations) + { + for(unsigned int i=0; i < ENUM_ELT_SIZE; i++) + delete fGlobalDeclarations[i]; + fMemoryManager->deallocate(fGlobalDeclarations);//delete [] fGlobalDeclarations; + } + + delete fNonXSAttList; + delete fImportedNSList; + delete fNotationRegistry; + delete fRedefineComponents; + delete fIdentityConstraintNames; + delete fDeclStack; + delete fIC_ElementsNS; + delete fIC_NodeListNS; + delete fPreprocessedNodes; + delete fLocator; + delete fParser; +} + +void TraverseSchema::processElemDeclAttrs(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + const XMLCh*& valueConstraint, + bool isTopLevel) +{ + int elementMiscFlags = 0; + const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED); + const XMLCh* nillable = getElementAttValue(elem, SchemaSymbols::fgATT_NILLABLE, DatatypeValidator::Boolean); + + // check constraint value + valueConstraint = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT); + if (fixedVal) + { + elementMiscFlags |= SchemaSymbols::XSD_FIXED; + + // if both default and fixed, emit an error + if (valueConstraint) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithFixedAndDefault, getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName)); + + // set constraint value to the fixed one + valueConstraint = fixedVal; + } + + // check nillable + if (nillable && *nillable) { + + if (XMLString::equals(nillable, SchemaSymbols::fgATTVAL_TRUE) + || XMLString::equals(nillable, fgValueOne)) { + elementMiscFlags |= SchemaSymbols::XSD_NILLABLE; + } + } + + if (isTopLevel) + { + const XMLCh* bAbstract = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT, DatatypeValidator::Boolean); + if (bAbstract && *bAbstract) { + + if (XMLString::equals(bAbstract, SchemaSymbols::fgATTVAL_TRUE) + || XMLString::equals(bAbstract, fgValueOne)) { + elementMiscFlags |= SchemaSymbols::XSD_ABSTRACT; + } + } + + elemDecl->setFinalSet(parseFinalSet(elem, EC_Final)); + } + + elemDecl->setBlockSet(parseBlockSet(elem, ES_Block)); + elemDecl->setMiscFlags(elementMiscFlags); +} + +void TraverseSchema::processElemDeclIC(DOMElement* const icElem, + SchemaElementDecl* const elemDecl) +{ + // key/keyref/unique processing + ValueVectorOf* icNodes = 0; + DOMElement* ic = icElem; + while (ic != 0) { + + if (XMLString::equals(ic->getLocalName(), SchemaSymbols::fgELT_KEY)) { + traverseKey(ic, elemDecl); + } + else if (XMLString::equals(ic->getLocalName(), SchemaSymbols::fgELT_UNIQUE)) { + traverseUnique(ic, elemDecl); + } + else { + + if (!icNodes) { + icNodes = new (fGrammarPoolMemoryManager) ValueVectorOf(8, fGrammarPoolMemoryManager); + } + + icNodes->addElement(ic); + } + + ic = XUtil::getNextSiblingElementNS( + ic, fgIdentityConstraints, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3); + } + + if (icNodes) { + + if (!fIC_ElementsNS) { + + fIC_ElementsNS = new (fMemoryManager) RefHashTableOf(13, fMemoryManager); + fIC_NodeListNS = new (fMemoryManager) RefHashTableOf, PtrHasher>(29, true, fMemoryManager); + } + + fIC_Elements = fIC_ElementsNS->get(fTargetNSURIString); + if (!fIC_Elements) { + fIC_Elements = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); + fIC_ElementsNS->put((void*) fTargetNSURIString, fIC_Elements); + } + + fIC_NodeListNS->put(elemDecl, icNodes); + fIC_Elements->addElement(elemDecl); + } +} + +bool +TraverseSchema::checkElemDeclValueConstraint(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + const XMLCh* const valConstraint, + ComplexTypeInfo* const typeInfo, + DatatypeValidator* const validator) +{ + bool isValid = false; + if (validator) + { + if (validator->getType() == DatatypeValidator::ID) + reportSchemaError( + elem, XMLUni::fgXMLErrDomain, XMLErrs::ElemIDValueConstraint + , elemDecl->getBaseName(), valConstraint + ); + + try + { + const XMLCh* valueToCheck = valConstraint; + short wsFacet = validator->getWSFacet(); + if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(valueToCheck)) || + (wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(valueToCheck))) + { + XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager); + ArrayJanitor tempURIName(normalizedValue, fMemoryManager); + if(wsFacet == DatatypeValidator::REPLACE) + XMLString::replaceWS(normalizedValue, fMemoryManager); + else if(wsFacet == DatatypeValidator::COLLAPSE) + XMLString::collapseWS(normalizedValue, fMemoryManager); + valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); + } + + validator->validate(valueToCheck,0,fMemoryManager); + + XMLCh* canonical = (XMLCh*) validator->getCanonicalRepresentation(valueToCheck, fMemoryManager); + ArrayJanitor tempCanonical(canonical, fMemoryManager); + + if(!XMLString::equals(canonical, valueToCheck)) + { + validator->validate(canonical, 0, fMemoryManager); + valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(canonical)); + } + + elemDecl->setDefaultValue(valueToCheck); + + isValid = true; + } + catch(const XMLException& excep) + { + reportSchemaError(elem, excep); + } + catch(const OutOfMemoryException&) + { + throw; + } + catch(...) + { + reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valConstraint); + } + } + + if (typeInfo) + { + int contentSpecType = typeInfo->getContentType(); + + if (contentSpecType != SchemaElementDecl::Simple && + contentSpecType != SchemaElementDecl::Mixed_Simple && + contentSpecType != SchemaElementDecl::Mixed_Complex) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotSimpleOrMixedElement, elemDecl->getBaseName()); + + if (((contentSpecType == SchemaElementDecl::Mixed_Complex + || contentSpecType == SchemaElementDecl::Mixed_Simple) + && !emptiableParticle(typeInfo->getContentSpec()))) + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::EmptiableMixedContent, elemDecl->getBaseName()); + } + + return isValid; +} + +void TraverseSchema::processSubstitutionGroup(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + ComplexTypeInfo*& typeInfo, + DatatypeValidator*& validator, + const XMLCh* const subsElemQName) +{ + NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); + + SchemaElementDecl* subsElemDecl = getGlobalElemDecl(elem, subsElemQName); + if (subsElemDecl) + { + if (isSubstitutionGroupCircular(elemDecl, subsElemDecl)) + { + reportSchemaError( + elem , XMLUni::fgXMLErrDomain , XMLErrs::CircularSubsGroup, elemDecl->getBaseName()); + } + else + { + // Check for substitution validity constraint + // Substitution allowed (block and blockDefault) && same type + if (isSubstitutionGroupValid(elem, subsElemDecl, typeInfo, validator, elemDecl->getBaseName())) + { + elemDecl->setSubstitutionGroupElem(subsElemDecl); + + // if type information is missing, use subsGroup one + if (!typeInfo && !validator) + { + typeInfo = subsElemDecl->getComplexTypeInfo(); + validator = subsElemDecl->getDatatypeValidator(); + + if (validator) + { + elemDecl->setDatatypeValidator(validator); + elemDecl->setModelType(SchemaElementDecl::Simple); + } + else if (typeInfo) + { + elemDecl->setComplexTypeInfo(typeInfo); + elemDecl->setModelType((SchemaElementDecl::ModelTypes)typeInfo->getContentType()); + } + } + + XMLCh* subsElemBaseName = subsElemDecl->getBaseName(); + int subsElemURI = subsElemDecl->getURI(); + ValueVectorOf* subsElements = + fValidSubstitutionGroups->get(subsElemBaseName, subsElemURI); + + if (!subsElements && fTargetNSURI != subsElemURI) + { + SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(fURIStringPool->getValueForId(subsElemURI)); + + if (aGrammar) + { + subsElements = aGrammar->getValidSubstitutionGroups()->get(subsElemBaseName, subsElemURI); + + if (subsElements) + { + subsElements = new (fGrammarPoolMemoryManager) ValueVectorOf(*subsElements); + fValidSubstitutionGroups->put(subsElemBaseName, subsElemURI, subsElements); + } + else if (fSchemaInfo->circularImportExist(subsElemURI)) + { + aGrammar->getValidSubstitutionGroups()->put( + subsElemBaseName, subsElemURI, new (fGrammarPoolMemoryManager) ValueVectorOf(8, fGrammarPoolMemoryManager)); + } + } + } + + if (!subsElements) + { + subsElements = new (fGrammarPoolMemoryManager) ValueVectorOf(8, fGrammarPoolMemoryManager); + fValidSubstitutionGroups->put(subsElemBaseName, subsElemURI, subsElements); + } + + subsElements->addElement(elemDecl); + + // update related subs. info in case of circular import + BaseRefVectorEnumerator importingEnum = fSchemaInfo->getImportingListEnumerator(); + + while (importingEnum.hasMoreElements()) + { + const SchemaInfo& curRef = importingEnum.nextElement(); + SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(curRef.getTargetNSURIString()); + ValueVectorOf* subsElemList = + aGrammar->getValidSubstitutionGroups()->get(subsElemBaseName, subsElemURI); + + if (subsElemList && !subsElemList->containsElement(elemDecl)) + subsElemList->addElement(elemDecl); + } + + buildValidSubstitutionListB(elem, elemDecl, subsElemDecl); + buildValidSubstitutionListF(elem, elemDecl, subsElemDecl); + } + } + } +} + +void TraverseSchema::processAttValue(const XMLCh* const attVal, + XMLBuffer& aBuf) +{ + // REVISIT-KN: assuming that attVal is not NULL + // + // normally, nothing will happen + const XMLCh* srcVal = attVal; + XMLCh nextCh = *srcVal; + while (nextCh) + { + if (nextCh <= chCloseAngle) { + switch (nextCh) { + case chDoubleQuote: + aBuf.append(chAmpersand); + aBuf.append(XMLUni::fgQuot); + aBuf.append(chSemiColon); + break; + case chSingleQuote: + aBuf.append(chAmpersand); + aBuf.append(XMLUni::fgApos); + aBuf.append(chSemiColon); + break; + case chCloseAngle: + aBuf.append(chAmpersand); + aBuf.append(XMLUni::fgGT); + aBuf.append(chSemiColon); + break; + case chOpenAngle: + aBuf.append(chAmpersand); + aBuf.append(XMLUni::fgLT); + aBuf.append(chSemiColon); + break; + case chAmpersand: + aBuf.append(chAmpersand); + aBuf.append(XMLUni::fgAmp); + aBuf.append(chSemiColon); + break; + default: + aBuf.append(nextCh); + break; + } // end switch + } + else + aBuf.append(nextCh); + + nextCh = *++srcVal; + } +} + +XSAnnotation* TraverseSchema::generateSyntheticAnnotation(const DOMElement* const elem + , ValueVectorOf* nonXSAttList) +{ + const XMLCh* prefix = elem->getPrefix(); + ValueHashTableOf* listOfURIs = new (fMemoryManager) ValueHashTableOf(29, fMemoryManager); + bool sawXMLNS = false; + + fBuffer.reset(); + fBuffer.append(chOpenAngle); + if (prefix) + { + fBuffer.append(prefix); + fBuffer.append(chColon); + } + fBuffer.append(SchemaSymbols::fgELT_ANNOTATION); + + // next is the nonXSAttList names & values + XMLSize_t nonXSAttSize = nonXSAttList->size(); + + for (XMLSize_t i=0; ielementAt(i); + + fBuffer.append(chSpace); + fBuffer.append(attNode->getNodeName()); + fBuffer.append(chEqual); + fBuffer.append(chDoubleQuote); + processAttValue(attNode->getNodeValue(), fBuffer); + fBuffer.append(chDoubleQuote); + } + + // next is the namespaces on the elem + DOMElement* currentElem = (DOMElement*) elem; + DOMNamedNodeMap* eltAttrs; + XMLSize_t attrCount; + do { + eltAttrs = currentElem->getAttributes(); + attrCount = eltAttrs->getLength(); + for (XMLSize_t j = 0; j < attrCount; j++) + { + DOMNode* attribute = eltAttrs->item(j); + const XMLCh* attName = attribute->getNodeName(); + + if (XMLString::startsWith(attName, XMLUni::fgXMLNSColonString)) + { + if (!listOfURIs->containsKey((void*) attName)) { + listOfURIs->put((void*) attName, 0); + fBuffer.append(chSpace); + fBuffer.append(attName); + fBuffer.append(chEqual); + fBuffer.append(chDoubleQuote); + processAttValue(attribute->getNodeValue(), fBuffer); + fBuffer.append(chDoubleQuote); + } + } + else if (!sawXMLNS && XMLString::equals(attName, XMLUni::fgXMLNSString)) + { + fBuffer.append(chSpace); + fBuffer.append(attName); + fBuffer.append(chEqual); + fBuffer.append(chDoubleQuote); + processAttValue(attribute->getNodeValue(), fBuffer); + fBuffer.append(chDoubleQuote); + sawXMLNS = true; + } + } + currentElem = (DOMElement*) currentElem->getParentNode(); + } + while (currentElem != fSchemaInfo->getRoot()->getParentNode()); + delete listOfURIs; + + fBuffer.append(chCloseAngle); + fBuffer.append(chLF); + fBuffer.append(chOpenAngle); + if (prefix) + { + fBuffer.append(prefix); + fBuffer.append(chColon); + } + fBuffer.append(SchemaSymbols::fgELT_DOCUMENTATION); + fBuffer.append(chCloseAngle); + fBuffer.append(fgSynthetic_Annotation); + fBuffer.append(chOpenAngle); + fBuffer.append(chForwardSlash); + if (prefix) + { + fBuffer.append(prefix); + fBuffer.append(chColon); + } + fBuffer.append(SchemaSymbols::fgELT_DOCUMENTATION); + fBuffer.append(chCloseAngle); + fBuffer.append(chLF); + fBuffer.append(chOpenAngle); + fBuffer.append(chForwardSlash); + if (prefix) + { + fBuffer.append(prefix); + fBuffer.append(chColon); + } + fBuffer.append(SchemaSymbols::fgELT_ANNOTATION); + fBuffer.append(chCloseAngle); + + XSAnnotation* annot = new (fGrammarPoolMemoryManager) XSAnnotation(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager); + annot->setLineCol( ((XSDElementNSImpl*)elem)->getLineNo() + , ((XSDElementNSImpl*)elem)->getColumnNo() ); + annot->setSystemId(fSchemaInfo->getCurrentSchemaURL()); + return annot; +} + +class AnnotationErrorReporter : public XMLErrorReporter +{ +public: + AnnotationErrorReporter(XMLErrorReporter* chainedErrorReporter) + { + fErrorReporter = chainedErrorReporter; + setSystemIdAndPosition(NULL, 0, 0); + } + + void setSystemIdAndPosition(const XMLCh* systemId, XMLFileLoc line, XMLFileLoc column) + { + fSystemId=systemId; + fLine=line; + fColumn=column; + } + + virtual void error + ( + const unsigned int errCode + , const XMLCh* const errDomain + , const ErrTypes type + , const XMLCh* const errorText + , const XMLCh* const /*systemId*/ + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ) + { + if(fErrorReporter) + fErrorReporter->error(errCode, errDomain, type, errorText, fSystemId, publicId, fLine+lineNum-1, lineNum==1?fColumn+colNum:colNum); + } + + virtual void resetErrors() {} + +protected: + XMLErrorReporter* fErrorReporter; + const XMLCh* fSystemId; + XMLFileLoc fLine, fColumn; +}; + +void TraverseSchema::validateAnnotations() { + + MemoryManager *memMgr = fMemoryManager; + RefHashTableOfEnumerator xsAnnotationEnum = RefHashTableOfEnumerator (fSchemaGrammar->getAnnotations(), false, memMgr); + XSAnnotation& xsAnnot = xsAnnotationEnum.nextElement(); + XSAnnotation* nextAnnot; + + // create schema grammar + SchemaGrammar *grammar = new (memMgr) SchemaGrammar(memMgr); + grammar->setComplexTypeRegistry(new (memMgr) RefHashTableOf(29, memMgr)); + grammar->setGroupInfoRegistry(new (memMgr) RefHashTableOf(13, memMgr)); + grammar->setAttGroupInfoRegistry(new (memMgr) RefHashTableOf(13, memMgr)); + grammar->setAttributeDeclRegistry(new (memMgr) RefHashTableOf(29, memMgr)); + grammar->setValidSubstitutionGroups(new (memMgr) RefHash2KeysTableOf(29, memMgr)); + grammar->setTargetNamespace(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) grammar->getGrammarDescription(); + gramDesc->setTargetNamespace(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + + // setup components of annotation grammar + SchemaElementDecl* annotElemDecl = new (memMgr) SchemaElementDecl + ( + XMLUni::fgZeroLenString , SchemaSymbols::fgELT_ANNOTATION + , fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + , SchemaElementDecl::Mixed_Complex, Grammar::TOP_LEVEL_SCOPE , memMgr + ); + annotElemDecl->setCreateReason(XMLElementDecl::Declared); + grammar->putElemDecl(annotElemDecl); + + ComplexTypeInfo* complexType = new (memMgr) ComplexTypeInfo(memMgr); + complexType->setAnonymous(); + complexType->setContentType(SchemaElementDecl::Mixed_Complex); + annotElemDecl->setComplexTypeInfo(complexType); + + fBuffer.set(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); + fBuffer.append(chComma); + fBuffer.append(chLatin_C); + fBuffer.append(chDigit_0); + const XMLCh* fullName = fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); + grammar->getComplexTypeRegistry()->put((void*) fullName, complexType); + complexType->setTypeName(fullName); + complexType->setAttWildCard + ( + new (memMgr) SchemaAttDef + ( + XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, + fEmptyNamespaceURI, XMLAttDef::Any_Any, + XMLAttDef::ProcessContents_Lax, memMgr + ) + ); + + SchemaElementDecl* appInfoElemDecl = new (memMgr) SchemaElementDecl + ( + XMLUni::fgZeroLenString , SchemaSymbols::fgELT_APPINFO + , fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE , memMgr + ); + + appInfoElemDecl->setCreateReason(XMLElementDecl::Declared); + appInfoElemDecl->setAttWildCard + ( + new (memMgr) SchemaAttDef + ( + XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, + fEmptyNamespaceURI, XMLAttDef::Any_Any, + XMLAttDef::ProcessContents_Lax, memMgr + ) + ); + grammar->putElemDecl(appInfoElemDecl); + complexType->addElement(appInfoElemDecl); + + SchemaElementDecl* docElemDecl = new (memMgr) SchemaElementDecl + ( + XMLUni::fgZeroLenString , SchemaSymbols::fgELT_DOCUMENTATION + , fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE , memMgr + ); + + docElemDecl->setCreateReason(XMLElementDecl::Declared); + docElemDecl->setAttWildCard + ( + new (memMgr) SchemaAttDef + ( + XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, + fEmptyNamespaceURI, XMLAttDef::Any_Any, + XMLAttDef::ProcessContents_Lax, memMgr + ) + ); + grammar->putElemDecl(docElemDecl); + complexType->addElement(docElemDecl); + + ContentSpecNode* left = new (memMgr) ContentSpecNode(appInfoElemDecl, memMgr); + ContentSpecNode* right = new (memMgr) ContentSpecNode(docElemDecl, memMgr); + ContentSpecNode* root = new (memMgr) ContentSpecNode(ContentSpecNode::ModelGroupChoice + , left + , right + , true + , true + , memMgr); + root->setMinOccurs(0); + root->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED); + complexType->setContentSpec(root); + + // create input source to scan + MemBufInputSource* memBufIS = new (memMgr) MemBufInputSource + ( + (const XMLByte*)xsAnnot.getAnnotationString() + , XMLString::stringLen(xsAnnot.getAnnotationString())*sizeof(XMLCh) + , SchemaSymbols::fgELT_ANNOTATION + , false + , memMgr + ); + Janitor janMemBuf(memBufIS); + memBufIS->setEncoding(XMLUni::fgXMLChEncodingString); + memBufIS->setCopyBufToStream(false); + + XSAXMLScanner *scanner = new (memMgr) XSAXMLScanner + ( + fGrammarResolver, fURIStringPool, grammar, memMgr + ); + Janitor janScanner(scanner); + + AnnotationErrorReporter annErrReporter(fErrorReporter); + scanner->setErrorReporter(&annErrReporter); + + XMLFileLoc line, col; + xsAnnot.getLineCol(line, col); + annErrReporter.setSystemIdAndPosition(xsAnnot.getSystemId(), line, col); + scanner->scanDocument(*memBufIS); + + nextAnnot = xsAnnot.getNext(); + + while (nextAnnot || xsAnnotationEnum.hasMoreElements()) + { + if (nextAnnot) { + memBufIS->resetMemBufInputSource((const XMLByte*)nextAnnot->getAnnotationString() + , XMLString::stringLen(nextAnnot->getAnnotationString())*sizeof(XMLCh)); + nextAnnot->getLineCol(line, col); + annErrReporter.setSystemIdAndPosition(nextAnnot->getSystemId(), line, col); + nextAnnot = nextAnnot->getNext(); + } + else { + XSAnnotation& xsAnnot = xsAnnotationEnum.nextElement(); + memBufIS->resetMemBufInputSource((const XMLByte*)xsAnnot.getAnnotationString() + , XMLString::stringLen(xsAnnot.getAnnotationString())*sizeof(XMLCh)); + xsAnnot.getLineCol(line, col); + annErrReporter.setSystemIdAndPosition(xsAnnot.getSystemId(), line, col); + nextAnnot = xsAnnot.getNext(); + } + scanner->scanDocument(*memBufIS); + } + +} + +const XMLCh* TraverseSchema::getElementAttValue(const DOMElement* const elem, + const XMLCh* const attName, + const DatatypeValidator::ValidatorType attType /* = UnKnown */) { + + DOMAttr* attNode = elem->getAttributeNode(attName); + + if (attNode == 0) { + return 0; + } + + const XMLCh* attValue = attNode->getValue(); + + if (attType < DatatypeValidator::ID) { + static bool bInitialized = false; + static short wsFacets[DatatypeValidator::ID] = {0}; + if(!bInitialized) + { + bInitialized=true; + DVHashTable* registry = DatatypeValidatorFactory::getBuiltInRegistry(); + wsFacets[DatatypeValidator::String] = registry->get(SchemaSymbols::fgDT_STRING)->getWSFacet(); + wsFacets[DatatypeValidator::AnyURI] = registry->get(SchemaSymbols::fgDT_ANYURI)->getWSFacet(); + wsFacets[DatatypeValidator::QName] = registry->get(SchemaSymbols::fgDT_QNAME)->getWSFacet(); + wsFacets[DatatypeValidator::Name] = registry->get(SchemaSymbols::fgDT_NAME)->getWSFacet(); + wsFacets[DatatypeValidator::NCName] = registry->get(SchemaSymbols::fgDT_NCNAME)->getWSFacet(); + wsFacets[DatatypeValidator::Boolean] = registry->get(SchemaSymbols::fgDT_BOOLEAN)->getWSFacet(); + wsFacets[DatatypeValidator::Float] = registry->get(SchemaSymbols::fgDT_FLOAT)->getWSFacet(); + wsFacets[DatatypeValidator::Double] = registry->get(SchemaSymbols::fgDT_DOUBLE)->getWSFacet(); + wsFacets[DatatypeValidator::Decimal] = registry->get(SchemaSymbols::fgDT_DECIMAL)->getWSFacet(); + wsFacets[DatatypeValidator::HexBinary] = registry->get(SchemaSymbols::fgDT_HEXBINARY)->getWSFacet(); + wsFacets[DatatypeValidator::Base64Binary]= registry->get(SchemaSymbols::fgDT_BASE64BINARY)->getWSFacet(); + wsFacets[DatatypeValidator::Duration] = registry->get(SchemaSymbols::fgDT_DURATION)->getWSFacet(); + wsFacets[DatatypeValidator::DateTime] = registry->get(SchemaSymbols::fgDT_DATETIME)->getWSFacet(); + wsFacets[DatatypeValidator::Date] = registry->get(SchemaSymbols::fgDT_DATE)->getWSFacet(); + wsFacets[DatatypeValidator::Time] = registry->get(SchemaSymbols::fgDT_TIME)->getWSFacet(); + wsFacets[DatatypeValidator::MonthDay] = registry->get(SchemaSymbols::fgDT_MONTHDAY)->getWSFacet(); + wsFacets[DatatypeValidator::YearMonth] = registry->get(SchemaSymbols::fgDT_YEARMONTH)->getWSFacet(); + wsFacets[DatatypeValidator::Year] = registry->get(SchemaSymbols::fgDT_YEAR)->getWSFacet(); + wsFacets[DatatypeValidator::Month] = registry->get(SchemaSymbols::fgDT_MONTH)->getWSFacet(); + wsFacets[DatatypeValidator::Day] = registry->get(SchemaSymbols::fgDT_DAY)->getWSFacet(); + } + short wsFacet = wsFacets[attType]; + if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(attValue)) || + (wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(attValue))) + { + XMLCh* normalizedValue=XMLString::replicate(attValue, fMemoryManager); + ArrayJanitor tempName(normalizedValue, fMemoryManager); + if(wsFacet == DatatypeValidator::REPLACE) + XMLString::replaceWS(normalizedValue, fMemoryManager); + else if(wsFacet == DatatypeValidator::COLLAPSE) + XMLString::collapseWS(normalizedValue, fMemoryManager); + if (!*normalizedValue) + return XMLUni::fgZeroLenString; + return fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); + } + } + + return attValue; +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file TraverseSchema.cpp + */ diff --git a/include/xercesc/validators/schema/TraverseSchema.hpp b/include/xercesc/validators/schema/TraverseSchema.hpp new file mode 100644 index 0000000..9fad434 --- /dev/null +++ b/include/xercesc/validators/schema/TraverseSchema.hpp @@ -0,0 +1,925 @@ +/* + * 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: TraverseSchema.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_TRAVERSESCHEMA_HPP) +#define XERCESC_INCLUDE_GUARD_TRAVERSESCHEMA_HPP + +/** + * Instances of this class get delegated to Traverse the Schema and + * to populate the SchemaGrammar internal representation. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class GrammarResolver; +class XMLEntityHandler; +class XMLScanner; +class DatatypeValidator; +class DatatypeValidatorFactory; +class QName; +class ComplexTypeInfo; +class XMLAttDef; +class NamespaceScope; +class SchemaAttDef; +class InputSource; +class XercesGroupInfo; +class XercesAttGroupInfo; +class IdentityConstraint; +class XSDLocator; +class XSDDOMParser; +class XMLErrorReporter; + + +class VALIDATORS_EXPORT TraverseSchema : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Public Constructors/Destructor + // ----------------------------------------------------------------------- + TraverseSchema + ( + DOMElement* const schemaRoot + , XMLStringPool* const uriStringPool + , SchemaGrammar* const schemaGrammar + , GrammarResolver* const grammarResolver + , RefHash2KeysTableOf* cachedSchemaInfoList + , RefHash2KeysTableOf* schemaInfoList + , XMLScanner* const xmlScanner + , const XMLCh* const schemaURL + , XMLEntityHandler* const entityHandler + , XMLErrorReporter* const errorReporter + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , bool multipleImport = false + ); + + ~TraverseSchema(); + +private: + // This enumeration is defined here for compatibility with the CodeWarrior + // compiler, which apparently doesn't like to accept default parameter + // arguments that it hasn't yet seen. The Not_All_Context argument is + // used in the declaration of checkMinMax, below. + // + // Flags indicate any special restrictions on minOccurs and maxOccurs + // relating to "all". + // Not_All_Context - not processing an + // All_Element - processing an in an + // Group_Ref_With_All - processing reference that contained + // All_Group - processing an group itself + enum + { + Not_All_Context = 0 + , All_Element = 1 + , Group_Ref_With_All = 2 + , All_Group = 4 + }; + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + TraverseSchema(const TraverseSchema&); + TraverseSchema& operator=(const TraverseSchema&); + + // ----------------------------------------------------------------------- + // Init/CleanUp methods + // ----------------------------------------------------------------------- + void init(); + void cleanUp(); + + // ----------------------------------------------------------------------- + // Traversal methods + // ----------------------------------------------------------------------- + /** + * Traverse the Schema DOM tree + */ + void doTraverseSchema(const DOMElement* const schemaRoot); + void preprocessSchema(DOMElement* const schemaRoot, + const XMLCh* const schemaURL, + bool multipleImport = false); + void traverseSchemaHeader(const DOMElement* const schemaRoot); + XSAnnotation* traverseAnnotationDecl(const DOMElement* const childElem, + ValueVectorOf* const nonXSAttList, + const bool topLevel = false); + void traverseInclude(const DOMElement* const childElem); + void traverseImport(const DOMElement* const childElem); + void traverseRedefine(const DOMElement* const childElem); + void traverseAttributeDecl(const DOMElement* const childElem, + ComplexTypeInfo* const typeInfo, + const bool topLevel = false); + void traverseSimpleContentDecl(const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const DOMElement* const contentDecl, + ComplexTypeInfo* const typeInfo, + Janitor* const janAnnot); + void traverseComplexContentDecl(const XMLCh* const typeName, + const DOMElement* const contentDecl, + ComplexTypeInfo* const typeInfo, + const bool isMixed, + Janitor* const janAnnot); + DatatypeValidator* traverseSimpleTypeDecl(const DOMElement* const childElem, + const bool topLevel = true, + int baseRefContext = SchemaSymbols::XSD_EMPTYSET); + int traverseComplexTypeDecl(const DOMElement* const childElem, + const bool topLevel = true, + const XMLCh* const recursingTypeName = 0); + DatatypeValidator* traverseByList(const DOMElement* const rootElem, + const DOMElement* const contentElem, + const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const int finalSet, + Janitor* const janAnnot); + DatatypeValidator* traverseByRestriction(const DOMElement* const rootElem, + const DOMElement* const contentElem, + const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const int finalSet, + Janitor* const janAnnot); + DatatypeValidator* traverseByUnion(const DOMElement* const rootElem, + const DOMElement* const contentElem, + const XMLCh* const typeName, + const XMLCh* const qualifiedName, + const int finalSet, + int baseRefContext, + Janitor* const janAnnot); + SchemaElementDecl* traverseElementDecl(const DOMElement* const childElem, + const bool topLevel = false); + const XMLCh* traverseNotationDecl(const DOMElement* const childElem); + const XMLCh* traverseNotationDecl(const DOMElement* const childElem, + const XMLCh* const name, + const XMLCh* const uriStr); + ContentSpecNode* traverseChoiceSequence(const DOMElement* const elemDecl, + const int modelGroupType, + bool& hasChildren); + ContentSpecNode* traverseAny(const DOMElement* const anyDecl); + ContentSpecNode* traverseAll(const DOMElement* const allElem, + bool& hasChildren); + XercesGroupInfo* traverseGroupDecl(const DOMElement* const childElem, + const bool topLevel = true); + XercesAttGroupInfo* traverseAttributeGroupDecl(const DOMElement* const elem, + ComplexTypeInfo* const typeInfo, + const bool topLevel = false); + XercesAttGroupInfo* traverseAttributeGroupDeclNS(const DOMElement* const elem, + const XMLCh* const uriStr, + const XMLCh* const name); + SchemaAttDef* traverseAnyAttribute(const DOMElement* const elem); + void traverseKey(const DOMElement* const icElem, + SchemaElementDecl* const elemDecl); + void traverseUnique(const DOMElement* const icElem, + SchemaElementDecl* const elemDecl); + void traverseKeyRef(const DOMElement* const icElem, + SchemaElementDecl* const elemDecl); + bool traverseIdentityConstraint(IdentityConstraint* const ic, + const DOMElement* const icElem); + + // ----------------------------------------------------------------------- + // Error Reporting methods + // ----------------------------------------------------------------------- + void reportSchemaError(const XSDLocator* const aLocator, + const XMLCh* const msgDomain, + const int errorCode); + void reportSchemaError(const XSDLocator* const aLocator, + const XMLCh* const msgDomain, + const int errorCode, + const XMLCh* const text1, + const XMLCh* const text2 = 0, + const XMLCh* const text3 = 0, + const XMLCh* const text4 = 0); + void reportSchemaError(const DOMElement* const elem, + const XMLCh* const msgDomain, + const int errorCode); + void reportSchemaError(const DOMElement* const elem, + const XMLCh* const msgDomain, + const int errorCode, + const XMLCh* const text1, + const XMLCh* const text2 = 0, + const XMLCh* const text3 = 0, + const XMLCh* const text4 = 0); + void reportSchemaError(const DOMElement* const elem, + const XMLException& except); + + // ----------------------------------------------------------------------- + // Private Helper methods + // ----------------------------------------------------------------------- + /** + * Keep track of the xs:import found + */ + bool isImportingNS(const int namespaceURI); + void addImportedNS(const int namespaceURI); + + /** + * Retrieved the Namespace mapping from the schema element + */ + bool retrieveNamespaceMapping(const DOMElement* const elem); + + /** + * Loop through the children, and traverse the corresponding schema type + * type declaration (simpleType, complexType, import, ....) + */ + void processChildren(const DOMElement* const root); + void preprocessChildren(const DOMElement* const root); + + void preprocessImport(const DOMElement* const elemNode); + void preprocessInclude(const DOMElement* const elemNode); + void preprocessRedefine(const DOMElement* const elemNode); + + /** + * Parameters: + * rootElem - top element for a given type declaration + * contentElem - content must be annotation? or some other simple content + * isEmpty: - true if (annotation?, smth_else), false if (annotation?) + * processAnnot - default is true, false if reprocessing a complex type + * since we have already processed the annotation. + * + * Check for Annotation if it is present, traverse it. If a sibling is + * found and it is not an annotation return it, otherwise return 0. + * Used by traverseSimpleTypeDecl. + */ + DOMElement* checkContent(const DOMElement* const rootElem, + DOMElement* const contentElem, + const bool isEmpty, bool processAnnot = true); + + /** + * Parameters: + * contentElem - content element to check + * + * Check for identity constraints content. + */ + const DOMElement* checkIdentityConstraintContent(const DOMElement* const contentElem); + + DatatypeValidator* getDatatypeValidator(const XMLCh* const uriStr, + const XMLCh* const localPartStr); + + /** + * Process simpleType content of a list|restriction|union + * Return a dataype validator if valid type, otherwise 0. + */ + DatatypeValidator* checkForSimpleTypeValidator(const DOMElement* const content, + int baseRefContext = SchemaSymbols::XSD_EMPTYSET); + + /** + * Process complexType content of an element + * Return a ComplexTypeInfo if valid type, otherwise 0. + */ + ComplexTypeInfo* checkForComplexTypeInfo(const DOMElement* const content); + + /** + * Return DatatypeValidator available for the baseTypeStr. + */ + DatatypeValidator* findDTValidator(const DOMElement* const elem, + const XMLCh* const derivedTypeName, + const XMLCh* const baseTypeName, + const int baseRefContext); + + const XMLCh* resolvePrefixToURI(const DOMElement* const elem, + const XMLCh* const prefix); + + /** + * Return the prefix for a given rawname string + * + * Function allocated, caller managed (facm) - pointer to be deleted by + * caller. + */ + const XMLCh* getPrefix(const XMLCh* const rawName); + + /** + * Return the local for a given rawname string + * + * caller allocated, caller managed (cacm) + */ + const XMLCh* getLocalPart(const XMLCh* const rawName); + + /** + * Process a 'ref' of an Element declaration + */ + SchemaElementDecl* processElementDeclRef(const DOMElement* const elem, + const XMLCh* const refName); + void processElemDeclAttrs(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + const XMLCh*& valConstraint, + bool isTopLevel = false); + void processElemDeclIC(DOMElement* const elem, + SchemaElementDecl* const elemDecl); + bool checkElemDeclValueConstraint(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + const XMLCh* const valConstraint, + ComplexTypeInfo* const typeInfo, + DatatypeValidator* const validator); + + /** + * Process a 'ref' of an Attribute declaration + */ + void processAttributeDeclRef(const DOMElement* const elem, + ComplexTypeInfo* const typeInfo, + const XMLCh* const refName, + const XMLCh* const useVal, + const XMLCh* const defaultVal, + const XMLCh* const fixedVal); + + /** + * Process a 'ref' on a group + */ + XercesGroupInfo* processGroupRef(const DOMElement* const elem, + const XMLCh* const refName); + + /** + * Process a 'ref' on a attributeGroup + */ + XercesAttGroupInfo* processAttributeGroupRef(const DOMElement* const elem, + const XMLCh* const refName, + ComplexTypeInfo* const typeInfo); + + /** + * Parse block & final items + */ + int parseBlockSet(const DOMElement* const elem, const int blockType, const bool isRoot = false); + int parseFinalSet(const DOMElement* const elem, const int finalType, const bool isRoot = false); + + /** + * Return true if a name is an identity constraint, otherwise false + */ + bool isIdentityConstraintName(const XMLCh* const constraintName); + + /** + * If 'typeStr' belongs to a different schema, return that schema URI, + * otherwise return 0; + */ + const XMLCh* checkTypeFromAnotherSchema(const DOMElement* const elem, + const XMLCh* const typeStr); + + /** + * Return the datatype validator for a given element type attribute if + * the type is a simple type + */ + DatatypeValidator* getElementTypeValidator(const DOMElement* const elem, + const XMLCh* const typeStr, + bool& noErrorDetected, + const XMLCh* const otherSchemaURI); + + /** + * Return the complexType info for a given element type attribute if + * the type is a complex type + */ + ComplexTypeInfo* getElementComplexTypeInfo(const DOMElement* const elem, + const XMLCh* const typeStr, + const XMLCh* const otherSchemaURI); + + /** + * Return global schema element declaration for a given element name + */ + SchemaElementDecl* getGlobalElemDecl(const DOMElement* const elem, + const XMLCh* const name); + + /** + * Check validity constraint of a substitutionGroup attribute in + * an element declaration + */ + bool isSubstitutionGroupValid(const DOMElement* const elem, + const SchemaElementDecl* const elemDecl, + const ComplexTypeInfo* const typeInfo, + const DatatypeValidator* const validator, + const XMLCh* const elemName, + const bool toEmit = true); + + bool isSubstitutionGroupCircular(SchemaElementDecl* const elemDecl, + SchemaElementDecl* const subsElemDecl); + + void processSubstitutionGroup(const DOMElement* const elem, + SchemaElementDecl* const elemDecl, + ComplexTypeInfo*& typeInfo, + DatatypeValidator*& validator, + const XMLCh* const subsElemQName); + + /** + * Create a 'SchemaElementDecl' object and add it to SchemaGrammar + */ + SchemaElementDecl* createSchemaElementDecl(const DOMElement* const elem, + const XMLCh* const name, + bool& isDuplicate, + const XMLCh*& valConstraint, + const bool topLevel); + + /** + * Return the value of a given attribute name from an element node + */ + const XMLCh* getElementAttValue(const DOMElement* const elem, + const XMLCh* const attName, + const DatatypeValidator::ValidatorType attType = DatatypeValidator::UnKnown); + + /* return minOccurs */ + int checkMinMax(ContentSpecNode* const specNode, + const DOMElement* const elem, + const int allContext = Not_All_Context); + + /** + * Process complex content for a complexType + */ + void processComplexContent(const DOMElement* const elem, + const XMLCh* const typeName, + const DOMElement* const childElem, + ComplexTypeInfo* const typeInfo, + const XMLCh* const baseLocalPart, + const bool isMixed, + const bool isBaseAnyType = false); + + /** + * Process "base" information for a complexType + */ + void processBaseTypeInfo(const DOMElement* const elem, + const XMLCh* const baseName, + const XMLCh* const localPart, + const XMLCh* const uriStr, + ComplexTypeInfo* const typeInfo); + + /** + * Check if base is from another schema + */ + bool isBaseFromAnotherSchema(const XMLCh* const baseURI); + + /** + * Get complexType infp from another schema + */ + ComplexTypeInfo* getTypeInfoFromNS(const DOMElement* const elem, + const XMLCh* const uriStr, + const XMLCh* const localPart); + + DatatypeValidator* + getAttrDatatypeValidatorNS(const DOMElement* const elem, + const XMLCh* localPart, + const XMLCh* typeURI); + + /** + * Returns true if a DOM Element is an attribute or attribute group + */ + bool isAttrOrAttrGroup(const DOMElement* const elem); + + /** + * Process attributes of a complex type + */ + void processAttributes(const DOMElement* const elem, + const DOMElement* const attElem, + ComplexTypeInfo* const typeInfo, + const bool isBaseAnyType = false); + + /** + * Generate a name for an anonymous type + */ + const XMLCh* genAnonTypeName(const XMLCh* const prefix); + + void defaultComplexTypeInfo(ComplexTypeInfo* const typeInfo); + + /** + * Resolve a schema location attribute value to an input source. + * Caller to delete the returned object. + */ + InputSource* resolveSchemaLocation + ( + const XMLCh* const loc + , const XMLResourceIdentifier::ResourceIdentifierType resourceIdentitiferType + , const XMLCh* const nameSpace=0 + ); + + void restoreSchemaInfo(SchemaInfo* const toRestore, + SchemaInfo::ListType const aListType = SchemaInfo::INCLUDE, + const unsigned int saveScope = Grammar::TOP_LEVEL_SCOPE); + void popCurrentTypeNameStack(); + + /** + * Check whether a mixed content is emptiable or not. + * Needed to validate element constraint values (defualt, fixed) + */ + bool emptiableParticle(const ContentSpecNode* const specNode); + + void checkFixedFacet(const DOMElement* const, const XMLCh* const, + const DatatypeValidator* const, unsigned int&); + void buildValidSubstitutionListF(const DOMElement* const elem, + SchemaElementDecl* const, + SchemaElementDecl* const); + void buildValidSubstitutionListB(const DOMElement* const elem, + SchemaElementDecl* const, + SchemaElementDecl* const); + + void checkEnumerationRequiredNotation(const DOMElement* const elem, + const XMLCh* const name, + const XMLCh* const typeStr); + + void processElements(const DOMElement* const elem, + ComplexTypeInfo* const baseTypeInfo, + ComplexTypeInfo* const newTypeInfo); + + void processElements(const DOMElement* const elem, + XercesGroupInfo* const fromGroup, + ComplexTypeInfo* const typeInfo); + + void copyGroupElements(const DOMElement* const elem, + XercesGroupInfo* const fromGroup, + XercesGroupInfo* const toGroup, + ComplexTypeInfo* const typeInfo); + + void copyAttGroupAttributes(const DOMElement* const elem, + XercesAttGroupInfo* const fromAttGroup, + XercesAttGroupInfo* const toAttGroup, + ComplexTypeInfo* const typeInfo); + + void checkForEmptyTargetNamespace(const DOMElement* const elem); + + /** + * Attribute wild card intersection. + * + * Note: + * The first parameter will be the result of the intersection, so + * we need to make sure that first parameter is a copy of the + * actual attribute definition we need to intersect with. + * + * What we need to wory about is: type, defaultType, namespace, + * and URI. All remaining data members should be the same. + */ + void attWildCardIntersection(SchemaAttDef* const resultWildCart, + const SchemaAttDef* const toCompareWildCard); + + /** + * Attribute wild card union. + * + * Note: + * The first parameter will be the result of the union, so + * we need to make sure that first parameter is a copy of the + * actual attribute definition we need to intersect with. + * + * What we need to wory about is: type, defaultType, namespace, + * and URI. All remaining data members should be the same. + */ + void attWildCardUnion(SchemaAttDef* const resultWildCart, + const SchemaAttDef* const toCompareWildCard); + + void copyWildCardData(const SchemaAttDef* const srcWildCard, + SchemaAttDef* const destWildCard); + + /** + * Check that the attributes of a type derived by restriction satisfy + * the constraints of derivation valid restriction + */ + void checkAttDerivationOK(const DOMElement* const elem, + const ComplexTypeInfo* const baseTypeInfo, + const ComplexTypeInfo* const childTypeInfo); + void checkAttDerivationOK(const DOMElement* const elem, + const XercesAttGroupInfo* const baseAttGrpInfo, + const XercesAttGroupInfo* const childAttGrpInfo); + + /** + * Check whether a namespace value is valid with respect to wildcard + * constraint + */ + bool wildcardAllowsNamespace(const SchemaAttDef* const baseAttWildCard, + const unsigned int nameURI); + + /** + * Check whether a namespace constraint is an intensional subset of + * another namespace constraint + */ + bool isWildCardSubset(const SchemaAttDef* const baseAttWildCard, + const SchemaAttDef* const childAttWildCard); + + bool openRedefinedSchema(const DOMElement* const redefineElem); + + /** + * The purpose of this method is twofold: + * 1. To find and appropriately modify all information items + * in redefinedSchema with names that are redefined by children of + * redefineElem. + * 2. To make sure the redefine element represented by + * redefineElem is valid as far as content goes and with regard to + * properly referencing components to be redefined. + * + * No traversing is done here! + * This method also takes actions to find and, if necessary, modify + * the names of elements in 's in the schema that's being + * redefined. + */ + void renameRedefinedComponents(const DOMElement* const redefineElem, + SchemaInfo* const redefiningSchemaInfo, + SchemaInfo* const redefinedSchemaInfo); + + /** + * This method returns true if the redefine component is valid, and if + * it was possible to revise it correctly. + */ + bool validateRedefineNameChange(const DOMElement* const redefineChildElem, + const XMLCh* const redefineChildElemName, + const XMLCh* const redefineChildDeclName, + const int redefineNameCounter, + SchemaInfo* const redefiningSchemaInfo); + + /** + * This function looks among the children of 'redefineChildElem' for a + * component of type 'redefineChildComponentName'. If it finds one, it + * evaluates whether its ref attribute contains a reference to + * 'refChildTypeName'. If it does, it returns 1 + the value returned by + * calls to itself on all other children. In all other cases it returns + * 0 plus the sum of the values returned by calls to itself on + * redefineChildElem's children. It also resets the value of ref so that + * it will refer to the renamed type from the schema being redefined. + */ + int changeRedefineGroup(const DOMElement* const redefineChildElem, + const XMLCh* const redefineChildComponentName, + const XMLCh* const redefineChildTypeName, + const int redefineNameCounter); + + /** This simple function looks for the first occurrence of a + * 'redefineChildTypeName' item in the redefined schema and appropriately + * changes the value of its name. If it turns out that what we're looking + * for is in a though, then we just rename it--and it's + * reference--to be the same. + */ + void fixRedefinedSchema(const DOMElement* const elem, + SchemaInfo* const redefinedSchemaInfo, + const XMLCh* const redefineChildComponentName, + const XMLCh* const redefineChildTypeName, + const int redefineNameCounter); + + void getRedefineNewTypeName(const XMLCh* const oldTypeName, + const int redefineCounter, + XMLBuffer& newTypeName); + + /** + * This purpose of this method is threefold: + * 1. To extract the schema information of included/redefined schema. + * 2. Rename redefined components. + * 3. Process components of included/redefined schemas + */ + void preprocessRedefineInclude(SchemaInfo* const currSchemaInfo); + + /** + * Update the list of valid substitution groups in the case of circular + * import. + */ + void updateCircularSubstitutionList(SchemaInfo* const aSchemaInfo); + + void processKeyRefFor(SchemaInfo* const aSchemaInfo, + ValueVectorOf* const infoList); + + void processAttValue(const XMLCh* const attVal, XMLBuffer& aBuf); + + // routine to generate synthetic annotations + XSAnnotation* generateSyntheticAnnotation(const DOMElement* const elem + , ValueVectorOf* nonXSAttList); + + // routine to validate annotations + void validateAnnotations(); + + // ----------------------------------------------------------------------- + // Private constants + // ----------------------------------------------------------------------- + enum + { + ES_Block + , C_Block + , S_Final + , EC_Final + , ECS_Final + }; + + enum ExceptionCodes + { + NoException = 0, + InvalidComplexTypeInfo = 1, + RecursingElement = 2 + }; + + enum + { + Elem_Def_Qualified = 1, + Attr_Def_Qualified = 2 + }; + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fFullConstraintChecking; + int fTargetNSURI; + int fEmptyNamespaceURI; + unsigned int fCurrentScope; + unsigned int fScopeCount; + unsigned int fAnonXSTypeCount; + XMLSize_t fCircularCheckIndex; + const XMLCh* fTargetNSURIString; + DatatypeValidatorFactory* fDatatypeRegistry; + GrammarResolver* fGrammarResolver; + SchemaGrammar* fSchemaGrammar; + XMLEntityHandler* fEntityHandler; + XMLErrorReporter* fErrorReporter; + XMLStringPool* fURIStringPool; + XMLStringPool* fStringPool; + XMLBuffer fBuffer; + XMLScanner* fScanner; + RefHashTableOf* fAttributeDeclRegistry; + RefHashTableOf* fComplexTypeRegistry; + RefHashTableOf* fGroupRegistry; + RefHashTableOf* fAttGroupRegistry; + RefHashTableOf* fIC_ElementsNS; + RefHashTableOf* fPreprocessedNodes; + SchemaInfo* fSchemaInfo; + XercesGroupInfo* fCurrentGroupInfo; + XercesAttGroupInfo* fCurrentAttGroupInfo; + ComplexTypeInfo* fCurrentComplexType; + ValueVectorOf* fCurrentTypeNameStack; + ValueVectorOf* fCurrentGroupStack; + ValueVectorOf* fIC_Elements; + ValueVectorOf* fDeclStack; + ValueVectorOf** fGlobalDeclarations; + ValueVectorOf* fNonXSAttList; + ValueVectorOf* fImportedNSList; + RefHashTableOf, PtrHasher>* fIC_NodeListNS; + RefHash2KeysTableOf* fNotationRegistry; + RefHash2KeysTableOf* fRedefineComponents; + RefHash2KeysTableOf* fIdentityConstraintNames; + RefHash2KeysTableOf* fValidSubstitutionGroups; + RefHash2KeysTableOf* fSchemaInfoList; + RefHash2KeysTableOf* fCachedSchemaInfoList; + XSDDOMParser* fParser; + XSDErrorReporter fXSDErrorReporter; + XSDLocator* fLocator; + MemoryManager* fMemoryManager; + MemoryManager* fGrammarPoolMemoryManager; + XSAnnotation* fAnnotation; + GeneralAttributeCheck fAttributeCheck; + + friend class GeneralAttributeCheck; + friend class NamespaceScopeManager; +}; + + +// --------------------------------------------------------------------------- +// TraverseSchema: Helper methods +// --------------------------------------------------------------------------- +inline const XMLCh* TraverseSchema::getPrefix(const XMLCh* const rawName) { + + int colonIndex = XMLString::indexOf(rawName, chColon); + + if (colonIndex == -1 || colonIndex == 0) { + return XMLUni::fgZeroLenString; + } + + fBuffer.set(rawName, colonIndex); + + return fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); +} + +inline const XMLCh* TraverseSchema::getLocalPart(const XMLCh* const rawName) { + + int colonIndex = XMLString::indexOf(rawName, chColon); + XMLSize_t rawNameLen = XMLString::stringLen(rawName); + + if (XMLSize_t(colonIndex + 1) == rawNameLen) { + return XMLUni::fgZeroLenString; + } + + if (colonIndex == -1) { + fBuffer.set(rawName, rawNameLen); + } + else { + + fBuffer.set(rawName + colonIndex + 1, rawNameLen - colonIndex - 1); + } + + return fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); +} + +inline void +TraverseSchema::checkForEmptyTargetNamespace(const DOMElement* const elem) { + + const XMLCh* targetNS = getElementAttValue(elem, SchemaSymbols::fgATT_TARGETNAMESPACE); + + if (targetNS && !*targetNS) { + reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidTargetNSValue); + } +} + +inline bool TraverseSchema::isBaseFromAnotherSchema(const XMLCh* const baseURI) +{ + if (!XMLString::equals(baseURI,fTargetNSURIString) + && !XMLString::equals(baseURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) + && (baseURI && *baseURI)) { + //REVISIT, !!!! a hack: for schema that has no + //target namespace, e.g. personal-schema.xml + return true; + } + + return false; +} + +inline bool TraverseSchema::isAttrOrAttrGroup(const DOMElement* const elem) { + + const XMLCh* elementName = elem->getLocalName(); + + if (XMLString::equals(elementName, SchemaSymbols::fgELT_ATTRIBUTE) || + XMLString::equals(elementName, SchemaSymbols::fgELT_ATTRIBUTEGROUP) || + XMLString::equals(elementName, SchemaSymbols::fgELT_ANYATTRIBUTE)) { + return true; + } + + return false; +} + +inline const XMLCh* TraverseSchema::genAnonTypeName(const XMLCh* const prefix) { + + XMLCh anonCountStr[16]; // a count of 15 digits should be enough + + XMLString::sizeToText(fAnonXSTypeCount++, anonCountStr, 15, 10, fMemoryManager); + fBuffer.set(prefix); + fBuffer.append(anonCountStr); + + return fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); +} + +inline void TraverseSchema::popCurrentTypeNameStack() { + + XMLSize_t stackSize = fCurrentTypeNameStack->size(); + + if (stackSize != 0) { + fCurrentTypeNameStack->removeElementAt(stackSize - 1); + } +} + +inline void +TraverseSchema::copyWildCardData(const SchemaAttDef* const srcWildCard, + SchemaAttDef* const destWildCard) { + + destWildCard->getAttName()->setURI(srcWildCard->getAttName()->getURI()); + destWildCard->setType(srcWildCard->getType()); + destWildCard->setDefaultType(srcWildCard->getDefaultType()); +} + +inline void TraverseSchema::getRedefineNewTypeName(const XMLCh* const oldTypeName, + const int redefineCounter, + XMLBuffer& newTypeName) { + + newTypeName.set(oldTypeName); + + for (int i=0; i < redefineCounter; i++) { + newTypeName.append(SchemaSymbols::fgRedefIdentifier); + } +} + +inline bool TraverseSchema::isImportingNS(const int namespaceURI) { + + if (!fImportedNSList) + return false; + + return (fImportedNSList->containsElement(namespaceURI)); +} + +inline void TraverseSchema::addImportedNS(const int namespaceURI) { + + if (!fImportedNSList) { + fImportedNSList = new (fMemoryManager) ValueVectorOf(4, fMemoryManager); + } + + if (!fImportedNSList->containsElement(namespaceURI)) + fImportedNSList->addElement(namespaceURI); +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file TraverseSchema.hpp + */ diff --git a/include/xercesc/validators/schema/XMLSchemaDescriptionImpl.cpp b/include/xercesc/validators/schema/XMLSchemaDescriptionImpl.cpp new file mode 100644 index 0000000..3369272 --- /dev/null +++ b/include/xercesc/validators/schema/XMLSchemaDescriptionImpl.cpp @@ -0,0 +1,235 @@ +/* + * 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: XMLSchemaDescriptionImpl.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XMLSchemaDescriptionImpl: constructor and destructor +// --------------------------------------------------------------------------- +XMLSchemaDescriptionImpl::XMLSchemaDescriptionImpl(const XMLCh* const targetNamespace + , MemoryManager* const memMgr) +:XMLSchemaDescription(memMgr) +,fContextType(CONTEXT_UNKNOWN) +,fNamespace(0) +,fLocationHints(0) +,fTriggeringComponent(0) +,fEnclosingElementName(0) +,fAttributes(0) +{ + if (targetNamespace) + fNamespace = XMLString::replicate(targetNamespace, memMgr); + + + fLocationHints = new (memMgr) RefArrayVectorOf(4, true, memMgr); + + /*** + fAttributes + ***/ +} + +XMLSchemaDescriptionImpl::~XMLSchemaDescriptionImpl() +{ + if (fNamespace) + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fNamespace); + + if (fLocationHints) + delete fLocationHints; + + if (fTriggeringComponent) + delete fTriggeringComponent; + + if (fEnclosingElementName) + delete fEnclosingElementName; + +} + +const XMLCh* XMLSchemaDescriptionImpl::getGrammarKey() const +{ + return getTargetNamespace(); +} + +XMLSchemaDescription::ContextType XMLSchemaDescriptionImpl::getContextType() const +{ + return fContextType; +} + +const XMLCh* XMLSchemaDescriptionImpl::getTargetNamespace() const +{ + return fNamespace; +} + +const RefArrayVectorOf* XMLSchemaDescriptionImpl::getLocationHints() const +{ + return fLocationHints; +} + +const QName* XMLSchemaDescriptionImpl::getTriggeringComponent() const +{ + return fTriggeringComponent; +} + +const QName* XMLSchemaDescriptionImpl::getEnclosingElementName() const +{ + return fEnclosingElementName; +} + +const XMLAttDef* XMLSchemaDescriptionImpl::getAttributes() const +{ + return fAttributes; +} + +void XMLSchemaDescriptionImpl::setContextType(ContextType type) +{ + fContextType = type; +} + +void XMLSchemaDescriptionImpl::setTargetNamespace(const XMLCh* const newNamespace) +{ + if (fNamespace) { + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fNamespace); + fNamespace = 0; + } + + fNamespace = XMLString::replicate(newNamespace, XMLGrammarDescription::getMemoryManager()); +} + +void XMLSchemaDescriptionImpl::setLocationHints(const XMLCh* const hint) +{ + fLocationHints->addElement(XMLString::replicate(hint, XMLGrammarDescription::getMemoryManager())); +} + +void XMLSchemaDescriptionImpl::setTriggeringComponent(QName* const trigComponent) +{ + if ( fTriggeringComponent) { + delete fTriggeringComponent; + fTriggeringComponent = 0; + } + + fTriggeringComponent = new (trigComponent->getMemoryManager()) QName(*trigComponent); + +} + +void XMLSchemaDescriptionImpl::setEnclosingElementName(QName* const encElement) +{ + if (fEnclosingElementName) { + delete fEnclosingElementName; + fEnclosingElementName = 0; + } + + fEnclosingElementName = new (encElement->getMemoryManager()) QName(*encElement); + +} + +void XMLSchemaDescriptionImpl::setAttributes(XMLAttDef* const attDefs) +{ + // XMLAttDef is part of the grammar that this description refers to + // so we reference to it instead of adopting/owning/cloning. + fAttributes = attDefs; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XMLSchemaDescriptionImpl) + +void XMLSchemaDescriptionImpl::serialize(XSerializeEngine& serEng) +{ + XMLSchemaDescription::serialize(serEng); + + if (serEng.isStoring()) + { + serEng<<(int)fContextType; + serEng.writeString(fNamespace); + + /*** + * + * Serialize RefArrayVectorOf* fLocationHints; + * + ***/ + XTemplateSerializer::storeObject(fLocationHints, serEng); + + QName* tempQName = (QName*)fTriggeringComponent; + serEng<>i; + + fContextType = (ContextType)i; + + //the original fNamespace which came from the ctor needs deallocated + if (fNamespace) + { + XMLGrammarDescription::getMemoryManager()->deallocate((void*)fNamespace); + } + serEng.readString((XMLCh*&)fNamespace); + + /*** + * + * Deserialize RefArrayVectorOf fLocationHints + * + ***/ + XTemplateSerializer::loadObject(&fLocationHints, 4, true, serEng); + + QName* tempQName; + serEng>>tempQName; + fTriggeringComponent = tempQName; + + serEng>>tempQName; + fEnclosingElementName = tempQName; + + XMLAttDef* tempAttDef; + serEng>>tempAttDef; + fAttributes=tempAttDef; + + } + +} + +XMLSchemaDescriptionImpl::XMLSchemaDescriptionImpl(MemoryManager* const memMgr) +:XMLSchemaDescription(memMgr) +,fContextType(CONTEXT_UNKNOWN) +,fNamespace(0) +,fLocationHints(0) +,fTriggeringComponent(0) +,fEnclosingElementName(0) +,fAttributes(0) +{ +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp b/include/xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp new file mode 100644 index 0000000..96b40c4 --- /dev/null +++ b/include/xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp @@ -0,0 +1,185 @@ +/* + * 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: XMLSchemaDescriptionImpl.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XMLSCHEMADESCRIPTIONIMPL_HPP) +#define XERCESC_INCLUDE_GUARD_XMLSCHEMADESCRIPTIONIMPL_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLAttDefs; + +class XMLPARSER_EXPORT XMLSchemaDescriptionImpl : public XMLSchemaDescription +{ +public : + // ----------------------------------------------------------------------- + /** @name constructor and destructor */ + // ----------------------------------------------------------------------- + //@{ + XMLSchemaDescriptionImpl( + const XMLCh* const targetNamespace + , MemoryManager* const memMgr + ); + + ~XMLSchemaDescriptionImpl(); + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of GrammarDescription Interface */ + // ----------------------------------------------------------------------- + //@{ + /** + * getGrammarKey + * + */ + virtual const XMLCh* getGrammarKey() const; + //@} + + // ----------------------------------------------------------------------- + /** @name Implementation of SchemaDescription Interface */ + // ----------------------------------------------------------------------- + //@{ + + /** + * getContextType + * + */ + virtual ContextType getContextType() const; + + /** + * getTargetNamespace + * + */ + virtual const XMLCh* getTargetNamespace() const; + + /** + * getLocationHints + * + */ + virtual const RefArrayVectorOf* getLocationHints() const; + + /** + * getTriggeringComponent + * + */ + virtual const QName* getTriggeringComponent() const; + + /** + * getenclosingElementName + * + */ + virtual const QName* getEnclosingElementName() const; + + /** + * getAttributes + * + */ + virtual const XMLAttDef* getAttributes() const; + + /** + * setContextType + * + */ + virtual void setContextType(ContextType); + + /** + * setTargetNamespace + * + */ + virtual void setTargetNamespace(const XMLCh* const); + + /** + * setLocationHints + * + */ + virtual void setLocationHints(const XMLCh* const); + + /** + * setTriggeringComponent + * + */ + virtual void setTriggeringComponent(QName* const); + + /** + * getenclosingElementName + * + */ + virtual void setEnclosingElementName(QName* const); + + /** + * setAttributes + * + */ + virtual void setAttributes(XMLAttDef* const); + //@} + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XMLSchemaDescriptionImpl) + + XMLSchemaDescriptionImpl(MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager); + +private : + // ----------------------------------------------------------------------- + /** name Unimplemented copy constructor and operator= */ + // ----------------------------------------------------------------------- + //@{ + XMLSchemaDescriptionImpl(const XMLSchemaDescriptionImpl& ); + XMLSchemaDescriptionImpl& operator=(const XMLSchemaDescriptionImpl& ); + //@} + + // ----------------------------------------------------------------------- + // Private data members + // + // All data member in this implementation are owned to out survive + // parser. Except for fNamespace which is replicated upon set, the + // rest shall be created by the embedded memoryManager. + // + // fContextType + // + // fNamespace owned + // + // fLocationHints owned + // + // fTriggeringComponent owned + // + // fEnclosingElementName owned + // + // fAttributes referenced + // + // ----------------------------------------------------------------------- + + XMLSchemaDescription::ContextType fContextType; + const XMLCh* fNamespace; + RefArrayVectorOf* fLocationHints; + const QName* fTriggeringComponent; + const QName* fEnclosingElementName; + const XMLAttDef* fAttributes; + +}; + + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/XSDDOMParser.cpp b/include/xercesc/validators/schema/XSDDOMParser.cpp new file mode 100644 index 0000000..91d46cf --- /dev/null +++ b/include/xercesc/validators/schema/XSDDOMParser.cpp @@ -0,0 +1,524 @@ +/* + * 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: XSDDOMParser.cpp 729944 2008-12-29 17:03:32Z amassari $ + */ + + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSDDOMParser: Constructors and Destructor +// --------------------------------------------------------------------------- +XSDDOMParser::XSDDOMParser( XMLValidator* const valToAdopt + , MemoryManager* const manager + , XMLGrammarPool* const gramPool): + XercesDOMParser(valToAdopt, manager, gramPool) + , fSawFatal(false) + , fAnnotationDepth(-1) + , fInnerAnnotationDepth(-1) + , fDepth(-1) + , fUserErrorReporter(0) + , fUserEntityHandler(0) + , fURIs(0) + , fAnnotationBuf(1023, manager) + +{ + fURIs = new (manager) ValueVectorOf(16, manager); + fXSDErrorReporter.setErrorReporter(this); + setValidationScheme(XercesDOMParser::Val_Never); + setDoNamespaces(true); +} + + +XSDDOMParser::~XSDDOMParser() +{ + delete fURIs; +} + + +// --------------------------------------------------------------------------- +// XSDDOMParser: Helper methods +// --------------------------------------------------------------------------- +DOMElement* XSDDOMParser::createElementNSNode(const XMLCh *namespaceURI, + const XMLCh *qualifiedName) +{ + ReaderMgr::LastExtEntityInfo lastInfo; + ((ReaderMgr*) fScanner->getLocator())->getLastExtEntityInfo(lastInfo); + + return getDocument()->createElementNS(namespaceURI, qualifiedName, + lastInfo.lineNumber, lastInfo.colNumber); +} + + +void XSDDOMParser::startAnnotation( const XMLElementDecl& elemDecl + , const RefVectorOf& attrList + , const XMLSize_t attrCount) +{ + fAnnotationBuf.append(chOpenAngle); + fAnnotationBuf.append(elemDecl.getFullName()); + fAnnotationBuf.append(chSpace); + + // attributes are a bit of a pain. To get this right, we have to keep track + // of the namespaces we've seen declared, then examine the namespace context + // for other namespaces so that we can also include them. + // optimized for simplicity and the case that not many + // namespaces are declared on this annotation... + fURIs->removeAllElements(); + for (XMLSize_t i=0; i < attrCount; i++) { + + const XMLAttr* oneAttrib = attrList.elementAt(i); + const XMLCh* attrValue = oneAttrib->getValue(); + + if (XMLString::equals(oneAttrib->getName(), XMLUni::fgXMLNSString)) + fURIs->addElement(fScanner->getPrefixId(XMLUni::fgZeroLenString)); + else if (!XMLString::compareNString(oneAttrib->getQName(), XMLUni::fgXMLNSColonString, 6)) + fURIs->addElement(fScanner->getPrefixId(oneAttrib->getName())); + + fAnnotationBuf.append(oneAttrib->getQName()); + fAnnotationBuf.append(chEqual); + fAnnotationBuf.append(chDoubleQuote); + fAnnotationBuf.append(attrValue); + fAnnotationBuf.append(chDoubleQuote); + fAnnotationBuf.append(chSpace); + } + + // now we have to look through currently in-scope namespaces to see what + // wasn't declared here + ValueVectorOf* namespaceContext = fScanner->getNamespaceContext(); + for (XMLSize_t j=0; j < namespaceContext->size(); j++) + { + unsigned int prefId = namespaceContext->elementAt(j)->fPrefId; + + if (!fURIs->containsElement(prefId)) { + + const XMLCh* prefix = fScanner->getPrefixForId(prefId); + + if (XMLString::equals(prefix, XMLUni::fgZeroLenString)) { + fAnnotationBuf.append(XMLUni::fgXMLNSString); + } + else { + fAnnotationBuf.append(XMLUni::fgXMLNSColonString); + fAnnotationBuf.append(prefix); + } + + fAnnotationBuf.append(chEqual); + fAnnotationBuf.append(chDoubleQuote); + fAnnotationBuf.append(fScanner->getURIText(namespaceContext->elementAt(j)->fURIId)); + fAnnotationBuf.append(chDoubleQuote); + fAnnotationBuf.append(chSpace); + + fURIs->addElement(prefId); + } + } + + fAnnotationBuf.append(chCloseAngle); + fAnnotationBuf.append(chLF); +} + +void XSDDOMParser::startAnnotationElement( const XMLElementDecl& elemDecl + , const RefVectorOf& attrList + , const XMLSize_t attrCount) +{ + fAnnotationBuf.append(chOpenAngle); + fAnnotationBuf.append(elemDecl.getFullName()); + //fAnnotationBuf.append(chSpace); + + for(XMLSize_t i=0; i < attrCount; i++) { + + const XMLAttr* oneAttr = attrList.elementAt(i); + fAnnotationBuf.append(chSpace); + fAnnotationBuf.append(oneAttr ->getQName()); + fAnnotationBuf.append(chEqual); + fAnnotationBuf.append(chDoubleQuote); + fAnnotationBuf.append(oneAttr->getValue()); + fAnnotationBuf.append(chDoubleQuote); + } + + fAnnotationBuf.append(chCloseAngle); +} + +void XSDDOMParser::endAnnotationElement( const XMLElementDecl& elemDecl + , bool complete) +{ + if (complete) + { + fAnnotationBuf.append(chLF); + fAnnotationBuf.append(chOpenAngle); + fAnnotationBuf.append(chForwardSlash); + fAnnotationBuf.append(elemDecl.getFullName()); + fAnnotationBuf.append(chCloseAngle); + + // note that this is always called after endElement on 's + // child and before endElement on annotation. + // hence, we must make this the child of the current + // parent's only child. + DOMTextImpl *node = (DOMTextImpl *)fDocument->createTextNode(fAnnotationBuf.getRawBuffer()); + fCurrentNode->appendChild(node); + fAnnotationBuf.reset(); + } + else //capturing character calls + { + fAnnotationBuf.append(chOpenAngle); + fAnnotationBuf.append(chForwardSlash); + fAnnotationBuf.append(elemDecl.getFullName()); + fAnnotationBuf.append(chCloseAngle); + } +} + + +// --------------------------------------------------------------------------- +// XSDDOMParser: Setter methods +// --------------------------------------------------------------------------- +void XSDDOMParser::setUserErrorReporter(XMLErrorReporter* const errorReporter) +{ + fUserErrorReporter = errorReporter; + fScanner->setErrorReporter(this); +} + +void XSDDOMParser::setUserEntityHandler(XMLEntityHandler* const entityHandler) +{ + fUserEntityHandler = entityHandler; + fScanner->setEntityHandler(this); +} + + +// --------------------------------------------------------------------------- +// XSDDOMParser: Implementation of the XMLDocumentHandler interface +// --------------------------------------------------------------------------- +void XSDDOMParser::startElement( const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot) +{ + fDepth++; + + // while it is true that non-whitespace character data + // may only occur in appInfo or documentation + // elements, it's certainly legal for comments and PI's to + // occur as children of annotation; we need + // to account for these here. + if (fAnnotationDepth == -1) + { + if (XMLString::equals(elemDecl.getBaseName(), SchemaSymbols::fgELT_ANNOTATION) && + XMLString::equals(getURIText(urlId), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) + { + + fAnnotationDepth = fDepth; + startAnnotation(elemDecl, attrList, attrCount); + } + } + else if (fDepth == fAnnotationDepth+1) + { + fInnerAnnotationDepth = fDepth; + startAnnotationElement(elemDecl, attrList, attrCount); + } + else + { + startAnnotationElement(elemDecl, attrList, attrCount); + if(isEmpty) + endElement(elemDecl, urlId, isRoot, elemPrefix); + // avoid falling through; don't call startElement in this case + return; + } + + DOMElement *elem; + if (urlId != fScanner->getEmptyNamespaceId()) //TagName has a prefix + { + if (elemPrefix && *elemPrefix) + { + XMLBufBid elemQName(&fBufMgr); + elemQName.set(elemPrefix); + elemQName.append(chColon); + elemQName.append(elemDecl.getBaseName()); + elem = createElementNSNode( + fScanner->getURIText(urlId), elemQName.getRawBuffer()); + } + else { + elem = createElementNSNode( + fScanner->getURIText(urlId), elemDecl.getBaseName()); + } + } + else { + elem = createElementNSNode(0, elemDecl.getBaseName()); + } + + DOMElementImpl *elemImpl = (DOMElementImpl *) elem; + for (XMLSize_t index = 0; index < attrCount; ++index) + { + const XMLAttr* oneAttrib = attrList.elementAt(index); + unsigned int attrURIId = oneAttrib->getURIId(); + const XMLCh* namespaceURI = 0; + + //for xmlns=... + if (XMLString::equals(oneAttrib->getName(), XMLUni::fgXMLNSString)) + attrURIId = fScanner->getXMLNSNamespaceId(); + + //TagName has a prefix + if (attrURIId != fScanner->getEmptyNamespaceId()) + namespaceURI = fScanner->getURIText(attrURIId); //get namespaceURI + + // revisit. Optimize to init the named node map to the + // right size up front. + DOMAttrImpl *attr = (DOMAttrImpl *) + fDocument->createAttributeNS(namespaceURI, oneAttrib->getQName()); + attr->setValue(oneAttrib -> getValue()); + DOMNode* remAttr = elemImpl->setAttributeNodeNS(attr); + if (remAttr) + remAttr->release(); + + // Attributes of type ID. If this is one, add it to the hashtable of IDs + // that is constructed for use by GetElementByID(). + if (oneAttrib->getType()==XMLAttDef::ID) + { + if (fDocument->fNodeIDMap == 0) + fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument); + fDocument->fNodeIDMap->add(attr); + attr->fNode.isIdAttr(true); + } + + attr->setSpecified(oneAttrib->getSpecified()); + } + + // set up the default attributes + if (elemDecl.hasAttDefs()) + { + XMLAttDefList* defAttrs = &elemDecl.getAttDefList(); + XMLAttDef* attr = 0; + DOMAttrImpl * insertAttr = 0; + + for (XMLSize_t i=0; igetAttDefCount(); i++) + { + attr = &defAttrs->getAttDef(i); + + const XMLAttDef::DefAttTypes defType = attr->getDefaultType(); + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + // DOM Level 2 wants all namespace declaration attributes + // to be bound to "http://www.w3.org/2000/xmlns/" + // So as long as the XML parser doesn't do it, it needs to + // done here. + const XMLCh* qualifiedName = attr->getFullName(); + XMLBufBid bbPrefixQName(&fBufMgr); + XMLBuffer& prefixBuf = bbPrefixQName.getBuffer(); + int colonPos = -1; + unsigned int uriId = fScanner->resolveQName(qualifiedName, prefixBuf, ElemStack::Mode_Attribute, colonPos); + + const XMLCh* namespaceURI = 0; + if (XMLString::equals(qualifiedName, XMLUni::fgXMLNSString)) + uriId = fScanner->getXMLNSNamespaceId(); + + //TagName has a prefix + if (uriId != fScanner->getEmptyNamespaceId()) + namespaceURI = fScanner->getURIText(uriId); + + insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS( + namespaceURI, qualifiedName); + + DOMAttr* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr); + if (remAttr) + remAttr->release(); + + if (attr->getValue() != 0) + { + insertAttr->setValue(attr->getValue()); + insertAttr->setSpecified(false); + } + } + + insertAttr = 0; + attr->reset(); + } + } + + fCurrentParent->appendChild(elem); + fCurrentParent = elem; + fCurrentNode = elem; + fWithinElement = true; + + // If an empty element, do end right now (no endElement() will be called) + if (isEmpty) + endElement(elemDecl, urlId, isRoot, elemPrefix); +} + + + +void XSDDOMParser::endElement( const XMLElementDecl& elemDecl + , const unsigned int + , const bool + , const XMLCh* const) +{ + if(fAnnotationDepth > -1) + { + if (fInnerAnnotationDepth == fDepth) + { + fInnerAnnotationDepth = -1; + endAnnotationElement(elemDecl, false); + } + else if (fAnnotationDepth == fDepth) + { + fAnnotationDepth = -1; + endAnnotationElement(elemDecl, true); + } + else + { // inside a child of annotation + endAnnotationElement(elemDecl, false); + fDepth--; + return; + } + } + + fDepth--; + fCurrentNode = fCurrentParent; + fCurrentParent = fCurrentNode->getParentNode (); + + // If we've hit the end of content, clear the flag. + // + if (fCurrentParent == fDocument) + fWithinElement = false; +} + +void XSDDOMParser::docCharacters( const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection) +{ + // Ignore chars outside of content + if (!fWithinElement) + return; + + if (fInnerAnnotationDepth == -1) + { + if (!((ReaderMgr*) fScanner->getReaderMgr())->getCurrentReader()->isAllSpaces(chars, length)) + { + ReaderMgr::LastExtEntityInfo lastInfo; + fScanner->getReaderMgr()->getLastExtEntityInfo(lastInfo); + fXSLocator.setValues(lastInfo.systemId, lastInfo.publicId, lastInfo.lineNumber, lastInfo.colNumber); + fXSDErrorReporter.emitError(XMLValid::NonWSContent, XMLUni::fgValidityDomain, &fXSLocator); + } + } + // when it's within either of the 2 annotation subelements, characters are + // allowed and we need to store them. + else if (cdataSection == true) + { + fAnnotationBuf.append(XMLUni::fgCDataStart); + fAnnotationBuf.append(chars, length); + fAnnotationBuf.append(XMLUni::fgCDataEnd); + } + else + { + for(unsigned int i = 0; i < length; i++ ) + { + if(chars[i] == chAmpersand) + { + fAnnotationBuf.append(chAmpersand); + fAnnotationBuf.append(XMLUni::fgAmp); + fAnnotationBuf.append(chSemiColon); + } + else if (chars[i] == chOpenAngle) + { + fAnnotationBuf.append(chAmpersand); + fAnnotationBuf.append(XMLUni::fgLT); + fAnnotationBuf.append(chSemiColon); + } + else { + fAnnotationBuf.append(chars[i]); + } + } + } +} + +void XSDDOMParser::docComment(const XMLCh* const comment) +{ + if (fAnnotationDepth > -1) + { + fAnnotationBuf.append(XMLUni::fgCommentString); + fAnnotationBuf.append(comment); + fAnnotationBuf.append(chDash); + fAnnotationBuf.append(chDash); + fAnnotationBuf.append(chCloseAngle); + } +} + +void XSDDOMParser::startEntityReference(const XMLEntityDecl&) +{ +} + +void XSDDOMParser::endEntityReference(const XMLEntityDecl&) +{ +} + +void XSDDOMParser::ignorableWhitespace( const XMLCh* const chars + , const XMLSize_t length + , const bool) +{ + // Ignore chars before the root element + if (!fWithinElement || !fIncludeIgnorableWhitespace) + return; + + if (fAnnotationDepth > -1) + fAnnotationBuf.append(chars, length); +} + +// --------------------------------------------------------------------------- +// XSDDOMParser: Implementation of the XMLErrorReporter interface +// --------------------------------------------------------------------------- +void XSDDOMParser::error(const unsigned int code + , const XMLCh* const msgDomain + , const XMLErrorReporter::ErrTypes errType + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum) +{ + if (errType >= XMLErrorReporter::ErrType_Fatal) + fSawFatal = true; + + if (fUserErrorReporter) + fUserErrorReporter->error(code, msgDomain, errType, errorText, + systemId, publicId, lineNum, colNum); +} + +InputSource* +XSDDOMParser::resolveEntity(XMLResourceIdentifier* resourceIdentifier) +{ + if (fUserEntityHandler) + return fUserEntityHandler->resolveEntity(resourceIdentifier); + + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/XSDDOMParser.hpp b/include/xercesc/validators/schema/XSDDOMParser.hpp new file mode 100644 index 0000000..70159b7 --- /dev/null +++ b/include/xercesc/validators/schema/XSDDOMParser.hpp @@ -0,0 +1,322 @@ +/* + * 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: XSDDOMParser.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSDDOMPARSER_HPP) +#define XERCESC_INCLUDE_GUARD_XSDDOMPARSER_HPP + + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMElement; +class XMLValidator; + + +/** + * This class is used to parse schema documents into DOM trees + */ +class PARSERS_EXPORT XSDDOMParser : public XercesDOMParser +{ +public : + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + /** @name Constructors and Destructor */ + //@{ + /** Construct a XSDDOMParser, with an optional validator + * + * Constructor with an instance of validator class to use for + * validation. If you don't provide a validator, a default one will + * be created for you in the scanner. + * + * @param gramPool Pointer to the grammar pool instance from + * external application. + * The parser does NOT own it. + * + * @param valToAdopt Pointer to the validator instance to use. The + * parser is responsible for freeing the memory. + */ + XSDDOMParser + ( + XMLValidator* const valToAdopt = 0 + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + , XMLGrammarPool* const gramPool = 0 + ); + + /** + * Destructor + */ + ~XSDDOMParser(); + + //@} + + // ----------------------------------------------------------------------- + // Implementation of the XMLDocumentHandler interface. + // ----------------------------------------------------------------------- + + /** @name Implementation of the XMLDocumentHandler interface. */ + //@{ + + /** Handle a start element event + * + * This method is used to report the start of an element. It is + * called at the end of the element, by which time all attributes + * specified are also parsed. A new DOM Element node is created + * along with as many attribute nodes as required. This new element + * is added appended as a child of the current node in the tree, and + * then replaces it as the current node (if the isEmpty flag is false.) + * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + * @param attrList A const reference to the object containing the + * list of attributes just scanned for this element. + * @param attrCount A count of number of attributes in the list + * specified by the parameter 'attrList'. + * @param isEmpty A flag indicating whether this is an empty element + * or not. If empty, then no endElement() call will + * be made. + * @param isRoot A flag indicating whether this element was the + * root element. + * @see DocumentHandler#startElement + */ + virtual void startElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , const bool isEmpty + , const bool isRoot + ); + + /** Handle and end of element event + * + * This method is used to indicate the end tag of an element. The + * DOM parser pops the current element off the top of the element + * stack, and make it the new current element. + * + * @param elemDecl A const reference to the object containing element + * declaration information. + * @param urlId An id referring to the namespace prefix, if + * namespaces setting is switched on. + * @param isRoot A flag indicating whether this element was the + * root element. + * @param elemPrefix A const pointer to a Unicode string containing + * the namespace prefix for this element. Applicable + * only when namespace processing is enabled. + */ + virtual void endElement + ( + const XMLElementDecl& elemDecl + , const unsigned int urlId + , const bool isRoot + , const XMLCh* const elemPrefix + ); + + /** Handle document character events + * + * This method is used to report all the characters scanned by the + * parser. This DOM implementation stores this data in the appropriate + * DOM node, creating one if necessary. + * + * @param chars A const pointer to a Unicode string representing the + * character data. + * @param length The length of the Unicode string returned in 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + */ + virtual void docCharacters + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + /** Handle a document comment event + * + * This method is used to report any comments scanned by the parser. + * A new comment node is created which stores this data. + * + * @param comment A const pointer to a null terminated Unicode + * string representing the comment text. + */ + virtual void docComment + ( + const XMLCh* const comment + ); + + /** Handle a start entity reference event + * + * This method is used to indicate the start of an entity reference. + * If the expand entity reference flag is true, then a new + * DOM Entity reference node is created. + * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void startEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** Handle and end of entity reference event + * + * This method is used to indicate that an end of an entity reference + * was just scanned. + * + * @param entDecl A const reference to the object containing the + * entity declaration information. + */ + virtual void endEntityReference + ( + const XMLEntityDecl& entDecl + ); + + /** Handle an ignorable whitespace vent + * + * This method is used to report all the whitespace characters, which + * are determined to be 'ignorable'. This distinction between characters + * is only made, if validation is enabled. + * + * Any whitespace before content is ignored. If the current node is + * already of type DOMNode::TEXT_NODE, then these whitespaces are + * appended, otherwise a new Text node is created which stores this + * data. Essentially all contiguous ignorable characters are collected + * in one node. + * + * @param chars A const pointer to a Unicode string representing the + * ignorable whitespace character data. + * @param length The length of the Unicode string 'chars'. + * @param cdataSection A flag indicating if the characters represent + * content from the CDATA section. + */ + virtual void ignorableWhitespace + ( + const XMLCh* const chars + , const XMLSize_t length + , const bool cdataSection + ); + + //@} + + // ----------------------------------------------------------------------- + // Get methods + // ----------------------------------------------------------------------- + bool getSawFatal() const; + + + // ----------------------------------------------------------------------- + // Set methods + // ----------------------------------------------------------------------- + void setUserErrorReporter(XMLErrorReporter* const errorReporter); + void setUserEntityHandler(XMLEntityHandler* const entityHandler); + + + // ----------------------------------------------------------------------- + // XMLErrorReporter interface + // ----------------------------------------------------------------------- + virtual void error + ( + const unsigned int errCode + , const XMLCh* const errDomain + , const ErrTypes type + , const XMLCh* const errorText + , const XMLCh* const systemId + , const XMLCh* const publicId + , const XMLFileLoc lineNum + , const XMLFileLoc colNum + ); + + // ----------------------------------------------------------------------- + // XMLEntityHandler interface + // ----------------------------------------------------------------------- + virtual InputSource* resolveEntity(XMLResourceIdentifier* resourceIdentifier); + +protected : + // ----------------------------------------------------------------------- + // Protected Helper methods + // ----------------------------------------------------------------------- + virtual DOMElement* createElementNSNode(const XMLCh *fNamespaceURI, + const XMLCh *qualifiedName); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XSDDOMParser(const XSDDOMParser&); + XSDDOMParser& operator=(const XSDDOMParser&); + + // ----------------------------------------------------------------------- + // Private Helper methods + // ----------------------------------------------------------------------- + void startAnnotation + ( + const XMLElementDecl& elemDecl + , const RefVectorOf& attrList + , const XMLSize_t attrCount + ); + void startAnnotationElement + ( + const XMLElementDecl& elemDecl + , const RefVectorOf& attrList + , const XMLSize_t attrCount + ); + void endAnnotationElement + ( + const XMLElementDecl& elemDecl + , bool complete + ); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fSawFatal; + int fAnnotationDepth; + int fInnerAnnotationDepth; + int fDepth; + XMLErrorReporter* fUserErrorReporter; + XMLEntityHandler* fUserEntityHandler; + ValueVectorOf* fURIs; + XMLBuffer fAnnotationBuf; + XSDErrorReporter fXSDErrorReporter; + XSDLocator fXSLocator; +}; + + +inline bool XSDDOMParser::getSawFatal() const +{ + return fSawFatal; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/XSDErrorReporter.cpp b/include/xercesc/validators/schema/XSDErrorReporter.cpp new file mode 100644 index 0000000..7657dd0 --- /dev/null +++ b/include/xercesc/validators/schema/XSDErrorReporter.cpp @@ -0,0 +1,179 @@ +/* + * 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. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local static data +// --------------------------------------------------------------------------- +static XMLMsgLoader* gErrMsgLoader = 0; +static XMLMsgLoader* gValidMsgLoader = 0; + +void XMLInitializer::initializeXSDErrorReporter() +{ + gErrMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain); + + if (!gErrMsgLoader) + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); + + gValidMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgValidityDomain); + + if (!gValidMsgLoader) + XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); +} + +void XMLInitializer::terminateXSDErrorReporter() +{ + delete gErrMsgLoader; + gErrMsgLoader = 0; + + delete gValidMsgLoader; + gValidMsgLoader = 0; +} + +// --------------------------------------------------------------------------- +// XSDErrorReporter: Constructors and Destructor +// --------------------------------------------------------------------------- +XSDErrorReporter::XSDErrorReporter(XMLErrorReporter* const errorReporter) : + fExitOnFirstFatal(false) + , fErrorReporter(errorReporter) +{ + +} + + +// --------------------------------------------------------------------------- +// XSDErrorReporter: Error reporting +// --------------------------------------------------------------------------- +void XSDErrorReporter::emitError(const unsigned int toEmit, + const XMLCh* const msgDomain, + const Locator* const aLocator) +{ + // Bump the error count if it is not a warning +// if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) +// incrementErrorCount(); + + // + // Load the message into alocal and replace any tokens found in + // the text. + // + const XMLSize_t msgSize = 1023; + XMLCh errText[msgSize + 1]; + XMLMsgLoader* msgLoader = gErrMsgLoader; + XMLErrorReporter::ErrTypes errType = XMLErrs::errorType((XMLErrs::Codes) toEmit); + + if (XMLString::equals(msgDomain, XMLUni::fgValidityDomain)) { + + errType = XMLValid::errorType((XMLValid::Codes) toEmit); + msgLoader = gValidMsgLoader; + } + + if (!msgLoader->loadMsg(toEmit, errText, msgSize)) + { + // Should probably load a default message here + } + + if (fErrorReporter) + fErrorReporter->error(toEmit, msgDomain, errType, errText, aLocator->getSystemId(), + aLocator->getPublicId(), aLocator->getLineNumber(), + aLocator->getColumnNumber()); + + // Bail out if its fatal an we are to give up on the first fatal error + if (errType == XMLErrorReporter::ErrType_Fatal && fExitOnFirstFatal) + throw (XMLErrs::Codes) toEmit; +} + +void XSDErrorReporter::emitError(const unsigned int toEmit, + const XMLCh* const msgDomain, + const Locator* const aLocator, + const XMLCh* const text1, + const XMLCh* const text2, + const XMLCh* const text3, + const XMLCh* const text4, + MemoryManager* const manager) +{ + // Bump the error count if it is not a warning +// if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning) +// incrementErrorCount(); + + // + // Load the message into alocal and replace any tokens found in + // the text. + // + const XMLSize_t maxChars = 2047; + XMLCh errText[maxChars + 1]; + XMLMsgLoader* msgLoader = gErrMsgLoader; + XMLErrorReporter::ErrTypes errType = XMLErrs::errorType((XMLErrs::Codes) toEmit); + + if (XMLString::equals(msgDomain, XMLUni::fgValidityDomain)) { + + errType = XMLValid::errorType((XMLValid::Codes) toEmit); + msgLoader = gValidMsgLoader; + } + + if (!msgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, manager)) + { + // Should probably load a default message here + } + + if (fErrorReporter) + fErrorReporter->error(toEmit, msgDomain, errType, errText, aLocator->getSystemId(), + aLocator->getPublicId(), aLocator->getLineNumber(), + aLocator->getColumnNumber()); + + // Bail out if its fatal an we are to give up on the first fatal error + if (errType == XMLErrorReporter::ErrType_Fatal && fExitOnFirstFatal) + throw (XMLErrs::Codes) toEmit; +} + +void XSDErrorReporter::emitError(const XMLException& except, + const Locator* const aLocator) +{ + const XMLCh* const errText = except.getMessage(); + const unsigned int toEmit = except.getCode(); + //Before the code was modified to call this routine it used to use + //the XMLErrs::DisplayErrorMessage error message, which is just {'0'} + //and that error message has errType of Error. So to be consistent + //with previous behaviour set the errType to be Error instead of + //getting the error type off of the exception. + //XMLErrorReporter::ErrTypes errType = XMLErrs::errorType((XMLErrs::Codes) toEmit); + XMLErrorReporter::ErrTypes errType = XMLErrorReporter::ErrType_Error; + + if (fErrorReporter) + fErrorReporter->error(toEmit, XMLUni::fgExceptDomain, errType, errText, aLocator->getSystemId(), + aLocator->getPublicId(), aLocator->getLineNumber(), + aLocator->getColumnNumber()); + + // Bail out if its fatal an we are to give up on the first fatal error + //if (errType == XMLErrorReporter::ErrType_Fatal && fExitOnFirstFatal) + // throw (XMLErrs::Codes) toEmit; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/XSDErrorReporter.hpp b/include/xercesc/validators/schema/XSDErrorReporter.hpp new file mode 100644 index 0000000..b9c7746 --- /dev/null +++ b/include/xercesc/validators/schema/XSDErrorReporter.hpp @@ -0,0 +1,115 @@ +/* + * 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: XSDErrorReporter.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSDERRORREPORTER_HPP) +#define XERCESC_INCLUDE_GUARD_XSDERRORREPORTER_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class Locator; +class XMLErrorReporter; + + +/** + * This class reports schema errors + */ +class VALIDATORS_EXPORT XSDErrorReporter : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors are hidden, only the virtual destructor is exposed + // ----------------------------------------------------------------------- + XSDErrorReporter(XMLErrorReporter* const errorReporter = 0); + + virtual ~XSDErrorReporter() + { + } + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getExitOnFirstFatal() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setErrorReporter(XMLErrorReporter* const errorReporter); + void setExitOnFirstFatal(const bool newValue); + + // ----------------------------------------------------------------------- + // Report error methods + // ----------------------------------------------------------------------- + void emitError(const unsigned int toEmit, + const XMLCh* const msgDomain, + const Locator* const aLocator); + void emitError(const unsigned int toEmit, + const XMLCh* const msgDomain, + const Locator* const aLocator, + const XMLCh* const text1, + const XMLCh* const text2 = 0, + const XMLCh* const text3 = 0, + const XMLCh* const text4 = 0, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + void emitError(const XMLException& except, + const Locator* const aLocator); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and destructor + // ----------------------------------------------------------------------- + XSDErrorReporter(const XSDErrorReporter&); + XSDErrorReporter& operator=(const XSDErrorReporter&); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fExitOnFirstFatal; + XMLErrorReporter* fErrorReporter; +}; + + +// --------------------------------------------------------------------------- +// XSDErrorReporter: Getter methods +// --------------------------------------------------------------------------- +inline bool XSDErrorReporter::getExitOnFirstFatal() const +{ + return fExitOnFirstFatal; +} + +// --------------------------------------------------------------------------- +// XSDErrorReporter: Setter methods +// --------------------------------------------------------------------------- +inline void XSDErrorReporter::setExitOnFirstFatal(const bool newValue) +{ + fExitOnFirstFatal = newValue; +} + +inline void XSDErrorReporter::setErrorReporter(XMLErrorReporter* const errorReporter) +{ + fErrorReporter = errorReporter; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/XSDLocator.cpp b/include/xercesc/validators/schema/XSDLocator.cpp new file mode 100644 index 0000000..ee45a4f --- /dev/null +++ b/include/xercesc/validators/schema/XSDLocator.cpp @@ -0,0 +1,57 @@ +/* + * 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: XSDLocator.cpp 672273 2008-06-27 13:57:00Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XSDLocator: Constructors and Destructor +// --------------------------------------------------------------------------- +XSDLocator::XSDLocator() : + fLineNo(0) + , fColumnNo(0) + , fSystemId(0) + , fPublicId(0) +{ + +} + + +// --------------------------------------------------------------------------- +// XSDLocator: Setter methods +// --------------------------------------------------------------------------- +void XSDLocator::setValues(const XMLCh* const systemId, + const XMLCh* const publicId, + const XMLFileLoc lineNo, + const XMLFileLoc columnNo) +{ + fLineNo = lineNo; + fColumnNo = columnNo; + fSystemId = systemId; + fPublicId = publicId; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/XSDLocator.hpp b/include/xercesc/validators/schema/XSDLocator.hpp new file mode 100644 index 0000000..0a21a36 --- /dev/null +++ b/include/xercesc/validators/schema/XSDLocator.hpp @@ -0,0 +1,141 @@ +/* + * 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: XSDLocator.hpp 672273 2008-06-27 13:57:00Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XSDLOCATOR_HPP) +#define XERCESC_INCLUDE_GUARD_XSDLOCATOR_HPP + +/** + * A Locator implementation + */ + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT XSDLocator: public XMemory, public Locator +{ +public: + + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + XSDLocator(); + + /** Destructor */ + virtual ~XSDLocator() + { + } + + //@} + + /** @name The locator interface */ + //@{ + /** + * Return the public identifier for the current document event. + *

This will be the public identifier + * @return A string containing the public identifier, or + * null if none is available. + * @see #getSystemId + */ + virtual const XMLCh* getPublicId() const; + + /** + * Return the system identifier for the current document event. + * + *

If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.

+ * + * @return A string containing the system identifier, or null + * if none is available. + * @see #getPublicId + */ + virtual const XMLCh* getSystemId() const; + + /** + * Return the line number where the current document event ends. + * Note that this is the line position of the first character + * after the text associated with the document event. + * @return The line number, or 0 if none is available. + * @see #getColumnNumber + */ + virtual XMLFileLoc getLineNumber() const; + + /** + * Return the column number where the current document event ends. + * Note that this is the column number of the first + * character after the text associated with the document + * event. The first column in a line is position 1. + * @return The column number, or 0 if none is available. + * @see #getLineNumber + */ + virtual XMLFileLoc getColumnNumber() const; + //@} + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setValues(const XMLCh* const systemId, + const XMLCh* const publicId, + const XMLFileLoc lineNo, const XMLFileLoc columnNo); + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and destructor + // ----------------------------------------------------------------------- + XSDLocator(const XSDLocator&); + XSDLocator& operator=(const XSDLocator&); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + XMLFileLoc fLineNo; + XMLFileLoc fColumnNo; + const XMLCh* fSystemId; + const XMLCh* fPublicId; +}; + +// --------------------------------------------------------------------------- +// XSDLocator: Getter methods +// --------------------------------------------------------------------------- +inline XMLFileLoc XSDLocator::getLineNumber() const +{ + return fLineNo; +} + +inline XMLFileLoc XSDLocator::getColumnNumber() const +{ + return fColumnNo; +} + +inline const XMLCh* XSDLocator::getPublicId() const +{ + return fPublicId; +} + +inline const XMLCh* XSDLocator::getSystemId() const +{ + return fSystemId; +} + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/XUtil.cpp b/include/xercesc/validators/schema/XUtil.cpp new file mode 100644 index 0000000..bc6f4dc --- /dev/null +++ b/include/xercesc/validators/schema/XUtil.cpp @@ -0,0 +1,125 @@ +/* + * 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: XUtil.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// Finds and returns the first child element node. +DOMElement* XUtil::getFirstChildElement(const DOMNode* const parent) +{ + // search for node + DOMNode* child = parent->getFirstChild(); + + while (child != 0) + { + if (child->getNodeType() == DOMNode::ELEMENT_NODE) + return (DOMElement*)child; + + child = child->getNextSibling(); + } + + // not found + return 0; +} + +// Finds and returns the first child node with the given name. +DOMElement* XUtil::getFirstChildElementNS(const DOMNode* const parent + , const XMLCh** const elemNames + , const XMLCh* const uriStr + , unsigned int length) +{ + // search for node + DOMNode* child = parent->getFirstChild(); + while (child != 0) + { + if (child->getNodeType() == DOMNode::ELEMENT_NODE) + { + for (unsigned int i = 0; i < length; i++) + { + if (XMLString::equals(child->getNamespaceURI(), uriStr) && + XMLString::equals(child->getLocalName(), elemNames[i])) + return (DOMElement*)child; + } + } + child = child->getNextSibling(); + } + + // not found + return 0; +} + +// Finds and returns the last child element node. +DOMElement* XUtil::getNextSiblingElement(const DOMNode* const node) +{ + // search for node + DOMNode* sibling = node->getNextSibling(); + + while (sibling != 0) + { + if (sibling->getNodeType() == DOMNode::ELEMENT_NODE) + return (DOMElement*)sibling; + + sibling = sibling->getNextSibling(); + } + + // not found + return 0; +} + +// Finds and returns the next sibling element node with the give name. +DOMElement* XUtil::getNextSiblingElementNS(const DOMNode* const node + , const XMLCh** const elemNames + , const XMLCh* const uriStr + , unsigned int length) +{ + // search for node + DOMNode* sibling = node->getNextSibling(); + while (sibling != 0) + { + if (sibling->getNodeType() == DOMNode::ELEMENT_NODE) + { + for (unsigned int i = 0; i < length; i++) + { + if (XMLString::equals(sibling->getNamespaceURI(), uriStr) && + XMLString::equals(sibling->getLocalName(), elemNames[i])) + return (DOMElement*)sibling; + } + } + sibling = sibling->getNextSibling(); + } + + // not found + return 0; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/XUtil.hpp b/include/xercesc/validators/schema/XUtil.hpp new file mode 100644 index 0000000..1a5380c --- /dev/null +++ b/include/xercesc/validators/schema/XUtil.hpp @@ -0,0 +1,71 @@ +/* + * 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: XUtil.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XUTIL_HPP) +#define XERCESC_INCLUDE_GUARD_XUTIL_HPP + +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class DOMNode; +class DOMElement; + +/** + * Some useful utility methods. + */ +class VALIDATORS_EXPORT XUtil +{ +public: + + // Finds and returns the first child element node. + static DOMElement* getFirstChildElement(const DOMNode* const parent); + + // Finds and returns the first child node with the given qualifiedname. + static DOMElement* getFirstChildElementNS(const DOMNode* const parent + , const XMLCh** const elemNames + , const XMLCh* const uriStr + , unsigned int length); + + // Finds and returns the next sibling element node. + static DOMElement* getNextSiblingElement(const DOMNode* const node); + + static DOMElement* getNextSiblingElementNS(const DOMNode* const node + , const XMLCh** const elemNames + , const XMLCh* const uriStr + , unsigned int length); + +private: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + + // This class cannot be instantiated. + XUtil() {}; + ~XUtil() {}; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/XercesAttGroupInfo.cpp b/include/xercesc/validators/schema/XercesAttGroupInfo.cpp new file mode 100644 index 0000000..ed2432a --- /dev/null +++ b/include/xercesc/validators/schema/XercesAttGroupInfo.cpp @@ -0,0 +1,182 @@ +/* + * 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: XercesAttGroupInfo.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XercesAttGroupInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesAttGroupInfo::XercesAttGroupInfo(MemoryManager* const manager) + : fTypeWithId(false) + , fNameId(0) + , fNamespaceId(0) + , fAttributes(0) + , fAnyAttributes(0) + , fCompleteWildCard(0) + , fMemoryManager(manager) +{ + +} + +XercesAttGroupInfo::XercesAttGroupInfo(unsigned int attGroupNameId, + unsigned int attGroupNamespaceId, + MemoryManager* const manager) + : fTypeWithId(false) + , fNameId(attGroupNameId) + , fNamespaceId(attGroupNamespaceId) + , fAttributes(0) + , fAnyAttributes(0) + , fCompleteWildCard(0) + , fMemoryManager(manager) +{ + +} + +XercesAttGroupInfo::~XercesAttGroupInfo() +{ + delete fAttributes; + delete fAnyAttributes; + delete fCompleteWildCard; +} + +bool XercesAttGroupInfo::containsAttribute(const XMLCh* const name, + const unsigned int uri) { + + if (fAttributes) { + + XMLSize_t attCount = fAttributes->size(); + + if (attCount) { + + for (XMLSize_t i=0; i < attCount; i++) { + + QName* attName = fAttributes->elementAt(i)->getAttName(); + + if (attName->getURI() == uri && + XMLString::equals(attName->getLocalPart(),name)) { + return true; + } + } + } + } + + return false; +} + +// --------------------------------------------------------------------------- +// XercesAttGroupInfo: Getter methods +// --------------------------------------------------------------------------- +const SchemaAttDef* XercesAttGroupInfo::getAttDef(const XMLCh* const baseName, + const int uriId) const { + + // If no list, then return a null + if (!fAttributes) + return 0; + + XMLSize_t attSize = fAttributes->size(); + + for (XMLSize_t i=0; ielementAt(i); + QName* attName = attDef->getAttName(); + + if (uriId == (int) attName->getURI() && + XMLString::equals(baseName, attName->getLocalPart())) { + + return attDef; + } + } + + return 0; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XercesAttGroupInfo) + +void XercesAttGroupInfo::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<* fAttributes; + * + ***/ + XTemplateSerializer::storeObject(fAttributes, serEng); + + /*** + * + * Serialize RefVectorOf* fAnyAttributes; + * + ***/ + XTemplateSerializer::storeObject(fAnyAttributes, serEng); + + serEng<>fTypeWithId; + serEng>>fNameId; + serEng>>fNamespaceId; + + /*** + * + * Deserialize RefVectorOf* fAttributes; + * + ***/ + XTemplateSerializer::loadObject(&fAttributes, 4, true, serEng); + + /*** + * + * Deserialize RefVectorOf* fAnyAttributes; + * + ***/ + + XTemplateSerializer::loadObject(&fAnyAttributes, 2, true, serEng); + + serEng>>fCompleteWildCard; + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file XercesAttGroupInfo.cpp + */ + + diff --git a/include/xercesc/validators/schema/XercesAttGroupInfo.hpp b/include/xercesc/validators/schema/XercesAttGroupInfo.hpp new file mode 100644 index 0000000..0c260cd --- /dev/null +++ b/include/xercesc/validators/schema/XercesAttGroupInfo.hpp @@ -0,0 +1,257 @@ +/* + * 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: XercesAttGroupInfo.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XERCESATTGROUPINFO_HPP) +#define XERCESC_INCLUDE_GUARD_XERCESATTGROUPINFO_HPP + + +/** + * The class act as a place holder to store attributeGroup information. + * + * The class is intended for internal use. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT XercesAttGroupInfo : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Public Constructors/Destructor + // ----------------------------------------------------------------------- + XercesAttGroupInfo + ( + unsigned int attGroupNameId + , unsigned int attGroupNamespaceId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~XercesAttGroupInfo(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool containsTypeWithId() const; + XMLSize_t attributeCount() const; + XMLSize_t anyAttributeCount() const; + unsigned int getNameId() const; + unsigned int getNamespaceId() const; + SchemaAttDef* attributeAt(const XMLSize_t index); + const SchemaAttDef* attributeAt(const XMLSize_t index) const; + SchemaAttDef* anyAttributeAt(const XMLSize_t index); + const SchemaAttDef* anyAttributeAt(const XMLSize_t index) const; + SchemaAttDef* getCompleteWildCard() const; + const SchemaAttDef* getAttDef(const XMLCh* const baseName, + const int uriId) const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setTypeWithId(const bool other); + void addAttDef(SchemaAttDef* const toAdd, const bool toClone = false); + void addAnyAttDef(SchemaAttDef* const toAdd, const bool toClone = false); + void setCompleteWildCard(SchemaAttDef* const toSet); + + // ----------------------------------------------------------------------- + // Query methods + // ----------------------------------------------------------------------- + bool containsAttribute(const XMLCh* const name, const unsigned int uri); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XercesAttGroupInfo) + XercesAttGroupInfo(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XercesAttGroupInfo(const XercesAttGroupInfo& elemInfo); + XercesAttGroupInfo& operator= (const XercesAttGroupInfo& other); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fTypeWithId; + unsigned int fNameId; + unsigned int fNamespaceId; + RefVectorOf* fAttributes; + RefVectorOf* fAnyAttributes; + SchemaAttDef* fCompleteWildCard; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// XercesAttGroupInfo: Getter methods +// --------------------------------------------------------------------------- +inline bool XercesAttGroupInfo::containsTypeWithId() const { + + return fTypeWithId; +} + +inline XMLSize_t XercesAttGroupInfo::attributeCount() const { + + if (fAttributes) { + return fAttributes->size(); + } + + return 0; +} + +inline XMLSize_t XercesAttGroupInfo::anyAttributeCount() const { + + if (fAnyAttributes) { + return fAnyAttributes->size(); + } + + return 0; +} + +inline unsigned int XercesAttGroupInfo::getNameId() const +{ + return fNameId; +} + +inline unsigned int XercesAttGroupInfo::getNamespaceId() const +{ + return fNamespaceId; +} + +inline SchemaAttDef* +XercesAttGroupInfo::attributeAt(const XMLSize_t index) { + + if (fAttributes) { + return fAttributes->elementAt(index); + } + + return 0; +} + +inline const SchemaAttDef* +XercesAttGroupInfo::attributeAt(const XMLSize_t index) const { + + if (fAttributes) { + return fAttributes->elementAt(index); + } + + return 0; +} + +inline SchemaAttDef* +XercesAttGroupInfo::anyAttributeAt(const XMLSize_t index) { + + if (fAnyAttributes) { + return fAnyAttributes->elementAt(index); + } + + return 0; +} + +inline const SchemaAttDef* +XercesAttGroupInfo::anyAttributeAt(const XMLSize_t index) const { + + if (fAnyAttributes) { + return fAnyAttributes->elementAt(index); + } + + return 0; +} + +inline SchemaAttDef* +XercesAttGroupInfo::getCompleteWildCard() const { + + return fCompleteWildCard; +} + +// --------------------------------------------------------------------------- +// XercesAttGroupInfo: Setter methods +// --------------------------------------------------------------------------- +inline void XercesAttGroupInfo::setTypeWithId(const bool other) { + + fTypeWithId = other; +} + +inline void XercesAttGroupInfo::addAttDef(SchemaAttDef* const toAdd, + const bool toClone) { + + if (!fAttributes) { + fAttributes = new (fMemoryManager) RefVectorOf(4, true, fMemoryManager); + } + + if (toClone) { + SchemaAttDef* clonedAttDef = new (fMemoryManager) SchemaAttDef(toAdd); + + if (!clonedAttDef->getBaseAttDecl()) + clonedAttDef->setBaseAttDecl(toAdd); + + fAttributes->addElement(clonedAttDef); + } + else { + fAttributes->addElement(toAdd); + } +} + +inline void XercesAttGroupInfo::addAnyAttDef(SchemaAttDef* const toAdd, + const bool toClone) { + + if (!fAnyAttributes) { + fAnyAttributes = new (fMemoryManager) RefVectorOf(2, true, fMemoryManager); + } + + if (toClone) { + SchemaAttDef* clonedAttDef = new (fMemoryManager) SchemaAttDef(toAdd); + + if (!clonedAttDef->getBaseAttDecl()) + clonedAttDef->setBaseAttDecl(toAdd); + + fAnyAttributes->addElement(clonedAttDef); + } + else { + fAnyAttributes->addElement(toAdd); + } +} + +inline void +XercesAttGroupInfo::setCompleteWildCard(SchemaAttDef* const toSet) { + + if (fCompleteWildCard) { + delete fCompleteWildCard; + } + + fCompleteWildCard = toSet; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XercesAttGroupInfo.hpp + */ + diff --git a/include/xercesc/validators/schema/XercesElementWildcard.cpp b/include/xercesc/validators/schema/XercesElementWildcard.cpp new file mode 100644 index 0000000..3934ef7 --- /dev/null +++ b/include/xercesc/validators/schema/XercesElementWildcard.cpp @@ -0,0 +1,120 @@ +/* + * 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: XercesElementWildcard.cpp 671133 2008-06-24 11:22:29Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local methods +// --------------------------------------------------------------------------- + +/** + * XercesElementWildcard is used to check whether two element declarations conflict + */ +/** + * Check whether two element declarations conflict + */ +bool XercesElementWildcard::conflict(SchemaGrammar* const pGrammar, + ContentSpecNode::NodeTypes type1, + QName* q1, + ContentSpecNode::NodeTypes type2, + QName* q2, + SubstitutionGroupComparator* comparator) +{ + if (type1 == ContentSpecNode::Leaf && + type2 == ContentSpecNode::Leaf) { + if (comparator->isEquivalentTo(q1, q2) || comparator->isEquivalentTo(q2, q1)) + return true; + } + else if (type1 == ContentSpecNode::Leaf) { + return uriInWildcard(pGrammar, q1, q2->getURI(), type2, comparator); + } + else if (type2 == ContentSpecNode::Leaf) { + return uriInWildcard(pGrammar, q2, q1->getURI(), type1, comparator); + } + else { + return wildcardIntersect(type1, q1->getURI(), type2, q2->getURI()); + } + return false; +} + +bool XercesElementWildcard::uriInWildcard(SchemaGrammar* const pGrammar, + QName* qname, + unsigned int wildcard, + ContentSpecNode::NodeTypes wtype, + SubstitutionGroupComparator* comparator) +{ + if ((wtype & 0x0f)== ContentSpecNode::Any) { + return true; + } + else if ((wtype & 0x0f)== ContentSpecNode::Any_NS) { + // substitution of "uri" satisfies "wtype:wildcard" + return comparator->isAllowedByWildcard(pGrammar, qname, wildcard, false); + } + else if ((wtype & 0x0f)== ContentSpecNode::Any_Other) { + // substitution of "uri" satisfies "wtype:wildcard" + return comparator->isAllowedByWildcard(pGrammar, qname, wildcard, true); + } + + return false; +} + +bool XercesElementWildcard::wildcardIntersect(ContentSpecNode::NodeTypes t1, + unsigned int w1, + ContentSpecNode::NodeTypes t2, + unsigned int w2) +{ + if (((t1 & 0x0f) == ContentSpecNode::Any) || + ((t2 & 0x0f) == ContentSpecNode::Any)) { + // if either one is "##any", then intersects + return true; + } + else if (((t1 & 0x0f) == ContentSpecNode::Any_NS) && + ((t2 & 0x0f) == ContentSpecNode::Any_NS)) { + // if both are "some_namespace" and equal, then intersects + return w1 == w2; + } + else if (((t1 & 0x0f) == ContentSpecNode::Any_Other) && + ((t2 & 0x0f) == ContentSpecNode::Any_Other)) { + // if both are "##other", then intersects + return true; + } + // Below we assume that empty string has id 1. + // + else if (((t1 & 0x0f) == ContentSpecNode::Any_NS) && + ((t2 & 0x0f) == ContentSpecNode::Any_Other)) + { + return w1 != w2 && w1 != 1; + } + else if (((t1 & 0x0f) == ContentSpecNode::Any_Other) && + ((t2 & 0x0f) == ContentSpecNode::Any_NS)) + { + return w1 != w2 && w2 != 1; + } + return false; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/validators/schema/XercesElementWildcard.hpp b/include/xercesc/validators/schema/XercesElementWildcard.hpp new file mode 100644 index 0000000..cd5b61f --- /dev/null +++ b/include/xercesc/validators/schema/XercesElementWildcard.hpp @@ -0,0 +1,81 @@ +/* + * 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: XercesElementWildcard.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XERCESELEMENTWILDCARD_HPP) +#define XERCESC_INCLUDE_GUARD_XERCESELEMENTWILDCARD_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward declarations +// --------------------------------------------------------------------------- +class SchemaGrammar; + + +class VALIDATORS_EXPORT XercesElementWildcard +{ + +public : + + // ----------------------------------------------------------------------- + // Class static methods + // ----------------------------------------------------------------------- + /* + * check whether two elements are in conflict + */ + static bool conflict(SchemaGrammar* const pGrammar, + ContentSpecNode::NodeTypes type1, + QName* q1, + ContentSpecNode::NodeTypes type2, + QName* q2, + SubstitutionGroupComparator* comparator); + +private: + + // ----------------------------------------------------------------------- + // private helper methods + // ----------------------------------------------------------------------- + static bool uriInWildcard(SchemaGrammar* const pGrammar, + QName* qname, + unsigned int wildcard, + ContentSpecNode::NodeTypes wtype, + SubstitutionGroupComparator* comparator); + + static bool wildcardIntersect(ContentSpecNode::NodeTypes t1, + unsigned int w1, + ContentSpecNode::NodeTypes t2, + unsigned int w2); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XercesElementWildcard(); + ~XercesElementWildcard(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif // XERCESELEMENTWILDCARD_HPP + diff --git a/include/xercesc/validators/schema/XercesGroupInfo.cpp b/include/xercesc/validators/schema/XercesGroupInfo.cpp new file mode 100644 index 0000000..7038c33 --- /dev/null +++ b/include/xercesc/validators/schema/XercesGroupInfo.cpp @@ -0,0 +1,141 @@ +/* + * 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: XercesGroupInfo.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// XercesGroupInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesGroupInfo::XercesGroupInfo(MemoryManager* const manager) + : fCheckElementConsistency(true) + , fScope(Grammar::TOP_LEVEL_SCOPE) + , fNameId(0) + , fNamespaceId(0) + , fContentSpec(0) + , fElements(0) + , fBaseGroup(0) + , fLocator(0) +{ + fElements = new (manager) RefVectorOf(4, false, manager); +} + +XercesGroupInfo::XercesGroupInfo(unsigned int groupNameId, + unsigned int groupNamespaceId, + MemoryManager* const manager) + : fCheckElementConsistency(true) + , fScope(Grammar::TOP_LEVEL_SCOPE) + , fNameId(groupNameId) + , fNamespaceId(groupNamespaceId) + , fContentSpec(0) + , fElements(0) + , fBaseGroup(0) + , fLocator(0) +{ + fElements = new (manager) RefVectorOf(4, false, manager); +} + + +XercesGroupInfo::~XercesGroupInfo() +{ + delete fElements; + delete fContentSpec; + delete fLocator; +} + + +// --------------------------------------------------------------------------- +// XercesGroupInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +void XercesGroupInfo::setLocator(XSDLocator* const aLocator) { + + if (fLocator) + delete fLocator; + + fLocator = aLocator; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XercesGroupInfo) + +void XercesGroupInfo::serialize(XSerializeEngine& serEng) +{ + if (serEng.isStoring()) + { + serEng<* fElements; + * + ***/ + + XTemplateSerializer::storeObject(fElements, serEng); + + serEng<>fCheckElementConsistency; + serEng>>fScope; + serEng>>fNameId; + serEng>>fNamespaceId; + serEng>>fContentSpec; + + /*** + * + * Deserialize RefVectorOf* fElements; + * + ***/ + XTemplateSerializer::loadObject(&fElements, 4, false, serEng); + + serEng>>fBaseGroup; + + //don't serialize XSDLocator* fLocator; + fLocator = 0; + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file XercesGroupInfo.cpp + */ + + diff --git a/include/xercesc/validators/schema/XercesGroupInfo.hpp b/include/xercesc/validators/schema/XercesGroupInfo.hpp new file mode 100644 index 0000000..1baa9b7 --- /dev/null +++ b/include/xercesc/validators/schema/XercesGroupInfo.hpp @@ -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: XercesGroupInfo.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XERCESGROUPINFO_HPP) +#define XERCESC_INCLUDE_GUARD_XERCESGROUPINFO_HPP + + +/** + * The class act as a place holder to store group information. + * + * The class is intended for internal use. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class ContentSpecNode; +class XSDLocator; + + +class VALIDATORS_EXPORT XercesGroupInfo : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Public Constructors/Destructor + // ----------------------------------------------------------------------- + XercesGroupInfo + ( + unsigned int groupNameId + , unsigned int groupNamespaceId + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + ~XercesGroupInfo(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getCheckElementConsistency() const; + unsigned int getScope() const; + XMLSize_t elementCount() const; + ContentSpecNode* getContentSpec() const; + SchemaElementDecl* elementAt(const XMLSize_t index); + const SchemaElementDecl* elementAt(const XMLSize_t index) const; + XSDLocator* getLocator() const; + XercesGroupInfo* getBaseGroup() const; + unsigned int getNameId() const; + unsigned int getNamespaceId() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setScope(const unsigned int other); + void setContentSpec(ContentSpecNode* const other); + void addElement(SchemaElementDecl* const toAdd); + void setLocator(XSDLocator* const aLocator); + void setBaseGroup(XercesGroupInfo* const baseGroup); + void setCheckElementConsistency(const bool aValue); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XercesGroupInfo) + XercesGroupInfo(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XercesGroupInfo(const XercesGroupInfo& elemInfo); + XercesGroupInfo& operator= (const XercesGroupInfo& other); + + // ----------------------------------------------------------------------- + // Private data members + // ----------------------------------------------------------------------- + bool fCheckElementConsistency; + unsigned int fScope; + unsigned int fNameId; + unsigned int fNamespaceId; + ContentSpecNode* fContentSpec; + RefVectorOf* fElements; + XercesGroupInfo* fBaseGroup; // redefine by restriction + XSDLocator* fLocator; +}; + +// --------------------------------------------------------------------------- +// XercesGroupInfo: Getter methods +// --------------------------------------------------------------------------- +inline unsigned int XercesGroupInfo::getScope() const { + + return fScope; +} + +inline XMLSize_t XercesGroupInfo::elementCount() const { + + return fElements->size(); +} + +inline ContentSpecNode* XercesGroupInfo::getContentSpec() const { + + return fContentSpec; +} + +inline SchemaElementDecl* +XercesGroupInfo::elementAt(const XMLSize_t index) { + + return fElements->elementAt(index); +} + +inline const SchemaElementDecl* +XercesGroupInfo::elementAt(const XMLSize_t index) const { + + return fElements->elementAt(index); +} + +inline XSDLocator* XercesGroupInfo::getLocator() const { + + return fLocator; +} + +inline XercesGroupInfo* XercesGroupInfo::getBaseGroup() const { + + return fBaseGroup; +} + +inline bool XercesGroupInfo::getCheckElementConsistency() const { + + return fCheckElementConsistency; +} + +inline unsigned int XercesGroupInfo::getNameId() const +{ + return fNameId; +} + +inline unsigned int XercesGroupInfo::getNamespaceId() const +{ + return fNamespaceId; +} + +// --------------------------------------------------------------------------- +// XercesGroupInfo: Setter methods +// ---------------------------------------------------------------------------} +inline void XercesGroupInfo::setScope(const unsigned int other) { + + fScope = other; +} + +inline void XercesGroupInfo::setContentSpec(ContentSpecNode* const other) { + + fContentSpec = other; +} + +inline void XercesGroupInfo::addElement(SchemaElementDecl* const elem) { + + if (!fElements->containsElement(elem)) + fElements->addElement(elem); +} + +inline void XercesGroupInfo::setBaseGroup(XercesGroupInfo* const baseGroup) { + + fBaseGroup = baseGroup; +} + +inline void XercesGroupInfo::setCheckElementConsistency(const bool aValue) { + + fCheckElementConsistency = aValue; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XercesGroupInfo.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/FieldActivator.cpp b/include/xercesc/validators/schema/identity/FieldActivator.cpp new file mode 100644 index 0000000..4ef9d82 --- /dev/null +++ b/include/xercesc/validators/schema/identity/FieldActivator.cpp @@ -0,0 +1,124 @@ +/* + * 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: FieldActivator.cpp 679340 2008-07-24 10:28:29Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// FieldActivator: Constructors and Destructor +// --------------------------------------------------------------------------- +FieldActivator::FieldActivator(ValueStoreCache* const valueStoreCache, + XPathMatcherStack* const matcherStack, + MemoryManager* const manager) + : fValueStoreCache(valueStoreCache) + , fMatcherStack(matcherStack) + , fMayMatch(0) + , fMemoryManager(manager) +{ + fMayMatch = new (manager) ValueHashTableOf(29, manager); +} + +FieldActivator::FieldActivator(const FieldActivator& other) + : XMemory(other) + , fValueStoreCache(other.fValueStoreCache) + , fMatcherStack(other.fMatcherStack) + , fMayMatch(0) + , fMemoryManager(other.fMemoryManager) +{ + fMayMatch = new (fMemoryManager) ValueHashTableOf(29, fMemoryManager); + ValueHashTableOfEnumerator mayMatchEnum(other.fMayMatch, false, fMemoryManager); + + // Build key set + while (mayMatchEnum.hasMoreElements()) + { + IC_Field* field = (IC_Field*) mayMatchEnum.nextElementKey(); + fMayMatch->put(field, other.fMayMatch->get(field)); + } +} + + +FieldActivator::~FieldActivator() +{ + delete fMayMatch; +} + +// --------------------------------------------------------------------------- +// FieldActivator: Operator methods +// --------------------------------------------------------------------------- +FieldActivator& FieldActivator::operator =(const FieldActivator& other) { + + if (this == &other) { + return *this; + } + + fValueStoreCache = other.fValueStoreCache; + fMatcherStack = other.fMatcherStack; + return *this; +} + +// --------------------------------------------------------------------------- +// FieldActivator: Operator methods +// --------------------------------------------------------------------------- +XPathMatcher* FieldActivator::activateField(IC_Field* const field, const int initialDepth) { + + ValueStore* valueStore = fValueStoreCache->getValueStoreFor(field, initialDepth); + XPathMatcher* matcher = field->createMatcher(this, valueStore, fMemoryManager); + + setMayMatch(field, true); + fMatcherStack->addMatcher(matcher); + matcher->startDocumentFragment(); + + return matcher; +} + +void FieldActivator::startValueScopeFor(const IdentityConstraint* const ic, + const int initialDepth) { + + XMLSize_t fieldCount = ic->getFieldCount(); + + for(XMLSize_t i=0; igetFieldAt(i); + ValueStore* valueStore = fValueStoreCache->getValueStoreFor(field, initialDepth); + + valueStore->startValueScope(); + } +} + +void FieldActivator::endValueScopeFor(const IdentityConstraint* const ic, const int initialDepth) { + + ValueStore* valueStore = fValueStoreCache->getValueStoreFor(ic, initialDepth); + + valueStore->endValueScope(); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file FieldActivator.cpp + */ diff --git a/include/xercesc/validators/schema/identity/FieldActivator.hpp b/include/xercesc/validators/schema/identity/FieldActivator.hpp new file mode 100644 index 0000000..6b1f0f7 --- /dev/null +++ b/include/xercesc/validators/schema/identity/FieldActivator.hpp @@ -0,0 +1,141 @@ +/* + * 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: FieldActivator.hpp 679340 2008-07-24 10:28:29Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_FIELDACTIVATOR_HPP) +#define XERCESC_INCLUDE_GUARD_FIELDACTIVATOR_HPP + +/** + * This class is responsible for activating fields within a specific scope; + * the caller merely requests the fields to be activated. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class IdentityConstraint; +class XPathMatcher; +class ValueStoreCache; +class IC_Field; +class XPathMatcherStack; + + +class VALIDATORS_EXPORT FieldActivator : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + FieldActivator(ValueStoreCache* const valueStoreCache, + XPathMatcherStack* const matcherStack, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + FieldActivator(const FieldActivator& other); + ~FieldActivator(); + + // ----------------------------------------------------------------------- + // Operator methods + // ----------------------------------------------------------------------- + FieldActivator& operator =(const FieldActivator& other); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getMayMatch(IC_Field* const field); + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setValueStoreCache(ValueStoreCache* const other); + void setMatcherStack(XPathMatcherStack* const matcherStack); + void setMayMatch(IC_Field* const field, bool value); + + // ----------------------------------------------------------------------- + // Activation methods + // ----------------------------------------------------------------------- + /** + * Start the value scope for the specified identity constraint. This + * method is called when the selector matches in order to initialize + * the value store. + */ + void startValueScopeFor(const IdentityConstraint* const ic, const int initialDepth); + + /** + * Request to activate the specified field. This method returns the + * matcher for the field. + */ + XPathMatcher* activateField(IC_Field* const field, const int initialDepth); + + /** + * Ends the value scope for the specified identity constraint. + */ + void endValueScopeFor(const IdentityConstraint* const ic, const int initialDepth); + +private: + // ----------------------------------------------------------------------- + // Data + // ----------------------------------------------------------------------- + ValueStoreCache* fValueStoreCache; + XPathMatcherStack* fMatcherStack; + ValueHashTableOf* fMayMatch; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// FieldActivator: Getter methods +// --------------------------------------------------------------------------- +inline bool FieldActivator::getMayMatch(IC_Field* const field) { + + return fMayMatch->get(field); +} + +// --------------------------------------------------------------------------- +// FieldActivator: Setter methods +// --------------------------------------------------------------------------- +inline void FieldActivator::setValueStoreCache(ValueStoreCache* const other) { + + fValueStoreCache = other; +} + +inline void +FieldActivator::setMatcherStack(XPathMatcherStack* const matcherStack) { + + fMatcherStack = matcherStack; +} + +inline void FieldActivator::setMayMatch(IC_Field* const field, bool value) { + + fMayMatch->put(field, value); +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file FieldActivator.hpp + */ diff --git a/include/xercesc/validators/schema/identity/FieldValueMap.cpp b/include/xercesc/validators/schema/identity/FieldValueMap.cpp new file mode 100644 index 0000000..6c1ee6e --- /dev/null +++ b/include/xercesc/validators/schema/identity/FieldValueMap.cpp @@ -0,0 +1,127 @@ +/* + * 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: FieldValueMap.cpp 708224 2008-10-27 16:02:26Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// FieldValueMap: Constructors and Destructor +// --------------------------------------------------------------------------- +FieldValueMap::FieldValueMap(MemoryManager* const manager) + : fFields(0) + , fValidators(0) + , fValues(0) + , fMemoryManager(manager) +{ +} + +FieldValueMap::FieldValueMap(const FieldValueMap& other) + : XMemory(other) + , fFields(0) + , fValidators(0) + , fValues(0) + , fMemoryManager(other.fMemoryManager) +{ + if (other.fFields) { + CleanupType cleanup(this, &FieldValueMap::cleanUp); + + try { + + XMLSize_t valuesSize = other.fValues->size(); + + fFields = new (fMemoryManager) ValueVectorOf(*(other.fFields)); + fValidators = new (fMemoryManager) ValueVectorOf(*(other.fValidators)); + fValues = new (fMemoryManager) RefArrayVectorOf(other.fFields->curCapacity(), true, fMemoryManager); + + for (XMLSize_t i=0; iaddElement(XMLString::replicate(other.fValues->elementAt(i), fMemoryManager)); + } + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); + } +} + +FieldValueMap::~FieldValueMap() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// FieldValueMap: Private helper methods. +// --------------------------------------------------------------------------- +void FieldValueMap::cleanUp() +{ + delete fFields; + delete fValidators; + delete fValues; +} + +// --------------------------------------------------------------------------- +// FieldValueMap: Helper methods +// --------------------------------------------------------------------------- +bool FieldValueMap::indexOf(const IC_Field* const key, XMLSize_t& location) const { + + if (fFields) { + + XMLSize_t fieldSize = fFields->size(); + + for (XMLSize_t i=0; i < fieldSize; i++) { + if (fFields->elementAt(i) == key) { + location=i; + return true; + } + } + } + + return false; +} + +void FieldValueMap::clear() +{ + if(fFields) + fFields->removeAllElements(); + if(fValidators) + fValidators->removeAllElements(); + if(fValues) + fValues->removeAllElements(); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file FieldValueMap.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/FieldValueMap.hpp b/include/xercesc/validators/schema/identity/FieldValueMap.hpp new file mode 100644 index 0000000..4b55630 --- /dev/null +++ b/include/xercesc/validators/schema/identity/FieldValueMap.hpp @@ -0,0 +1,198 @@ +/* + * 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: FieldValueMap.hpp 708224 2008-10-27 16:02:26Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_FIELDVALUEMAP_HPP) +#define XERCESC_INCLUDE_GUARD_FIELDVALUEMAP_HPP + +/** + * This class maps values associated with fields of an identity constraint + * that have successfully matched some string in an instance document. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class IC_Field; +class DatatypeValidator; + + +class VALIDATORS_EXPORT FieldValueMap : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + FieldValueMap(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + FieldValueMap(const FieldValueMap& other); + ~FieldValueMap(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + DatatypeValidator* getDatatypeValidatorAt(const XMLSize_t index) const; + DatatypeValidator* getDatatypeValidatorFor(const IC_Field* const key) const; + XMLCh* getValueAt(const XMLSize_t index) const; + XMLCh* getValueFor(const IC_Field* const key) const; + IC_Field* keyAt(const XMLSize_t index) const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void put(IC_Field* const key, DatatypeValidator* const dv, + const XMLCh* const value); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + XMLSize_t size() const; + bool indexOf(const IC_Field* const key, XMLSize_t& location) const; + void clear(); + +private: + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Unimplemented operators + // ----------------------------------------------------------------------- + FieldValueMap& operator= (const FieldValueMap& other); + + // ----------------------------------------------------------------------- + // Data + // ----------------------------------------------------------------------- + ValueVectorOf* fFields; + ValueVectorOf* fValidators; + RefArrayVectorOf* fValues; + MemoryManager* fMemoryManager; +}; + + +// --------------------------------------------------------------------------- +// FieldValueMap: Getter methods +// --------------------------------------------------------------------------- +inline DatatypeValidator* +FieldValueMap::getDatatypeValidatorAt(const XMLSize_t index) const { + + if (fValidators) { + return fValidators->elementAt(index); + } + + return 0; +} + +inline DatatypeValidator* +FieldValueMap::getDatatypeValidatorFor(const IC_Field* const key) const { + + XMLSize_t location; + if (fValidators && indexOf(key, location)) { + return fValidators->elementAt(location); + } + + return 0; +} + +inline XMLCh* FieldValueMap::getValueAt(const XMLSize_t index) const { + + if (fValues) { + return fValues->elementAt(index); + } + + return 0; +} + +inline XMLCh* FieldValueMap::getValueFor(const IC_Field* const key) const { + + XMLSize_t location; + if (fValues && indexOf(key, location)) { + return fValues->elementAt(location); + } + + return 0; +} + +inline IC_Field* FieldValueMap::keyAt(const XMLSize_t index) const { + + if (fFields) { + return fFields->elementAt(index); + } + + return 0; +} + +// --------------------------------------------------------------------------- +// FieldValueMap: Helper methods +// --------------------------------------------------------------------------- +inline XMLSize_t FieldValueMap::size() const { + + if (fFields) { + return fFields->size(); + } + + return 0; +} + +// --------------------------------------------------------------------------- +// FieldValueMap: Setter methods +// --------------------------------------------------------------------------- +inline void FieldValueMap::put(IC_Field* const key, + DatatypeValidator* const dv, + const XMLCh* const value) { + + if (!fFields) { + fFields = new (fMemoryManager) ValueVectorOf(4, fMemoryManager); + fValidators = new (fMemoryManager) ValueVectorOf(4, fMemoryManager); + fValues = new (fMemoryManager) RefArrayVectorOf(4, true, fMemoryManager); + } + + XMLSize_t keyIndex; + bool bFound=indexOf(key, keyIndex); + + if (!bFound) { + + fFields->addElement(key); + fValidators->addElement(dv); + fValues->addElement(XMLString::replicate(value, fMemoryManager)); + } + else { + fValidators->setElementAt(dv, keyIndex); + fValues->setElementAt(XMLString::replicate(value, fMemoryManager), keyIndex); + } +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file FieldValueMap.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Field.cpp b/include/xercesc/validators/schema/identity/IC_Field.cpp new file mode 100644 index 0000000..ef48295 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Field.cpp @@ -0,0 +1,141 @@ +/* + * 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: IC_Field.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// FieldMatcher: Constructors and Destructor +// --------------------------------------------------------------------------- +FieldMatcher::FieldMatcher(XercesXPath* const xpath, + IC_Field* const aField, + ValueStore* const valueStore, + FieldActivator* const fieldActivator, + MemoryManager* const manager) + : XPathMatcher(xpath, (IdentityConstraint*) 0, manager) + , fValueStore(valueStore) + , fField(aField) + , fFieldActivator(fieldActivator) +{ +} + +// --------------------------------------------------------------------------- +// FieldMatcher: Match methods +// --------------------------------------------------------------------------- +void FieldMatcher::matched(const XMLCh* const content, + DatatypeValidator* const dv, + const bool isNil) { + + if(isNil) { + fValueStore->reportNilError(fField->getIdentityConstraint()); + } + + fValueStore->addValue(fFieldActivator, fField, dv, content); + + // once we've stored the value for this field, we set the mayMatch + // member to false so that, in the same scope, we don't match any more + // values (and throw an error instead). + fFieldActivator->setMayMatch(fField, false); +} + +// --------------------------------------------------------------------------- +// IC_Field: Constructors and Destructor +// --------------------------------------------------------------------------- +IC_Field::IC_Field(XercesXPath* const xpath, + IdentityConstraint* const identityConstraint) + : fXPath(xpath) + , fIdentityConstraint(identityConstraint) +{ +} + + +IC_Field::~IC_Field() +{ + delete fXPath; +} + +// --------------------------------------------------------------------------- +// IC_Field: operators +// --------------------------------------------------------------------------- +bool IC_Field::operator== (const IC_Field& other) const { + + return (*fXPath == *(other.fXPath)); +} + +bool IC_Field::operator!= (const IC_Field& other) const { + + return !operator==(other); +} + +// --------------------------------------------------------------------------- +// IC_Field: Factory methods +// --------------------------------------------------------------------------- +XPathMatcher* IC_Field::createMatcher(FieldActivator* const fieldActivator, + ValueStore* const valueStore, + MemoryManager* const manager) +{ + return new (manager) FieldMatcher(fXPath, this, valueStore, fieldActivator, manager); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IC_Field) + +void IC_Field::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<>fXPath; + + fIdentityConstraint = IdentityConstraint::loadIC(serEng); + } + +} + +IC_Field::IC_Field(MemoryManager* const ) +:fXPath(0) +,fIdentityConstraint(0) +{ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IC_Field.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Field.hpp b/include/xercesc/validators/schema/identity/IC_Field.hpp new file mode 100644 index 0000000..2998130 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Field.hpp @@ -0,0 +1,152 @@ +/* + * 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: IC_Field.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IC_FIELD_HPP) +#define XERCESC_INCLUDE_GUARD_IC_FIELD_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class ValueStore; +class FieldActivator; + + +class VALIDATORS_EXPORT IC_Field : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + IC_Field(XercesXPath* const xpath, + IdentityConstraint* const identityConstraint); + ~IC_Field(); + + // ----------------------------------------------------------------------- + // operators + // ----------------------------------------------------------------------- + bool operator== (const IC_Field& other) const; + bool operator!= (const IC_Field& other) const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XercesXPath* getXPath() const { return fXPath; } + IdentityConstraint* getIdentityConstraint() const { return fIdentityConstraint; } + + // ----------------------------------------------------------------------- + // Factory methods + // ----------------------------------------------------------------------- + XPathMatcher* createMatcher + ( + FieldActivator* const fieldActivator + , ValueStore* const valueStore + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IC_Field) + + IC_Field(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IC_Field(const IC_Field& other); + IC_Field& operator= (const IC_Field& other); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + XercesXPath* fXPath; + IdentityConstraint* fIdentityConstraint; +}; + + +class VALIDATORS_EXPORT FieldMatcher : public XPathMatcher +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + ~FieldMatcher() {} + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + ValueStore* getValueStore() const { return fValueStore; } + IC_Field* getField() const { return fField; } + + // ----------------------------------------------------------------------- + // Virtual methods + // ----------------------------------------------------------------------- + void matched(const XMLCh* const content, DatatypeValidator* const dv, + const bool isNil); + +private: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + FieldMatcher(XercesXPath* const anXPath, + IC_Field* const aField, + ValueStore* const valueStore, + FieldActivator* const fieldActivator, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + FieldMatcher(const FieldMatcher& other); + FieldMatcher& operator= (const FieldMatcher& other); + + // ----------------------------------------------------------------------- + // Friends + // ----------------------------------------------------------------------- + friend class IC_Field; + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + ValueStore* fValueStore; + IC_Field* fField; + FieldActivator* fFieldActivator; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IC_Field.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Key.cpp b/include/xercesc/validators/schema/identity/IC_Key.cpp new file mode 100644 index 0000000..4cebd50 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Key.cpp @@ -0,0 +1,67 @@ +/* + * 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: IC_Key.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// IC_Key: Constructors and Destructor +// --------------------------------------------------------------------------- +IC_Key::IC_Key(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + MemoryManager* const manager) +:IdentityConstraint(identityConstraintName, elemName, manager) +{ +} + + +IC_Key::~IC_Key() +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IC_Key) + +void IC_Key::serialize(XSerializeEngine& serEng) +{ + IdentityConstraint::serialize(serEng); + + //no data +} + +IC_Key::IC_Key(MemoryManager* const manager) +:IdentityConstraint(0, 0, manager) +{ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IC_Key.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Key.hpp b/include/xercesc/validators/schema/identity/IC_Key.hpp new file mode 100644 index 0000000..26c9f32 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Key.hpp @@ -0,0 +1,80 @@ +/* + * 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: IC_Key.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IC_KEY_HPP) +#define XERCESC_INCLUDE_GUARD_IC_KEY_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT IC_Key: public IdentityConstraint +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + IC_Key(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~IC_Key(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + short getType() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IC_Key) + + IC_Key(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IC_Key(const IC_Key& other); + IC_Key& operator= (const IC_Key& other); +}; + + +// --------------------------------------------------------------------------- +// IC_Key: Getter methods +// --------------------------------------------------------------------------- +inline short IC_Key::getType() const { + + return IdentityConstraint::ICType_KEY; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IC_Key.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_KeyRef.cpp b/include/xercesc/validators/schema/identity/IC_KeyRef.cpp new file mode 100644 index 0000000..9f70f2d --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_KeyRef.cpp @@ -0,0 +1,79 @@ +/* + * 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: IC_KeyRef.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// IC_KeyRef: Constructors and Destructor +// --------------------------------------------------------------------------- +IC_KeyRef::IC_KeyRef(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + IdentityConstraint* const icKey, + MemoryManager* const manager) + : IdentityConstraint(identityConstraintName, elemName, manager) + , fKey(icKey) +{ +} + + +IC_KeyRef::~IC_KeyRef() +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IC_KeyRef) + +void IC_KeyRef::serialize(XSerializeEngine& serEng) +{ + IdentityConstraint::serialize(serEng); + + if (serEng.isStoring()) + { + IdentityConstraint::storeIC(serEng, fKey); + } + else + { + fKey = IdentityConstraint::loadIC(serEng); + } + +} + +IC_KeyRef::IC_KeyRef(MemoryManager* const manager) +:IdentityConstraint(0, 0, manager) +,fKey(0) +{ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IC_KeyRef.cpp + */ + + diff --git a/include/xercesc/validators/schema/identity/IC_KeyRef.hpp b/include/xercesc/validators/schema/identity/IC_KeyRef.hpp new file mode 100644 index 0000000..7f30fb4 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_KeyRef.hpp @@ -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: IC_KeyRef.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IC_KEYREF_HPP) +#define XERCESC_INCLUDE_GUARD_IC_KEYREF_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT IC_KeyRef: public IdentityConstraint +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + IC_KeyRef(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + IdentityConstraint* const icKey, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~IC_KeyRef(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + short getType() const; + IdentityConstraint* getKey() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IC_KeyRef) + + IC_KeyRef(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IC_KeyRef(const IC_KeyRef& other); + IC_KeyRef& operator= (const IC_KeyRef& other); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + IdentityConstraint* fKey; +}; + + +// --------------------------------------------------------------------------- +// IC_KeyRef: Getter methods +// --------------------------------------------------------------------------- +inline short IC_KeyRef::getType() const { + + return IdentityConstraint::ICType_KEYREF; +} + +inline IdentityConstraint* IC_KeyRef::getKey() const { + + return fKey; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IC_KeyRef.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Selector.cpp b/include/xercesc/validators/schema/identity/IC_Selector.cpp new file mode 100644 index 0000000..c09f164 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Selector.cpp @@ -0,0 +1,178 @@ +/* + * 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: IC_Selector.cpp 803869 2009-08-13 12:56:21Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SelectorMatcher: Constructors and Destructor +// --------------------------------------------------------------------------- +SelectorMatcher::SelectorMatcher(XercesXPath* const xpath, + IC_Selector* const selector, + FieldActivator* const fieldActivator, + const int initialDepth, + MemoryManager* const manager) + : XPathMatcher(xpath, selector->getIdentityConstraint(), manager) + , fInitialDepth(initialDepth) + , fElementDepth(0) + , fMatchedDepth(-1) + , fSelector(selector) + , fFieldActivator(fieldActivator) +{ +} + +// --------------------------------------------------------------------------- +// FieldMatcher: XMLDocumentHandler methods +// --------------------------------------------------------------------------- +void SelectorMatcher::startDocumentFragment() { + + XPathMatcher::startDocumentFragment(); + fElementDepth = 0; + fMatchedDepth = -1; +} + +void SelectorMatcher::startElement(const XMLElementDecl& elemDecl, + const unsigned int urlId, + const XMLCh* const elemPrefix, + const RefVectorOf& attrList, + const XMLSize_t attrCount, + ValidationContext* validationContext /*=0*/) +{ + + XPathMatcher::startElement(elemDecl, urlId, elemPrefix, attrList, attrCount, validationContext); + fElementDepth++; + + // activate the fields, if selector is matched + unsigned char matched = isMatched(); + if ((fMatchedDepth == -1 && ((matched & XP_MATCHED) == XP_MATCHED)) + || ((matched & XP_MATCHED_D) == XP_MATCHED_D)) { + + IdentityConstraint* ic = fSelector->getIdentityConstraint(); + XMLSize_t count = ic->getFieldCount(); + + fMatchedDepth = fElementDepth; + fFieldActivator->startValueScopeFor(ic, fInitialDepth); + + for (XMLSize_t i = 0; i < count; i++) { + + XPathMatcher* matcher = fFieldActivator->activateField(ic->getFieldAt(i), fInitialDepth); + matcher->startElement(elemDecl, urlId, elemPrefix, attrList, attrCount, validationContext); + } + } +} + +void SelectorMatcher::endElement(const XMLElementDecl& elemDecl, + const XMLCh* const elemContent, + ValidationContext* validationContext /*=0*/, + DatatypeValidator* actualValidator /*=0*/) +{ + + XPathMatcher::endElement(elemDecl, elemContent, validationContext, actualValidator); + + if (fElementDepth-- == fMatchedDepth) { + + fMatchedDepth = -1; + fFieldActivator->endValueScopeFor(fSelector->getIdentityConstraint(), fInitialDepth); + } +} + +// --------------------------------------------------------------------------- +// IC_Selector: Constructors and Destructor +// --------------------------------------------------------------------------- +IC_Selector::IC_Selector(XercesXPath* const xpath, + IdentityConstraint* const identityConstraint) + : fXPath(xpath) + , fIdentityConstraint(identityConstraint) +{ +} + + +IC_Selector::~IC_Selector() +{ + delete fXPath; +} + +// --------------------------------------------------------------------------- +// IC_Selector: operators +// --------------------------------------------------------------------------- +bool IC_Selector::operator ==(const IC_Selector& other) const { + + return (*fXPath == *(other.fXPath)); +} + +bool IC_Selector::operator !=(const IC_Selector& other) const { + + return !operator==(other); +} + +// --------------------------------------------------------------------------- +// IC_Selector: Factory methods +// --------------------------------------------------------------------------- +XPathMatcher* IC_Selector::createMatcher(FieldActivator* const fieldActivator, + const int initialDepth, + MemoryManager* const manager) { + + return new (manager) SelectorMatcher(fXPath, this, fieldActivator, initialDepth, manager); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IC_Selector) + +void IC_Selector::serialize(XSerializeEngine& serEng) +{ + if (serEng.isStoring()) + { + serEng<>fXPath; + + fIdentityConstraint = IdentityConstraint::loadIC(serEng); + } + +} + +IC_Selector::IC_Selector(MemoryManager* const ) +:fXPath(0) +,fIdentityConstraint(0) +{ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IC_Selector.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Selector.hpp b/include/xercesc/validators/schema/identity/IC_Selector.hpp new file mode 100644 index 0000000..a4d242f --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Selector.hpp @@ -0,0 +1,155 @@ +/* + * 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: IC_Selector.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IC_SELECTOR_HPP) +#define XERCESC_INCLUDE_GUARD_IC_SELECTOR_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class FieldActivator; + + +class VALIDATORS_EXPORT IC_Selector : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + IC_Selector(XercesXPath* const xpath, + IdentityConstraint* const identityConstraint); + ~IC_Selector(); + + // ----------------------------------------------------------------------- + // operators + // ----------------------------------------------------------------------- + bool operator== (const IC_Selector& other) const; + bool operator!= (const IC_Selector& other) const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XercesXPath* getXPath() const { return fXPath; } + IdentityConstraint* getIdentityConstraint() const { return fIdentityConstraint; } + + // ----------------------------------------------------------------------- + // Factory methods + // ----------------------------------------------------------------------- + XPathMatcher* createMatcher(FieldActivator* const fieldActivator, + const int initialDepth, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IC_Selector) + + IC_Selector(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IC_Selector(const IC_Selector& other); + IC_Selector& operator= (const IC_Selector& other); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + XercesXPath* fXPath; + IdentityConstraint* fIdentityConstraint; +}; + + +class VALIDATORS_EXPORT SelectorMatcher : public XPathMatcher +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + ~SelectorMatcher() {} + + int getInitialDepth() const { return fInitialDepth; } + + // ----------------------------------------------------------------------- + // XMLDocumentHandler methods + // ----------------------------------------------------------------------- + virtual void startDocumentFragment(); + virtual void startElement(const XMLElementDecl& elemDecl, + const unsigned int urlId, + const XMLCh* const elemPrefix, + const RefVectorOf& attrList, + const XMLSize_t attrCount, + ValidationContext* validationContext = 0); + virtual void endElement(const XMLElementDecl& elemDecl, + const XMLCh* const elemContent, + ValidationContext* validationContext = 0, + DatatypeValidator* actualValidator = 0); + +private: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + SelectorMatcher(XercesXPath* const anXPath, + IC_Selector* const selector, + FieldActivator* const fieldActivator, + const int initialDepth, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + SelectorMatcher(const SelectorMatcher& other); + SelectorMatcher& operator= (const SelectorMatcher& other); + + // ----------------------------------------------------------------------- + // Friends + // ----------------------------------------------------------------------- + friend class IC_Selector; + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + int fInitialDepth; + int fElementDepth; + int fMatchedDepth; + IC_Selector* fSelector; + FieldActivator* fFieldActivator; +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IC_Selector.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IC_Unique.cpp b/include/xercesc/validators/schema/identity/IC_Unique.cpp new file mode 100644 index 0000000..d238499 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Unique.cpp @@ -0,0 +1,68 @@ +/* + * 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: IC_Unique.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// IC_Unique: Constructors and Destructor +// --------------------------------------------------------------------------- +IC_Unique::IC_Unique(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + MemoryManager* const manager) + : IdentityConstraint(identityConstraintName, elemName, manager) +{ +} + + +IC_Unique::~IC_Unique() +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(IC_Unique) + +void IC_Unique::serialize(XSerializeEngine& serEng) +{ + IdentityConstraint::serialize(serEng); + + //no data +} + +IC_Unique::IC_Unique(MemoryManager* const manager) +:IdentityConstraint(0, 0, manager) +{ +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IC_Unique.cpp + */ + + diff --git a/include/xercesc/validators/schema/identity/IC_Unique.hpp b/include/xercesc/validators/schema/identity/IC_Unique.hpp new file mode 100644 index 0000000..52ad029 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IC_Unique.hpp @@ -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: IC_Unique.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IC_UNIQUE_HPP) +#define XERCESC_INCLUDE_GUARD_IC_UNIQUE_HPP + + +/** + * Schema unique identity constraint + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT IC_Unique: public IdentityConstraint +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + IC_Unique(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~IC_Unique(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + short getType() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IC_Unique) + + IC_Unique(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IC_Unique(const IC_Unique& other); + IC_Unique& operator= (const IC_Unique& other); +}; + + +// --------------------------------------------------------------------------- +// IC_Unique: Getter methods +// --------------------------------------------------------------------------- +inline short IC_Unique::getType() const { + + return IdentityConstraint::ICType_UNIQUE; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IC_Unique.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IdentityConstraint.cpp b/include/xercesc/validators/schema/identity/IdentityConstraint.cpp new file mode 100644 index 0000000..475aba3 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IdentityConstraint.cpp @@ -0,0 +1,226 @@ +/* + * 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: IdentityConstraint.cpp 676911 2008-07-15 13:27:32Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +//since we need to dynamically created each and every derivatives +//during deserialization by XSerializeEngine>>Derivative, we got +//to include all hpp +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// IdentityConstraint: Constructors and Destructor +// --------------------------------------------------------------------------- +IdentityConstraint::IdentityConstraint(const XMLCh* const identityConstraintName, + const XMLCh* const elemName, + MemoryManager* const manager) + : fIdentityConstraintName(0) + , fElemName(0) + , fSelector(0) + , fFields(0) + , fMemoryManager(manager) + , fNamespaceURI(-1) +{ + CleanupType cleanup(this, &IdentityConstraint::cleanUp); + + try { + fIdentityConstraintName = XMLString::replicate(identityConstraintName, fMemoryManager); + fElemName = XMLString::replicate(elemName, fMemoryManager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +IdentityConstraint::~IdentityConstraint() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// IdentityConstraint: operators +// --------------------------------------------------------------------------- +bool IdentityConstraint::operator ==(const IdentityConstraint& other) const { + + if (getType() != other.getType()) + return false; + + if (!XMLString::equals(fIdentityConstraintName, other.fIdentityConstraintName)) + return false; + + if (*fSelector != *(other.fSelector)) + return false; + + XMLSize_t fieldCount = fFields->size(); + + if (fieldCount != other.fFields->size()) + return false; + + for (XMLSize_t i = 0; i < fieldCount; i++) { + if (*(fFields->elementAt(i)) != *(other.fFields->elementAt(i))) + return false; + } + + return true; +} + +bool IdentityConstraint::operator !=(const IdentityConstraint& other) const { + + return !operator==(other); +} + +// --------------------------------------------------------------------------- +// IdentityConstraint: Setter methods +// --------------------------------------------------------------------------- +void IdentityConstraint::setSelector(IC_Selector* const selector) { + + if (fSelector) { + delete fSelector; + } + + fSelector = selector; +} + + +// --------------------------------------------------------------------------- +// IdentityConstraint: cleanUp methods +// --------------------------------------------------------------------------- +void IdentityConstraint::cleanUp() { + + fMemoryManager->deallocate(fIdentityConstraintName);//delete [] fIdentityConstraintName; + fMemoryManager->deallocate(fElemName);//delete [] fElemName; + delete fFields; + delete fSelector; +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_NOCREATE(IdentityConstraint) + +void IdentityConstraint::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng.writeString(fIdentityConstraintName); + serEng.writeString(fElemName); + + serEng<* fFields; + * + ***/ + XTemplateSerializer::storeObject(fFields, serEng); + + } + else + { + + serEng.readString(fIdentityConstraintName); + serEng.readString(fElemName); + + serEng>>fSelector; + serEng>>fNamespaceURI; + /*** + * + * Deserialize RefVectorOf* fFields; + * + ***/ + XTemplateSerializer::loadObject(&fFields, 4, true, serEng); + + } + +} + +void IdentityConstraint::storeIC(XSerializeEngine& serEng + , IdentityConstraint* const ic) +{ + if (ic) + { + serEng<<(int) ic->getType(); + serEng<>type; + + switch((ICType)type) + { + case ICType_UNIQUE: + IC_Unique* ic_unique; + serEng>>ic_unique; + return ic_unique; + case ICType_KEY: + IC_Key* ic_key; + serEng>>ic_key; + return ic_key; + case ICType_KEYREF: + IC_KeyRef* ic_keyref; + serEng>>ic_keyref; + return ic_keyref; + case ICType_UNKNOWN: + return 0; + default: //we treat this same as UnKnown + return 0; + } + +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IdentityConstraint.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/IdentityConstraint.hpp b/include/xercesc/validators/schema/identity/IdentityConstraint.hpp new file mode 100644 index 0000000..b6c49b5 --- /dev/null +++ b/include/xercesc/validators/schema/identity/IdentityConstraint.hpp @@ -0,0 +1,223 @@ +/* + * 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: IdentityConstraint.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IDENTITYCONSTRAINT_HPP) +#define XERCESC_INCLUDE_GUARD_IDENTITYCONSTRAINT_HPP + + +/** + * The class act as a base class for schema identity constraints. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class IC_Selector; + +class VALIDATORS_EXPORT IdentityConstraint : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constants + // ----------------------------------------------------------------------- + enum ICType { + ICType_UNIQUE = 0, + ICType_KEY = 1, + ICType_KEYREF = 2, + ICType_UNKNOWN + }; + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + virtual ~IdentityConstraint(); + + // ----------------------------------------------------------------------- + // operators + // ----------------------------------------------------------------------- + bool operator== (const IdentityConstraint& other) const; + bool operator!= (const IdentityConstraint& other) const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + virtual short getType() const = 0; + XMLSize_t getFieldCount() const; + XMLCh* getIdentityConstraintName() const; + XMLCh* getElementName() const; + IC_Selector* getSelector() const; + int getNamespaceURI() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + void setSelector(IC_Selector* const selector); + void setNamespaceURI(int uri); + + // ----------------------------------------------------------------------- + // Access methods + // ----------------------------------------------------------------------- + void addField(IC_Field* const field); + const IC_Field* getFieldAt(const XMLSize_t index) const; + IC_Field* getFieldAt(const XMLSize_t index); + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(IdentityConstraint) + + static void storeIC(XSerializeEngine& serEng + , IdentityConstraint* const ic); + + static IdentityConstraint* loadIC(XSerializeEngine& serEng); + +protected: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + IdentityConstraint(const XMLCh* const identityConstraintName, + const XMLCh* const elementName, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IdentityConstraint(const IdentityConstraint& other); + IdentityConstraint& operator= (const IdentityConstraint& other); + + // ----------------------------------------------------------------------- + // CleanUp methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Data members + // + // fIdentityConstraintName + // The identity constraint name + // + // fElemName + // The element name + // + // fSelector + // The selector information + // + // fFields + // The field(s) information + // ----------------------------------------------------------------------- + XMLCh* fIdentityConstraintName; + XMLCh* fElemName; + IC_Selector* fSelector; + RefVectorOf* fFields; + MemoryManager* fMemoryManager; + int fNamespaceURI; +}; + + +// --------------------------------------------------------------------------- +// IdentityConstraint: Getter methods +// --------------------------------------------------------------------------- +inline XMLSize_t IdentityConstraint::getFieldCount() const { + + if (fFields) { + return fFields->size(); + } + + return 0; +} + +inline XMLCh* IdentityConstraint::getIdentityConstraintName() const { + + return fIdentityConstraintName; +} + +inline XMLCh* IdentityConstraint::getElementName() const { + + return fElemName; +} + +inline IC_Selector* IdentityConstraint::getSelector() const { + + return fSelector; +} + +inline int IdentityConstraint::getNamespaceURI() const +{ + return fNamespaceURI; +} + +// --------------------------------------------------------------------------- +// IdentityConstraint: Setter methods +// --------------------------------------------------------------------------- +inline void IdentityConstraint::setNamespaceURI(int uri) +{ + fNamespaceURI = uri; +} + +// --------------------------------------------------------------------------- +// IdentityConstraint: Access methods +// --------------------------------------------------------------------------- +inline void IdentityConstraint::addField(IC_Field* const field) { + + if (!fFields) { + fFields = new (fMemoryManager) RefVectorOf(4, true, fMemoryManager); + } + + fFields->addElement(field); +} + +inline const IC_Field* IdentityConstraint::getFieldAt(const XMLSize_t index) const { + + if (fFields) { + return (fFields->elementAt(index)); + } + + return 0; +} + +inline IC_Field* IdentityConstraint::getFieldAt(const XMLSize_t index) { + + if (fFields) { + return (fFields->elementAt(index)); + } + + return 0; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IdentityConstraint.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/IdentityConstraintHandler.cpp b/include/xercesc/validators/schema/identity/IdentityConstraintHandler.cpp new file mode 100644 index 0000000..ca7ecbc --- /dev/null +++ b/include/xercesc/validators/schema/identity/IdentityConstraintHandler.cpp @@ -0,0 +1,215 @@ +/* + * 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: IdentityConstraintHandler.cpp 803869 2009-08-13 12:56:21Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include "IdentityConstraintHandler.hpp" + +#include + +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// IdentityConstraintHandler: Constructors and Destructor +// --------------------------------------------------------------------------- +IdentityConstraintHandler::IdentityConstraintHandler(XMLScanner* const scanner + , MemoryManager* const manager) +: fScanner(scanner) +, fMemoryManager(manager) +, fMatcherStack(0) +, fValueStoreCache(0) +, fFieldActivator(0) +{ + CleanupType cleanup(this, &IdentityConstraintHandler::cleanUp); + + try { + + fMatcherStack = new (fMemoryManager) XPathMatcherStack(fMemoryManager); + fValueStoreCache = new (fMemoryManager) ValueStoreCache(fMemoryManager); + fFieldActivator = new (fMemoryManager) FieldActivator(fValueStoreCache, fMatcherStack, fMemoryManager); + + fValueStoreCache->setScanner(scanner); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +IdentityConstraintHandler::~IdentityConstraintHandler() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// IdentityConstraintHandler: methods +// --------------------------------------------------------------------------- +void IdentityConstraintHandler::deactivateContext( SchemaElementDecl* const elem + , const XMLCh* const content + , ValidationContext* validationContext /*=0*/ + , DatatypeValidator* actualValidator /*=0*/) +{ + + XMLSize_t oldCount = fMatcherStack->getMatcherCount(); + + if (oldCount || elem->getIdentityConstraintCount()) + { + + for (XMLSize_t i = oldCount; i > 0; i--) + { + XPathMatcher* matcher = fMatcherStack->getMatcherAt(i-1); + matcher->endElement(*(elem), content, validationContext, actualValidator); + } + + if (fMatcherStack->size() > 0) + { + fMatcherStack->popContext(); + } + + // handle everything *but* keyref's. + XMLSize_t newCount = fMatcherStack->getMatcherCount(); + + for (XMLSize_t j = oldCount; j > newCount; j--) + { + XPathMatcher* matcher = fMatcherStack->getMatcherAt(j-1); + IdentityConstraint* ic = matcher->getIdentityConstraint(); + + if (ic && (ic->getType() != IdentityConstraint::ICType_KEYREF)) + fValueStoreCache->transplant(ic, matcher->getInitialDepth()); + } + + // now handle keyref's... + for (XMLSize_t k = oldCount; k > newCount; k--) + { + XPathMatcher* matcher = fMatcherStack->getMatcherAt(k-1); + IdentityConstraint* ic = matcher->getIdentityConstraint(); + + if (ic && (ic->getType() == IdentityConstraint::ICType_KEYREF)) + { + ValueStore* values = fValueStoreCache->getValueStoreFor(ic, matcher->getInitialDepth()); + + if (values) { // nothing to do if nothing matched! + values->endDocumentFragment(fValueStoreCache); + } + } + } + + fValueStoreCache->endElement(); + + } +} + +void IdentityConstraintHandler::activateIdentityConstraint + ( + SchemaElementDecl* const elem + , int elemDepth + , const unsigned int uriId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , ValidationContext* validationContext /*=0*/) +{ + + XMLSize_t count = elem->getIdentityConstraintCount(); + + if (count || fMatcherStack->getMatcherCount()) + { + + fValueStoreCache->startElement(); + fMatcherStack->pushContext(); + fValueStoreCache->initValueStoresFor( elem, elemDepth); + + for (XMLSize_t i = 0; i < count; i++) + { + activateSelectorFor(elem->getIdentityConstraintAt(i), elemDepth); + } + + // call all active identity constraints + count = fMatcherStack->getMatcherCount(); + + for (XMLSize_t j = 0; j < count; j++) + { + XPathMatcher* matcher = fMatcherStack->getMatcherAt(j); + matcher->startElement(*elem, uriId, elemPrefix, attrList, attrCount, validationContext); + } + } +} + +void IdentityConstraintHandler::activateSelectorFor( IdentityConstraint* const ic + , const int initialDepth) +{ + + IC_Selector* selector = ic->getSelector(); + + if (!selector) + return; + + XPathMatcher* matcher = selector->createMatcher(fFieldActivator, initialDepth, fMemoryManager); + + fMatcherStack->addMatcher(matcher); + matcher->startDocumentFragment(); +} + +// --------------------------------------------------------------------------- +// IdentityConstraintHandler: Getter methods +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +// IdentityConstraintHandler: cleanUp methods +// --------------------------------------------------------------------------- +void IdentityConstraintHandler::cleanUp() +{ + if (fMatcherStack) + delete fMatcherStack; + + if (fValueStoreCache) + delete fValueStoreCache; + + if (fFieldActivator) + delete fFieldActivator; + +} + +void IdentityConstraintHandler::reset() +{ + fValueStoreCache->startDocument(); + fMatcherStack->clear(); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file IdentityConstraintHandler.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/IdentityConstraintHandler.hpp b/include/xercesc/validators/schema/identity/IdentityConstraintHandler.hpp new file mode 100644 index 0000000..f3cff4f --- /dev/null +++ b/include/xercesc/validators/schema/identity/IdentityConstraintHandler.hpp @@ -0,0 +1,159 @@ +/* + * 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: IdentityConstraintHandler.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_IDENTITYCONSTRAINT_HANDLER_HPP) +#define XERCESC_INCLUDE_GUARD_IDENTITYCONSTRAINT_HANDLER_HPP + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- + +class XMLScanner; +class FieldActivator; +class MemoryManager; +class XMLElementDecl; + +class VALIDATORS_EXPORT IdentityConstraintHandler: public XMemory +{ +public: + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + virtual ~IdentityConstraintHandler(); + + IdentityConstraintHandler + ( + XMLScanner* const scanner + , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager + ); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + inline XMLSize_t getMatcherCount() const; + + // ----------------------------------------------------------------------- + // Setter methods + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Access methods + // ----------------------------------------------------------------------- + inline void endDocument(); + + void deactivateContext + ( + SchemaElementDecl* const elem + , const XMLCh* const content + , ValidationContext* validationContext = 0 + , DatatypeValidator* actualValidator = 0); + + void activateIdentityConstraint + ( + SchemaElementDecl* const elem + , int elemDepth + , const unsigned int uriId + , const XMLCh* const elemPrefix + , const RefVectorOf& attrList + , const XMLSize_t attrCount + , ValidationContext* validationContext = 0 ); + + void reset(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + IdentityConstraintHandler(const IdentityConstraintHandler& other); + IdentityConstraintHandler& operator= (const IdentityConstraintHandler& other); + + // ----------------------------------------------------------------------- + // CleanUp methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Helper + // ----------------------------------------------------------------------- + void activateSelectorFor( + IdentityConstraint* const ic + , const int initialDepth + ) ; + + // ----------------------------------------------------------------------- + // Data members + // + // fMatcherStack + // Stack of active XPath matchers for identity constraints. All + // active XPath matchers are notified of startElement, characters + // and endElement callbacks in order to perform their matches. + // + // fValueStoreCache + // Cache of value stores for identity constraint fields. + // + // fFieldActivator + // Activates fields within a certain scope when a selector matches + // its xpath. + // + // ----------------------------------------------------------------------- + XMLScanner* fScanner; + MemoryManager* fMemoryManager; + + XPathMatcherStack* fMatcherStack; + ValueStoreCache* fValueStoreCache; + FieldActivator* fFieldActivator; + +}; + + +// --------------------------------------------------------------------------- +// IdentityConstraintHandler: +// --------------------------------------------------------------------------- + +inline +void IdentityConstraintHandler::endDocument() +{ + fValueStoreCache->endDocument(); +} + +inline +XMLSize_t IdentityConstraintHandler::getMatcherCount() const +{ + return fMatcherStack->getMatcherCount(); +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file IdentityConstraintHandler.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/ValueStore.cpp b/include/xercesc/validators/schema/identity/ValueStore.cpp new file mode 100644 index 0000000..cd3c86d --- /dev/null +++ b/include/xercesc/validators/schema/identity/ValueStore.cpp @@ -0,0 +1,352 @@ +/* + * 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: ValueStore.cpp 804209 2009-08-14 13:15:05Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// +// --------------------------------------------------------------------------- +// ICValueHasher: the hasher for identity constraints values +// --------------------------------------------------------------------------- +XMLSize_t ICValueHasher::getHashVal(const void* key, XMLSize_t mod) const +{ + const FieldValueMap* valueMap=(const FieldValueMap*)key; + XMLSize_t hashVal = 0; + + XMLSize_t size = valueMap->size(); + for (XMLSize_t j=0; jgetDatatypeValidatorAt(j); + while(dv && dv->getBaseValidator()) + dv = dv->getBaseValidator(); + const XMLCh* const val = valueMap->getValueAt(j); + const XMLCh* canonVal = (dv && val)?dv->getCanonicalRepresentation(val, fMemoryManager):0; + if(canonVal) + { + hashVal += XMLString::hash(canonVal, mod); + fMemoryManager->deallocate((void*)canonVal); + } + else if(val) + hashVal += XMLString::hash(val, mod); + } + + return hashVal % mod; +} + +bool ICValueHasher::equals(const void *const key1, const void *const key2) const +{ + const FieldValueMap* left=(const FieldValueMap*)key1; + const FieldValueMap* right=(const FieldValueMap*)key2; + + XMLSize_t lSize = left->size(); + XMLSize_t rSize = right->size(); + if (lSize == rSize) + { + bool matchFound = true; + + for (XMLSize_t j=0; jgetDatatypeValidatorAt(j), left->getValueAt(j), + right->getDatatypeValidatorAt(j), right->getValueAt(j))) { + matchFound = false; + break; + } + } + + if (matchFound) { // found it + return true; + } + } + return false; +} + +bool ICValueHasher::isDuplicateOf(DatatypeValidator* const dv1, const XMLCh* const val1, + DatatypeValidator* const dv2, const XMLCh* const val2) const +{ + + // if either validator's null, fall back on string comparison + if(!dv1 || !dv2) { + return (XMLString::equals(val1, val2)); + } + + bool val1IsEmpty = (val1==0 || *val1==0); + bool val2IsEmpty = (val2==0 || *val2==0); + + if (val1IsEmpty && val2IsEmpty) { + + if (dv1 == dv2) { + return true; + } + + return false; + } + + if (val1IsEmpty || val2IsEmpty) { + return false; + } + + // find the common ancestor, if there is one + DatatypeValidator* tempVal1 = dv1; + while(tempVal1) + { + DatatypeValidator* tempVal2 = dv2; + for(; tempVal2 != NULL && tempVal2 != tempVal1; tempVal2 = tempVal2->getBaseValidator()) ; + if (tempVal2) + return ((tempVal2->compare(val1, val2, fMemoryManager)) == 0); + tempVal1=tempVal1->getBaseValidator(); + } + + // if we're here it means the types weren't related. They are different: + return false; +} + +// --------------------------------------------------------------------------- +// ValueStore: Constructors and Destructor +// --------------------------------------------------------------------------- +ValueStore::ValueStore(IdentityConstraint* const ic, + XMLScanner* const scanner, + MemoryManager* const manager) + : fDoReportError(false) + , fValuesCount(0) + , fIdentityConstraint(ic) + , fValues(manager) + , fValueTuples(0) + , fScanner(scanner) + , fMemoryManager(manager) +{ + fDoReportError = (scanner && (scanner->getValidationScheme() == XMLScanner::Val_Always)); +} + + +ValueStore::~ValueStore() +{ + delete fValueTuples; +} + +// --------------------------------------------------------------------------- +// ValueStore: Helper methods +// --------------------------------------------------------------------------- +void ValueStore::addValue(FieldActivator* const fieldActivator, + IC_Field* const field, + DatatypeValidator* const dv, + const XMLCh* const value) { + + if (!fieldActivator->getMayMatch(field) && fDoReportError) { + fScanner->getValidator()->emitError(XMLValid::IC_FieldMultipleMatch); + } + + // do we even know this field? + XMLSize_t index; + bool bFound = fValues.indexOf(field, index); + + if (!bFound) { + + if (fDoReportError) { + fScanner->getValidator()->emitError(XMLValid::IC_UnknownField); + } + + return; + } + + // store value + if (!fValues.getDatatypeValidatorAt(index) && + !fValues.getValueAt(index)) { + fValuesCount++; + } + + fValues.put(field, dv, value); + + if (fValuesCount == fValues.size()) { + + // is this value as a group duplicated? + if (contains(&fValues)) { + duplicateValue(); + } + + // store values + if (!fValueTuples) { + fValueTuples = new (fMemoryManager) RefHashTableOf(107, true, ICValueHasher(fMemoryManager), fMemoryManager); + } + + FieldValueMap* pICItem = new (fMemoryManager) FieldValueMap(fValues); + fValueTuples->put(pICItem, pICItem); + } +} + +void ValueStore::append(const ValueStore* const other) { + + if (!other->fValueTuples) { + return; + } + + RefHashTableOfEnumerator iter(other->fValueTuples, false, fMemoryManager); + while(iter.hasMoreElements()) + { + FieldValueMap& valueMap = iter.nextElement(); + + if (!contains(&valueMap)) { + + if (!fValueTuples) { + fValueTuples = new (fMemoryManager) RefHashTableOf(107, true, ICValueHasher(fMemoryManager), fMemoryManager); + } + + FieldValueMap* pICItem = new (fMemoryManager) FieldValueMap(valueMap); + fValueTuples->put(pICItem, pICItem); + } + } +} + +void ValueStore::startValueScope() { + + fValuesCount = 0; + + XMLSize_t count = fIdentityConstraint->getFieldCount(); + + for (XMLSize_t i = 0; i < count; i++) { + fValues.put(fIdentityConstraint->getFieldAt(i), 0, 0); + } +} + +void ValueStore::endValueScope() { + + if (fValuesCount == 0) { + + if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEY && fDoReportError) { + fScanner->getValidator()->emitError(XMLValid::IC_AbsentKeyValue, + fIdentityConstraint->getElementName()); + } + + return; + } + + // do we have enough values? + if ((fValuesCount != fIdentityConstraint->getFieldCount()) && fDoReportError) { + + if(fIdentityConstraint->getType()==IdentityConstraint::ICType_KEY) + { + fScanner->getValidator()->emitError(XMLValid::IC_KeyNotEnoughValues, + fIdentityConstraint->getElementName(), fIdentityConstraint->getIdentityConstraintName()); + } + } +} + +bool ValueStore::contains(const FieldValueMap* const other) { + + if (fValueTuples) + return fValueTuples->get(other)!=0; + + return false; +} + +void ValueStore::clear() +{ + fValuesCount=0; + fValues.clear(); + if(fValueTuples) + fValueTuples->removeAll(); +} + +// --------------------------------------------------------------------------- +// ValueStore: Document handling methods +// --------------------------------------------------------------------------- +void ValueStore::endDocumentFragment(ValueStoreCache* const valueStoreCache) { + + if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEYREF) { + + // verify references + // get the key store corresponding (if it exists): + ValueStore* keyValueStore = valueStoreCache->getGlobalValueStoreFor(((IC_KeyRef*) fIdentityConstraint)->getKey()); + + if (!keyValueStore) { + + if (fDoReportError) { + fScanner->getValidator()->emitError(XMLValid::IC_KeyRefOutOfScope, + fIdentityConstraint->getIdentityConstraintName()); + } + + return; + } + + if(fValueTuples) + { + RefHashTableOfEnumerator iter(fValueTuples, false, fMemoryManager); + while(iter.hasMoreElements()) + { + FieldValueMap& valueMap = iter.nextElement(); + + if (!keyValueStore->contains(&valueMap) && fDoReportError) { + + fScanner->getValidator()->emitError(XMLValid::IC_KeyNotFound, + fIdentityConstraint->getElementName()); + } + } + } + } +} + +// --------------------------------------------------------------------------- +// ValueStore: Error reporting methods +// --------------------------------------------------------------------------- +void ValueStore::reportNilError(IdentityConstraint* const ic) { + + if (fDoReportError && ic->getType() == IdentityConstraint::ICType_KEY) { + fScanner->getValidator()->emitError(XMLValid::IC_KeyMatchesNillable, + ic->getElementName()); + } +} + +void ValueStore::duplicateValue() { + + if (fDoReportError) { + + switch (fIdentityConstraint->getType()) { + case IdentityConstraint::ICType_UNIQUE: + { + fScanner->getValidator()->emitError(XMLValid::IC_DuplicateUnique, + fIdentityConstraint->getElementName()); + break; + } + case IdentityConstraint::ICType_KEY: + { + fScanner->getValidator()->emitError(XMLValid::IC_DuplicateKey, + fIdentityConstraint->getElementName()); + break; + } + } + } +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file ValueStore.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/ValueStore.hpp b/include/xercesc/validators/schema/identity/ValueStore.hpp new file mode 100644 index 0000000..1d52c48 --- /dev/null +++ b/include/xercesc/validators/schema/identity/ValueStore.hpp @@ -0,0 +1,146 @@ +/* + * 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: ValueStore.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_VALUESTORE_HPP) +#define XERCESC_INCLUDE_GUARD_VALUESTORE_HPP + +/** + * This class stores values associated to an identity constraint. + * Each value stored corresponds to a field declared for the identity + * constraint. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class FieldActivator; +class IdentityConstraint; +class XMLScanner; +class ValueStoreCache; + +struct ICValueHasher +{ + ICValueHasher(MemoryManager* const manager) : fMemoryManager(manager) {} + + XMLSize_t getHashVal(const void* key, XMLSize_t mod) const; + bool equals(const void *const key1, const void *const key2) const; + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + /** + * Returns whether a field associated value + * is a duplicate of another associated value. + * It is a duplicate only if either of these conditions are true: + * - The Datatypes are the same or related by derivation and the values + * are in the same valuespace. + * - The datatypes are unrelated and the values are Stringwise identical. + */ + bool isDuplicateOf(DatatypeValidator* const dv1, const XMLCh* const val1, + DatatypeValidator* const dv2, const XMLCh* const val2) const; + + + MemoryManager* fMemoryManager; +}; + +class VALIDATORS_EXPORT ValueStore : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + ValueStore(IdentityConstraint* const ic, + XMLScanner* const scanner, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~ValueStore(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + IdentityConstraint* getIdentityConstraint() const; + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void append(const ValueStore* const other); + void startValueScope(); + void endValueScope(); + void addValue(FieldActivator* const fieldActivator, + IC_Field* const field, + DatatypeValidator* const dv, + const XMLCh* const value); + bool contains(const FieldValueMap* const other); + void clear(); + + // ----------------------------------------------------------------------- + // Document handling methods + // ----------------------------------------------------------------------- + void endDocumentFragment(ValueStoreCache* const valueStoreCache); + + // ----------------------------------------------------------------------- + // Error reporting methods + // ----------------------------------------------------------------------- + void duplicateValue(); + void reportNilError(IdentityConstraint* const ic); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ValueStore(const ValueStore& other); + ValueStore& operator= (const ValueStore& other); + + // ----------------------------------------------------------------------- + // Data + // ----------------------------------------------------------------------- + bool fDoReportError; + XMLSize_t fValuesCount; + IdentityConstraint* fIdentityConstraint; + FieldValueMap fValues; + RefHashTableOf* fValueTuples; + XMLScanner* fScanner; // for error reporting - REVISIT + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// ValueStore: Getter methods +// --------------------------------------------------------------------------- +inline IdentityConstraint* +ValueStore::getIdentityConstraint() const { + return fIdentityConstraint; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file ValueStore.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/ValueStoreCache.cpp b/include/xercesc/validators/schema/identity/ValueStoreCache.cpp new file mode 100644 index 0000000..ee3258f --- /dev/null +++ b/include/xercesc/validators/schema/identity/ValueStoreCache.cpp @@ -0,0 +1,184 @@ +/* + * 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: ValueStoreCache.cpp 708224 2008-10-27 16:02:26Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// ValueStoreCache: Constructors and Destructor +// --------------------------------------------------------------------------- +ValueStoreCache::ValueStoreCache(MemoryManager* const manager) + : fValueStores(0) + , fGlobalICMap(0) + , fIC2ValueStoreMap(0) + , fGlobalMapStack(0) + , fScanner(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &ValueStoreCache::cleanUp); + + try { + init(); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +ValueStoreCache::~ValueStoreCache() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// ValueStoreCache: Document handling methods +// --------------------------------------------------------------------------- +void ValueStoreCache::startDocument() { + + fIC2ValueStoreMap->removeAll(); + fGlobalICMap->removeAll(); + fValueStores->removeAllElements(); + fGlobalMapStack->removeAllElements(); +} + +void ValueStoreCache::startElement() { + + fGlobalMapStack->push(fGlobalICMap); + fGlobalICMap = new (fMemoryManager) RefHashTableOf + ( + 13 + , false + , fMemoryManager + ); +} + +void ValueStoreCache::endElement() { + + if (fGlobalMapStack->empty()) { + return; // must be an invalid doc! + } + + RefHashTableOf* oldMap = fGlobalMapStack->pop(); + RefHashTableOfEnumerator mapEnum(oldMap, false, fMemoryManager); +// Janitor > janMap(oldMap); + + while (mapEnum.hasMoreElements()) { + + ValueStore& oldVal = mapEnum.nextElement(); + IdentityConstraint* ic = oldVal.getIdentityConstraint(); + ValueStore* currVal = fGlobalICMap->get(ic); + + if (!currVal) { + fGlobalICMap->put(ic, &oldVal); + } + else { + currVal->append(&oldVal); + } + } + delete oldMap; +} + +// --------------------------------------------------------------------------- +// ValueStoreCache: Helper methods +// --------------------------------------------------------------------------- +void ValueStoreCache::cleanUp() { + + delete fIC2ValueStoreMap; + delete fGlobalICMap; + delete fGlobalMapStack; + delete fValueStores; +} + +void ValueStoreCache::init() { + + fValueStores = new (fMemoryManager) RefVectorOf(8, false, fMemoryManager); + fGlobalICMap = new (fMemoryManager) RefHashTableOf + ( + 13 + , false + , fMemoryManager + ); + fIC2ValueStoreMap = new (fMemoryManager) RefHash2KeysTableOf + ( + 13 + , true + , fMemoryManager + ); + fGlobalMapStack = new (fMemoryManager) RefStackOf >(8, true, fMemoryManager); +} + +void ValueStoreCache::initValueStoresFor(SchemaElementDecl* const elemDecl, + const int initialDepth) { + + // initialize value stores for unique fields + XMLSize_t icCount = elemDecl->getIdentityConstraintCount(); + + for (XMLSize_t i=0; igetIdentityConstraintAt(i); + ValueStore* valueStore=fIC2ValueStoreMap->get(ic, initialDepth); + if(valueStore==0) + { + valueStore = new (fMemoryManager) ValueStore(ic, fScanner, fMemoryManager); + fIC2ValueStoreMap->put(ic, initialDepth, valueStore); + } + else + valueStore->clear(); + fValueStores->addElement(valueStore); + } +} + +void ValueStoreCache::transplant(IdentityConstraint* const ic, const int initialDepth) { + + if (ic->getType() == IdentityConstraint::ICType_KEYREF) { + return; + } + + ValueStore* newVals = fIC2ValueStoreMap->get(ic, initialDepth); + ValueStore* currVals = fGlobalICMap->get(ic); + + if (currVals) { + currVals->append(newVals); + } else { + fGlobalICMap->put(ic, newVals); + } +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file ValueStoreCache.cpp + */ diff --git a/include/xercesc/validators/schema/identity/ValueStoreCache.hpp b/include/xercesc/validators/schema/identity/ValueStoreCache.hpp new file mode 100644 index 0000000..91fa4bf --- /dev/null +++ b/include/xercesc/validators/schema/identity/ValueStoreCache.hpp @@ -0,0 +1,172 @@ +/* + * 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: ValueStoreCache.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_VALUESTORECACHE_HPP) +#define XERCESC_INCLUDE_GUARD_VALUESTORECACHE_HPP + +/** + * This class is used to store the values for identity constraints. + * + * Sketch of algorithm: + * - When a constraint is first encountered, its values are stored in the + * (local) fIC2ValueStoreMap; + * - Once it is validated (i.e., when it goes out of scope), its values are + * merged into the fGlobalICMap; + * - As we encounter keyref's, we look at the global table to validate them. + * - Validation always occurs against the fGlobalIDConstraintMap (which + * comprises all the "eligible" id constraints). When an endelement is + * found, this Hashtable is merged with the one below in the stack. When a + * start tag is encountered, we create a new fGlobalICMap. + * i.e., the top of the fGlobalIDMapStack always contains the preceding + * siblings' eligible id constraints; the fGlobalICMap contains + * descendants+self. Keyrefs can only match descendants+self. + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class ValueStore; +class SchemaElementDecl; +class XMLScanner; + + +class VALIDATORS_EXPORT ValueStoreCache : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + ValueStoreCache(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~ValueStoreCache(); + + // ----------------------------------------------------------------------- + // Setter Methods + // ----------------------------------------------------------------------- + void setScanner(XMLScanner* const scanner); + + // ----------------------------------------------------------------------- + // Document Handling methods + // ----------------------------------------------------------------------- + void startDocument(); + void startElement(); + void endElement(); + void endDocument(); + + // ----------------------------------------------------------------------- + // Initialization methods + // ----------------------------------------------------------------------- + void initValueStoresFor(SchemaElementDecl* const elemDecl, const int initialDepth); + + + // ----------------------------------------------------------------------- + // Access methods + // ----------------------------------------------------------------------- + ValueStore* getValueStoreFor(const IC_Field* const field, const int initialDepth); + ValueStore* getValueStoreFor(const IdentityConstraint* const ic, const int initialDepth); + ValueStore* getGlobalValueStoreFor(const IdentityConstraint* const ic); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + /** This method takes the contents of the (local) ValueStore associated + * with ic and moves them into the global hashtable, if ic is a + * or a . If it's a , then we leave it for later. + */ + void transplant(IdentityConstraint* const ic, const int initialDepth); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + ValueStoreCache(const ValueStoreCache& other); + ValueStoreCache& operator= (const ValueStoreCache& other); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void init(); + void cleanUp(); + + // ----------------------------------------------------------------------- + // Data + // ----------------------------------------------------------------------- + RefVectorOf* fValueStores; + RefHashTableOf* fGlobalICMap; + RefHash2KeysTableOf* fIC2ValueStoreMap; + RefStackOf >* fGlobalMapStack; + XMLScanner* fScanner; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// ValueStoreCache: Access methods +// --------------------------------------------------------------------------- +inline void ValueStoreCache::setScanner(XMLScanner* const scanner) { + + fScanner = scanner; +} + +// --------------------------------------------------------------------------- +// ValueStoreCache: Access methods +// --------------------------------------------------------------------------- +inline ValueStore* +ValueStoreCache::getValueStoreFor(const IC_Field* const field, const int initialDepth) { + + return fIC2ValueStoreMap->get(field->getIdentityConstraint(), initialDepth); +} + +inline ValueStore* +ValueStoreCache::getValueStoreFor(const IdentityConstraint* const ic, const int initialDepth) { + + return fIC2ValueStoreMap->get(ic, initialDepth); +} + +inline ValueStore* +ValueStoreCache::getGlobalValueStoreFor(const IdentityConstraint* const ic) { + + return fGlobalICMap->get(ic); +} + +// --------------------------------------------------------------------------- +// ValueStoreCache: Document handling methods +// --------------------------------------------------------------------------- +inline void ValueStoreCache::endDocument() { +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file ValueStoreCache.hpp + */ diff --git a/include/xercesc/validators/schema/identity/XPathException.hpp b/include/xercesc/validators/schema/identity/XPathException.hpp new file mode 100644 index 0000000..af59aa4 --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathException.hpp @@ -0,0 +1,34 @@ +/* + * 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: XPathException.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XPATHEXCEPTION_HPP) +#define XERCESC_INCLUDE_GUARD_XPATHEXCEPTION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +MakeXMLException(XPathException, VALIDATORS_EXPORT) + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/include/xercesc/validators/schema/identity/XPathMatcher.cpp b/include/xercesc/validators/schema/identity/XPathMatcher.cpp new file mode 100644 index 0000000..9e6bbbd --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathMatcher.cpp @@ -0,0 +1,413 @@ +/* + * 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: XPathMatcher.cpp 804234 2009-08-14 14:20:16Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// XPathMatcher: Constructors and Destructor +// --------------------------------------------------------------------------- +XPathMatcher::XPathMatcher( XercesXPath* const xpath + , MemoryManager* const manager) + : fLocationPathSize(0) + , fMatched(0) + , fNoMatchDepth(0) + , fCurrentStep(0) + , fStepIndexes(0) + , fLocationPaths(0) + , fIdentityConstraint(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XPathMatcher::cleanUp); + + try { + init(xpath); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +XPathMatcher::XPathMatcher(XercesXPath* const xpath, + IdentityConstraint* const ic, + MemoryManager* const manager) + : fLocationPathSize(0) + , fMatched(0) + , fNoMatchDepth(0) + , fCurrentStep(0) + , fStepIndexes(0) + , fLocationPaths(0) + , fIdentityConstraint(ic) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XPathMatcher::cleanUp); + + try { + init(xpath); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + + +XPathMatcher::~XPathMatcher() +{ + cleanUp(); +} + +// --------------------------------------------------------------------------- +// XPathMatcher: Helper methods +// --------------------------------------------------------------------------- +void XPathMatcher::init(XercesXPath* const xpath) { + + if (xpath) { + + fLocationPaths = xpath->getLocationPaths(); + fLocationPathSize = (fLocationPaths ? fLocationPaths->size() : 0); + + if (fLocationPathSize) { + + fStepIndexes = new (fMemoryManager) RefVectorOf >(fLocationPathSize, true, fMemoryManager); + fCurrentStep = (XMLSize_t*) fMemoryManager->allocate + ( + fLocationPathSize * sizeof(XMLSize_t) + );//new int[fLocationPathSize]; + fNoMatchDepth = (XMLSize_t*) fMemoryManager->allocate + ( + fLocationPathSize * sizeof(XMLSize_t) + );//new int[fLocationPathSize]; + fMatched = (unsigned char*) fMemoryManager->allocate + ( + fLocationPathSize * sizeof(unsigned char) + );//new int[fLocationPathSize]; + + for(XMLSize_t i=0; i < fLocationPathSize; i++) { + fStepIndexes->addElement(new (fMemoryManager) ValueStackOf(8, fMemoryManager)); + } + } + } +} + + +// --------------------------------------------------------------------------- +// XPathMatcher: XMLDocumentHandler methods +// --------------------------------------------------------------------------- +void XPathMatcher::startDocumentFragment() { + + for(XMLSize_t i = 0; i < fLocationPathSize; i++) { + + fStepIndexes->elementAt(i)->removeAllElements(); + fCurrentStep[i] = 0; + fNoMatchDepth[i] = 0; + fMatched[i] = 0; + } +} + +void XPathMatcher::startElement(const XMLElementDecl& elemDecl, + const unsigned int urlId, + const XMLCh* const elemPrefix, + const RefVectorOf& attrList, + const XMLSize_t attrCount, + ValidationContext* validationContext /*=0*/) { + + for (XMLSize_t i = 0; i < fLocationPathSize; i++) { + + // push context + XMLSize_t startStep = fCurrentStep[i]; + fStepIndexes->elementAt(i)->push(startStep); + + // try next xpath, if not matching + if ((fMatched[i] & XP_MATCHED_D) == XP_MATCHED || fNoMatchDepth[i] > 0) { + fNoMatchDepth[i]++; + continue; + } + + if((fMatched[i] & XP_MATCHED_D) == XP_MATCHED_D) { + fMatched[i] = XP_MATCHED_DP; + } + + // consume self::node() steps + XercesLocationPath* locPath = fLocationPaths->elementAt(i); + XMLSize_t stepSize = locPath->getStepSize(); + + while (fCurrentStep[i] < stepSize && + locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_SELF) { + fCurrentStep[i]++; + } + + if (fCurrentStep[i] == stepSize) { + + fMatched[i] = XP_MATCHED; + continue; + } + + // now if the current step is a descendant step, we let the next + // step do its thing; if it fails, we reset ourselves + // to look at this step for next time we're called. + // so first consume all descendants: + XMLSize_t descendantStep = fCurrentStep[i]; + + while (fCurrentStep[i] < stepSize && + locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_DESCENDANT) { + fCurrentStep[i]++; + } + + bool sawDescendant = fCurrentStep[i] > descendantStep; + if (fCurrentStep[i] == stepSize) { + + fNoMatchDepth[i]++; + continue; + } + + // match child::... step, if haven't consumed any self::node() + if ((fCurrentStep[i] == startStep || fCurrentStep[i] > descendantStep) && + locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_CHILD) { + + XercesStep* step = locPath->getStep(fCurrentStep[i]); + XercesNodeTest* nodeTest = step->getNodeTest(); + + QName elemQName(elemPrefix, elemDecl.getElementName()->getLocalPart(), urlId, fMemoryManager); + if (!matches(nodeTest, &elemQName)) { + + if(fCurrentStep[i] > descendantStep) { + fCurrentStep[i] = descendantStep; + continue; + } + + fNoMatchDepth[i]++; + continue; + } + + fCurrentStep[i]++; + } + + if (fCurrentStep[i] == stepSize) { + + if (sawDescendant) { + + fCurrentStep[i] = descendantStep; + fMatched[i] = XP_MATCHED_D; + } + else { + fMatched[i] = XP_MATCHED; + } + + continue; + } + + // match attribute::... step + if (fCurrentStep[i] < stepSize && + locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_ATTRIBUTE) { + + if (attrCount) { + + XercesNodeTest* nodeTest = locPath->getStep(fCurrentStep[i])->getNodeTest(); + + for (XMLSize_t attrIndex = 0; attrIndex < attrCount; attrIndex++) { + + const XMLAttr* curDef = attrList.elementAt(attrIndex); + + if (matches(nodeTest, curDef->getAttName())) { + + fCurrentStep[i]++; + + if (fCurrentStep[i] == stepSize) { + + fMatched[i] = XP_MATCHED_A; + + SchemaAttDef* attDef = ((SchemaElementDecl&) elemDecl).getAttDef(curDef->getName(), curDef->getURIId()); + DatatypeValidator* dv = (attDef) ? attDef->getDatatypeValidator() : 0; + const XMLCh* value = curDef->getValue(); + // store QName using their Clark name + if(dv && dv->getType()==DatatypeValidator::QName) + { + int index=XMLString::indexOf(value, chColon); + if(index==-1) + matched(value, dv, false); + else + { + XMLBuffer buff(1023, fMemoryManager); + buff.append(chOpenCurly); + if(validationContext) + { + XMLCh* prefix=(XMLCh*)fMemoryManager->allocate((index+1)*sizeof(XMLCh)); + ArrayJanitor janPrefix(prefix, fMemoryManager); + XMLString::subString(prefix, value, 0, (XMLSize_t)index, fMemoryManager); + buff.append(validationContext->getURIForPrefix(prefix)); + } + buff.append(chCloseCurly); + buff.append(value+index+1); + matched(buff.getRawBuffer(), dv, false); + } + } + else + matched(value, dv, false); + } + break; + } + } + } + + if ((fMatched[i] & XP_MATCHED) != XP_MATCHED) { + + if(fCurrentStep[i] > descendantStep) { + + fCurrentStep[i] = descendantStep; + continue; + } + + fNoMatchDepth[i]++; + } + } + } +} + +void XPathMatcher::endElement(const XMLElementDecl& elemDecl, + const XMLCh* const elemContent, + ValidationContext* validationContext /*=0*/, + DatatypeValidator* actualValidator /*=0*/) { + + for(XMLSize_t i = 0; i < fLocationPathSize; i++) { + + // go back a step + fCurrentStep[i] = fStepIndexes->elementAt(i)->pop(); + + // don't do anything, if not matching + if (fNoMatchDepth[i] > 0) { + fNoMatchDepth[i]--; + } + // signal match, if appropriate + else { + + if (fMatched[i] == 0) + continue; + + if ((fMatched[i] & XP_MATCHED_A) == XP_MATCHED_A) { + fMatched[i] = 0; + continue; + } + + DatatypeValidator* dv = actualValidator?actualValidator:((SchemaElementDecl*) &elemDecl)->getDatatypeValidator(); + bool isNillable = (((SchemaElementDecl *) &elemDecl)->getMiscFlags() & SchemaSymbols::XSD_NILLABLE) != 0; + + // store QName using their Clark name + if(dv && dv->getType()==DatatypeValidator::QName) + { + int index=XMLString::indexOf(elemContent, chColon); + if(index==-1) + matched(elemContent, dv, isNillable); + else + { + XMLBuffer buff(1023, fMemoryManager); + buff.append(chOpenCurly); + if(validationContext) + { + XMLCh* prefix=(XMLCh*)fMemoryManager->allocate((index+1)*sizeof(XMLCh)); + ArrayJanitor janPrefix(prefix, fMemoryManager); + XMLString::subString(prefix, elemContent, 0, (XMLSize_t)index, fMemoryManager); + buff.append(validationContext->getURIForPrefix(prefix)); + } + buff.append(chCloseCurly); + buff.append(elemContent+index+1); + matched(buff.getRawBuffer(), dv, isNillable); + } + } + else + matched(elemContent, dv, isNillable); + fMatched[i] = 0; + } + } +} + + +// --------------------------------------------------------------------------- +// XPathMatcher: Match methods +// --------------------------------------------------------------------------- +unsigned char XPathMatcher::isMatched() { + + // xpath has been matched if any one of the members of the union have matched. + for (XMLSize_t i=0; i < fLocationPathSize; i++) { + if (((fMatched[i] & XP_MATCHED) == XP_MATCHED) + && ((fMatched[i] & XP_MATCHED_DP) != XP_MATCHED_DP)) + return fMatched[i]; + } + + return 0; +} + +void XPathMatcher::matched(const XMLCh* const, + DatatypeValidator* const, + const bool) { + return; +} + +bool XPathMatcher::matches(const XercesNodeTest* nodeTest, const QName* qName) +{ + if (nodeTest->getType() == XercesNodeTest::NodeType_QNAME) { + return (*nodeTest->getName())==(*qName); + } + if (nodeTest->getType() == XercesNodeTest::NodeType_NAMESPACE) { + return nodeTest->getName()->getURI() == qName->getURI(); + } + // NodeType_WILDCARD + return true; +} + +// --------------------------------------------------------------------------- +// XPathMatcher: Match methods +// --------------------------------------------------------------------------- +int XPathMatcher::getInitialDepth() const +{ + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Regex_NotSupported, fMemoryManager); + return 0; // to make some compilers happy +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file XPathMatcher.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/XPathMatcher.hpp b/include/xercesc/validators/schema/identity/XPathMatcher.hpp new file mode 100644 index 0000000..dfdbd8a --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathMatcher.hpp @@ -0,0 +1,182 @@ +/* + * 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: XPathMatcher.hpp 803869 2009-08-13 12:56:21Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XPATHMATCHER_HPP) +#define XERCESC_INCLUDE_GUARD_XPATHMATCHER_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declaration +// --------------------------------------------------------------------------- +class XMLElementDecl; +class XercesXPath; +class IdentityConstraint; +class DatatypeValidator; +class XMLStringPool; +class XercesLocationPath; +class XMLAttr; +class XercesNodeTest; +class QName; +class ValidationContext; + +class VALIDATORS_EXPORT XPathMatcher : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XPathMatcher(XercesXPath* const xpath, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + XPathMatcher(XercesXPath* const xpath, + IdentityConstraint* const ic, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + virtual ~XPathMatcher(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + IdentityConstraint* getIdentityConstraint() const { return fIdentityConstraint; } + MemoryManager* getMemoryManager() const { return fMemoryManager; } + + // ----------------------------------------------------------------------- + // Match methods + // ----------------------------------------------------------------------- + /** + * Returns true if XPath has been matched. + */ + unsigned char isMatched(); + virtual int getInitialDepth() const; + + // ----------------------------------------------------------------------- + // XMLDocumentHandler methods + // ----------------------------------------------------------------------- + virtual void startDocumentFragment(); + virtual void startElement(const XMLElementDecl& elemDecl, + const unsigned int urlId, + const XMLCh* const elemPrefix, + const RefVectorOf& attrList, + const XMLSize_t attrCount, + ValidationContext* validationContext = 0); + virtual void endElement(const XMLElementDecl& elemDecl, + const XMLCh* const elemContent, + ValidationContext* validationContext = 0, + DatatypeValidator* actualValidator = 0); + + enum + { + XP_MATCHED = 1 // matched any way + , XP_MATCHED_A = 3 // matched on the attribute axis + , XP_MATCHED_D = 5 // matched on the descendant-or-self axixs + , XP_MATCHED_DP = 13 // matched some previous (ancestor) node on the + // descendant-or-self-axis, but not this node + }; + +protected: + + // ----------------------------------------------------------------------- + // Match methods + // ----------------------------------------------------------------------- + /** + * This method is called when the XPath handler matches the XPath + * expression. Subclasses can override this method to provide default + * handling upon a match. + */ + virtual void matched(const XMLCh* const content, + DatatypeValidator* const dv, const bool isNil); + + bool matches(const XercesNodeTest* nodeTest, const QName* qName); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XPathMatcher(const XPathMatcher&); + XPathMatcher& operator=(const XPathMatcher&); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void init(XercesXPath* const xpath); + void cleanUp(); + + // ----------------------------------------------------------------------- + // Data members + // + // fMatched + // Indicates whether XPath has been matched or not + // + // fNoMatchDepth + // Indicates whether matching is successful for the given xpath + // expression. + // + // fCurrentStep + // Stores current step. + // + // fStepIndexes + // Integer stack of step indexes. + // + // fLocationPaths + // fLocationPathSize + // XPath location path, and its size. + // + // fIdentityConstraint + // The identity constraint we're the matcher for. Only used for + // selectors. + // + // ----------------------------------------------------------------------- + XMLSize_t fLocationPathSize; + unsigned char* fMatched; + XMLSize_t* fNoMatchDepth; + XMLSize_t* fCurrentStep; + RefVectorOf >* fStepIndexes; + RefVectorOf* fLocationPaths; + IdentityConstraint* fIdentityConstraint; + MemoryManager* fMemoryManager; +}; + +// --------------------------------------------------------------------------- +// XPathMatcher: Helper methods +// --------------------------------------------------------------------------- +inline void XPathMatcher::cleanUp() { + + fMemoryManager->deallocate(fMatched);//delete [] fMatched; + fMemoryManager->deallocate(fNoMatchDepth);//delete [] fNoMatchDepth; + fMemoryManager->deallocate(fCurrentStep);//delete [] fCurrentStep; + delete fStepIndexes; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XPathMatcher.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/XPathMatcherStack.cpp b/include/xercesc/validators/schema/identity/XPathMatcherStack.cpp new file mode 100644 index 0000000..0b5d546 --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathMatcherStack.cpp @@ -0,0 +1,86 @@ +/* + * 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: XPathMatcherStack.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// XPathMatherStack: Constructors and Destructor +// --------------------------------------------------------------------------- +XPathMatcherStack::XPathMatcherStack(MemoryManager* const manager) + : fMatchersCount(0) + , fContextStack(0) + , fMatchers(0) +{ + CleanupType cleanup(this, &XPathMatcherStack::cleanUp); + + try { + fContextStack = new (manager) ValueStackOf(8, manager); + fMatchers = new (manager) RefVectorOf(8, true, manager); + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XPathMatcherStack::~XPathMatcherStack() { + + cleanUp(); +} + +// --------------------------------------------------------------------------- +// XPathMatcherStack: Private helper methods. +// --------------------------------------------------------------------------- +void XPathMatcherStack::cleanUp() +{ + delete fContextStack; + delete fMatchers; +} + +// --------------------------------------------------------------------------- +// XPathMatherStack: Clear methods +// --------------------------------------------------------------------------- +void XPathMatcherStack::clear() { + + fContextStack->removeAllElements(); + fMatchers->removeAllElements(); + fMatchersCount = 0; +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file XPathMatcherStack.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/XPathMatcherStack.hpp b/include/xercesc/validators/schema/identity/XPathMatcherStack.hpp new file mode 100644 index 0000000..273b38a --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathMatcherStack.hpp @@ -0,0 +1,139 @@ +/* + * 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: XPathMatcherStack.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XPATHMATCHERSTACK_HPP) +#define XERCESC_INCLUDE_GUARD_XPATHMATCHERSTACK_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class VALIDATORS_EXPORT XPathMatcherStack : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XPathMatcherStack(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~XPathMatcherStack(); + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + XPathMatcher* getMatcherAt(const XMLSize_t index) const; + XMLSize_t getMatcherCount() const; + XMLSize_t size() const; + + // ----------------------------------------------------------------------- + // Access methods + // ----------------------------------------------------------------------- + void addMatcher(XPathMatcher* const matcher); + + // ----------------------------------------------------------------------- + // Stack methods + // ----------------------------------------------------------------------- + void pushContext(); + void popContext(); + + // ----------------------------------------------------------------------- + // Reset methods + // ----------------------------------------------------------------------- + void clear(); + +private: + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XPathMatcherStack(const XPathMatcherStack& other); + XPathMatcherStack& operator= (const XPathMatcherStack& other); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + unsigned int fMatchersCount; + ValueStackOf* fContextStack; + RefVectorOf* fMatchers; +}; + +// --------------------------------------------------------------------------- +// XPathMatcherStack: Getter methods +// --------------------------------------------------------------------------- +inline XMLSize_t XPathMatcherStack::size() const { + + return fContextStack->size(); +} + +inline XMLSize_t XPathMatcherStack::getMatcherCount() const { + + return fMatchersCount; +} + +inline XPathMatcher* +XPathMatcherStack::getMatcherAt(const XMLSize_t index) const { + + return fMatchers->elementAt(index); +} + +// --------------------------------------------------------------------------- +// XPathMatcherStack: Stack methods +// --------------------------------------------------------------------------- +inline void XPathMatcherStack::pushContext() { + + fContextStack->push(fMatchersCount); +} + +inline void XPathMatcherStack::popContext() { + + fMatchersCount = fContextStack->pop(); +} + +// --------------------------------------------------------------------------- +// XPathMatcherStack: Access methods +// --------------------------------------------------------------------------- +inline void XPathMatcherStack::addMatcher(XPathMatcher* const matcher) { + + if (fMatchersCount == fMatchers->size()) { + + fMatchers->addElement(matcher); + fMatchersCount++; + } + else { + fMatchers->setElementAt(matcher, fMatchersCount++); + } +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XPathMatcherStack.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/XPathSymbols.cpp b/include/xercesc/validators/schema/identity/XPathSymbols.cpp new file mode 100644 index 0000000..766b834 --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathSymbols.cpp @@ -0,0 +1,161 @@ +/* + * 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: XPathSymbols.cpp 471747 2006-11-06 14:31:56Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// SchemaSymbols: Static data +// --------------------------------------------------------------------------- +const XMLCh XPathSymbols::fgSYMBOL_AND[] = +{ + chLatin_a, chLatin_n, chLatin_d, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_OR[] = +{ + chLatin_o, chLatin_r, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_MOD[] = +{ + chLatin_m, chLatin_o, chLatin_d, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_DIV[] = +{ + chLatin_d, chLatin_i, chLatin_v, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_COMMENT[] = +{ + chLatin_c, chLatin_o, chLatin_m, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_TEXT[] = +{ + chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_PI[] = +{ + chLatin_p, chLatin_r, chLatin_o, chLatin_c, chLatin_e, chLatin_s, chLatin_s, + chLatin_i, chLatin_n, chLatin_g, chDash, chLatin_i, chLatin_n, chLatin_s, chLatin_t, + chLatin_r, chLatin_u, chLatin_c, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_NODE[] = +{ + chLatin_n, chLatin_o, chLatin_d, chLatin_e, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_ANCESTOR[] = +{ + chLatin_a, chLatin_n, chLatin_c, chLatin_e, chLatin_s, chLatin_t, chLatin_o, + chLatin_r, chNull +}; + + +const XMLCh XPathSymbols::fgSYMBOL_ANCESTOR_OR_SELF[] = +{ + chLatin_a, chLatin_n, chLatin_c, chLatin_e, chLatin_s, chLatin_t, chLatin_o, + chLatin_r, chDash, chLatin_o, chLatin_r, chDash, chLatin_s, chLatin_e, + chLatin_l, chLatin_f, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_ATTRIBUTE[] = +{ + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, + chLatin_t, chLatin_e, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_CHILD[] = +{ + chLatin_c, chLatin_h, chLatin_i, chLatin_l, chLatin_d, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_DESCENDANT[] = +{ + chLatin_d, chLatin_e, chLatin_s, chLatin_c, chLatin_e, chLatin_n, chLatin_d, + chLatin_a, chLatin_n, chLatin_t, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_DESCENDANT_OR_SELF[] = +{ + chLatin_d, chLatin_e, chLatin_s, chLatin_c, chLatin_e, chLatin_n, chLatin_d, + chLatin_a, chLatin_n, chLatin_t, chDash, chLatin_o, chLatin_r, chDash, chLatin_s, + chLatin_e, chLatin_l, chLatin_f, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_FOLLOWING[] = +{ + chLatin_f, chLatin_o, chLatin_l, chLatin_l, chLatin_o, chLatin_w, chLatin_i, + chLatin_n, chLatin_g, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_FOLLOWING_SIBLING[] = +{ + chLatin_f, chLatin_o, chLatin_l, chLatin_l, chLatin_o, chLatin_w, chLatin_i, + chLatin_n, chLatin_g, chDash, chLatin_s, chLatin_i, chLatin_b, chLatin_l, chLatin_i, + chLatin_n, chLatin_g, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_NAMESPACE[] = +{ + chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, + chLatin_c, chLatin_e, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_PARENT[] = +{ + chLatin_p, chLatin_a, chLatin_r, chLatin_e, chLatin_n, chLatin_t, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_PRECEDING[] = +{ + chLatin_p, chLatin_r, chLatin_e, chLatin_c, chLatin_e, chLatin_d, chLatin_i, + chLatin_n, chLatin_g, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_PRECEDING_SIBLING[] = +{ + chLatin_p, chLatin_r, chLatin_e, chLatin_c, chLatin_e, chLatin_d, chLatin_i, + chLatin_n, chLatin_g, chDash, chLatin_s, chLatin_i, chLatin_b, chLatin_l, chLatin_i, + chLatin_n, chLatin_g, chNull +}; + +const XMLCh XPathSymbols::fgSYMBOL_SELF[] = +{ + chLatin_s, chLatin_e, chLatin_l, chLatin_f, chNull +}; + +XERCES_CPP_NAMESPACE_END + +/** + * End of file XPathSymbols.cpp + */ + diff --git a/include/xercesc/validators/schema/identity/XPathSymbols.hpp b/include/xercesc/validators/schema/identity/XPathSymbols.hpp new file mode 100644 index 0000000..7842186 --- /dev/null +++ b/include/xercesc/validators/schema/identity/XPathSymbols.hpp @@ -0,0 +1,75 @@ +/* + * 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: XPathSymbols.hpp 527149 2007-04-10 14:56:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XPATHSYMBOLS_HPP) +#define XERCESC_INCLUDE_GUARD_XPATHSYMBOLS_HPP + +#include + +XERCES_CPP_NAMESPACE_BEGIN + +/* + * Collection of symbols used to parse a Schema Grammar + */ + +class VALIDATORS_EXPORT XPathSymbols +{ +public : + // ----------------------------------------------------------------------- + // Constant data + // ----------------------------------------------------------------------- + static const XMLCh fgSYMBOL_AND[]; + static const XMLCh fgSYMBOL_OR[]; + static const XMLCh fgSYMBOL_MOD[]; + static const XMLCh fgSYMBOL_DIV[]; + static const XMLCh fgSYMBOL_COMMENT[]; + static const XMLCh fgSYMBOL_TEXT[]; + static const XMLCh fgSYMBOL_PI[]; + static const XMLCh fgSYMBOL_NODE[]; + static const XMLCh fgSYMBOL_ANCESTOR[]; + static const XMLCh fgSYMBOL_ANCESTOR_OR_SELF[]; + static const XMLCh fgSYMBOL_ATTRIBUTE[]; + static const XMLCh fgSYMBOL_CHILD[]; + static const XMLCh fgSYMBOL_DESCENDANT[]; + static const XMLCh fgSYMBOL_DESCENDANT_OR_SELF[]; + static const XMLCh fgSYMBOL_FOLLOWING[]; + static const XMLCh fgSYMBOL_FOLLOWING_SIBLING[]; + static const XMLCh fgSYMBOL_NAMESPACE[]; + static const XMLCh fgSYMBOL_PARENT[]; + static const XMLCh fgSYMBOL_PRECEDING[]; + static const XMLCh fgSYMBOL_PRECEDING_SIBLING[]; + static const XMLCh fgSYMBOL_SELF[]; + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XPathSymbols(); +}; + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XPathSymbols.hpp + */ + diff --git a/include/xercesc/validators/schema/identity/XercesXPath.cpp b/include/xercesc/validators/schema/identity/XercesXPath.cpp new file mode 100644 index 0000000..ec55081 --- /dev/null +++ b/include/xercesc/validators/schema/identity/XercesXPath.cpp @@ -0,0 +1,1460 @@ +/* + * 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: XercesXPath.cpp 903997 2010-01-28 08:28:06Z borisk $ + */ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +// --------------------------------------------------------------------------- +// Static data +// --------------------------------------------------------------------------- +const XMLByte XPathScanner::fASCIICharMap[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 4, 1, 5, 1, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 16, 17, 18, 1, + 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 1, 22, 1, 23, + 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 24, 1, 1, 1 +}; + + +// --------------------------------------------------------------------------- +// XercesNodeTest: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesNodeTest::XercesNodeTest(const short aType, + MemoryManager* const manager) + : fType(aType) + , fName(new (manager) QName(manager)) +{ +} + +XercesNodeTest::XercesNodeTest(const QName* const qName) + : fType(NodeType_QNAME) + , fName(new (qName->getMemoryManager()) QName(*qName)) +{ +} + +XercesNodeTest::XercesNodeTest(const XMLCh* const prefix, + const unsigned int uriId, + MemoryManager* const manager) + : fType(NodeType_NAMESPACE) + , fName(new (manager) QName(manager)) +{ + fName->setURI(uriId); + fName->setPrefix(prefix); +} + +XercesNodeTest::XercesNodeTest(const XercesNodeTest& other) + : XSerializable(other) + , XMemory(other) + , fType(other.fType) + , fName(new ((other.fName)->getMemoryManager()) QName(*other.fName)) +{ +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XercesNodeTest) + +void XercesNodeTest::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<>fType; + serEng>>fName; + } +} + +XercesNodeTest::XercesNodeTest(MemoryManager* const) +:fType(NodeType_UNKNOWN) +,fName(0) +{ +} + +// --------------------------------------------------------------------------- +// XercesNodeTest: Operators +// --------------------------------------------------------------------------- +XercesNodeTest& XercesNodeTest::operator=(const XercesNodeTest& other) +{ + if (this == &other) + return *this; + + fType = other.fType; + fName->setValues(*(other.fName)); + return *this; +} + +bool XercesNodeTest::operator ==(const XercesNodeTest& other) const { + + if (this == &other) + return true; + + if (fType != other.fType) + return false; + + return (*fName == *(other.fName)); +} + + +bool XercesNodeTest::operator !=(const XercesNodeTest& other) const { + + return !operator==(other); +} + +// --------------------------------------------------------------------------- +// XercesStep: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesStep::XercesStep(const unsigned short axisType, XercesNodeTest* const nodeTest) + : fAxisType(axisType) + , fNodeTest(nodeTest) +{ +} + +XercesStep::XercesStep(const XercesStep& other) + : XSerializable(other) + , XMemory(other) + , fAxisType(other.fAxisType) + , fNodeTest(0) +{ + fNodeTest = new (other.fNodeTest->getName()->getMemoryManager()) XercesNodeTest(*(other.fNodeTest)); +} + + +// --------------------------------------------------------------------------- +// XercesStep: Operators +// --------------------------------------------------------------------------- +XercesStep& XercesStep::operator=(const XercesStep& other) +{ + if (this == &other) + return *this; + + fAxisType = other.fAxisType; + *fNodeTest = *(other.fNodeTest); + return *this; +} + +bool XercesStep::operator==(const XercesStep& other) const { + + if (this == &other) + return true; + + if (fAxisType != other.fAxisType) + return false; + + if (fAxisType == XercesStep::AxisType_CHILD || + fAxisType == XercesStep::AxisType_ATTRIBUTE) { + return (*fNodeTest == *(other.fNodeTest)); + } + + return true; +} + +bool XercesStep::operator!=(const XercesStep& other) const { + + return !operator==(other); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XercesStep) + +void XercesStep::serialize(XSerializeEngine& serEng) +{ + if (serEng.isStoring()) + { + serEng<<(int)fAxisType; + serEng<>i; + fAxisType = (unsigned short) i; + + serEng>>fNodeTest; + } +} + +XercesStep::XercesStep(MemoryManager* const) +:fAxisType(AxisType_UNKNOWN) +,fNodeTest(0) +{ +} + +// --------------------------------------------------------------------------- +// XercesLocationPath: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesLocationPath::XercesLocationPath(RefVectorOf* const steps) + : fSteps(steps) +{ +} + +// --------------------------------------------------------------------------- +// XercesLocationPath: Operators +// --------------------------------------------------------------------------- +bool XercesLocationPath::operator==(const XercesLocationPath& other) const { + + XMLSize_t stepsSize = fSteps->size(); + + if (stepsSize != other.fSteps->size()) + return false; + + for (XMLSize_t i=0; i < stepsSize; i++) { + if (*(fSteps->elementAt(i)) != *(other.fSteps->elementAt(i))) + return false; + } + + return true; +} + +bool XercesLocationPath::operator!=(const XercesLocationPath& other) const { + + return !operator==(other); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XercesLocationPath) + +void XercesLocationPath::serialize(XSerializeEngine& serEng) +{ + if (serEng.isStoring()) + { + /*** + * Serialize RefVectorOf* fSteps; + ***/ + XTemplateSerializer::storeObject(fSteps, serEng); + } + else + { + /*** + * Deserialize RefVectorOf* fSteps; + ***/ + XTemplateSerializer::loadObject(&fSteps, 8, true, serEng); + } +} + +XercesLocationPath::XercesLocationPath(MemoryManager* const) +:fSteps(0) +{ +} + +typedef JanitorMemFunCall CleanupType; + +// --------------------------------------------------------------------------- +// XercesPath: Constructors and Destructor +// --------------------------------------------------------------------------- +XercesXPath::XercesXPath(const XMLCh* const xpathExpr, + XMLStringPool* const stringPool, + XercesNamespaceResolver* const scopeContext, + const unsigned int emptyNamespaceId, + const bool isSelector, + MemoryManager* const manager) + : fEmptyNamespaceId(emptyNamespaceId) + , fExpression(0) + , fLocationPaths(0) + , fMemoryManager(manager) +{ + CleanupType cleanup(this, &XercesXPath::cleanUp); + + try + { + fExpression = XMLString::replicate(xpathExpr, fMemoryManager); + parseExpression(stringPool, scopeContext); + + if (isSelector) { + checkForSelectedAttributes(); + } + } + catch(const OutOfMemoryException&) + { + cleanup.release(); + + throw; + } + + cleanup.release(); +} + +XercesXPath::~XercesXPath() { + cleanUp(); +} + + +// --------------------------------------------------------------------------- +// XercesXPath: Operators +// --------------------------------------------------------------------------- +bool XercesXPath::operator==(const XercesXPath& other) const { + + XMLSize_t locPathSize = fLocationPaths->size(); + + if (locPathSize != other.fLocationPaths->size()) + return false; + + for (XMLSize_t i=0; i < locPathSize; i++) { + if (*(fLocationPaths->elementAt(i)) != *(other.fLocationPaths->elementAt(i))) + return false; + } + + return true; +} + +bool XercesXPath::operator!=(const XercesXPath& other) const { + + return !operator==(other); +} + +// --------------------------------------------------------------------------- +// XercesPath: Helper methods +// --------------------------------------------------------------------------- +void XercesXPath::cleanUp() { + + fMemoryManager->deallocate(fExpression);//delete [] fExpression; + delete fLocationPaths; +} + +void XercesXPath::checkForSelectedAttributes() { + + // verify that an attribute is not selected + XMLSize_t locSize = (fLocationPaths) ? fLocationPaths->size() : 0; + + for (XMLSize_t i = 0; i < locSize; i++) { + + XercesLocationPath* locPath = fLocationPaths->elementAt(i); + XMLSize_t stepSize = locPath->getStepSize(); + + if (stepSize) { + if (locPath->getStep(stepSize - 1)->getAxisType() == XercesStep::AxisType_ATTRIBUTE) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoAttrSelector, fMemoryManager); + } + } + } +} + +void XercesXPath::parseExpression(XMLStringPool* const stringPool, + XercesNamespaceResolver* const scopeContext) { + + XMLSize_t length = XMLString::stringLen(fExpression); + + if (!length) { + return; + } + + ValueVectorOf tokens(16, fMemoryManager); + XPathScannerForSchema scanner(stringPool); + if(!scanner.scanExpression(fExpression, 0, length, &tokens)) + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, fMemoryManager); + + bool firstTokenOfLocationPath=true; + XMLSize_t tokenCount = tokens.size(); + RefVectorOf* stepsVector = new (fMemoryManager) RefVectorOf(16, true, fMemoryManager); + Janitor > janSteps(stepsVector); + + if (tokenCount) { + fLocationPaths = new (fMemoryManager) RefVectorOf(8, true, fMemoryManager); + } + + for (XMLSize_t i = 0; i < tokenCount; i++) { + + int aToken = tokens.elementAt(i); + bool isNamespace=false; + + switch (aToken) { + case XercesXPath::EXPRTOKEN_OPERATOR_UNION: + { + if (i == 0) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtStart, fMemoryManager); + } + + XMLSize_t stepsSize = stepsVector->size(); + + if (stepsSize == 0) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoMultipleUnion, fMemoryManager); + } + + if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF) + { + // prepend ./ + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest); + stepsVector->insertElementAt(step, 0); + } + XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector); + janSteps.orphan(); + bool bFound=false; + for(XMLSize_t i=0;isize();i++) + if((*(fLocationPaths->elementAt(i)))==(*newPath)) + { + bFound=true; + break; + } + if(bFound) + delete newPath; + else + fLocationPaths->addElement(newPath); + stepsVector = new (fMemoryManager) RefVectorOf(16, true, fMemoryManager); + janSteps.reset(stepsVector); + firstTokenOfLocationPath = true; + } + break; + case XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE: + { + // consume "::" token and drop through + i++; + } + case XercesXPath::EXPRTOKEN_ATSIGN: + { + // consume QName token + if (i == tokenCount - 1) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_MissingAttr, fMemoryManager); + } + + aToken = tokens.elementAt(++i); + + if (aToken != XercesXPath::EXPRTOKEN_NAMETEST_QNAME + && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_ANY + && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedToken1, fMemoryManager); + } + + bool isNamespaceAtt=false; + + switch (aToken) { + + case XercesXPath::EXPRTOKEN_NAMETEST_ANY: + { + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest); + stepsVector->addElement(step); + break; + } + case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE: + { + isNamespaceAtt = true; + } + case XercesXPath::EXPRTOKEN_NAMETEST_QNAME: + { + aToken = tokens.elementAt(++i); + + const XMLCh* prefix = XMLUni::fgZeroLenString; + unsigned int uri = fEmptyNamespaceId; + + if (scopeContext && aToken != -1) { + + prefix = stringPool->getValueForId(aToken); + uri = scopeContext->getNamespaceForPrefix(prefix); + } + + if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) { + ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager); + } + + if (isNamespaceAtt) { + + // build step + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest); + stepsVector->addElement(step); + break; + } + + aToken = tokens.elementAt(++i); + + const XMLCh* localPart = stringPool->getValueForId(aToken); + QName aQName(prefix, localPart, uri, fMemoryManager); + + // build step + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest); + stepsVector->addElement(step); + break; + } + } + + firstTokenOfLocationPath=false; + break; + } + case XercesXPath::EXPRTOKEN_DOUBLE_COLON: + { + // should never have a bare double colon + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleColon, fMemoryManager); + } + case XercesXPath::EXPRTOKEN_AXISNAME_CHILD: + { + // consume "::" token and drop through + i++; + + if (i == tokenCount - 1) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep1, fMemoryManager); + } + + firstTokenOfLocationPath=false; + break; + } + case XercesXPath::EXPRTOKEN_NAMETEST_ANY: + { + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest); + stepsVector->addElement(step); + firstTokenOfLocationPath = false; + break; + } + case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE: + { + isNamespace=true; + } + case XercesXPath::EXPRTOKEN_NAMETEST_QNAME: + { + // consume QName token + aToken = tokens.elementAt(++i); + + const XMLCh* prefix = XMLUni::fgZeroLenString; + unsigned int uri = fEmptyNamespaceId; + + if (scopeContext && aToken != -1) { + + prefix = stringPool->getValueForId(aToken); + uri = scopeContext->getNamespaceForPrefix(prefix); + } + + if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) { + ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager); + } + + if (isNamespace) { + + // build step + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest); + stepsVector->addElement(step); + break; + } + + aToken = tokens.elementAt(++i); + const XMLCh* localPart = stringPool->getValueForId(aToken); + QName aQName(prefix, localPart, uri, fMemoryManager); + + // build step + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest); + stepsVector->addElement(step); + firstTokenOfLocationPath = false; + break; + } + case XercesXPath::EXPRTOKEN_PERIOD: + { + // build step + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest); + stepsVector->addElement(step); + + if (firstTokenOfLocationPath && i+1 < tokenCount) { + + aToken = tokens.elementAt(i+1); + + if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH){ + + if (++i == tokenCount - 1) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep2, fMemoryManager); + } + + if (i+1 < tokenCount) { + + aToken = tokens.elementAt(i+1); + + if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlash, fMemoryManager); + } + } + // build step + nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager); + step = new (fMemoryManager) XercesStep(XercesStep::AxisType_DESCENDANT, nodeTest); + stepsVector->addElement(step); + } + } + firstTokenOfLocationPath=false; + break; + } + case XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH: + { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleForwardSlash, fMemoryManager); + } + case XercesXPath::EXPRTOKEN_OPERATOR_SLASH: + { + if (i == 0) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlashAtStart, fMemoryManager); + } + + // keep on truckin' + if (firstTokenOfLocationPath) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoSelectionOfRoot, fMemoryManager); + } + + if (i == tokenCount - 1) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager); + } + + aToken = tokens.elementAt(i+1); + if(aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION) + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager); + + firstTokenOfLocationPath=false; + break; + } + default: + firstTokenOfLocationPath=false; + } + } + + XMLSize_t stepsSize = stepsVector->size(); + + if (stepsSize == 0) { + if (!fLocationPaths || fLocationPaths->size() == 0) { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_EmptyExpr, fMemoryManager); + } + else { + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtEnd, fMemoryManager); + } + } + + if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF) + { + // prepend ./ + XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager); + XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest); + stepsVector->insertElementAt(step, 0); + } + XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector); + janSteps.orphan(); + bool bFound=false; + for(XMLSize_t j=0;jsize();j++) + if((*(fLocationPaths->elementAt(j)))==(*newPath)) + { + bFound=true; + break; + } + if(bFound) + delete newPath; + else + fLocationPaths->addElement(newPath); +} + +/*** + * Support for Serialization/De-serialization + ***/ + +IMPL_XSERIALIZABLE_TOCREATE(XercesXPath) + +void XercesXPath::serialize(XSerializeEngine& serEng) +{ + + if (serEng.isStoring()) + { + serEng<* fLocationPaths; + ***/ + XTemplateSerializer::storeObject(fLocationPaths, serEng); + } + else + { + serEng>>fEmptyNamespaceId; + serEng.readString(fExpression); + + /*** + * Deserialize RefVectorOf* fLocationPaths; + ***/ + XTemplateSerializer::loadObject(&fLocationPaths, 8, true, serEng); + } +} + +XercesXPath::XercesXPath(MemoryManager* const manager) +:fEmptyNamespaceId(0) +,fExpression(0) +,fLocationPaths(0) +,fMemoryManager(manager) +{ +} + +// --------------------------------------------------------------------------- +// XPathScanner: Constructors and Destructor +// --------------------------------------------------------------------------- +XPathScanner::XPathScanner(XMLStringPool* const stringPool) + : fAndSymbol (0) + , fOrSymbol(0) + , fModSymbol(0) + , fDivSymbol(0) + , fCommentSymbol(0) + , fTextSymbol(0) + , fPISymbol(0) + , fNodeSymbol(0) + , fAncestorSymbol(0) + , fAncestorOrSelfSymbol(0) + , fAttributeSymbol(0) + , fChildSymbol(0) + , fDescendantSymbol(0) + , fDescendantOrSelfSymbol(0) + , fFollowingSymbol(0) + , fFollowingSiblingSymbol(0) + , fNamespaceSymbol(0) + , fParentSymbol(0) + , fPrecedingSymbol(0) + , fPrecedingSiblingSymbol(0) + , fSelfSymbol(0) + , fStringPool(stringPool) +{ + init(); +} + +// --------------------------------------------------------------------------- +// XPathScanner: Helper methods +// --------------------------------------------------------------------------- +void XPathScanner::init() { + + fAndSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_AND); + fOrSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_OR); + fModSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_MOD); + fDivSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DIV); + fCommentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_COMMENT); + fTextSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_TEXT); + fPISymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PI); + fNodeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NODE); + fAncestorSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR); + fAncestorOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR_OR_SELF); + fAttributeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ATTRIBUTE); + fChildSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_CHILD); + fDescendantSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT); + fDescendantOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT_OR_SELF); + fFollowingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING); + fFollowingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING_SIBLING); + fNamespaceSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NAMESPACE); + fParentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PARENT); + fPrecedingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING); + fPrecedingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING_SIBLING); + fSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_SELF); +} + + +// --------------------------------------------------------------------------- +// XPathScanner: Scan methods +// --------------------------------------------------------------------------- +bool XPathScanner::scanExpression(const XMLCh* const data, + XMLSize_t currentOffset, + const XMLSize_t endOffset, + ValueVectorOf* const tokens) { + + bool starIsMultiplyOperator = false; + XMLSize_t nameOffset = 0; + int nameHandle = -1; + int prefixHandle = -1; + XMLCh ch; + XMLBuffer dataBuffer(128, tokens->getMemoryManager()); + + while (currentOffset != endOffset) { + + ch = data[currentOffset]; + + while (XMLChar1_0::isWhitespace(ch)) { + + if (++currentOffset == endOffset) { + break; + } + + ch = data[currentOffset]; + } + + if (currentOffset == endOffset) { + break; + } + // + // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + // | NameTest | NodeType | Operator | FunctionName + // | AxisName | Literal | Number | VariableReference + // + XMLByte chartype = (ch >= 0x80) ? (XMLByte)CHARTYPE_NONASCII : fASCIICharMap[ch]; + + switch (chartype) { + case CHARTYPE_OPEN_PAREN: // '(' + addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_CLOSE_PAREN: // ')' + addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_PAREN); + starIsMultiplyOperator = true; + ++currentOffset; + break; + case CHARTYPE_OPEN_BRACKET: // '[' + addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_BRACKET); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_CLOSE_BRACKET: // ']' + addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_BRACKET); + starIsMultiplyOperator = true; + ++currentOffset; + break; + // + // [30] Number ::= Digits ('.' Digits?)? | '.' Digits + // ^^^^^^^^^^ + // + case CHARTYPE_PERIOD: // '.', '..' or '.' Digits + if (currentOffset + 1 == endOffset) { + addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD); + starIsMultiplyOperator = true; + currentOffset++; + break; + } + + ch = data[currentOffset + 1]; + + if (ch == chPeriod) { // '..' + addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_PERIOD); + starIsMultiplyOperator = true; + currentOffset += 2; + } else if (ch >= chDigit_0 && ch <= chDigit_9) { + addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER); + starIsMultiplyOperator = true; + currentOffset = scanNumber(data, endOffset, currentOffset, tokens); + } else if (ch == chForwardSlash) { + addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD); + starIsMultiplyOperator = true; + currentOffset++; + } else if (ch == chPipe) { // '|' + addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD); + starIsMultiplyOperator = true; + currentOffset++; + } else if (XMLChar1_0::isWhitespace(ch)) { + do { + if (++currentOffset == endOffset) + break; + + ch = data[currentOffset]; + } while (XMLChar1_0::isWhitespace(ch)); + + if (currentOffset == endOffset || ch == chPipe || ch == chForwardSlash) { + addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD); + starIsMultiplyOperator = true; + break; + } + } else { + XMLCh str[2]= {ch, 0 }; + ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_InvalidChar, str, tokens->getMemoryManager()); + } + + break; + case CHARTYPE_ATSIGN: // '@' + addToken(tokens, XercesXPath::EXPRTOKEN_ATSIGN); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_COMMA: // ',' + addToken(tokens, XercesXPath::EXPRTOKEN_COMMA); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_COLON: // '::' + if (++currentOffset == endOffset) { + return false; // REVISIT + } + ch = data[currentOffset]; + + if (ch != chColon) { + return false; // REVISIT + } + addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_SLASH: // '/' and '//' + if (++currentOffset == endOffset) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH); + starIsMultiplyOperator = false; + break; + } + + ch = data[currentOffset]; + + if (ch == chForwardSlash) { // '//' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH); + starIsMultiplyOperator = false; + ++currentOffset; + } else { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH); + starIsMultiplyOperator = false; + } + break; + case CHARTYPE_UNION: // '|' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_UNION); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_PLUS: // '+' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_PLUS); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_MINUS: // '-' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MINUS); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_EQUAL: // '=' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_EQUAL); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_EXCLAMATION: // '!=' + if (++currentOffset == endOffset) { + return false; // REVISIT + } + + ch = data[currentOffset]; + + if (ch != chEqual) { + return false; // REVISIT + } + + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_NOT_EQUAL); + starIsMultiplyOperator = false; + ++currentOffset; + break; + case CHARTYPE_LESS: // '<' and '<=' + if (++currentOffset == endOffset) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS); + starIsMultiplyOperator = false; + break; + } + + ch = data[currentOffset]; + + if (ch == chEqual) { // '<=' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS_EQUAL); + starIsMultiplyOperator = false; + ++currentOffset; + } else { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS); + starIsMultiplyOperator = false; + } + break; + case CHARTYPE_GREATER: // '>' and '>=' + if (++currentOffset == endOffset) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER); + starIsMultiplyOperator = false; + break; + } + + ch = data[currentOffset]; + + if (ch == chEqual) { // '>=' + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER_EQUAL); + starIsMultiplyOperator = false; + ++currentOffset; + } else { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER); + starIsMultiplyOperator = false; + } + break; + // + // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'" + // + case CHARTYPE_QUOTE: // '\"' or '\'' + { + XMLCh qchar = ch; + if (++currentOffset == endOffset) { + return false; // REVISIT + } + + ch = data[currentOffset]; + + XMLSize_t litOffset = currentOffset; + while (ch != qchar) { + if (++currentOffset == endOffset) { + return false; // REVISIT + } + + ch = data[currentOffset]; + } + + addToken(tokens, XercesXPath::EXPRTOKEN_LITERAL); + starIsMultiplyOperator = true; + + dataBuffer.set(data + litOffset, currentOffset - litOffset); + tokens->addElement(fStringPool->addOrFind(dataBuffer.getRawBuffer())); + ++currentOffset; + break; + } + // + // [30] Number ::= Digits ('.' Digits?)? | '.' Digits + // [31] Digits ::= [0-9]+ + // + case CHARTYPE_DIGIT: + addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER); + starIsMultiplyOperator = true; + currentOffset = scanNumber(data, endOffset, currentOffset, tokens); + break; + // + // [36] VariableReference ::= '$' QName + // + case CHARTYPE_DOLLAR: + if (++currentOffset == endOffset) { + return false; // REVISIT + } + nameOffset = currentOffset; + currentOffset = scanNCName(data, endOffset, currentOffset); + + if (currentOffset == nameOffset) { + return false; // REVISIT + } + + if (currentOffset < endOffset) { + ch = data[currentOffset]; + } + else { + ch = 0; + } + + dataBuffer.set(data + nameOffset, currentOffset - nameOffset); + nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer()); + prefixHandle = -1; + + if (ch == chColon) { + + prefixHandle = nameHandle; + if (++currentOffset == endOffset) { + return false; // REVISIT + } + nameOffset = currentOffset; + currentOffset = scanNCName(data, endOffset, currentOffset); + + if (currentOffset == nameOffset) { + return false; // REVISIT + } + + dataBuffer.set(data + nameOffset, currentOffset - nameOffset); + nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer()); + } + addToken(tokens, XercesXPath::EXPRTOKEN_VARIABLE_REFERENCE); + starIsMultiplyOperator = true; + tokens->addElement(prefixHandle); + tokens->addElement(nameHandle); + break; + // + // [37] NameTest ::= '*' | NCName ':' '*' | QName + // [34] MultiplyOperator ::= '*' + // + case CHARTYPE_STAR: // '*' + // + // 3.7 Lexical Structure + // + // If there is a preceding token and the preceding token is not one of @, ::, (, [, , or + // an Operator, then a * must be recognized as a MultiplyOperator. + // + // Otherwise, the token must not be recognized as a MultiplyOperator. + // + if (starIsMultiplyOperator) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MULT); + starIsMultiplyOperator = false; + } else { + addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_ANY); + starIsMultiplyOperator = true; + } + + ++currentOffset; + break; + // + // NCName, QName and non-terminals + // + case CHARTYPE_NONASCII: // possibly a valid non-ascii 'Letter' (BaseChar | Ideographic) + case CHARTYPE_LETTER: + case CHARTYPE_UNDERSCORE: + { + // + // 3.7 Lexical Structure + // + // If there is a preceding token and the preceding token is not one of @, ::, (, [, , or + // an Operator, then an NCName must be recognized as an OperatorName. + // + // If the character following an NCName (possibly after intervening ExprWhitespace) is (, + // then the token must be recognized as a NodeType or a FunctionName. + // + // If the two characters following an NCName (possibly after intervening ExprWhitespace) + // are ::, then the token must be recognized as an AxisName. + // + // Otherwise, the token must not be recognized as an OperatorName, a NodeType, a + // FunctionName, or an AxisName. + // + // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' + // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node' + // [35] FunctionName ::= QName - NodeType + // [6] AxisName ::= (see above) + // + // [37] NameTest ::= '*' | NCName ':' '*' | QName + // [5] NCName ::= (Letter | '_') (NCNameChar)* + // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_' (ascii subset of 'NCNameChar') + // [?] QName ::= (NCName ':')? NCName + // [?] Letter ::= [A-Za-z] (ascii subset of 'Letter') + // [?] Digit ::= [0-9] (ascii subset of 'Digit') + // + nameOffset = currentOffset; + currentOffset = scanNCName(data, endOffset, currentOffset); + if (currentOffset == nameOffset) { + return false; // REVISIT + } + + if (currentOffset < endOffset) { + ch = data[currentOffset]; + } + else { + ch = 0; + } + + dataBuffer.set(data + nameOffset, currentOffset - nameOffset); + nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer()); + + bool isNameTestNCName = false; + bool isAxisName = false; + prefixHandle = -1; + + if (ch == chColon) { + + if (++currentOffset == endOffset) { + return false; // REVISIT + } + + ch = data[currentOffset]; + + if (ch == chAsterisk) { + if (++currentOffset < endOffset) { + ch = data[currentOffset]; + } + + isNameTestNCName = true; + } else if (ch == chColon) { + if (++currentOffset < endOffset) { + ch = data[currentOffset]; + } + + isAxisName = true; + } else { + prefixHandle = nameHandle; + nameOffset = currentOffset; + currentOffset = scanNCName(data, endOffset, currentOffset); + if (currentOffset == nameOffset) { + return false; // REVISIT + } + if (currentOffset < endOffset) { + ch = data[currentOffset]; + } + else { + ch = 0; + } + + dataBuffer.set(data + nameOffset, currentOffset - nameOffset); + nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer()); + } + } + // + // [39] ExprWhitespace ::= S + // + while (XMLChar1_0::isWhitespace(ch)) { + if (++currentOffset == endOffset) { + break; + } + ch = data[currentOffset]; + } + + // + // If there is a preceding token and the preceding token is not one of @, ::, (, [, , or + // an Operator, then an NCName must be recognized as an OperatorName. + // + if (starIsMultiplyOperator) { + if (nameHandle == fAndSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_AND); + starIsMultiplyOperator = false; + } else if (nameHandle == fOrSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_OR); + starIsMultiplyOperator = false; + } else if (nameHandle == fModSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MOD); + starIsMultiplyOperator = false; + } else if (nameHandle == fDivSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DIV); + starIsMultiplyOperator = false; + } else { + return false; // REVISIT + } + + if (isNameTestNCName) { + return false; // REVISIT - NCName:* where an OperatorName is required + } else if (isAxisName) { + return false; // REVISIT - AxisName:: where an OperatorName is required + } + break; + } + // + // If the character following an NCName (possibly after intervening ExprWhitespace) is (, + // then the token must be recognized as a NodeType or a FunctionName. + // + if (ch == chOpenParen && !isNameTestNCName && !isAxisName) { + if (nameHandle == fCommentSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_COMMENT); + } else if (nameHandle == fTextSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_TEXT); + } else if (nameHandle == fPISymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_PI); + } else if (nameHandle == fNodeSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_NODE); + } else { + addToken(tokens, XercesXPath::EXPRTOKEN_FUNCTION_NAME); + tokens->addElement(prefixHandle); + tokens->addElement(nameHandle); + } + addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN); + starIsMultiplyOperator = false; + ++currentOffset; + break; + } + + // + // If the two characters following an NCName (possibly after intervening ExprWhitespace) + // are ::, then the token must be recognized as an AxisName. + // + if (isAxisName || + (ch == chColon && currentOffset + 1 < endOffset && + data[currentOffset + 1] == chColon)) { + + if (nameHandle == fAncestorSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR); + } else if (nameHandle == fAncestorOrSelfSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF); + } else if (nameHandle == fAttributeSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE); + } else if (nameHandle == fChildSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_CHILD); + } else if (nameHandle == fDescendantSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT); + } else if (nameHandle == fDescendantOrSelfSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF); + } else if (nameHandle == fFollowingSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING); + } else if (nameHandle == fFollowingSiblingSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING); + } else if (nameHandle == fNamespaceSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_NAMESPACE); + } else if (nameHandle == fParentSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PARENT); + } else if (nameHandle == fPrecedingSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING); + } else if (nameHandle == fPrecedingSiblingSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING_SIBLING); + } else if (nameHandle == fSelfSymbol) { + addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_SELF); + } else { + return false; // REVISIT + } + + if (isNameTestNCName) { + return false; // REVISIT - "NCName:* ::" where "AxisName ::" is required + } + + addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON); + starIsMultiplyOperator = false; + if (!isAxisName) { + currentOffset += 2; + } + break; + } + // + // Otherwise, the token must not be recognized as an OperatorName, a NodeType, a + // FunctionName, or an AxisName. + // + if (isNameTestNCName) { + addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE); + tokens->addElement(nameHandle); + } else { + addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_QNAME); + tokens->addElement(prefixHandle); + tokens->addElement(nameHandle); + } + + starIsMultiplyOperator = true; + break; + } + default: + { + XMLCh str[2]= {ch, 0 }; + ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_InvalidChar, str, tokens->getMemoryManager()); + break; + } + } + } + + return true; +} + + +XMLSize_t XPathScanner::scanNCName(const XMLCh* const data, + const XMLSize_t endOffset, + XMLSize_t currentOffset) { + + XMLCh ch = data[currentOffset]; + + if (!XMLChar1_0::isFirstNCNameChar(ch)) { + return currentOffset; + } + + while (++currentOffset < endOffset) { + + ch = data[currentOffset]; + + if (!XMLChar1_0::isNCNameChar(ch)) { + break; + } + } + + return currentOffset; +} + + +XMLSize_t XPathScanner::scanNumber(const XMLCh* const data, + const XMLSize_t endOffset, + XMLSize_t currentOffset, + ValueVectorOf* const tokens) { + + XMLCh ch = data[currentOffset]; + int whole = 0; + int part = 0; + + while (ch >= chDigit_0 && ch <= chDigit_9) { + + whole = (whole * 10) + (ch - chDigit_0); + + if (++currentOffset == endOffset) { + break; + } + + ch = data[currentOffset]; + } + + if (ch == chPeriod) { + + if (++currentOffset < endOffset) { + + ch = data[currentOffset]; + + while (ch >= chDigit_0 && ch <= chDigit_9) { + + part = (part * 10) + (ch - chDigit_0); + + if (++currentOffset == endOffset) { + break; + } + + ch = data[currentOffset]; + } + + if (part != 0) { + ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::XPath_FindSolution, tokens->getMemoryManager()); + } + } + } + + tokens->addElement(whole); + tokens->addElement(part); + + return currentOffset; +} + + +// --------------------------------------------------------------------------- +// XPathScannerForSchema: Constructors and Destructor +// --------------------------------------------------------------------------- +XPathScannerForSchema::XPathScannerForSchema(XMLStringPool* const stringPool) + : XPathScanner(stringPool) +{ +} + + +// --------------------------------------------------------------------------- +// XPathScannerForSchema: Helper methods +// --------------------------------------------------------------------------- +void XPathScannerForSchema::addToken(ValueVectorOf* const tokens, + const int aToken) { + + if (aToken == XercesXPath::EXPRTOKEN_ATSIGN || + aToken == XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE || + aToken == XercesXPath::EXPRTOKEN_AXISNAME_CHILD || + //token == XercesXPath::EXPRTOKEN_AXISNAME_SELF || + aToken == XercesXPath::EXPRTOKEN_DOUBLE_COLON || + aToken == XercesXPath::EXPRTOKEN_NAMETEST_QNAME || + //token == XercesXPath::EXPRTOKEN_NODETYPE_NODE || + aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH || + aToken == XercesXPath::EXPRTOKEN_PERIOD || + aToken == XercesXPath::EXPRTOKEN_NAMETEST_ANY || + aToken == XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE || + aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH || + aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION) { + + tokens->addElement(aToken); + return; + } + + ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, tokens->getMemoryManager()); +} + +XERCES_CPP_NAMESPACE_END + +/** + * End of file XercesPath.cpp + */ diff --git a/include/xercesc/validators/schema/identity/XercesXPath.hpp b/include/xercesc/validators/schema/identity/XercesXPath.hpp new file mode 100644 index 0000000..d388da8 --- /dev/null +++ b/include/xercesc/validators/schema/identity/XercesXPath.hpp @@ -0,0 +1,499 @@ +/* + * 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: XercesXPath.hpp 932887 2010-04-11 13:04:59Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XERCESXPATH_HPP) +#define XERCESC_INCLUDE_GUARD_XERCESXPATH_HPP + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Forward Declarations +// --------------------------------------------------------------------------- +class XMLStringPool; + +class VALIDATORS_EXPORT XercesNodeTest : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constants + // ----------------------------------------------------------------------- + enum NodeType { + NodeType_QNAME = 1, + NodeType_WILDCARD = 2, + NodeType_NODE = 3, + NodeType_NAMESPACE= 4, + NodeType_UNKNOWN + }; + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XercesNodeTest(const short type, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + XercesNodeTest(const QName* const qName); + XercesNodeTest(const XMLCh* const prefix, const unsigned int uriId, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + XercesNodeTest(const XercesNodeTest& other); + ~XercesNodeTest() { delete fName; } + + // ----------------------------------------------------------------------- + // Operators + // ----------------------------------------------------------------------- + XercesNodeTest& operator= (const XercesNodeTest& other); + bool operator== (const XercesNodeTest& other) const; + bool operator!= (const XercesNodeTest& other) const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + short getType() const { return fType; } + QName* getName() const { return fName; } + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XercesNodeTest) + + XercesNodeTest(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + short fType; + QName* fName; +}; + + +/** + * A location path step comprised of an axis and node test. + */ +class VALIDATORS_EXPORT XercesStep : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constants + // ----------------------------------------------------------------------- + enum AxisType { // Axis type + AxisType_CHILD = 1, + AxisType_ATTRIBUTE = 2, + AxisType_SELF = 3, + AxisType_DESCENDANT = 4, + AxisType_UNKNOWN + }; + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XercesStep(const unsigned short axisType, XercesNodeTest* const nodeTest); + XercesStep(const XercesStep& other); + ~XercesStep() { delete fNodeTest; } + + // ----------------------------------------------------------------------- + // Operators + // ----------------------------------------------------------------------- + XercesStep& operator= (const XercesStep& other); + bool operator== (const XercesStep& other) const; + bool operator!= (const XercesStep& other) const; + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + unsigned short getAxisType() const { return fAxisType; } + XercesNodeTest* getNodeTest() const { return fNodeTest; } + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XercesStep) + + XercesStep(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + unsigned short fAxisType; + XercesNodeTest* fNodeTest; +}; + + +/** + * A location path representation for an XPath expression. + */ +class VALIDATORS_EXPORT XercesLocationPath : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XercesLocationPath(RefVectorOf* const steps); + ~XercesLocationPath() { delete fSteps; } + + // ----------------------------------------------------------------------- + // Operators + // ----------------------------------------------------------------------- + bool operator== (const XercesLocationPath& other) const; + bool operator!= (const XercesLocationPath& other) const; + + // ----------------------------------------------------------------------- + // Access methods + // ----------------------------------------------------------------------- + XMLSize_t getStepSize() const; + void addStep(XercesStep* const aStep); + XercesStep* getStep(const XMLSize_t index) const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XercesLocationPath) + + XercesLocationPath(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XercesLocationPath(const XercesLocationPath& other); + XercesLocationPath& operator= (const XercesLocationPath& other); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + RefVectorOf* fSteps; +}; + + +class VALIDATORS_EXPORT XercesXPath : public XSerializable, public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constants + // ----------------------------------------------------------------------- + /** + * [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + * | NameTest | NodeType | Operator | FunctionName + * | AxisName | Literal | Number | VariableReference + */ + enum { + EXPRTOKEN_OPEN_PAREN = 0, + EXPRTOKEN_CLOSE_PAREN = 1, + EXPRTOKEN_OPEN_BRACKET = 2, + EXPRTOKEN_CLOSE_BRACKET = 3, + EXPRTOKEN_PERIOD = 4, + EXPRTOKEN_DOUBLE_PERIOD = 5, + EXPRTOKEN_ATSIGN = 6, + EXPRTOKEN_COMMA = 7, + EXPRTOKEN_DOUBLE_COLON = 8, + EXPRTOKEN_NAMETEST_ANY = 9, + EXPRTOKEN_NAMETEST_NAMESPACE = 10, + EXPRTOKEN_NAMETEST_QNAME = 11, + EXPRTOKEN_NODETYPE_COMMENT = 12, + EXPRTOKEN_NODETYPE_TEXT = 13, + EXPRTOKEN_NODETYPE_PI = 14, + EXPRTOKEN_NODETYPE_NODE = 15, + EXPRTOKEN_OPERATOR_AND = 16, + EXPRTOKEN_OPERATOR_OR = 17, + EXPRTOKEN_OPERATOR_MOD = 18, + EXPRTOKEN_OPERATOR_DIV = 19, + EXPRTOKEN_OPERATOR_MULT = 20, + EXPRTOKEN_OPERATOR_SLASH = 21, + EXPRTOKEN_OPERATOR_DOUBLE_SLASH = 22, + EXPRTOKEN_OPERATOR_UNION = 23, + EXPRTOKEN_OPERATOR_PLUS = 24, + EXPRTOKEN_OPERATOR_MINUS = 25, + EXPRTOKEN_OPERATOR_EQUAL = 26, + EXPRTOKEN_OPERATOR_NOT_EQUAL = 27, + EXPRTOKEN_OPERATOR_LESS = 28, + EXPRTOKEN_OPERATOR_LESS_EQUAL = 29, + EXPRTOKEN_OPERATOR_GREATER = 30, + EXPRTOKEN_OPERATOR_GREATER_EQUAL = 31, + EXPRTOKEN_FUNCTION_NAME = 32, + EXPRTOKEN_AXISNAME_ANCESTOR = 33, + EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF = 34, + EXPRTOKEN_AXISNAME_ATTRIBUTE = 35, + EXPRTOKEN_AXISNAME_CHILD = 36, + EXPRTOKEN_AXISNAME_DESCENDANT = 37, + EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF = 38, + EXPRTOKEN_AXISNAME_FOLLOWING = 39, + EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING = 40, + EXPRTOKEN_AXISNAME_NAMESPACE = 41, + EXPRTOKEN_AXISNAME_PARENT = 42, + EXPRTOKEN_AXISNAME_PRECEDING = 43, + EXPRTOKEN_AXISNAME_PRECEDING_SIBLING = 44, + EXPRTOKEN_AXISNAME_SELF = 45, + EXPRTOKEN_LITERAL = 46, + EXPRTOKEN_NUMBER = 47, + EXPRTOKEN_VARIABLE_REFERENCE = 48 + }; + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XercesXPath(const XMLCh* const xpathExpr, + XMLStringPool* const stringPool, + XercesNamespaceResolver* const scopeContext, + const unsigned int emptyNamespaceId, + const bool isSelector = false, + MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + ~XercesXPath(); + + // ----------------------------------------------------------------------- + // Operators + // ----------------------------------------------------------------------- + bool operator== (const XercesXPath& other) const; + bool operator!= (const XercesXPath& other) const; + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + RefVectorOf* getLocationPaths() const; + + /*** + * Support for Serialization/De-serialization + ***/ + DECL_XSERIALIZABLE(XercesXPath) + + XercesXPath(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); + + XMLCh* getExpression(); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XercesXPath(const XercesXPath& other); + XercesXPath& operator= (const XercesXPath& other); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void cleanUp(); + void checkForSelectedAttributes(); + void parseExpression(XMLStringPool* const stringPool, + XercesNamespaceResolver* const scopeContext); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + unsigned int fEmptyNamespaceId; + XMLCh* fExpression; + RefVectorOf* fLocationPaths; + MemoryManager* fMemoryManager; +}; + + +class VALIDATORS_EXPORT XPathScanner : public XMemory +{ +public: + // ----------------------------------------------------------------------- + // Constants + // ----------------------------------------------------------------------- + enum { + CHARTYPE_INVALID = 0, // invalid XML character + CHARTYPE_OTHER = 1, // not special - one of "#%&;?\^`{}~" or DEL + CHARTYPE_WHITESPACE = 2, // one of "\t\n\r " (0x09, 0x0A, 0x0D, 0x20) + CHARTYPE_EXCLAMATION = 3, // '!' (0x21) + CHARTYPE_QUOTE = 4, // '\"' or '\'' (0x22 and 0x27) + CHARTYPE_DOLLAR = 5, // '$' (0x24) + CHARTYPE_OPEN_PAREN = 6, // '(' (0x28) + CHARTYPE_CLOSE_PAREN = 7, // ')' (0x29) + CHARTYPE_STAR = 8, // '*' (0x2A) + CHARTYPE_PLUS = 9, // '+' (0x2B) + CHARTYPE_COMMA = 10, // ',' (0x2C) + CHARTYPE_MINUS = 11, // '-' (0x2D) + CHARTYPE_PERIOD = 12, // '.' (0x2E) + CHARTYPE_SLASH = 13, // '/' (0x2F) + CHARTYPE_DIGIT = 14, // '0'-'9' (0x30 to 0x39) + CHARTYPE_COLON = 15, // ':' (0x3A) + CHARTYPE_LESS = 16, // '<' (0x3C) + CHARTYPE_EQUAL = 17, // '=' (0x3D) + CHARTYPE_GREATER = 18, // '>' (0x3E) + CHARTYPE_ATSIGN = 19, // '@' (0x40) + CHARTYPE_LETTER = 20, // 'A'-'Z' or 'a'-'z' (0x41 to 0x5A and 0x61 to 0x7A) + CHARTYPE_OPEN_BRACKET = 21, // '[' (0x5B) + CHARTYPE_CLOSE_BRACKET = 22, // ']' (0x5D) + CHARTYPE_UNDERSCORE = 23, // '_' (0x5F) + CHARTYPE_UNION = 24, // '|' (0x7C) + CHARTYPE_NONASCII = 25 // Non-ASCII Unicode codepoint (>= 0x80) + }; + + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XPathScanner(XMLStringPool* const stringPool); + virtual ~XPathScanner() {} + + // ----------------------------------------------------------------------- + // Scan methods + // ----------------------------------------------------------------------- + bool scanExpression(const XMLCh* const data, XMLSize_t currentOffset, + const XMLSize_t endOffset, ValueVectorOf* const tokens); + +protected: + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + /** + * This method adds the specified token to the token list. By default, + * this method allows all tokens. However, subclasses can can override + * this method in order to disallow certain tokens from being used in the + * scanned XPath expression. This is a convenient way of allowing only + * a subset of XPath. + */ + virtual void addToken(ValueVectorOf* const tokens, const int aToken); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XPathScanner(const XPathScanner& other); + XPathScanner& operator= (const XPathScanner& other); + + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void init(); + + // ----------------------------------------------------------------------- + // Scan methods + // ----------------------------------------------------------------------- + XMLSize_t scanNCName(const XMLCh* const data, const XMLSize_t endOffset, + XMLSize_t currentOffset); + XMLSize_t scanNumber(const XMLCh* const data, const XMLSize_t endOffset, + XMLSize_t currentOffset, ValueVectorOf* const tokens); + + // ----------------------------------------------------------------------- + // Data members + // ----------------------------------------------------------------------- + int fAndSymbol; + int fOrSymbol; + int fModSymbol; + int fDivSymbol; + int fCommentSymbol; + int fTextSymbol; + int fPISymbol; + int fNodeSymbol; + int fAncestorSymbol; + int fAncestorOrSelfSymbol; + int fAttributeSymbol; + int fChildSymbol; + int fDescendantSymbol; + int fDescendantOrSelfSymbol; + int fFollowingSymbol; + int fFollowingSiblingSymbol; + int fNamespaceSymbol; + int fParentSymbol; + int fPrecedingSymbol; + int fPrecedingSiblingSymbol; + int fSelfSymbol; + XMLStringPool* fStringPool; + + static const XMLByte fASCIICharMap[128]; +}; + + +class VALIDATORS_EXPORT XPathScannerForSchema: public XPathScanner +{ +public: + // ----------------------------------------------------------------------- + // Constructors/Destructor + // ----------------------------------------------------------------------- + XPathScannerForSchema(XMLStringPool* const stringPool); + ~XPathScannerForSchema() {} + +protected: + // ----------------------------------------------------------------------- + // Helper methods + // ----------------------------------------------------------------------- + void addToken(ValueVectorOf* const tokens, const int aToken); + +private: + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + XPathScannerForSchema(const XPathScannerForSchema& other); + XPathScannerForSchema& operator= (const XPathScannerForSchema& other); +}; + +// --------------------------------------------------------------------------- +// XercesLocationPath: Access methods +// --------------------------------------------------------------------------- +inline XMLSize_t XercesLocationPath::getStepSize() const { + + if (fSteps) + return fSteps->size(); + + return 0; +} + +inline void XercesLocationPath::addStep(XercesStep* const aStep) { + + fSteps->addElement(aStep); +} + +inline XercesStep* XercesLocationPath::getStep(const XMLSize_t index) const { + + if (fSteps) + return fSteps->elementAt(index); + + return 0; +} + +// --------------------------------------------------------------------------- +// XercesScanner: Helper methods +// --------------------------------------------------------------------------- +inline void XPathScanner::addToken(ValueVectorOf* const tokens, + const int aToken) { + tokens->addElement(aToken); +} + + +// --------------------------------------------------------------------------- +// XercesXPath: Getter methods +// --------------------------------------------------------------------------- +inline RefVectorOf* XercesXPath::getLocationPaths() const { + + return fLocationPaths; +} + +inline XMLCh* XercesXPath::getExpression() { + return fExpression; +} + +XERCES_CPP_NAMESPACE_END + +#endif + +/** + * End of file XercesPath.hpp + */ + diff --git a/include/xercesc/xinclude/XIncludeDOMDocumentProcessor.cpp b/include/xercesc/xinclude/XIncludeDOMDocumentProcessor.cpp new file mode 100644 index 0000000..82583d2 --- /dev/null +++ b/include/xercesc/xinclude/XIncludeDOMDocumentProcessor.cpp @@ -0,0 +1,80 @@ +/* + * 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: XIncludeDOMDocumentProcessor.cpp 655706 2008-05-13 01:08:39Z amassari $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +DOMDocument * +XIncludeDOMDocumentProcessor::doXIncludeDOMProcess(const DOMDocument * const source, XMLErrorReporter *errorHandler, XMLEntityHandler* entityResolver /*=NULL*/){ + XIncludeUtils xiu(errorHandler); + + DOMImplementation* impl = source->getImplementation(); + DOMDocument *xincludedDocument = impl->createDocument(); + + try + { + /* set up the declaration etc of the output document to match the source */ + xincludedDocument->setDocumentURI( source->getDocumentURI()); + xincludedDocument->setXmlStandalone( source->getXmlStandalone()); + xincludedDocument->setXmlVersion( source->getXmlVersion()); + + /* copy entire source document into the xincluded document. Xincluded document can + then be modified in place */ + DOMNode *child = source->getFirstChild(); + for (; child != NULL; child = child->getNextSibling()){ + if (child->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE){ + /* I am simply ignoring these at the moment */ + continue; + } + DOMNode *newNode = xincludedDocument->importNode(child, true); + xincludedDocument->appendChild(newNode); + } + + DOMNode *docNode = xincludedDocument->getDocumentElement(); + /* parse and include the document node */ + xiu.parseDOMNodeDoingXInclude(docNode, xincludedDocument, entityResolver); + + xincludedDocument->normalizeDocument(); + } + catch(const XMLErrs::Codes) + { + xincludedDocument->release(); + return NULL; + } + catch(...) + { + xincludedDocument->release(); + throw; + } + + return xincludedDocument; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/xinclude/XIncludeDOMDocumentProcessor.hpp b/include/xercesc/xinclude/XIncludeDOMDocumentProcessor.hpp new file mode 100644 index 0000000..1f30440 --- /dev/null +++ b/include/xercesc/xinclude/XIncludeDOMDocumentProcessor.hpp @@ -0,0 +1,58 @@ +/* + * 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: XIncludeDOMDocumentProcessor.hpp 655706 2008-05-13 01:08:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XINCLUDEDOMDOCUMENTPROCESSOR_HPP) +#define XERCESC_INCLUDE_GUARD_XINCLUDEDOMDOCUMENTPROCESSOR_HPP + +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLEntityHandler; + +/** + * Class for representing and manipulating the XMLCh * href's used + * by an xi:include element. + * + * This class is designed primarily for internal use. This class implements + * the functionality required to calculate relative hrefs and the base URI + * fixups required for performing XInclude functionality. + */ +class XINCLUDE_EXPORT XIncludeDOMDocumentProcessor +{ +public: + /** Walk the supplied DOMDocument performing all XInclude's as encountered. + * + * @param source A DOMDocument to parse, this document is not modified. + * @param errorHandled An errorHandler to call back in case of problems + * + * @return a newly created DOMDocument containing the parsed and actioned + * xinclude elements. + */ + DOMDocument *doXIncludeDOMProcess(const DOMDocument * const source, XMLErrorReporter *errorHandler, XMLEntityHandler* entityResolver=NULL); +}; + +XERCES_CPP_NAMESPACE_END + +#endif /* XINCLUDEDOMDOCUMENTPROCESSOR_HPP */ + diff --git a/include/xercesc/xinclude/XIncludeLocation.cpp b/include/xercesc/xinclude/XIncludeLocation.cpp new file mode 100644 index 0000000..1b078ac --- /dev/null +++ b/include/xercesc/xinclude/XIncludeLocation.cpp @@ -0,0 +1,141 @@ +/* + * 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: XIncludeLocation.cpp 932949 2010-04-11 17:40:33Z borisk $ + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +const XMLCh *allocate(const XMLCh *href){ + XMLCh *allocated; + XMLSize_t length = XMLString::stringLen(href); + allocated = (XMLCh*)XMLPlatformUtils::fgMemoryManager->allocate((length+1) * sizeof(XMLCh)); + XMLString::copyString(allocated, href); + XMLPlatformUtils::removeDotDotSlash(allocated); + + return allocated; +} + +void deallocate(void *ptr){ + if (ptr) + XMLPlatformUtils::fgMemoryManager->deallocate((void *)ptr); +} + +// --------------------------------------------------------------------------- +// Destructor and Constructor +// --------------------------------------------------------------------------- +XIncludeLocation::XIncludeLocation(const XMLCh *href){ + fHref = allocate(href); +} + +XIncludeLocation::~XIncludeLocation(){ + deallocate((void *)fHref); +} + +const XMLCh * +XIncludeLocation::prependPath(const XMLCh *baseToAdd){ + XMLCh *relativeHref = NULL; + if (fHref == NULL){ + return NULL; + } + + if (baseToAdd == NULL){ + return fHref; + } + + XMLPlatformUtils::removeDotDotSlash((XMLCh*)baseToAdd); + XMLSize_t baseLength = XMLString::stringLen(baseToAdd); + + int lastSlash = XMLString::lastIndexOf(baseToAdd, chForwardSlash); + if (lastSlash == -1){ + /* not found, try another platform */ + lastSlash = XMLString::lastIndexOf(baseToAdd, chBackSlash); + } + + // Skip the scheme (e.g., file://) if fHref has one. Ideally we + // should detect also if the URI is absolute. + // + const XMLCh* hrefPath = findEndOfProtocol (fHref); + XMLSize_t hrefPathLength = XMLString::stringLen(hrefPath); + + relativeHref = (XMLCh *)XMLPlatformUtils::fgMemoryManager->allocate((hrefPathLength + baseLength + 2) * sizeof(XMLCh)); + if (relativeHref == NULL){ + return NULL; + } + XMLString::copyNString(relativeHref, baseToAdd, lastSlash + 1); + relativeHref[lastSlash + 1] = chNull; + XMLString::catString(relativeHref, hrefPath); + + /* free the old reference */ + deallocate((void *)fHref); + + fHref = relativeHref; + return fHref; +} + +const XMLCh * +XIncludeLocation::findEndOfProtocol(const XMLCh *URI){ + if ( URI[0] == chLatin_f && + URI[1] == chLatin_i && + URI[2] == chLatin_l && + URI[3] == chLatin_e && + URI[4] == chColon && + URI[5] == chForwardSlash && + URI[6] == chForwardSlash && + URI[7] == chForwardSlash ) + { + return URI + 8; + } + + if ( URI[0] == chLatin_f && + URI[1] == chLatin_t && + URI[2] == chLatin_p && + URI[3] == chColon && + URI[4] == chForwardSlash && + URI[5] == chForwardSlash && + URI[6] == chForwardSlash ) + { + return URI + 7; + } + + if ( URI[0] == chLatin_h && + URI[1] == chLatin_t && + URI[2] == chLatin_t && + URI[3] == chLatin_p && + URI[4] == chColon && + URI[5] == chForwardSlash && + URI[6] == chForwardSlash && + URI[7] == chForwardSlash ) + { + return URI + 8; + } + + /* if method fails, simply return the URI and let the problem be detected + * and reported down the line (it may not have a protocol of course) */ + return URI; +} + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/xinclude/XIncludeLocation.hpp b/include/xercesc/xinclude/XIncludeLocation.hpp new file mode 100644 index 0000000..b3dc331 --- /dev/null +++ b/include/xercesc/xinclude/XIncludeLocation.hpp @@ -0,0 +1,89 @@ +/* + * 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: XIncludeLocation.hpp 655706 2008-05-13 01:08:39Z amassari $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XINCLUDELOCATION_HPP) +#define XERCESC_INCLUDE_GUARD_XINCLUDELOCATION_HPP + +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + + +/** + * Class for representing and manipulating the XMLCh * href's used + * by an xi:include element. + * + * This class is designed primarily for internal use. This class implements + * the functionality required to calculate relative hrefs and the base URI + * fixups required for performing XInclude functionality. + */ +class XINCLUDE_EXPORT XIncludeLocation +{ +public: + /** Create an XIncludeLocation, primed with the supplied href + * + * @param href the initial URI value + * + * @return nothing + */ + XIncludeLocation(const XMLCh *href); + + /** Destructor + * + * @return nothing + */ + ~XIncludeLocation(); + + /** Prepend the supplied href to the current location and modify the current XIncludeLocation's + * internal href field + * + * @param toPrepend the path to prepend + * + * @return the resultant compound URI + */ + const XMLCh *prependPath(const XMLCh *toPrepend); + + /** Get the current XIncludeLocation's compound URI location + * + * @return the current URI + */ + const XMLCh *getLocation(){ + return fHref; + }; + + /** Get a pointer to the end of the protocol section of a URI + * + * @param URI a URI to strip the protocol from + * + * @return a pointer into the supplied URI immediately after the last character of the protocol section + * the pointer points to the first character after the protocol. + */ + static const XMLCh *findEndOfProtocol(const XMLCh *URI); + +private: + const XMLCh *fHref; +}; + +XERCES_CPP_NAMESPACE_END + +#endif /* XINCLUDELOCATION_HPP */ + diff --git a/include/xercesc/xinclude/XIncludeUtils.cpp b/include/xercesc/xinclude/XIncludeUtils.cpp new file mode 100644 index 0000000..4100a31 --- /dev/null +++ b/include/xercesc/xinclude/XIncludeUtils.cpp @@ -0,0 +1,838 @@ +/* + * 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: XIncludeUtils.cpp 933212 2010-04-12 12:17:58Z amassari $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +XIncludeUtils::XIncludeUtils(XMLErrorReporter *errorReporter){ + fErrorReporter = errorReporter; + fIncludeHistoryHead = NULL; +} + +XIncludeUtils::~XIncludeUtils(){ + freeInclusionHistory(); +} + +// --------------------------------------------------------------------------- +// Generic function to parse a dom node performing any Xinclude's it ecounters, +// storing its results in parsedDocument, which is expected to be a real +// document. sourceNode is the current location in parsedDocument, and +// all xinclude manipulation is done in place (i.e. source is manipulated). +// --------------------------------------------------------------------------- +bool +XIncludeUtils::parseDOMNodeDoingXInclude(DOMNode *sourceNode, DOMDocument *parsedDocument, XMLEntityHandler* entityResolver){ + if (sourceNode) { + /* create the list of child elements here, since it gets changed during the parse */ + RefVectorOf children(10, false); + for (DOMNode *child = sourceNode->getFirstChild(); child != NULL; child = child->getNextSibling()){ + children.addElement(child); + } + + if (sourceNode->getNodeType() == DOMNode::ELEMENT_NODE){ + if (isXIIncludeDOMNode(sourceNode)){ + /* once we do an include on the source element, it is unsafe to do the include + on the children, since they will have been changed by the top level include */ + bool success = doDOMNodeXInclude(sourceNode, parsedDocument, entityResolver); + + //popFromCurrentInclusionHistoryStack(NULL); + /* return here as we do not want to fall through to the parsing of the children below + - they should have been replaced by the XInclude */ + return success; + } else if (isXIFallbackDOMNode(sourceNode)){ + /* This must be a fallback element that is not a child of an include element. + This is defined as a fatal error */ + XIncludeUtils::reportError(sourceNode, XMLErrs::XIncludeOrphanFallback, + NULL, parsedDocument->getDocumentURI()); + return false; + } + } + + /* to have got here, we must not have found an xinclude element in the current element, so + need to walk the entire child list parsing for each. An xinclude in a + node does not affect a peer, so we can simply parse each child in turn */ + for (XMLSize_t i = 0; i < children.size(); i++){ + parseDOMNodeDoingXInclude(children.elementAt(i), parsedDocument, entityResolver); + } + } + return false; +} + +// --------------------------------------------------------------------------- +// utility func to extract a DOMNodes Base attr value if present +// --------------------------------------------------------------------------- +static const XMLCh * +getBaseAttrValue(DOMNode *node){ + if (node->getNodeType() == DOMNode::ELEMENT_NODE){ + DOMElement *elem = (DOMElement *)node; + if(elem->hasAttributes()) { + /* get all the attributes of the node */ + DOMNamedNodeMap *pAttributes = elem->getAttributes(); + XMLSize_t nSize = pAttributes->getLength(); + for(XMLSize_t i=0;iitem(i); + /* get attribute name */ + if (XMLString::equals(pAttributeNode->getName(), XIncludeUtils::fgXIBaseAttrName)){ + /*if (namespace == XMLUni::fgXMLString){ + + }*/ + return pAttributeNode->getValue(); + } + } + } + } + return NULL; +} + +// --------------------------------------------------------------------------- +// This method assumes that currentNode is an xinclude element and parses +// it accordingly, acting on what it finds. +// --------------------------------------------------------------------------- +bool +XIncludeUtils::doDOMNodeXInclude(DOMNode *xincludeNode, DOMDocument *parsedDocument, XMLEntityHandler* entityResolver){ + bool modifiedNode = false; + /* the relevant attributes to look for */ + const XMLCh *href = NULL; + const XMLCh *parse = NULL; + const XMLCh *xpointer = NULL; + const XMLCh *encoding = NULL; + const XMLCh *accept = NULL; + const XMLCh *acceptlanguage = NULL; + DOMNode *includeParent = xincludeNode->getParentNode(); + + + if(xincludeNode->hasAttributes()) { + /* get all the attributes of the node */ + DOMNamedNodeMap *pAttributes = xincludeNode->getAttributes(); + XMLSize_t nSize = pAttributes->getLength(); + for(XMLSize_t i=0;iitem(i); + const XMLCh *attrName = pAttributeNode->getName(); + /* check each attribute against the potential useful names */ + if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeHREFAttrName)){ + href = pAttributeNode->getValue(); + } else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeParseAttrName)){ + parse = pAttributeNode->getValue(); + } else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeXPointerAttrName)){ + xpointer = pAttributeNode->getValue(); + } else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeEncodingAttrName)){ + encoding = pAttributeNode->getValue(); + } else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeAcceptAttrName)){ + accept = pAttributeNode->getValue(); + } else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeAcceptLanguageAttrName)){ + acceptlanguage = pAttributeNode->getValue(); + } else { + /* if any other attribute is in the xi namespace, it's an error */ + const XMLCh *attrNamespaceURI = pAttributeNode->getNamespaceURI(); + if (attrNamespaceURI && XMLString::equals(attrNamespaceURI, XIncludeUtils::fgXIIIncludeNamespaceURI)){ + } else { + /* ignore - any other attribute is allowed according to spec, + and must be ignored */ + } + } + } + } + // 3.1 xi:include Element + // The children property of the xi:include element may include a single xi:fallback element; + // the appearance of more than one xi:fallback element, an xi:include element, + // or any other element from the XInclude namespace is a fatal error. + DOMNode *child; + DOMElement *fallback = NULL; + for (child = xincludeNode->getFirstChild(); child != 0; child=child->getNextSibling()){ + if(child->getNodeType()!=DOMNode::ELEMENT_NODE) + continue; + if ( isXIFallbackDOMNode(child) ){ + if (fallback != NULL){ + /* fatal error - there are more than one fallback children */ + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeMultipleFallbackElems, + parsedDocument->getDocumentURI(), parsedDocument->getDocumentURI()); + return false; + } + fallback = (DOMElement*)child; + } + else if(isXIIncludeDOMNode(child) || XMLString::equals(child->getNamespaceURI(), XIncludeUtils::fgXIIIncludeNamespaceURI)) { + /* fatal error - an xi element different from xi:fallback is a child of xi:include */ + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeDisallowedChild, + child->getNodeName(), parsedDocument->getDocumentURI()); + return false; + } + } + + if (href == NULL){ + /* this is an unrecoverable error until we have xpointer support - + if there is an xpointer, the current document is assumed + however, there is no xpointer support yet */ + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeNoHref, + NULL, parsedDocument->getDocumentURI()); + return false; + } + + /* set up the accept and accept-language values */ + if (accept != NULL){ + + } + + if (parse == NULL){ + /* use the default, as specified */ + parse = XIncludeUtils::fgXIIncludeParseAttrXMLValue; + } + + if (xpointer != NULL){ + /* not supported yet */ + /* Note that finding an xpointer attr along with parse="text" is a Fatal Error + * - http://www.w3.org/TR/xinclude/#include-location */ + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeXPointerNotSupported, + NULL, href); + return false; + } + + /* set up the href according to what has gone before */ + XIncludeLocation hrefLoc(href); + XIncludeLocation relativeLocation(href); + const XMLCh *includeBase = xincludeNode->getBaseURI(); + if (includeBase != NULL){ + hrefLoc.prependPath(includeBase); + } + + if (getBaseAttrValue(xincludeNode) != NULL){ + relativeLocation.prependPath(getBaseAttrValue(xincludeNode)); + } + + /* Take the relevant action - we need to retrieve the target as a whole before + we can know if it was successful or not, therefore the do* methods do + not modify the parsedDocument. Swapping the results in is left to the + caller (i.e. here) */ + DOMText *includedText = NULL; + DOMDocument *includedDoc = NULL; + if (XMLString::equals(parse, XIncludeUtils::fgXIIncludeParseAttrXMLValue)){ + /* including a XML element */ + includedDoc = doXIncludeXMLFileDOM(hrefLoc.getLocation(), relativeLocation.getLocation(), xincludeNode, parsedDocument, entityResolver); + } else if (XMLString::equals(parse, XIncludeUtils::fgXIIncludeParseAttrTextValue)){ + /* including a text value */ + includedText = doXIncludeTEXTFileDOM(hrefLoc.getLocation(), relativeLocation.getLocation(), encoding, xincludeNode, parsedDocument, entityResolver); + } else { + /* invalid parse attribute value - fatal error according to the specification */ + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeInvalidParseVal, + parse, parsedDocument->getDocumentURI()); + return false; + } + + RefVectorOf delayedProcessing(12,false); + if (includedDoc == NULL && includedText == NULL){ + /* there was an error - this is now a resource error + let's see if there is a fallback */ + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeIncludeFailedResourceError, + hrefLoc.getLocation(), parsedDocument->getDocumentURI()); + + if (includeParent == NULL){ + includeParent = parsedDocument; + } + + // we could be getting errors trying to insert elements at the root of the document, so we should use replaceChild; + // in order to handle multiple nodes, add them to a document fragment and use that to replace the original node + if (fallback){ + /* baseURI fixups - see http://www.w3.org/TR/xinclude/#base for details. */ + XMLUri parentURI(includeParent->getBaseURI()); + XMLUri includedURI(fallback->getBaseURI()); + + if (fallback->hasChildNodes()){ + DOMDocumentFragment* frag = parsedDocument->createDocumentFragment(); + DOMNode *child = fallback->getFirstChild(); + /* add the content of the fallback element, and remove the fallback elem itself */ + for ( ; child != NULL ; child=child->getNextSibling()){ + if (child->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE){ + continue; + } + DOMNode *newNode = parsedDocument->importNode(child, true); + /* if the paths differ we need to add a base attribute */ + if (newNode->getNodeType()==DOMNode::ELEMENT_NODE && !XMLString::equals(parentURI.getPath(), includedURI.getPath())){ + if (getBaseAttrValue(newNode) == NULL){ + /* need to calculate the proper path difference to get the relativePath */ + ((DOMElement*)newNode)->setAttribute(fgXIBaseAttrName, getBaseAttrValue(fallback->getParentNode())); + } else { + /* the included node has base of its own which takes precedence */ + XIncludeLocation xil(getBaseAttrValue(newNode)); + if (getBaseAttrValue(fallback->getParentNode()) != NULL){ + /* prepend any specific base modification of the xinclude node */ + xil.prependPath(getBaseAttrValue(fallback->getParentNode())); + } + ((DOMElement*)newNode)->setAttribute(fgXIBaseAttrName, xil.getLocation()); + } + } + DOMNode *newChild = frag->appendChild(newNode); + // don't process the node now, wait until it is placed in the final position + delayedProcessing.addElement(newChild); + //parseDOMNodeDoingXInclude(newChild, parsedDocument, entityResolver); + } + includeParent->replaceChild(frag, xincludeNode); + frag->release(); + + for(XMLSize_t i=0;iremoveChild(xincludeNode); + modifiedNode = true; + } + } else { + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeIncludeFailedNoFallback, + parsedDocument->getDocumentURI(), parsedDocument->getDocumentURI()); + return false; + } + } else { + if (includedDoc){ + /* record the successful include while we process the children */ + addDocumentURIToCurrentInclusionHistoryStack(hrefLoc.getLocation()); + + DOMDocumentFragment* frag = parsedDocument->createDocumentFragment(); + /* need to import the document prolog here */ + DOMNode *child = includedDoc->getFirstChild(); + for (; child != NULL; child = child->getNextSibling()) { + if (child->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) + continue; + // check for NOTATION or ENTITY clash + if(child->getNodeType()==DOMNode::ELEMENT_NODE && includedDoc->getDoctype()!=NULL) { + DOMNamedNodeMap *pAttributes = child->getAttributes(); + XMLSize_t nSize = pAttributes->getLength(); + for(XMLSize_t i=0;iitem(i); + const DOMTypeInfo * typeInfo=pAttributeNode->getSchemaTypeInfo(); + if(typeInfo && XMLString::equals(typeInfo->getTypeNamespace(), XMLUni::fgInfosetURIName)) { + if(XMLString::equals(typeInfo->getTypeName(), XMLUni::fgNotationString)) { + const XMLCh* notationName=pAttributeNode->getNodeValue(); + DOMNotation* notat=(DOMNotation*)includedDoc->getDoctype()->getNotations()->getNamedItem(notationName); + // ensure we have a DTD + if(parsedDocument->getDoctype()==NULL) + parsedDocument->insertBefore(parsedDocument->createDocumentType(parsedDocument->getDocumentElement()->getNodeName(), NULL,NULL), parsedDocument->getFirstChild()); + DOMNotation* myNotation=(DOMNotation*)parsedDocument->getDoctype()->getNotations()->getNamedItem(notationName); + if(myNotation==NULL) + { + // it's missing, add it + parsedDocument->getDoctype()->getNotations()->setNamedItem(parsedDocument->importNode(notat, true)); + } + else if(XMLString::equals(myNotation->getPublicId(), notat->getPublicId()) && + XMLString::equals(myNotation->getSystemId(), notat->getSystemId()) && + XMLString::equals(myNotation->getBaseURI(), notat->getBaseURI())) + { + // it's duplicate, ignore it + } + else + { + // it's a conflict, report it + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeConflictingNotation, + notationName, parsedDocument->getDocumentURI()); + } + } + else if(XMLString::equals(typeInfo->getTypeName(), XMLUni::fgEntityString)) { + const XMLCh* entityName=pAttributeNode->getNodeValue(); + DOMEntity* ent=(DOMEntity*)includedDoc->getDoctype()->getEntities()->getNamedItem(entityName); + // ensure we have a DTD + if(parsedDocument->getDoctype()==NULL) + parsedDocument->insertBefore(parsedDocument->createDocumentType(parsedDocument->getDocumentElement()->getNodeName(), NULL,NULL), parsedDocument->getFirstChild()); + DOMEntity* myEnt=(DOMEntity*)parsedDocument->getDoctype()->getEntities()->getNamedItem(entityName); + if(myEnt==NULL) + { + // it's missing, add it + parsedDocument->getDoctype()->getEntities()->setNamedItem(parsedDocument->importNode(ent, true)); + } + else if(XMLString::equals(myEnt->getPublicId(), ent->getPublicId()) && + XMLString::equals(myEnt->getSystemId(), ent->getSystemId()) && + XMLString::equals(myEnt->getBaseURI(), ent->getBaseURI())) + { + // it's duplicate, ignore it + } + else + { + // it's a conflict, report it + XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeConflictingEntity, + entityName, parsedDocument->getDocumentURI()); + } + } + } + } + } + DOMNode *newNode = parsedDocument->importNode(child, true); + DOMNode *newChild = frag->appendChild(newNode); + // don't process the node now, wait until it is placed in the final position + delayedProcessing.addElement(newChild); + //parseDOMNodeDoingXInclude(newChild, parsedDocument, entityResolver); + } + includeParent->replaceChild(frag, xincludeNode); + frag->release(); + + for(XMLSize_t i=0;ireplaceChild(includedText, xincludeNode); + modifiedNode = true; + } + } + + if (includedDoc) + includedDoc->release(); + + return modifiedNode; +} + +DOMDocument * +XIncludeUtils::doXIncludeXMLFileDOM(const XMLCh *href, + const XMLCh *relativeHref, + DOMNode *includeNode, + DOMDocument *parsedDocument, + XMLEntityHandler* entityResolver){ + if (XIncludeUtils::isInCurrentInclusionHistoryStack(href)){ + /* including something back up the current history */ + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCircularInclusionLoop, + href, href); + return NULL; + } + + if (XMLString::equals(href, parsedDocument->getBaseURI())){ + /* trying to include itself */ + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCircularInclusionDocIncludesSelf, + href, href); + return NULL; + } + + /* Instantiate the DOM parser. */ + XercesDOMParser parser; + parser.setDoNamespaces(true); + /* don't want to recurse the xi processing here */ + parser.setDoXInclude(false); + /* create the schema info nodes, so that we can detect conflicting notations */ + parser.setCreateSchemaInfo(true); + XMLInternalErrorHandler xierrhandler; + parser.setErrorHandler(&xierrhandler); + + DOMDocument *includedNode = NULL; + try { + InputSource* is=NULL; + Janitor janIS(is); + if(entityResolver) { + XMLResourceIdentifier resIdentifier(XMLResourceIdentifier::ExternalEntity, + relativeHref, + NULL, + NULL, + includeNode->getBaseURI()); + is=entityResolver->resolveEntity(&resIdentifier); + janIS.reset(is); + } + if(janIS.get()!=NULL) + parser.parse(*janIS.get()); + else + parser.parse(href); + /* need to be able to release the parser but keep the document */ + if (!xierrhandler.getSawError() && !xierrhandler.getSawFatal()) + includedNode = parser.adoptDocument(); + } + catch (const XMLException& /*toCatch*/) + { + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeResourceErrorWarning, + href, href); + } + catch (const DOMException& /*toCatch*/) + { + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeResourceErrorWarning, + href, href); + } + catch (...) + { + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeResourceErrorWarning, + href, href); + } + + //addDocumentURIToCurrentInclusionHistoryStack(href); + + if(includedNode != NULL){ + /* baseURI fixups - see http://www.w3.org/TR/xinclude/#base for details. */ + DOMElement *topLevelElement = includedNode->getDocumentElement(); + if (topLevelElement && topLevelElement->getNodeType() == DOMNode::ELEMENT_NODE ){ + XMLUri parentURI(includeNode->getBaseURI()); + XMLUri includedURI(includedNode->getBaseURI()); + + /* if the paths differ we need to add a base attribute */ + if (!XMLString::equals(parentURI.getPath(), includedURI.getPath())){ + if (getBaseAttrValue(topLevelElement) == NULL){ + /* need to calculate the proper path difference to get the relativePath */ + topLevelElement->setAttribute(fgXIBaseAttrName, relativeHref); + } else { + /* the included node has base of its own which takes precedence */ + XIncludeLocation xil(getBaseAttrValue(topLevelElement)); + if (getBaseAttrValue(includeNode) != NULL){ + /* prepend any specific base modification of the xinclude node */ + xil.prependPath(getBaseAttrValue(includeNode)); + } + topLevelElement->setAttribute(fgXIBaseAttrName, xil.getLocation()); + } + } + } + } + return includedNode; +} + +DOMText * +XIncludeUtils::doXIncludeTEXTFileDOM(const XMLCh *href, + const XMLCh *relativeHref, + const XMLCh *encoding, + DOMNode *includeNode, + DOMDocument *parsedDocument, + XMLEntityHandler* entityResolver){ + if (encoding == NULL) + /* "UTF-8" is stipulated default by spec */ + encoding = XMLUni::fgUTF8EncodingString; + + XMLTransService::Codes failReason; + XMLTranscoder* transcoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, 16*1024); + Janitor janTranscoder(transcoder); + if (failReason){ + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile, href, href); + return NULL; + } + + //addDocumentURIToCurrentInclusionHistoryStack(href); + + InputSource* is=NULL; + Janitor janIS(is); + if(entityResolver) { + XMLResourceIdentifier resIdentifier(XMLResourceIdentifier::ExternalEntity, + relativeHref, + NULL, + NULL, + includeNode->getBaseURI()); + is=entityResolver->resolveEntity(&resIdentifier); + janIS.reset(is); + } + if(janIS.get()==NULL) + janIS.reset(new URLInputSource(href)); + if(janIS.get()==NULL) { + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile, + href, href); + return NULL; + } + BinInputStream* stream=janIS.get()->makeStream(); + if(stream==NULL) { + XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile, + href, href); + return NULL; + } + Janitor janStream(stream); + const XMLSize_t maxToRead=16*1024; + XMLByte* buffer=(XMLByte*)XMLPlatformUtils::fgMemoryManager->allocate(maxToRead * sizeof(XMLByte)); + if(buffer==NULL) + throw OutOfMemoryException(); + ArrayJanitor janBuffer(buffer, XMLPlatformUtils::fgMemoryManager); + XMLCh* xmlChars=(XMLCh*)XMLPlatformUtils::fgMemoryManager->allocate(maxToRead*2*sizeof(XMLCh)); + if(xmlChars==NULL) + throw OutOfMemoryException(); + ArrayJanitor janUniBuffer(xmlChars, XMLPlatformUtils::fgMemoryManager); + unsigned char *charSizes = (unsigned char *)XMLPlatformUtils::fgMemoryManager->allocate(maxToRead * sizeof(unsigned char)); + if(charSizes==NULL) + throw OutOfMemoryException(); + ArrayJanitor janCharSizes(charSizes, XMLPlatformUtils::fgMemoryManager); + + XMLSize_t nRead, nOffset=0; + XMLBuffer repository; + while((nRead=stream->readBytes(buffer+nOffset, maxToRead-nOffset))>0){ + XMLSize_t bytesEaten=0; + XMLSize_t nCount = transcoder->transcodeFrom(buffer, nRead, xmlChars, maxToRead*2, bytesEaten, charSizes); + repository.append(xmlChars, nCount); + if(bytesEatencreateTextNode(repository.getRawBuffer()); +} + +/*static*/ bool +XIncludeUtils::isXIIncludeDOMNode(DOMNode *node){ + const XMLCh *nodeName = node->getLocalName(); + const XMLCh *namespaceURI = node->getNamespaceURI(); + + return isXIIncludeElement(nodeName, namespaceURI); +} + +/*static*/ bool +XIncludeUtils::isXIFallbackDOMNode(DOMNode *node){ + const XMLCh *nodeName = node->getLocalName(); + const XMLCh *namespaceURI = node->getNamespaceURI(); + + return isXIFallbackElement(nodeName, namespaceURI); +} + +/*static*/ bool +XIncludeUtils::isXIIncludeElement(const XMLCh *name, const XMLCh *namespaceURI){ + if (namespaceURI == NULL || name == NULL){ + /* no namespaces not supported */ + return false; + } + if (XMLString::equals(name, fgXIIncludeQName) + && XMLString::equals(namespaceURI, fgXIIIncludeNamespaceURI)){ + return true; + } + return false; +} + +/*static*/ bool +XIncludeUtils::isXIFallbackElement(const XMLCh *name, const XMLCh *namespaceURI){ + if (namespaceURI == NULL || name == NULL){ + /* no namespaces not supported */ + return false; + } + if (XMLString::equals(name, fgXIFallbackQName) + && XMLString::equals(namespaceURI, fgXIIIncludeNamespaceURI)){ + return true; + } + return false; +} + +/* 4.1.1 */ +const XMLCh * +XIncludeUtils::getEscapedHRefAttrValue(const XMLCh * /*hrefAttrValue*/, bool & /*needsDeallocating*/){ + XMLCh *escapedAttr = NULL; + return escapedAttr; +} + +/* 4.1.2 */ +bool +XIncludeUtils::setContentNegotiation(const XMLCh * /*acceptAttrValue*/, const XMLCh * /*acceptLangAttrValue*/){ + return false; +} + +bool +XIncludeUtils::checkTextIsValidForInclude(XMLCh * /*includeChars*/){ + return false; +} + +// ======================================================== +// the stack utilities are slightly convoluted debug versions, they +// will be pared down for the release code +// ======================================================== +static XIncludeHistoryNode * +getTopOfCurrentInclusionHistoryStack(XIncludeHistoryNode *head){ + XIncludeHistoryNode *historyCursor = head; + if (historyCursor == NULL){ + return NULL; + } + while (historyCursor->next != NULL){ + historyCursor = historyCursor->next; + } + return historyCursor; +} + +bool +XIncludeUtils::addDocumentURIToCurrentInclusionHistoryStack(const XMLCh *URItoAdd){ + XIncludeHistoryNode *newNode = (XIncludeHistoryNode *)XMLPlatformUtils::fgMemoryManager->allocate(sizeof(XIncludeHistoryNode)); + if (newNode == NULL){ + return false; + } + newNode->URI = XMLString::replicate(URItoAdd); + newNode->next = NULL; + + if (fIncludeHistoryHead == NULL){ + fIncludeHistoryHead = newNode; + return true; + } + XIncludeHistoryNode *topNode = getTopOfCurrentInclusionHistoryStack(fIncludeHistoryHead); + topNode->next = newNode; + return true; +} + +bool +XIncludeUtils::isInCurrentInclusionHistoryStack(const XMLCh *toFind){ + XIncludeHistoryNode *historyCursor = fIncludeHistoryHead; + /* walk the list */ + while (historyCursor != NULL){ + if (XMLString::equals(toFind, historyCursor->URI)){ + return true; + } + historyCursor = historyCursor->next; + } + return false; +} + +XIncludeHistoryNode * +XIncludeUtils::popFromCurrentInclusionHistoryStack(const XMLCh * /*toPop*/){ + XIncludeHistoryNode *historyCursor = fIncludeHistoryHead; + XIncludeHistoryNode *penultimateCursor = historyCursor; + + if (fIncludeHistoryHead == NULL){ + return NULL; + } + + while (historyCursor->next != NULL){ + penultimateCursor = historyCursor; + historyCursor = historyCursor->next; + } + + if (historyCursor == fIncludeHistoryHead){ + fIncludeHistoryHead = NULL; + } else { + penultimateCursor->next = NULL; + } + + XMLString::release(&(historyCursor->URI)); + XMLPlatformUtils::fgMemoryManager->deallocate((void *)historyCursor); + return NULL; +} + +void +XIncludeUtils::freeInclusionHistory(){ + XIncludeHistoryNode *historyCursor = XIncludeUtils::fIncludeHistoryHead; + while (historyCursor != NULL){ + XIncludeHistoryNode *next = historyCursor->next; + XMLString::release(&(historyCursor->URI)); + XMLPlatformUtils::fgMemoryManager->deallocate((void *)historyCursor); + historyCursor = next; + } + XIncludeUtils::fIncludeHistoryHead = NULL; +} + +bool +XIncludeUtils::reportError(const DOMNode* const /*errorNode*/ + , XMLErrs::Codes errorType + , const XMLCh* const errorMsg + , const XMLCh * const href) +{ + bool toContinueProcess = true; /* default value for no error handler */ + + const XMLCh* const systemId = href; + const XMLCh* const publicId = href; + /* TODO - look these up somehow? */ + const XMLFileLoc lineNum = 0; + const XMLFileLoc colNum = 0; + + if (fErrorReporter) + { + // Load the message into a local for display + const XMLSize_t msgSize = 1023; + XMLCh errText[msgSize + 1]; + + /* TODO - investigate whether this is complete */ + XMLMsgLoader *errMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain); + if (errorMsg == NULL){ + if (errMsgLoader->loadMsg(errorType, errText, msgSize)) + { + // Probably should load a default msg here + } + } else { + if (errMsgLoader->loadMsg(errorType, errText, msgSize, errorMsg)) + { + // Probably should load a default msg here + } + } + + fErrorReporter->error(errorType + , XMLUni::fgXMLErrDomain //fgXMLErrDomain + , XMLErrs::errorType(errorType) + , errText + , systemId + , publicId + , lineNum + , colNum); + } + + if (XMLErrs::isFatal(errorType)) + fErrorCount++; + + return toContinueProcess; +} + +/* TODO - declared in this file for convenience, prob ought to be moved out to + util/XMLUni.cpp before releasing */ +const XMLCh XIncludeUtils::fgXIIncludeQName[] = +{ + chLatin_i, chLatin_n, chLatin_c, chLatin_l, chLatin_u, chLatin_d, chLatin_e, chNull +}; +const XMLCh XIncludeUtils::fgXIFallbackQName[] = +{ + chLatin_f, chLatin_a, chLatin_l, chLatin_l, chLatin_b, chLatin_a, chLatin_c, chLatin_k, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeHREFAttrName[] = +{ + chLatin_h, chLatin_r, chLatin_e, chLatin_f, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeParseAttrName[] = +{ + chLatin_p, chLatin_a, chLatin_r, chLatin_s, chLatin_e, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeXPointerAttrName[] = +{ + chLatin_x, chLatin_p, chLatin_o, chLatin_i, chLatin_n, chLatin_t, chLatin_e, chLatin_r, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeEncodingAttrName[] = +{ + chLatin_e, chLatin_n, chLatin_c, chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeAcceptAttrName[] = +{ + chLatin_a, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeAcceptLanguageAttrName[] = +{ + chLatin_a, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chDash, chLatin_l, chLatin_a, + chLatin_n, chLatin_g, chLatin_u, chLatin_a, chLatin_g, chLatin_e, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeParseAttrXMLValue[] = +{ + chLatin_x, chLatin_m, chLatin_l, chNull +}; +const XMLCh XIncludeUtils::fgXIIncludeParseAttrTextValue[] = +{ + chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull +}; +const XMLCh XIncludeUtils::fgXIIIncludeNamespaceURI[] = +{ + /* http://www.w3.org/2001/XInclude */ + chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash + , chForwardSlash, chLatin_w, chLatin_w, chLatin_w, chPeriod + , chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g + , chForwardSlash, chDigit_2, chDigit_0, chDigit_0, chDigit_1 + , chForwardSlash, chLatin_X, chLatin_I, chLatin_n, chLatin_c, chLatin_l + , chLatin_u, chLatin_d, chLatin_e, chNull +}; +const XMLCh XIncludeUtils::fgXIBaseAttrName[] = +{ + chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull +}; + +XERCES_CPP_NAMESPACE_END diff --git a/include/xercesc/xinclude/XIncludeUtils.hpp b/include/xercesc/xinclude/XIncludeUtils.hpp new file mode 100644 index 0000000..8f5f248 --- /dev/null +++ b/include/xercesc/xinclude/XIncludeUtils.hpp @@ -0,0 +1,267 @@ +/* + * 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: XIncludeUtils.hpp 673949 2008-07-04 08:04:44Z borisk $ + */ + +#if !defined(XERCESC_INCLUDE_GUARD_XINCLUDEUTILS_HPP) +#define XERCESC_INCLUDE_GUARD_XINCLUDEUTILS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +XERCES_CPP_NAMESPACE_BEGIN + +class XMLEntityHandler; + +typedef struct XIncludeHistoryNode{ + XMLCh *URI; + struct XIncludeHistoryNode *next; +}XIncludeHistoryNode; + +/** + * Class implementing all the utility functions required by an XInclude parser. + * + * This class is designed primarily for internal use. This class implements + * utility methods to be called by an XInclude parser. It is intended to encapsulate + * the actual processing and recognition of XInclude components. + */ +class XINCLUDE_EXPORT XIncludeUtils +{ +private: + + /** Constructor + * + */ + XIncludeUtils(XMLErrorReporter *errorReporter); + + /** Destructor + * + */ + ~XIncludeUtils(); + + /** Parse the supplied XInclude element performing relevant XInclude functionality + * + * @param xincludeNode The XInclude node to parse and action + * @param parsedDocument The DOMDocument to which the results of the XInclude are to be added + * + * @return true if the XInclude processing was successful, false if not. Note that an + * XInclude that fails resulting in a successful fallback action would return true. + */ + bool doDOMNodeXInclude(DOMNode *xincludeNode, DOMDocument *parsedDocument, XMLEntityHandler* entityResolver); + + /** Parse an XInclude xml file into a DOMDocument node. + * + * @param href the location of the document to include + * @param relativeHref + * @param parsedDocument + * + * @return a newly created DOMDocument containing the parsed and actioned + * href, or NULL if the document could not be loaded. + */ + DOMDocument *doXIncludeXMLFileDOM(const XMLCh *href, + const XMLCh *relativeHref, + DOMNode *xincludeNode, + DOMDocument *parsedDocument, + XMLEntityHandler* entityResolver); + + /** Parse an XInclude text file into a DOMText node. + * + * @param href the location of the document to include + * @param relativeHref + * @param encoding + * @param parsedDocument + * + * @return a newly created DOMText containing the parsed and actioned + * href, or NULL if the document could not be loaded. + */ + DOMText *doXIncludeTEXTFileDOM(const XMLCh *href, + const XMLCh *relativeHref, + const XMLCh *encoding, + DOMNode *xincludeNode, + DOMDocument *parsedDocument, + XMLEntityHandler* entityResolver); + + /** Detect whether the supplied details are correct for an xi:include element + * + * @param name the element name + * @param namespaceURI the element namespace + * + * @return true if details are valid for an xi:include element, false + * if not. + */ + static bool isXIIncludeElement(const XMLCh *name, const XMLCh *namespaceURI); + + /** Detect whether the supplied details are correct for an xi:fallback element + * + * @param name the element name + * @param namespaceURI the element namespace + * + * @return true if details are valid for an xi:fallback element, false + * if not. + */ + static bool isXIFallbackElement(const XMLCh *name, const XMLCh *namespaceURI); + + /** Detect whether the supplied DOMNode is an xi:include element + * + * @param node The node to check + * + * @return true if node is an xi:include element, false + * if not. + */ + static bool isXIIncludeDOMNode(DOMNode *node); + + /** Detect whether the supplied DOMNode is an xi:fallback element + * + * @param node The DOMNode to check + * + * @return true if node is an xi:fallback element, false + * if not. + */ + static bool isXIFallbackDOMNode(DOMNode *node); + + /** Walk the content of the supplied source node, performing any xinclude actions + * that are encountered. + * + * @param source A DOMNode to parse, this node may be modified by the method + * @param parsedDocument the DOMDocument to which the parsed results are to be copied. + * + * @return true if XInclude behaviour was successfully performed on source, false if not. + */ + bool parseDOMNodeDoingXInclude(DOMNode *source, DOMDocument *parsedDocument, XMLEntityHandler* entityResolver); + + /** Parse the supplied URI and escape all characters as specified by + * the XINclusions specification. + * + * @param hrefAttrValue the href to parse and escape. + * @param needsDeallocating set to true if the return value needs deallocating + * by the caller after use, false if the value returned is the same as the + * hrefAttrValue passed in. + * + * @return an escaped version of hrefAttrValue or hrefAttrValue itself if + * hrefAttrValue contains only valid characters. + */ + /* 4.1.1 */ + const XMLCh *getEscapedHRefAttrValue(const XMLCh *hrefAttrValue, bool &needsDeallocating); + + /** Set the accept and accept-lang parameters on HTTP requests generated while + * XIncluding. + * + * @param acceptAttrValue + * @param acceptLangAttrValue + * + * @return true if the values were successfully added to the HTTP request, false + * if not. + */ + /* 4.1.2 */ + bool setContentNegotiation(const XMLCh *acceptAttrValue, const XMLCh *acceptLangAttrValue); + + /** Check the characters passed in are all valid characters for XInclusion + * as specified at http://www.w3.org/TR/xinclude/#text-included-items + * + * @param includeChars the characters to parse for validity + * + * @return true if the includeChars parameter contains only valid characters + * for inclusion, false if there are invalid characters in includeChars. + */ + bool checkTextIsValidForInclude(XMLCh *includeChars); + + /** Add the supplied parameter to the InclusionHistoryStack + * + * @param URItoAdd the URI to add to the InclusionHistoryStack/ + * + * @return true if the URI was added, false if a problem prevented + * the URI being added. + */ + bool addDocumentURIToCurrentInclusionHistoryStack(const XMLCh *URItoAdd); + + /** Check the XInclude InclusionHistoryStack to see if the supplied URI + * has already been included. This is used to ensure that circular inclusion + * chains are detected and that the inclusion mechanism does not get stuck in + * a loop. + * + * @param toFind the URI to look up. + * + * @return true if the toFind parameter is found in the InclusionHistortStack, + * false if the parameter is not in the stack or the stack is empty. + */ + bool isInCurrentInclusionHistoryStack(const XMLCh *toFind); + + /** Pop (i.e. remove and return) the top value from the InclusionHistoryStack + * + * @param toPop the value that is expected to be at the top of the stack, or + * NULL if no checking is required. + * + * @return the element at the top of the stack + */ + XIncludeHistoryNode * popFromCurrentInclusionHistoryStack(const XMLCh *toPop); + + /** Free the internal inclusion history list. + * + * @return nothing + */ + void freeInclusionHistory(); + + /** Construct and pass on an error description + * + * @param errorNode The DOMNode that was being parsed when the error occurred + * @param errorType The severity of the error + * @param errorMsg An optional message to include in the error report + * @param href The URI of the document being parsed. + * + * @return true if the errorHandler requests continuation of parsing despite error + * false if the errorHandler requests parsing end on encountering error, or it + * there is no error handler. + */ + bool reportError(const DOMNode* const errorNode + , XMLErrs::Codes errorType + , const XMLCh* const errorMsg + , const XMLCh* const href); + +public: + /* temporarily public to facilitate helper func getBaseAttrValue */ + static const XMLCh fgXIBaseAttrName[]; +private: + XIncludeHistoryNode *fIncludeHistoryHead; + XMLSize_t fErrorCount; + XMLErrorReporter *fErrorReporter; + static const XMLCh fgXIIncludeQName[]; + static const XMLCh fgXIFallbackQName[]; + static const XMLCh fgXIIncludeHREFAttrName[]; + static const XMLCh fgXIIncludeParseAttrName[]; + static const XMLCh fgXIIncludeParseAttrXMLValue[]; + static const XMLCh fgXIIncludeParseAttrTextValue[]; + static const XMLCh fgXIIncludeXPointerAttrName[]; + static const XMLCh fgXIIncludeEncodingAttrName[]; + static const XMLCh fgXIIncludeAcceptAttrName[]; + static const XMLCh fgXIIncludeAcceptLanguageAttrName[]; + static const XMLCh fgXIIIncludeNamespaceURI[]; + + friend class XIncludeDOMDocumentProcessor; + friend class AbstractDOMParser; +}; + +XERCES_CPP_NAMESPACE_END + +#endif diff --git a/lib/msvc14/x64/xerces-c_3.lib b/lib/msvc14/x64/xerces-c_3.lib new file mode 100644 index 0000000..ad61d77 Binary files /dev/null and b/lib/msvc14/x64/xerces-c_3.lib differ diff --git a/lib/msvc14/x64/xerces-c_3D.lib b/lib/msvc14/x64/xerces-c_3D.lib new file mode 100644 index 0000000..2a1252f Binary files /dev/null and b/lib/msvc14/x64/xerces-c_3D.lib differ