Subversion Repositories HomeAutomation

Rev

Rev 1914 | 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
{
1989 runge 46
  std::ifstream file(filename.data());
47
 
48
  if (!file.is_open())
49
  {
50
    throw std::runtime_error("Could not find " + filename);
51
    return;
52
  }
53
 
54
  std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
55
 
56
  file.close();
57
 
58
  this->Parse(buffer);
1596 runge 59
}
60
 
61
void Node::Parse(std::string data)
62
{
63
    char c;
64
    int position = 0;
65
 
1914 linlun 66
    while ((unsigned int)position < data.length())
1596 runge 67
    {
68
        c = data.at(position);
69
 
70
        switch (c)
71
        {
72
            case '<':
73
            {
74
                position = this->ParseTag(data, position);
75
                break;
76
            }
77
        }
78
 
79
        position++;
80
    }
81
}
82
 
83
int Node::ParseTag(std::string data, int position)
84
{
85
    if (data.at(position) != '<')
86
    {
87
        throw std::runtime_error("Id not find < as expected. Character " + boost::lexical_cast<std::string>(position));
88
    }
89
 
90
    position++;
91
 
92
    int end_position = data.find('>', position);
93
 
94
    if (data.at(position) == '?' || data.at(position) == '!' || data.at(position) == '/')
95
    {
96
        return end_position;
97
    }
98
 
99
    std::string tag_string;
100
 
101
    try
102
    {
103
        tag_string = data.substr(position, end_position - position);
104
    }
105
    catch (std::out_of_range& e)
106
    {
107
        throw std::runtime_error(e.what());
108
    }
109
 
110
    boost::algorithm::trim(tag_string);
111
    boost::algorithm::trim_if(tag_string, boost::is_any_of("\n"));
112
    boost::algorithm::trim(tag_string);
113
    tag_string += " ";
114
 
115
    bool found_end = false;
116
    bool found_tag = false;
117
    std::string buffer;
118
    int pos = 0;
119
    char c;
120
    int s, e;
121
 
1914 linlun 122
    while ((unsigned int)pos < tag_string.length())
1596 runge 123
    {
124
        c = tag_string.at(pos);
125
 
126
        switch (c)
127
        {
128
            case ' ':
129
            {
130
                if (!found_tag)
131
                {
132
                    this->tag_name_ = buffer;
133
                    buffer = "";
134
                    //std::cout << "Found tag: " << this->tag_name_ << std::endl;
135
                    found_tag = true;
136
                }
137
                break;
138
            }  
139
            case '/':
140
            {
141
                found_end = true;
142
                break;
143
            }
144
            case '=':
145
            {
146
                s = tag_string.find('"', pos) + 1;
147
                e = tag_string.find('"', s);
148
 
149
                try
150
                {
151
                    this->attributes_[buffer] = tag_string.substr(s, e - s);
152
                }
153
                catch (std::out_of_range& ex)
154
                {
155
                    throw std::runtime_error(ex.what());
156
                }
157
 
158
                pos = e;
159
                buffer = "";
160
                break;
161
            }
162
            default:
163
            {
164
                buffer += c;
165
                break;
166
            }
167
        }
168
 
169
        pos++;
170
    }
171
 
172
    position = end_position;
173
 
174
    if (!found_end)
175
    {
1914 linlun 176
        while ((unsigned int)position < data.length())
1596 runge 177
        {
178
            c = data.at(position);
179
 
180
            switch (c)
181
            {
182
                case '<':
183
                {
184
                    if (data.at(position+1) == '/')
185
                    {
186
                        position += 2;
187
                        end_position = data.find('>', position);
188
 
189
                        try
190
                        {
191
                            if (this->tag_name_.compare(data.substr(position, end_position - position)) == 0)
192
                            {
193
                                //std::cout << "Found end tag: " << this->tag_name_ << std::endl;
194
                                return end_position;
195
                            }
196
                            else
197
                            {
198
                                throw std::runtime_error("Invalid end tag found. " + data.substr(position, end_position - position) + "::" + this->tag_name_);
199
                            }
200
                        }
201
                        catch (std::out_of_range& e)
202
                        {
203
                            throw std::runtime_error(e.what());
204
                        }
205
 
206
 
207
                    }
208
 
209
                    Node sub_node;
210
                    position = sub_node.ParseTag(data, position);
211
                    this->children_.push_back(sub_node);
212
                    break;
213
                }
214
            }
215
 
216
            position++;
217
        }
218
    }
219
 
220
    return position;
221
}
222
 
223
Node Node::FindChild(std::string tag_name)
224
{
1914 linlun 225
    for (unsigned int n = 0; n < this->children_.size(); n++)
1596 runge 226
    {
227
        if (this->children_[n].GetTagName().compare(tag_name) == 0)
228
        {
229
            return this->children_[n];
230
        }
231
    }
232
 
233
    throw std::runtime_error("No child with that tag name found, " + tag_name);
234
}
235
 
236
Node Node::SelectChild(std::string attribute_name, std::string attribute_value)
237
{
1914 linlun 238
    for (unsigned int n = 0; n < this->children_.size(); n++)
1596 runge 239
    {
240
        if (this->children_[n].GetAttributeValue(attribute_name) == attribute_value)
241
        {
242
            return this->children_[n];
243
        }
244
    }
245
 
246
    throw std::runtime_error("No child with that attribute combination found, " + attribute_name + " = " + attribute_value);
247
}
248
 
249
Node Node::SelectChild(std::string attribute_name1, std::string attribute_value1, std::string attribute_name2, std::string attribute_value2)
250
{
1914 linlun 251
    for (unsigned int n = 0; n < this->children_.size(); n++)
1596 runge 252
    {
253
        if (this->children_[n].GetAttributeValue(attribute_name1) == attribute_value1 && this->children_[n].GetAttributeValue(attribute_name2) == attribute_value2)
254
        {
255
            return this->children_[n];
256
        }
257
    }
258
 
259
    throw std::runtime_error("No child with that attribute combination found, " + attribute_name1 + " = " + attribute_value1 + " && " + attribute_name2 + " = " + attribute_value2);
260
}
261
 
262
std::string Node::GetAttributeValue(std::string attribute_name)
263
{
264
    AttributeList::const_iterator iterator = this->attributes_.find(attribute_name);
265
 
266
    if (iterator == this->attributes_.end())
267
    {
268
        throw std::runtime_error("No attribute with that name found, " + attribute_name);
269
    }
270
 
271
    return iterator->second;
272
}
273
 
274
Node::AttributeList Node::GetAttributes()
275
{
276
    return this->attributes_;
277
}
278
 
279
std::vector<Node> Node::GetChildren()
280
{
281
    return this->children_;
282
}
283
 
284
std::string Node::GetTagName()
285
{
286
    return this->tag_name_;
287
}
288
 
289
}; // namespace xml
290
}; // namespace atom