7 #include "Atlas/Codecs/XML.h"
8 #include "Atlas/Message/Element.h"
17 XML::XML(std::istream &in, std::ostream &out,
Atlas::Bridge &b)
18 : m_istream(in), m_ostream(out), m_bridge(b) {
20 m_state.push(PARSE_NOTHING);
24 void XML::tokenTag(
char next) {
29 m_token = TOKEN_END_TAG;
38 m_token = TOKEN_START_TAG;
44 void XML::tokenStartTag(
char next) {
59 m_token = TOKEN_END_TAG;
69 void XML::tokenEndTag(
char next) {
88 void XML::tokenData(
char next) {
100 m_data.top() += next;
105 void XML::parseStartTag() {
106 int tag_end = (int) m_tag.find(
' ');
107 int name_start = (int) m_tag.find(
"name=\"") + 6;
108 int name_end = (int) m_tag.rfind(
'\"');
110 if (name_start < name_end) {
112 std::string(m_tag, (
unsigned long) name_start, (
unsigned long) (name_end - name_start)));
117 m_tag = std::string(m_tag, 0, (
unsigned long) tag_end);
119 switch (m_state.top()) {
121 if (m_tag ==
"atlas") {
122 m_bridge.streamBegin();
123 m_state.push(PARSE_STREAM);
131 if (m_tag ==
"map") {
132 m_bridge.streamMessage();
133 m_state.push(PARSE_MAP);
141 if (m_tag ==
"map") {
142 m_bridge.mapMapItem(m_name);
143 m_state.push(PARSE_MAP);
144 }
else if (m_tag ==
"list") {
145 m_bridge.mapListItem(m_name);
146 m_state.push(PARSE_LIST);
147 }
else if (m_tag ==
"int") {
148 m_state.push(PARSE_INT);
149 }
else if (m_tag ==
"float") {
150 m_state.push(PARSE_FLOAT);
151 }
else if (m_tag ==
"string") {
152 m_state.push(PARSE_STRING);
153 }
else if (m_tag ==
"none") {
154 m_state.push(PARSE_NONE);
162 if (m_tag ==
"map") {
163 m_bridge.listMapItem();
164 m_state.push(PARSE_MAP);
165 }
else if (m_tag ==
"list") {
166 m_bridge.listListItem();
167 m_state.push(PARSE_LIST);
168 }
else if (m_tag ==
"int") {
169 m_state.push(PARSE_INT);
170 }
else if (m_tag ==
"float") {
171 m_state.push(PARSE_FLOAT);
172 }
else if (m_tag ==
"string") {
173 m_state.push(PARSE_STRING);
174 }
else if (m_tag ==
"none") {
175 m_state.push(PARSE_NONE);
192 void XML::parseEndTag() {
193 switch (m_state.top()) {
200 if (m_tag ==
"atlas") {
201 m_bridge.streamEnd();
210 if (m_tag ==
"map") {
220 if (m_tag ==
"list") {
230 if (m_tag ==
"int") {
233 Atlas::Message::IntType value = 0;
234 auto data = m_data.top();
236 value = std::stol(data);
238 if (m_state.top() == PARSE_MAP) {
239 m_bridge.mapIntItem(m_name, value);
241 m_bridge.listIntItem(value);
253 if (m_tag ==
"float") {
256 Atlas::Message::FloatType value = 0;
257 auto data = m_data.top();
259 value = std::stod(data);
261 if (m_state.top() == PARSE_MAP) {
262 m_bridge.mapFloatItem(m_name, value);
264 m_bridge.listFloatItem(value);
276 if (m_tag ==
"string") {
278 if (m_state.top() == PARSE_MAP) {
279 m_bridge.mapStringItem(m_name, unescape(m_data.top()));
281 m_bridge.listStringItem(unescape(m_data.top()));
289 if (m_tag ==
"none") {
291 if (m_state.top() == PARSE_MAP) {
292 m_bridge.mapNoneItem(m_name);
294 m_bridge.listNoneItem();
307 std::streamsize count;
309 while ((count = m_istream.rdbuf()->in_avail()) > 0) {
311 for (std::streamsize i = 0; i < count; ++i) {
313 char next = m_istream.rdbuf()->sbumpc();
319 case TOKEN_START_TAG:
333 void XML::streamBegin() {
334 m_ostream <<
"<atlas>";
337 void XML::streamEnd() {
338 m_ostream <<
"</atlas>";
341 void XML::streamMessage() {
342 m_ostream <<
"<map>";
345 void XML::mapMapItem(std::string name) {
346 m_ostream <<
"<map name=\"" << escape(name) <<
"\">";
349 void XML::mapListItem(std::string name) {
350 m_ostream <<
"<list name=\"" << escape(name) <<
"\">";
353 void XML::mapIntItem(std::string name, std::int64_t data) {
354 m_ostream <<
"<int name=\"" << escape(name) <<
"\">" << data <<
"</int>";
357 void XML::mapFloatItem(std::string name,
double data) {
358 m_ostream <<
"<float name=\"" << escape(name) <<
"\">" << data <<
"</float>";
361 void XML::mapStringItem(std::string name, std::string data) {
362 m_ostream <<
"<string name=\"" << escape(name) <<
"\">" << escape(data) <<
"</string>";
365 void XML::mapNoneItem(std::string name) {
366 m_ostream <<
"<none name=\"" << escape(name) <<
"\"></none>";
370 m_ostream <<
"</map>";
373 void XML::listMapItem() {
374 m_ostream <<
"<map>";
377 void XML::listListItem() {
378 m_ostream <<
"<list>";
381 void XML::listIntItem(std::int64_t data) {
382 m_ostream <<
"<int>" << data <<
"</int>";
385 void XML::listFloatItem(
double data) {
386 m_ostream <<
"<float>" << data <<
"</float>";
389 void XML::listStringItem(std::string data) {
390 m_ostream <<
"<string>" << escape(data) <<
"</string>";
393 void XML::listNoneItem() {
394 m_ostream <<
"<none></none>";
397 void XML::listEnd() {
398 m_ostream <<
"</list>";
401 std::string XML::escape(
const std::string &original) {
403 buffer.reserve(original.size() + (original.size() / 2));
404 for (
size_t pos = 0; pos != original.size(); ++pos) {
405 switch (original[pos]) {
407 buffer.append(
"&");
410 buffer.append(
""");
413 buffer.append(
"'");
416 buffer.append(
"<");
419 buffer.append(
">");
422 buffer.append(1, original[pos]);
429 std::string XML::unescape(
const std::string &original) {
431 buffer.reserve(original.size());
432 for (
size_t pos = 0; pos != original.size(); ++pos) {
433 if (original[pos] ==
'&') {
434 if (original.size() - pos >= 3) {
435 if (original[pos + 1] ==
'l' && original[pos + 2] ==
't' && original[pos + 3] ==
';') {
436 buffer.append(1,
'<');
439 }
else if (original[pos + 1] ==
'g' && original[pos + 2] ==
't' && original[pos + 3] ==
';') {
440 buffer.append(1,
'>');
445 if (original.size() - pos >= 4) {
446 if (original[pos + 1] ==
'a' && original[pos + 2] ==
'm' && original[pos + 3] ==
'p' &&
447 original[pos + 4] ==
';') {
448 buffer.append(1,
'&');
453 if (original.size() - pos >= 5) {
454 if (original[pos + 1] ==
'q' && original[pos + 2] ==
'u' && original[pos + 3] ==
'o' &&
455 original[pos + 4] ==
't' && original[pos + 5] ==
';') {
456 buffer.append(1,
'"');
459 }
else if (original[pos + 1] ==
'a' && original[pos + 2] ==
'p' && original[pos + 3] ==
'o' &&
460 original[pos + 4] ==
's' && original[pos + 5] ==
';') {
461 buffer.append(1,
'\'');
467 buffer.append(1, original[pos]);