//////////////////////////////////////////////////////////////////////// // Copyright (c) Nehmulos 2011-2014 // This file is part of N0 Strain Serialization Library. // // N0Strain-Serialization-Library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // N0Strain-Serialization-Library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with N0Strain-Serialization-Library. If not, see https://gnu.org/licenses/lgpl-3.0 //////////////////////////////////////////////////////////////////////// #ifndef TAG_H_ #define TAG_H_ #include #include #include #include #include #include #include "N0SlibConstants.h" #include "N0SlibUtils.h" namespace nw { /// workaround for template type-Overloading /// many thanks to Johannes Schaub /// http://stackoverflow.com/questions/3052579/explicit-specialization-in-non-namespace-scope/3057522#3057522 template struct identity { typedef T type; }; /// States for the XmlParser. TODO 1.2 move to XmlReader typedef enum { readTagType, readTagName, searchNewTags, closeTag, searchAttributes, readAttributeName, assignAttribute, readAttributeValue, readXmlVersion, readCommentType, definitionTagName, definitionValue, cDataTagName, cDataValue, xmlComment, } PARSER_STATE; class Tag { public: Tag(); ///< Set's the name to "Unnamed" Tag(const String tagName); ///< Set's the Tag's name virtual ~Tag(); virtual Tag* addNewChild(const String tagName); ///< Adds a new Tag with the given Name and without value. template Tag* addNewChild(const String tagName, const String tagValue) ///< Adds a new Tag with the given String value. { Tag* newChild = new Tag(tagName); newChild->setValue(tagValue); newChild->setParent(this); newChild->setLevel(this->level+1); children.push_back(newChild); return newChild; } template Tag* addNewChild(const String tagName, T tagValue) ///< Adds a new Tag with the given String value. { Tag* newChild = new Tag(tagName); newChild->setValue(tagValue); newChild->setParent(this); newChild->setLevel(this->level+1); children.push_back(newChild); return newChild; } void addComment(const String text); ///< Adds a new Tag as a comment void addChild(Tag* child); ///< Add's a childTag to the childrenVector. void removeChild(Tag* child); ///< Removes a childTag form the vector. Does not Delete. bool hasGrandChildren(); ///< scary helper I provided publicly for some reason bool hasChildren(); ///< Returns true if the childrenVector is not empty /// Get the first child-Tag for the given Name. /// Returns NULL if there is no childtag with such a name. Tag* getChildWithName(const String childrenTagName); Tag* getLastChild(); ///< Get the latest added child String getName(); ///< Get the tag's name String getValue(); ///< Get the value String long double getLongDoubleValue(); ///< Converts the value String long long getLongLongValue(); ///< Converts the value String double getDoubleValue(); ///< Converts the value String float getFloatValue(); ///< Converts the value String long getLongValue(); ///< Converts the value String int getIntegerValue(); ///< Converts the value String short getShortValue(); ///< Converts the value String bool getBooleanValue(); ///< Parse "true" and "1" as true, everything else as false void* getPointerValue(); ///< Converts the value String char getCharacterValue(); ///< Converts the value String template T getValueAs() { return getValueAs(identity()); } unsigned char getUnsignedCharacterValue(); ///< Converts the value String signed char getSignedCharacterValue(); ///< Converts the value String unsigned short getUnsignedShortValue(); ///< Converts the value String unsigned int getUnsignedIntegerValue(); ///< Converts the value String unsigned long getUnsignedLongValue(); ///< Converts the value String void* getBase64Value(); ///< Converts the value String and creates a pointer to the result void* getHexValue(); ///< Converts the value String and creates a pointer to the result std::stack getCsvTags(); ///< Parse a CsvString into a stack of Tags (specialized for MarkupReder) Tag* getParent(); ///< Returns the Parent Tag. std::vector& getChildren(); ///< Returns a reference to a vector of it's child tags void setParent(Tag* parent); ///< Set's a new Parent Tag. void setName(const String value); ///< Set's the Tag's name void setValue(const String value); ///< Set's the Tag's value String template void setValue(T value) ///< Set's the Tag's value String { std::stringstream ss; String stringValue; ss << value; ss >> stringValue; setValue(stringValue); } static void writeXmlHeader(std::ostream& file); ///< Writes the Header for a xml File, TODO 1.2 move to xmlWriter // static String valueToHexaDecimalString(String value); void writeAsXmlWithAttributes(std::ostream& file); ///< Writes the current Tag and it's children to a fstream static bool useAttribute; ///< Init value for canBeAttribute void setLevel(int level); ///< Sets the numberOfTabs used bool operator==(Tag& that); ///< Returns true if the values and names are equal bool getIsComent() const; ///< Returns true if the tag is a comment bool getCanBeAttribute() const; ///< Returns ture if canBeAttribute is true void setIsComment(bool isComment); ///< Sets if the Tag is written as Comment void setCanBeAttribute(bool canBe); ///< Sets if the Tag can be written as Attribute void setIsValueArray(bool isVarray);///< Sets if the tag contains anonymous values void setCanBeAttributeRecursive(bool canBe); ///< sets canBeAttribute for itself and it's children protected: std::vector children; ///< All children that this tag holds Tag* parent; ///< The Tag that contains this tag, NULL if this is the motherTag String name; ///< The name of the Tag String value; ///< The value that is saved inside the Tag. int level; ///< Determins the Number of tabs infront of a tag bool isComment; ///< If it's true the Tag will be written as Comment. bool canBeAttribute; ///< If it's false it will never be written as Argument TODO move to XmlWriter bool isValueArray; ///< Does this Tag contain namesless values? This Boolean will tell us. inline void writeAsXmlAttribute(std::ostream& file); ///< Writes this Tag as Xml-Attribute to a fstream /////////////////////////////////////////////////////////////////////////// // // overloaded templates // /////////////////////////////////////////////////////////////////////////// template T getValueAs(identity) { std::stringstream ss(value); T ret; ss >> ret; return ret; } bool getValueAs(identity) { return this->getBooleanValue(); } const char* getValueAs(identity) { return this->value.c_str(); } String getValueAs(identity) { return this->value; } char getValueAs(identity) { return this->getValueAs(identity()); } unsigned char getValueAs(identity) { return this->getValueAs(identity()); } signed char getValueAs(identity) { return this->getValueAs(identity()); } }; } // namespace nw #endif /* TAG_H_ */