33473ed8dc9e8425bb5505ffb70a64b7a91bc441
[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_;
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), 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     return true;
41   }
42
43   bool boolean(bool val) override
44   {
45     current_object_ << std::quoted(val ? "true" : "false");
46     return true;
47   }
48
49   bool number_integer(number_integer_t val) override
50   {
51     current_object_ << std::quoted(std::to_string(val));
52     return true;
53   }
54
55   bool number_unsigned(number_unsigned_t val) override
56   {
57     current_object_ << std::quoted(std::to_string(val));
58     return true;
59   }
60
61   bool number_float(number_float_t val, const string_t& s) override
62   {
63     current_object_ << std::quoted(s);
64     return true;
65   }
66
67   bool string(string_t& val) override
68   {
69     current_object_ << std::quoted(val);
70     return true;
71   }
72
73   bool start_object(std::size_t elements) override
74   {
75     nodes_stack_.push(key_);
76     if (!started_) { started_ = true ; return true; } // ignore first start object (which is whole json object {)
77     indent_ += ANNA_XML_INDENTATION_SPACES;
78     result_ << std::string(indent_, ' ') << "<" << nodes_stack_.top();
79     return true;
80   }
81
82   bool end_object() override
83   {
84     std::string close = "/>";
85     if (current_object_.str().empty()) close = "";
86     result_ << current_object_.str() << close;
87     if (indent_ < 0) return true;
88     indent_ -= ANNA_XML_INDENTATION_SPACES;
89     if (close == "") result_ << "</" << nodes_stack_.top() << ">";
90     result_ << "\n";
91     current_object_.str("");
92     nodes_stack_.pop();
93     return true;
94   }
95
96   bool start_array(std::size_t elements) override
97   {
98     nodes_stack_.push(key_);
99     result_ << current_object_.str() << ">\n";
100     current_object_.str("");
101     return true;
102   }
103
104   bool end_array() override
105   {
106     result_ << std::string(indent_, ' ');
107     nodes_stack_.pop();
108     return true;
109   }
110
111   bool key(string_t& val) override
112   {
113     if (val[0] != '@') {
114       key_ = val;
115     }
116     else {
117       current_object_ << " " << val.substr(1) << "=";
118     }
119     return true;
120   }
121
122   bool parse_error(std::size_t position, const std::string& last_token, const nlohmann::json::exception& ex) override
123   {
124     result_ << std::string(ex.what());
125     return false;
126   }
127 };
128
129 }
130 }
131
132 #endif