Subversion Repositories HomeAutomation

Rev

Rev 1596 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1596 runge 1
/*
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License along
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 */
20
 
21
#include "Node.h"
22
 
23
//#include <iostream>
24
 
25
#include <fstream>
26
#include <stdexcept>
27
 
28
#include <boost/lexical_cast.hpp>
29
#include <boost/algorithm/string/trim.hpp>
30
 
31
namespace atom {
32
namespace xml {
33
 
34
Node::Node()
35
{
36
 
37
}
38
 
39
Node::~Node()
40
{
41
 
42
}
43
 
44
void Node::LoadFile(std::string filename)
45
{
1601 runge 46
    std::ifstream srcfile(filename.data());
1596 runge 47
 
48
    if (!srcfile.is_open())
49
    {
50
        srcfile.close();
51
        throw std::runtime_error("Could not find " + filename);
52
        return;
53
    }
54
 
55
    std::string buffer = "";
56
    std::string line;
57
 
58
    while (!srcfile.eof())
59
    {
60
        std::getline(srcfile, line);
61
 
62
        if (srcfile.eof())
63
        {
64
            break;
65
        }
66
 
67
        buffer += line + "\n";
68
    }
69
 
70
    srcfile.close();
71
 
72
    this->Parse(buffer);
73
}
74
 
75
void Node::Parse(std::string data)
76
{
77
    char c;
78
    int position = 0;
79
 
80
    while (position < data.length())
81
    {
82
        c = data.at(position);
83
 
84
        switch (c)
85
        {
86
            case '<':
87
            {
88
                position = this->ParseTag(data, position);
89
                break;
90
            }
91
        }
92
 
93
        position++;
94
    }
95
}
96
 
97
int Node::ParseTag(std::string data, int position)
98
{
99
    if (data.at(position) != '<')
100
    {
101
        throw std::runtime_error("Id not find < as expected. Character " + boost::lexical_cast<std::string>(position));
102
    }
103
 
104
    position++;
105
 
106
    int end_position = data.find('>', position);
107
 
108
    if (data.at(position) == '?' || data.at(position) == '!' || data.at(position) == '/')
109
    {
110
        return end_position;
111
    }
112
 
113
    std::string tag_string;
114
 
115
    try
116
    {
117
        tag_string = data.substr(position, end_position - position);
118
    }
119
    catch (std::out_of_range& e)
120
    {
121
        throw std::runtime_error(e.what());
122
    }
123
 
124
    boost::algorithm::trim(tag_string);
125
    boost::algorithm::trim_if(tag_string, boost::is_any_of("\n"));
126
    boost::algorithm::trim(tag_string);
127
    tag_string += " ";
128
 
129
    bool found_end = false;
130
    bool found_tag = false;
131
    std::string buffer;
132
    int pos = 0;
133
    char c;
134
    int s, e;
135
 
136
    while (pos < tag_string.length())
137
    {
138
        c = tag_string.at(pos);
139
 
140
        switch (c)
141
        {
142
            case ' ':
143
            {
144
                if (!found_tag)
145
                {
146
                    this->tag_name_ = buffer;
147
                    buffer = "";
148
                    //std::cout << "Found tag: " << this->tag_name_ << std::endl;
149
                    found_tag = true;
150
                }
151
                break;
152
            }  
153
            case '/':
154
            {
155
                found_end = true;
156
                break;
157
            }
158
            case '=':
159
            {
160
                s = tag_string.find('"', pos) + 1;
161
                e = tag_string.find('"', s);
162
 
163
                try
164
                {
165
                    this->attributes_[buffer] = tag_string.substr(s, e - s);
166
                }
167
                catch (std::out_of_range& ex)
168
                {
169
                    throw std::runtime_error(ex.what());
170
                }
171
 
172
                pos = e;
173
                buffer = "";
174
                break;
175
            }
176
            default:
177
            {
178
                buffer += c;
179
                break;
180
            }
181
        }
182
 
183
        pos++;
184
    }
185
 
186
    position = end_position;
187
 
188
    if (!found_end)
189
    {
190
        while (position < data.length())
191
        {
192
            c = data.at(position);
193
 
194
            switch (c)
195
            {
196
                case '<':
197
                {
198
                    if (data.at(position+1) == '/')
199
                    {
200
                        position += 2;
201
                        end_position = data.find('>', position);
202
 
203
                        try
204
                        {
205
                            if (this->tag_name_.compare(data.substr(position, end_position - position)) == 0)
206
                            {
207
                                //std::cout << "Found end tag: " << this->tag_name_ << std::endl;
208
                                return end_position;
209
                            }
210
                            else
211
                            {
212
                                throw std::runtime_error("Invalid end tag found. " + data.substr(position, end_position - position) + "::" + this->tag_name_);
213
                            }
214
                        }
215
                        catch (std::out_of_range& e)
216
                        {
217
                            throw std::runtime_error(e.what());
218
                        }
219
 
220
 
221
                    }
222
 
223
                    Node sub_node;
224
                    position = sub_node.ParseTag(data, position);
225
                    this->children_.push_back(sub_node);
226
                    break;
227
                }
228
            }
229
 
230
            position++;
231
        }
232
    }
233
 
234
    return position;
235
}
236
 
237
Node Node::FindChild(std::string tag_name)
238
{
239
    for (int n = 0; n < this->children_.size(); n++)
240
    {
241
        if (this->children_[n].GetTagName().compare(tag_name) == 0)
242
        {
243
            return this->children_[n];
244
        }
245
    }
246
 
247
    throw std::runtime_error("No child with that tag name found, " + tag_name);
248
}
249
 
250
Node Node::SelectChild(std::string attribute_name, std::string attribute_value)
251
{
252
    for (int n = 0; n < this->children_.size(); n++)
253
    {
254
        if (this->children_[n].GetAttributeValue(attribute_name) == attribute_value)
255
        {
256
            return this->children_[n];
257
        }
258
    }
259
 
260
    throw std::runtime_error("No child with that attribute combination found, " + attribute_name + " = " + attribute_value);
261
}
262
 
263
Node Node::SelectChild(std::string attribute_name1, std::string attribute_value1, std::string attribute_name2, std::string attribute_value2)
264
{
265
    for (int n = 0; n < this->children_.size(); n++)
266
    {
267
        if (this->children_[n].GetAttributeValue(attribute_name1) == attribute_value1 && this->children_[n].GetAttributeValue(attribute_name2) == attribute_value2)
268
        {
269
            return this->children_[n];
270
        }
271
    }
272
 
273
    throw std::runtime_error("No child with that attribute combination found, " + attribute_name1 + " = " + attribute_value1 + " && " + attribute_name2 + " = " + attribute_value2);
274
}
275
 
276
std::string Node::GetAttributeValue(std::string attribute_name)
277
{
278
    AttributeList::const_iterator iterator = this->attributes_.find(attribute_name);
279
 
280
    if (iterator == this->attributes_.end())
281
    {
282
        throw std::runtime_error("No attribute with that name found, " + attribute_name);
283
    }
284
 
285
    return iterator->second;
286
}
287
 
288
Node::AttributeList Node::GetAttributes()
289
{
290
    return this->attributes_;
291
}
292
 
293
std::vector<Node> Node::GetChildren()
294
{
295
    return this->children_;
296
}
297
 
298
std::string Node::GetTagName()
299
{
300
    return this->tag_name_;
301
}
302
 
303
}; // namespace xml
304
}; // namespace atom