From: Jacob Lifshay Date: Fri, 2 Jun 2017 08:38:21 +0000 (-0700) Subject: added json pretty printing X-Git-Tag: gsoc-2017~114 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6a754c6549ca6c7a377fb25287c6f23cdbdca6c2;p=kazan.git added json pretty printing --- diff --git a/src/generate_spirv_parser/generate_spirv_parser.cpp b/src/generate_spirv_parser/generate_spirv_parser.cpp index df3b453..e38b216 100644 --- a/src/generate_spirv_parser/generate_spirv_parser.cpp +++ b/src/generate_spirv_parser/generate_spirv_parser.cpp @@ -45,7 +45,7 @@ int generate_spirv_parser_main(int argc, char **argv) const auto source = file_name == "-" ? json::source::load_stdin() : json::source::load_file(std::move(file_name)); auto value = json::parse(&source); - ast::write(std::cout, value); + json::write(std::cout, value, json::write_options::pretty()); std::cout << std::endl; } catch(json::parse_error &e) diff --git a/src/json/json.cpp b/src/json/json.cpp index cb213aa..1dfad87 100644 --- a/src/json/json.cpp +++ b/src/json/json.cpp @@ -27,22 +27,29 @@ #include #include #include +#include #include "../util/soft_float.h" namespace vulkan_cpu { namespace json { +void write_state::write_indent(std::ostream &os) const +{ + for(std::size_t i = indent_level; i > 0; i--) + os << options.indent_text; +} + namespace ast { namespace soft_float = util::soft_float; -void null_value::write(std::ostream &os) const +void null_value::write(std::ostream &os, write_state &state) const { os << "null"; } -void boolean_value::write(std::ostream &os) const +void boolean_value::write(std::ostream &os, write_state &state) const { os << (value ? "true" : "false"); } @@ -59,7 +66,7 @@ constexpr char get_digit_char(unsigned digit, bool uppercase) noexcept } } -void string_value::write(std::ostream &os, const std::string &value) +void string_value::write(std::ostream &os, const std::string &value, write_state &state) { os << '\"'; for(unsigned char ch : value) @@ -452,7 +459,7 @@ std::size_t number_value::signed_integer_to_buffer(std::int64_t value, return used_buffer_size; // report used buffer excluding the null terminator } -void number_value::write(std::ostream &os, unsigned base) const +void number_value::write(std::ostream &os, write_state &state, unsigned base) const { write_number( [&](char ch) @@ -463,32 +470,82 @@ void number_value::write(std::ostream &os, unsigned base) const base); } -void object::write(std::ostream &os) const +void object::write(std::ostream &os, write_state &state) const { os << '{'; - auto seperator = ""; - for(auto &entry : values) + if(!values.empty()) { - const std::string &key = std::get<0>(entry); - const value &value = std::get<1>(entry); - os << seperator; - seperator = ","; - string_value::write(os, key); - os << ':'; - ast::write(os, value); + write_state::push_indent push_indent(state); + auto seperator = ""; + auto write_entry = [&](const std::pair &entry) + { + const std::string &key = std::get<0>(entry); + const value &value = std::get<1>(entry); + os << seperator; + seperator = ","; + if(state.options.composite_value_elements_on_seperate_lines) + { + os << '\n'; + state.write_indent(os); + } + string_value::write(os, key, state); + os << ':'; + json::write(os, value, state); + }; + if(state.options.sort_object_values) + { + auto compare_fn = [](decltype(values)::const_iterator a, + decltype(values)::const_iterator b) -> bool + { + return std::get<0>(*a) < std::get<0>(*b); + }; + std::vector entry_iterators; + entry_iterators.reserve(values.size()); + for(auto i = values.begin(); i != values.end(); ++i) + entry_iterators.push_back(i); + std::sort(entry_iterators.begin(), entry_iterators.end(), compare_fn); + for(auto &i : entry_iterators) + write_entry(*i); + } + else + { + for(auto &entry : values) + write_entry(entry); + } + push_indent.finish(); + if(state.options.composite_value_elements_on_seperate_lines) + { + os << '\n'; + state.write_indent(os); + } } os << '}'; } -void array::write(std::ostream &os) const +void array::write(std::ostream &os, write_state &state) const { os << '['; - auto seperator = ""; - for(const value &v : values) + if(!values.empty()) { - os << seperator; - seperator = ","; - ast::write(os, v); + write_state::push_indent push_indent(state); + auto seperator = ""; + for(const value &v : values) + { + os << seperator; + seperator = ","; + if(state.options.composite_value_elements_on_seperate_lines) + { + os << '\n'; + state.write_indent(os); + } + json::write(os, v, state); + } + push_indent.finish(); + if(state.options.composite_value_elements_on_seperate_lines) + { + os << '\n'; + state.write_indent(os); + } } os << ']'; } diff --git a/src/json/json.h b/src/json/json.h index d54fa90..2676a4e 100644 --- a/src/json/json.h +++ b/src/json/json.h @@ -32,12 +32,75 @@ #include #include #include +#include #include "../util/variant.h" namespace vulkan_cpu { namespace json { +struct write_options +{ + bool composite_value_elements_on_seperate_lines = false; + bool sort_object_values = false; + std::string indent_text = ""; + write_options() + { + } + write_options(bool composite_value_elements_on_seperate_lines, + bool sort_object_values, + std::string indent_text) noexcept + : composite_value_elements_on_seperate_lines(composite_value_elements_on_seperate_lines), + sort_object_values(sort_object_values), + indent_text(std::move(indent_text)) + { + } + static write_options defaults() + { + return {}; + } + static write_options pretty(std::string indent_text = " ") + { + return write_options(true, true, std::move(indent_text)); + } +}; + +struct write_state +{ + write_options options; + std::size_t indent_level = 0; + class push_indent final + { + push_indent(const push_indent &) = delete; + push_indent &operator=(const push_indent &) = delete; + + private: + write_state &state; + bool finished = false; + + public: + push_indent(write_state &state) : state(state) + { + state.indent_level++; + } + void finish() + { + assert(!finished); + state.indent_level--; + finished = true; + } + ~push_indent() + { + if(!finished) + state.indent_level--; + } + }; + write_state(write_options options) : options(std::move(options)) + { + } + void write_indent(std::ostream &os) const; +}; + namespace ast { struct null_value final @@ -46,7 +109,7 @@ struct null_value final constexpr null_value(std::nullptr_t) noexcept { } - void write(std::ostream &os) const; + void write(std::ostream &os, write_state &state) const; null_value duplicate() const noexcept { return {}; @@ -68,7 +131,7 @@ struct boolean_value final constexpr boolean_value(T value) noexcept : value(value) { } - void write(std::ostream &os) const; + void write(std::ostream &os, write_state &state) const; boolean_value duplicate() const noexcept { return *this; @@ -93,10 +156,10 @@ struct string_value final string_value(T value) noexcept : value(std::move(value)) { } - static void write(std::ostream &os, const std::string &value); - void write(std::ostream &os) const + static void write(std::ostream &os, const std::string &value, write_state &state); + void write(std::ostream &os, write_state &state) const { - write(os, value); + write(os, value, state); } string_value duplicate() const noexcept { @@ -191,7 +254,7 @@ struct number_value final std::size_t output_buffer_size, bool require_null_terminator = true, unsigned base = default_base) noexcept; - void write(std::ostream &os, unsigned base = default_base) const; + void write(std::ostream &os, write_state &state, unsigned base = default_base) const; number_value duplicate() const noexcept { return *this; @@ -237,7 +300,7 @@ struct composite_value { composite_value() = default; virtual ~composite_value() = default; - virtual void write(std::ostream &os) const = 0; + virtual void write(std::ostream &os, write_state &state) const = 0; virtual composite_value_pointer duplicate() const = 0; operator value() const { @@ -255,16 +318,6 @@ inline value duplicate(const value &v) v); } -inline void write(std::ostream &os, const value &v) -{ - util::visit( - [&](const auto &v) -> void - { - return v->write(os); - }, - v); -} - struct object final : public composite_value { std::unordered_map values; @@ -274,7 +327,7 @@ struct object final : public composite_value object(std::unordered_map values) noexcept : values(std::move(values)) { } - virtual void write(std::ostream &os) const override; + virtual void write(std::ostream &os, write_state &state) const override; virtual composite_value_pointer duplicate() const override { std::unordered_map new_values; @@ -295,7 +348,7 @@ struct array final : public composite_value array(std::vector values) noexcept : values(std::move(values)) { } - virtual void write(std::ostream &os) const override; + virtual void write(std::ostream &os, write_state &state) const override; virtual composite_value_pointer duplicate() const override { std::vector new_values; @@ -306,6 +359,22 @@ struct array final : public composite_value } }; } + +inline void write(std::ostream &os, const ast::value &v, write_state &state) +{ + util::visit( + [&](const auto &v) -> void + { + return v->write(os, state); + }, + v); +} + +inline void write(std::ostream &os, const ast::value &v, write_options options = {}) +{ + write_state state(std::move(options)); + write(os, v, state); +} } }