/*========================================================================= Program: Visualization Toolkit Module: vtkXMLDataElement.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkXMLDataElement * @brief Represents an XML element and those nested inside. * * vtkXMLDataElement is used by vtkXMLDataParser to represent an XML * element. It provides methods to access the element's attributes * and nested elements in a convenient manner. This allows easy * traversal of an input XML file by vtkXMLReader and its subclasses. * * @sa * vtkXMLDataParser */ #ifndef vtkXMLDataElement_h #define vtkXMLDataElement_h #include "vtkCommonDataModelModule.h" // For export macro #include "vtkObject.h" class vtkXMLDataParser; class VTKCOMMONDATAMODEL_EXPORT vtkXMLDataElement : public vtkObject { public: vtkTypeMacro(vtkXMLDataElement, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; static vtkXMLDataElement* New(); //@{ /** * Set/Get the name of the element. This is its XML tag. */ vtkGetStringMacro(Name); virtual void SetName(const char* _arg); //@} //@{ /** * Set/Get the value of the id attribute of the element, if any. */ vtkGetStringMacro(Id); vtkSetStringMacro(Id); //@} /** * Get the attribute with the given name. If it doesn't exist, * returns 0. */ const char* GetAttribute(const char* name); /** * Set the attribute with the given name and value. If it doesn't exist, * adds it. */ void SetAttribute(const char* name, const char* value); //@{ /** * Set/Get the character data between XML start/end tags. */ void SetCharacterData(const char* c, int length); void AddCharacterData(const char* c, size_t length); vtkGetStringMacro(CharacterData); //@} //@{ /** * Get the attribute with the given name and converted to a scalar * value. Returns whether value was extracted. */ int GetScalarAttribute(const char* name, int& value); int GetScalarAttribute(const char* name, float& value); int GetScalarAttribute(const char* name, double& value); int GetScalarAttribute(const char* name, long& value); int GetScalarAttribute(const char* name, unsigned long& value); //@} //@{ /** * Set the attribute with the given name. * We can not use the same GetScalarAttribute() construct since * the compiler will not be able to resolve between * SetAttribute(..., int) and SetAttribute(..., unsigned long). */ void SetIntAttribute(const char* name, int value); void SetFloatAttribute(const char* name, float value); void SetDoubleAttribute(const char* name, double value); void SetUnsignedLongAttribute(const char* name, unsigned long value); //@} //@{ /** * Get the attribute with the given name and converted to a scalar * value. Returns length of vector read. */ int GetVectorAttribute(const char* name, int length, int* value); int GetVectorAttribute(const char* name, int length, float* value); int GetVectorAttribute(const char* name, int length, double* value); int GetVectorAttribute(const char* name, int length, long* value); int GetVectorAttribute(const char* name, int length, unsigned long* value); //@} //@{ /** * Set the attribute with the given name. */ void SetVectorAttribute(const char* name, int length, const int* value); void SetVectorAttribute(const char* name, int length, const float* value); void SetVectorAttribute(const char* name, int length, const double* value); void SetVectorAttribute(const char* name, int length, const unsigned long* value); //@} int GetScalarAttribute(const char* name, long long& value); int GetVectorAttribute(const char* name, int length, long long* value); void SetVectorAttribute(const char* name, int length, long long const* value); int GetScalarAttribute(const char* name, unsigned long long& value); int GetVectorAttribute(const char* name, int length, unsigned long long* value); void SetVectorAttribute(const char* name, int length, unsigned long long const* value); /** * Get the attribute with the given name and converted to a word type * such as VTK_FLOAT or VTK_UNSIGNED_LONG. */ int GetWordTypeAttribute(const char* name, int& value); //@{ /** * Get the number of attributes. */ vtkGetMacro(NumberOfAttributes, int); //@} /** * Get the n-th attribute name. * Returns 0 if there is no such attribute. */ const char* GetAttributeName(int idx); /** * Get the n-th attribute value. * Returns 0 if there is no such attribute. */ const char* GetAttributeValue(int idx); //@{ /** * Remove one or all attributes. */ virtual void RemoveAttribute(const char* name); virtual void RemoveAllAttributes(); //@} //@{ /** * Set/Get the parent of this element. */ vtkXMLDataElement* GetParent(); void SetParent(vtkXMLDataElement* parent); //@} /** * Get root of the XML tree this element is part of. */ virtual vtkXMLDataElement* GetRoot(); /** * Get the number of elements nested in this one. */ int GetNumberOfNestedElements(); /** * Get the element nested in this one at the given index. */ vtkXMLDataElement* GetNestedElement(int index); /** * Add nested element */ void AddNestedElement(vtkXMLDataElement* element); /** * Remove nested element. */ virtual void RemoveNestedElement(vtkXMLDataElement*); /** * Remove all nested elements. */ virtual void RemoveAllNestedElements(); //@{ /** * Find the first nested element with the given id, given name, or given * name and id. * WARNING: the search is only performed on the children, not * the grand-children. */ vtkXMLDataElement* FindNestedElement(const char* id); vtkXMLDataElement* FindNestedElementWithName(const char* name); vtkXMLDataElement* FindNestedElementWithNameAndId(const char* name, const char* id); vtkXMLDataElement* FindNestedElementWithNameAndAttribute( const char* name, const char* att_name, const char* att_value); //@} /** * Find the first nested element with given name. * WARNING: the search is performed on the whole XML tree. */ vtkXMLDataElement* LookupElementWithName(const char* name); /** * Lookup the element with the given id, starting at this scope. */ vtkXMLDataElement* LookupElement(const char* id); //@{ /** * Set/Get the offset from the beginning of the XML document to this element. */ vtkGetMacro(XMLByteIndex, vtkTypeInt64); vtkSetMacro(XMLByteIndex, vtkTypeInt64); //@} /** * Check if the instance has the same name, attributes, character data * and nested elements contents than the given element (this method is * applied recursively on the nested elements, and they must be stored in * the same order). * Warning: Id, Parent, XMLByteIndex are ignored. */ virtual int IsEqualTo(vtkXMLDataElement* elem); /** * Copy this element from another of the same type (elem), recursively. * Old attributes and nested elements are removed, new ones are created * given the contents of 'elem'. * Warning: Parent is ignored. */ virtual void DeepCopy(vtkXMLDataElement* elem); //@{ /** * Get/Set the internal character encoding of the attributes. * Default type is VTK_ENCODING_UTF_8. * Note that a vtkXMLDataParser has its own AttributesEncoding ivar. If * this ivar is set to something other than VTK_ENCODING_NONE, it will be * used to set the attribute encoding of each vtkXMLDataElement * created by this vtkXMLDataParser. */ vtkSetClampMacro(AttributeEncoding, int, VTK_ENCODING_NONE, VTK_ENCODING_UNKNOWN); vtkGetMacro(AttributeEncoding, int); //@} //@{ /** * Prints element tree as XML. */ void PrintXML(ostream& os, vtkIndent indent); void PrintXML(const char* fname); //@} //@{ /** * Get/Set the width (in number of fields) that character * data (that between open and closing tags ie. ... ) * is printed. If the width is less than one the tag's character * data is printed all on one line. If it is greater than one * the character data is streamed insterting line feeds every * width number of fields. See PrintXML. */ vtkGetMacro(CharacterDataWidth, int); vtkSetMacro(CharacterDataWidth, int); //@} protected: vtkXMLDataElement(); ~vtkXMLDataElement() override; // The name of the element from the XML file. char* Name; // The value of the "id" attribute, if any was given. char* Id; int CharacterDataWidth; // Data inside of the tag's open and close. ie character data char* CharacterData; // Null terminated buffer. size_t CharacterDataBlockSize; // Allocation size if buffer needs expand size_t CharacterDataBufferSize; // Allocated size. size_t EndOfCharacterData; // Number of bytes used. // Tags that have specialized character data handlers // can set this flag to improve performance. The default is unset. int IgnoreCharacterData; // Get/Set the stream position of the elements inline data. vtkGetMacro(InlineDataPosition, vtkTypeInt64); vtkSetMacro(InlineDataPosition, vtkTypeInt64); // The offset into the XML stream where the inline data begins. vtkTypeInt64 InlineDataPosition; // The offset into the XML stream where the element begins. vtkTypeInt64 XMLByteIndex; // The raw property name/value pairs read from the XML attributes. char** AttributeNames; char** AttributeValues; int NumberOfAttributes; int AttributesSize; int AttributeEncoding; // The set of nested elements. int NumberOfNestedElements; int NestedElementsSize; vtkXMLDataElement** NestedElements; // The parent of this element. vtkXMLDataElement* Parent; // Internal utility methods. vtkXMLDataElement* LookupElementInScope(const char* id); vtkXMLDataElement* LookupElementUpScope(const char* id); static int IsSpace(char c); void PrintCharacterData(ostream& os, vtkIndent indent); static void PrintWithEscapedData(ostream& os, const char* data); friend class vtkXMLDataParser; friend class vtkXMLMaterialParser; private: vtkXMLDataElement(const vtkXMLDataElement&) = delete; void operator=(const vtkXMLDataElement&) = delete; }; //---------------------------------------------------------------------------- inline void vtkXMLDataElement::AddCharacterData(const char* data, size_t length) { if (this->IgnoreCharacterData) { return; } // This is the index where we start to put the new data at. size_t eod = this->EndOfCharacterData - 1; // Check if the new data will write off the end. If it does // resize the character data buffer. this->EndOfCharacterData += length; if (this->EndOfCharacterData >= this->CharacterDataBufferSize) { while (this->EndOfCharacterData >= this->CharacterDataBufferSize) { this->CharacterDataBufferSize += this->CharacterDataBlockSize; } this->CharacterData = static_cast(realloc(this->CharacterData, this->CharacterDataBufferSize)); } // put the new data at the end of the buffer, and null terminate. char* pCD = this->CharacterData + eod; memmove(pCD, data, length); pCD[length] = '\0'; return; } #endif