X-Git-Url: https://git.teslayout.com/public/public/public/?p=anna.git;a=blobdiff_plain;f=include%2Fanna%2Fjson%2FSaxConsumer.hpp;h=1557575063cf232165e3eba34bb987bc49159c8a;hp=a3cd1941d2f3ff7a42ab4d33e548173aa51cbb24;hb=c881c12ed7e116f1d43760a0d9873f860c10a357;hpb=af14877201a9856708ec43086a229777d9cb3da7 diff --git a/include/anna/json/SaxConsumer.hpp b/include/anna/json/SaxConsumer.hpp index a3cd194..1557575 100644 --- a/include/anna/json/SaxConsumer.hpp +++ b/include/anna/json/SaxConsumer.hpp @@ -21,106 +21,121 @@ namespace json { class SaxConsumer : public nlohmann::json::json_sax_t { + char attr_prefix_; int indent_; - bool started_, last_was_start_, last_was_array_; std::stringstream result_; std::stringstream current_object_; std::stack nodes_stack_; std::string key_; + bool has_attributes_; + + const std::string & get_top() { return nodes_stack_.top(); } + public: - SaxConsumer() : started_(false), last_was_start_(false), last_was_array_(false), indent_(-ANNA_XML_INDENTATION_SPACES) {} + SaxConsumer(char attrPrefix = '@') : attr_prefix_(attrPrefix), + has_attributes_(false), + indent_(-ANNA_XML_INDENTATION_SPACES) {}; const std::stringstream & getResult() const { return result_; } bool null() override { current_object_ << ""; - last_was_start_ = false; + has_attributes_ = true; return true; } bool boolean(bool val) override { current_object_ << std::quoted(val ? "true" : "false"); - last_was_start_ = false; + has_attributes_ = true; return true; } bool number_integer(number_integer_t val) override { current_object_ << std::quoted(std::to_string(val)); - last_was_start_ = false; + has_attributes_ = true; return true; } bool number_unsigned(number_unsigned_t val) override { current_object_ << std::quoted(std::to_string(val)); - last_was_start_ = false; + has_attributes_ = true; return true; } bool number_float(number_float_t val, const string_t& s) override { current_object_ << std::quoted(s); - last_was_start_ = false; + has_attributes_ = true; return true; } bool string(string_t& val) override { current_object_ << std::quoted(val); - last_was_start_ = false; + has_attributes_ = true; return true; } bool start_object(std::size_t elements) override { - if (!started_) { started_ = true ; return true; } - indent_ += ANNA_XML_INDENTATION_SPACES; - if (last_was_start_) result_ << ">\n"; - last_was_start_ = true; - if (!last_was_array_) nodes_stack_.push(key_); - result_ << std::string(indent_, ' ') << "<" << nodes_stack_.top(); - if (last_was_array_) nodes_stack_.push(key_); - last_was_array_ = false; + if (key_ == "") return true; // global object condition (first start object) + nodes_stack_.push(key_); // push on starts + indent_ += ANNA_XML_INDENTATION_SPACES; // increase indentation on object start + + if (indent_ != 0) { + // New object when previous hadn't attributes: + if (current_object_.str().empty() && !has_attributes_) result_ <<">"; + result_ << "\n"; + } + result_ << std::string(indent_, ' ') << "<" << get_top(); + + has_attributes_ = false; return true; } bool end_object() override { - std::string close = "/>"; - if (current_object_.str().empty()) close = ""; - result_ << current_object_.str() << close; if (indent_ < 0) return true; - if (close == "") result_ << std::string(indent_, ' ') << ""; - indent_ -= ANNA_XML_INDENTATION_SPACES; - result_ << "\n"; - current_object_.str(""); - nodes_stack_.pop(); + if (current_object_.str().empty()) { + result_ << "\n" << std::string(indent_, ' ') << ""; + } + else { + result_ << current_object_.str() << "/>"; + current_object_.str(""); + } + + nodes_stack_.pop(); // pop on ends + indent_ -= ANNA_XML_INDENTATION_SPACES; // decrease indentation on object end return true; } bool start_array(std::size_t elements) override { - nodes_stack_.push(key_); - result_ << current_object_.str() << ">\n"; + nodes_stack_.push(key_); // push on starts + + result_ << current_object_.str(); + current_object_.str(""); + has_attributes_ = false; + return true; } bool end_array() override { - nodes_stack_.pop(); - last_was_array_ = true; + nodes_stack_.pop(); // pop on ends return true; } bool key(string_t& val) override { - if (val[0] != '@') { + if (val[0] != attr_prefix_) { key_ = val; } else {