]> git.stg.codes - stg.git/blob - projects/sgconf/xml.cpp
Fix build on Darwin.
[stg.git] / projects / sgconf / xml.cpp
1 #include "xml.h"
2
3 #include "api_action.h"
4 #include "options.h"
5 #include "makeproto.h"
6 #include "config.h"
7
8 #include "stg/servconf.h"
9
10 #include <iostream>
11 #include <string>
12 #include <map>
13
14 #include <expat.h>
15
16 namespace
17 {
18
19 struct ParserState
20 {
21 size_t level;
22 };
23
24 std::string Indent(size_t level)
25 {
26 return std::string(level * 4, ' ');
27 }
28
29 std::string PrintAttr(const char ** attr)
30 {
31 std::string res;
32 if (attr == NULL)
33     return res;
34 while (*attr)
35     {
36     if (*(attr + 1) == NULL)
37         return res;
38     res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
39     ++attr; ++attr;
40     }
41 return res;
42 }
43
44 void Start(void * data, const char * el, const char ** attr)
45 {
46 ParserState * state = static_cast<ParserState *>(data);
47 if (el != NULL)
48     std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
49 ++state->level;
50 }
51
52 void End(void * data, const char * el)
53 {
54 ParserState * state = static_cast<ParserState *>(data);
55 --state->level;
56 if (el != NULL)
57     std::cout << Indent(state->level) << "</" << el << ">\n";
58 }
59
60 void PrintXML(const std::string& xml)
61 {
62 ParserState state = { 0 };
63
64 XML_Parser parser = XML_ParserCreate(NULL);
65 XML_ParserReset(parser, NULL);
66 XML_SetElementHandler(parser, Start, End);
67 XML_SetUserData(parser, &state);
68
69 if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
70     std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
71               << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
72               << std::endl;
73
74 XML_ParserFree(parser);
75 }
76
77 void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
78 {
79 if (!result)
80     {
81     std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
82     return;
83     }
84 PrintXML(response);
85 }
86
87 bool RawXMLFunction(const SGCONF::CONFIG & config,
88                     const std::string & arg,
89                     const std::map<std::string, std::string> & /*options*/)
90 {
91 return makeProto(config).RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
92 }
93
94 }
95
96 void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
97 {
98 blocks.Add("Raw XML")
99       .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
100 }