~ubuntu-branches/ubuntu/maverick/libtorrent-rasterbar/maverick

« back to all changes in this revision

Viewing changes to include/libtorrent/xml_parse.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Cristian Greco
  • Date: 2008-07-02 10:46:21 UTC
  • Revision ID: james.westby@ubuntu.com-20080702104621-jzx3pfke9lkcxfxn
Tags: upstream-0.13.1
ImportĀ upstreamĀ versionĀ 0.13.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright (c) 2007, Arvid Norberg
 
4
All rights reserved.
 
5
 
 
6
Redistribution and use in source and binary forms, with or without
 
7
modification, are permitted provided that the following conditions
 
8
are met:
 
9
 
 
10
    * Redistributions of source code must retain the above copyright
 
11
      notice, this list of conditions and the following disclaimer.
 
12
    * Redistributions in binary form must reproduce the above copyright
 
13
      notice, this list of conditions and the following disclaimer in
 
14
      the documentation and/or other materials provided with the distribution.
 
15
    * Neither the name of the author nor the names of its
 
16
      contributors may be used to endorse or promote products derived
 
17
      from this software without specific prior written permission.
 
18
 
 
19
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
20
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
21
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
22
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
23
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
24
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
25
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
26
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
27
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
28
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
29
POSSIBILITY OF SUCH DAMAGE.
 
30
 
 
31
*/
 
32
 
 
33
#ifndef TORRENT_XML_PARSE_HPP
 
34
#define TORRENT_XML_PARSE_HPP
 
35
 
 
36
#include <cctype>
 
37
 
 
38
namespace libtorrent
 
