a3cd1941d2f3ff7a42ab4d33e548173aa51cbb24
[anna.git] / include / anna / json / SaxConsumer.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_json_SaxConsumer_hpp
10 #define anna_json_SaxConsumer_hpp
11
12 #include <iomanip>
13 #include <sstream>
14 #include <stack>
15 #include <anna/json/json.hpp> // nlohmann::json
16 #include <anna/core/util/defines.hpp>
17
18 namespace anna {
19
20 namespace json {
21
22 class SaxConsumer : public nlohmann::json::json_sax_t
23 {
24   int indent_;
25   bool started_, last_was_start_, last_was_array_;
26   std::stringstream result_;
27   std::stringstream current_object_;
28   std::stack<std::string> nodes_stack_;
29   std::string key_;
30
31   public:
32
33   SaxConsumer() : started_(false), last_was_start_(false), last_was_array_(false), indent_(-ANNA_XML_INDENTATION_SPACES) {}
34
35   const std::stringstream & getResult() const { return result_; }
36
37   bool null() override
38   {
39     current_object_ << "<null>";
40     last_was_start_ = false;
41     return true;
42   }
43
44   bool boolean(bool val) override
45   {
46     current_object_ << std::quoted(val ? "true" : "false");
47     last_was_start_ = false;
48     return true;
49   }
50
51   bool number_integer(number_integer_t val) override
52   {
53     current_object_ << std::quoted(std::to_string(val));
54     last_was_start_ = false;
55     return true;
56   }
57
58   bool number_unsigned(number_unsigned_t val) override
59   {
60     current_object_ << std::quoted(std::to_string(val));
61     last_was_start_ = false;
62     return true;
63   }
64
65   bool number_float(number_float_t val, const string_t& s) override
66   {
67     current_object_ << std::quoted(s);
68     last_was_start_ = false;
69     return true;
70   }
71
72   bool string(string_t& val) override
73   {
74     current_object_ << std::quoted(val);
75     last_was_start_ = false;
76     return true;
77   }
78
79   bool start_object(std::size_t elements) override
80   {
81     if (!started_) { started_ = true ; return true; }
82     indent_ += ANNA_XML_INDENTATION_SPACES;
83     if (last_was_start_) result_ << ">\n";
84     last_was_start_ = true;
85     if (!last_was_array_) nodes_stack_.push(key_);
86     result_ << std::string(indent_, ' ') << "<" << nodes_stack_.top();
87     if (last_was_array_) nodes_stack_.push(key_);
88     last_was_array_ = false;
89     return true;
90   }
91
92   bool end_object() override
93   {
94     std::string close = "/>";
95     if (current_object_.str().empty()) close = "";
96     result_ << current_object_.str() << close;
97     if (indent_ < 0) return true;
98     if (close == "") result_ << std::string(indent_, ' ') << "</" << nodes_stack_.top() << ">";
99     indent_ -= ANNA_XML_INDENTATION_SPACES;
100     result_ << "\n";
101     current_object_.str("");
102     nodes_stack_.pop();
103     return true;
104   }
105
106   bool start_array(std::size_t elements) override
107   {
108     nodes_stack_.push(key_);
109     result_ << current_object_.str() << ">\n";
110     current_object_.str("");
111     return true;
112   }
113
114   bool end_array() override
115   {
116     nodes_stack_.pop();
117     last_was_array_ = true;
118     return true;
119   }
120
121   bool key(string_t& val) override
122   {
123     if (val[0] != '@') {
124       key_ = val;
125     }
126     else {
127       current_object_ << " " << val.substr(1) << "=";
128     }
129     return true;
130   }
131
132   bool parse_error(std::size_t position, const std::string& last_token, const nlohmann::json::exception& ex) override
133   {
134     result_ << std::string(ex.what());
135     return false;
136   }
137 };
138
139 }
140 }
141
142 #endif