Subversion Repositories HomeAutomation

Rev

Rev 1601 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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