39
{
 
40
        enum
 
41
        {
 
42
                xml_start_tag,
 
43
                xml_end_tag,
 
44
                xml_empty_tag,
 
45
                xml_declaration_tag,
 
46
                xml_string,
 
47
                xml_attribute,
 
48
                xml_comment,
 
49
                xml_parse_error
 
50
        };
 
51
 
 
52
        // callback(int type, char const* name, char const* val)
 
53
        // str2 is only used for attributes. name is element or attribute
 
54
        // name and val is attribute value
 
55
 
 
56
        template <class CallbackType>   
 
57
        void xml_parse(char* p, char* end, CallbackType callback)
 
58
        {
 
59
                for(;p != end; ++p)
 
60
                {
 
61
                        char const* start = p;
 
62
                        char const* val_start = 0;
 
63
                        int token;
 
64
                        // look for tag start
 
65
                        for(; *p != '<' && p != end; ++p);
 
66
 
 
67
                        if (p != start)
 
68
                        {
 
69
                                if (p != end)
 
70
                                {
 
71
                                        TORRENT_ASSERT(*p == '<');
 
72
                                        *p = 0;
 
73
                                }
 
74
                                token = xml_string;
 
75
                                callback(token, start, val_start);
 
76
                                if (p != end) *p = '<';
 
77
                        }
 
78
 
 
79
                        if (p == end) break;
 
80
                
 
81
                        // skip '<'
 
82
                        ++p;    
 
83
 
 
84
                        // parse the name of the tag.
 
85
                        for (start = p; p != end && *p != '>' && !std::isspace(*p); ++p);
 
86
 
 
87
                        char* tag_name_end = p;
 
88
 
 
89
                        // skip the attributes for now
 
90
                        for (; p != end && *p != '>'; ++p);
 
91
 
 
92
                        // parse error
 
93
                        if (p == end)
 
94
                        {
 
95
                                token = xml_parse_error;
 
96
                                start = "unexpected end of file";
 
97
                                callback(token, start, val_start);
 
98
                                break;
 
99
                        }
 
100
                        
 
101
                        TORRENT_ASSERT(*p == '>');
 
102
                        // save the character that terminated the tag name
 
103
                        // it could be both '>' and ' '.
 
104
                        char save = *tag_name_end;
 
105
                        *tag_name_end = 0;
 
106
 
 
107
                        char* tag_end = p;
 
108
                        if (*start == '/')
 
109
                        {
 
110
                                ++start;
 
111
                                token = xml_end_tag;
 
112
                                callback(token, start, val_start);
 
113
                        }
 
114
                        else if (*(p-1) == '/')
 
115
                        {
 
116
                                *(p-1) = 0;
 
117
                                token = xml_empty_tag;
 
118
                                callback(token, start, val_start);
 
119
                                *(p-1) = '/';
 
120
                                tag_end = p - 1;
 
121
                        }
 
122
                        else if (*start == '?' && *(p-1) == '?')
 
123
                        {
 
124
                                *(p-1) = 0;
 
125
                                ++start;
 
126
                                token = xml_declaration_tag;
 
127
                                callback(token, start, val_start);
 
128
                                *(p-1) = '?';
 
129
                                tag_end = p - 1;
 
130
                        }
 
131
                        else if (start + 5 < p && memcmp(start, "!--", 3) == 0 && memcmp(p-2, "--", 2) == 0)
 
132
                        {
 
133
                                start += 3;
 
134
                                *(p-2) = 0;
 
135
                                token = xml_comment;
 
136
                                callback(token, start, val_start);
 
137
                                *(p-2) = '-';
 
138
                                tag_end = p - 2;
 
139
                        }
 
140
                        else
 
141
                        {
 
142
                                token = xml_start_tag;
 
143
                                callback(token, start, val_start);
 
144
                        }
 
145
 
 
146
                        *tag_name_end = save;
 
147
 
 
148
                        // parse attributes
 
149
                        for (char* i = tag_name_end; i < tag_end; ++i)
 
150
                        {
 
151
                                // find start of attribute name
 
152
                                for (; i != tag_end && std::isspace(*i); ++i);
 
153
                                if (i == tag_end) break;
 
154
                                start = i;
 
155
                                // find end of attribute name
 
156
                                for (; i != tag_end && *i != '=' && !std::isspace(*i); ++i);
 
157
                                char* name_end = i;
 
158
 
 
159
                                // look for equality sign
 
160
                                for (; i != tag_end && *i != '='; ++i);
 
161
 
 
162
                                if (i == tag_end)
 
163
                                {
 
164
                                        token = xml_parse_error;
 
165
                                        val_start = 0;
 
166
                                        start = "garbage inside element brackets";
 
167
                                        callback(token, start, val_start);
 
168
                                        break;
 
169
                                }
 
170
 
 
171
                                ++i;
 
172
                                for (; i != tag_end && std::isspace(*i); ++i);
 
173
                                // check for parse error (values must be quoted)
 
174
                                if (i == tag_end || (*i != '\'' && *i != '\"'))
 
175
                                {
 
176
                                        token = xml_parse_error;
 
177
                                        val_start = 0;
 
178
                                        start = "unquoted attribute value";
 
179
                                        callback(token, start, val_start);
 
180
                                        break;
 
181
                                }
 
182
                                char quote = *i;
 
183
                                ++i;
 
184
                                val_start = i;
 
185
                                for (; i != tag_end && *i != quote; ++i);
 
186
                                // parse error (missing end quote)
 
187
                                if (i == tag_end)
 
188
                                {
 
189
                                        token = xml_parse_error;
 
190
                                        val_start = 0;
 
191
                                        start = "missing end quote on attribute";
 
192
                                        callback(token, start, val_start);
 
193
                                        break;
 
194
                                }
 
195
                                save = *i;
 
196
                                *i = 0;
 
197
                                *name_end = 0;
 
198
                                token = xml_attribute;
 
199
                                callback(token, start, val_start);
 
200
                                *name_end = '=';
 
201
                                *i = save;
 
202
                        }
 
203
                }
 
204
        
 
205
        }
 
206
 
 
207
}
 
208
 
 
209
 
 
210
#endif
 
211