Subversion Repositories HomeAutomation

Rev

Rev 1914 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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