root/src/Tag.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
////////////////////////////////////////////////////////////////////////
// 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 <string>
#include <sstream>
#include <vector>
#include <stack>
#include <fstream>
#include <iostream>

#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<typename T> 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 <class T>
        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 <class T>
        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<typename T> T getValueAs()
        {
                return getValueAs(identity<T>());
        }

        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<Tag*> getCsvTags();                   ///< Parse a CsvString into a stack of Tags (specialized for MarkupReder)
        Tag* getParent();                                                       ///< Returns the Parent Tag.
        std::vector<Tag*>& 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 <class T>
        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<Tag*> 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<typename T> T getValueAs(identity<T>)
        {
        std::stringstream ss(value);
                T ret;
                ss >> ret;
                return ret;
        }

    bool getValueAs(identity<bool>)
        {
                return this->getBooleanValue();
        }

    const char* getValueAs(identity<const char*>)
        {
                return this->value.c_str();
        }

    String getValueAs(identity<String>)
        {
                return this->value;
        }

    char getValueAs(identity<char>)
        {
                return this->getValueAs(identity<short>());
        }

    unsigned char getValueAs(identity<unsigned char>)
        {
                return this->getValueAs(identity<short>());
        }

    signed char getValueAs(identity<signed char>)
        {
                return this->getValueAs(identity<short>());
        }

};

}  // namespace nw
#endif /* TAG_H_ */