Skip to content

Commit 7240a2d

Browse files
committed
Update client, but there are still bugs in the XML parser...
1 parent 18da44f commit 7240a2d

File tree

14 files changed

+424
-496
lines changed

14 files changed

+424
-496
lines changed

boost/network/detail/xml_wrappers/element.hpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ class basic_element {
131131
}
132132

133133
boost::optional<string_type> get_lang() const {
134-
return get_attribute("xml:lang");
134+
boost::optional<string_type> lang
135+
= get_attribute("xml:lang");
136+
if (!lang) {
137+
lang = get_attribute("lang");
138+
}
139+
return lang;
135140
}
136141

137142
boost::optional<string_type> get_id() const {
@@ -144,6 +149,17 @@ class basic_element {
144149
children_.push_back(shared_element);
145150
}
146151

152+
boost::optional<const basic_element<Tag> &> get_child(const string_type &name) const {
153+
for (typename element_children_type::const_iterator it = children_.begin();
154+
it != children_.end();
155+
++it) {
156+
if ((*it)->get_name() == name) {
157+
return **it;
158+
}
159+
}
160+
return boost::none;
161+
}
162+
147163
boost::iterator_range<typename element_children_type::const_iterator>
148164
get_children() const {
149165
return boost::make_iterator_range(boost::begin(children_),

boost/network/detail/xml_wrappers/element_io.hpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010

1111
# include <boost/network/detail/xml_wrappers/element.hpp>
12+
# include <boost/range/algorithm_ext/for_each.hpp>
13+
# include <boost/spirit/home/phoenix/core.hpp>
1214
# include <ostream>
1315

1416

@@ -20,25 +22,24 @@ template <
2022
>
2123
std::ostream &operator << (std::ostream &os,
2224
const basic_element<Tag> &element) {
25+
typedef typename basic_element<Tag>::headers_container_type::const_iterator header_iterator;
26+
typedef typename basic_element<Tag>::element_children_type::const_iterator children_iterator;
27+
typedef boost::iterator_range<header_iterator> header_range;
28+
typedef boost::iterator_range<children_iterator> children_range;
29+
2330
if (element.is_tag()) {
2431
os << "<" << element.get_name();
25-
boost::iterator_range<typename basic_element<Tag>::headers_container_type::const_iterator>
26-
attributes(element.get_attributes());
27-
28-
typename basic_element<Tag>::headers_container_type::const_iterator
29-
attr_it(boost::begin(attributes)),
30-
attr_end(boost::end(attributes));
32+
header_range attributes(element.get_attributes());
33+
34+
header_iterator attr_it(boost::begin(attributes)), attr_end(boost::end(attributes));
3135
for (; attr_it != attr_end; ++attr_it) {
32-
os << " " << attr_it->first << "=\"" << attr_it->second << "\"";
36+
os << " " << attr_it->first << "='" << attr_it->second << "'";
3337
}
3438
os << ">";
3539

36-
boost::iterator_range<typename basic_element<Tag>::element_children_type::const_iterator>
37-
children(element.get_children());
40+
children_range children(element.get_children());
3841

39-
typename basic_element<Tag>::element_children_type::const_iterator
40-
child_it(boost::begin(children)),
41-
child_end(boost::end(children));
42+
children_iterator child_it(boost::begin(children)), child_end(boost::end(children));
4243
for (; child_it != child_end; ++child_it) {
4344
os << **child_it;
4445
}

boost/network/detail/xml_wrappers/parser_backends/expat/element_parser.hpp

Lines changed: 0 additions & 147 deletions
This file was deleted.

boost/network/detail/xml_wrappers/parser_backends/expat_parser.hpp

Lines changed: 120 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
# define __BOOST_NETWORK_DETAIL_XML_WRAPPERS_PARSER_BACKENDS_EXPAT_PARSER_INC__
99

1010

11-
# include <boost/network/detail/xml_wrappers/parser_backends/expat/element_parser.hpp>
11+
# include <boost/network/traits/string.hpp>
12+
# include <boost/network/detail/xml_wrappers/element.hpp>
13+
# include <boost/noncopyable.hpp>
14+
# include <expat.h>
15+
# include <cstring>
16+
# include <stack>
1217

1318

1419
namespace boost {
@@ -17,11 +22,122 @@ namespace detail {
1722
template <
1823
class Tag
1924
>
20-
class basic_expat_parser
21-
: public basic_expat_element_parser<Tag> {
22-
25+
class basic_expat_parser : boost::noncopyable {
2326
public:
2427

28+
typedef typename string<Tag>::type string_type;
29+
30+
typedef basic_element<Tag> element_type;
31+
32+
basic_expat_parser()
33+
: parser_(XML_ParserCreate(NULL)), depth_(0) {
34+
assert(parser_);
35+
XML_SetUserData(parser_, this);
36+
XML_SetElementHandler(parser_, start_element, end_element);
37+
XML_SetCharacterDataHandler(parser_, cdata);
38+
}
39+
40+
~basic_expat_parser() {
41+
XML_ParserFree(parser_);
42+
}
43+
44+
bool feed(const string_type &chunk) {
45+
while (!elements_.empty()) {
46+
elements_.pop();
47+
}
48+
elements_.push(0);
49+
depth_ = 0;
50+
return XML_Parse(parser_, chunk.c_str(), chunk.size(), 0) != 0;
51+
}
52+
53+
bool feed(const string_type &chunk, element_type &element) {
54+
while (!elements_.empty()) {
55+
elements_.pop();
56+
}
57+
elements_.push(&element);
58+
depth_ = 0;
59+
return XML_Parse(parser_, chunk.c_str(), chunk.size(), 0) != 0;
60+
}
61+
62+
private:
63+
64+
static void set_name(element_type *element, const XML_Char *name) {
65+
const XML_Char *name_begin = name;
66+
const XML_Char *name_end = name_begin + std::strlen(name_begin);
67+
68+
element->set_name(string_type(name_begin, name_end));
69+
}
70+
71+
static void set_attributes(element_type *element, const XML_Char **attrs) {
72+
if (attrs) {
73+
for (int i = 0; attrs[i]; i += 2) {
74+
const XML_Char *key_begin = attrs[i];
75+
const XML_Char *key_end = key_begin + std::strlen(key_begin);
76+
77+
const XML_Char *val_begin = attrs[i + 1];
78+
const XML_Char *val_end = val_begin + std::strlen(val_begin);
79+
80+
element->set_attribute(string_type(key_begin, key_end),
81+
string_type(val_begin, val_end));
82+
}
83+
}
84+
}
85+
86+
static void start_element(void *userdata,
87+
const XML_Char *name,
88+
const XML_Char **attrs) {
89+
basic_expat_parser<Tag> *parser
90+
= static_cast<basic_expat_parser<Tag> *>(userdata);
91+
92+
if (!parser->elements_.top()) {
93+
return;
94+
}
95+
96+
if (parser->depth_ > 0) {
97+
element_type *child = new element_type;
98+
parser->elements_.top()->add_child(child);
99+
parser->elements_.push(child);
100+
}
101+
set_name(parser->elements_.top(), name);
102+
set_attributes(parser->elements_.top(), attrs);
103+
104+
++parser->depth_;
105+
}
106+
107+
static void end_element(void *userdata,
108+
const XML_Char *name) {
109+
basic_expat_parser<Tag> *parser
110+
= static_cast<basic_expat_parser<Tag> *>(userdata);
111+
112+
if (!parser->elements_.top()) {
113+
return;
114+
}
115+
116+
if (parser->depth_ > 0) {
117+
parser->elements_.pop();
118+
}
119+
120+
--parser->depth_;
121+
}
122+
123+
static void cdata(void *userdata,
124+
const XML_Char *s,
125+
int len) {
126+
basic_expat_parser<Tag> *parser
127+
= static_cast<basic_expat_parser<Tag> *>(userdata);
128+
129+
if (!parser->elements_.top()) {
130+
return;
131+
}
132+
133+
parser->elements_.top()->add_child(
134+
new element_type(typename element_type::text(), string_type(s, s + len)));
135+
}
136+
137+
XML_Parser parser_;
138+
std::stack<element_type *> elements_;
139+
int depth_;
140+
25141
};
26142
} // namespace detail
27143
} // namespace network

0 commit comments

Comments
 (0)