added json pretty printing
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 2 Jun 2017 08:38:21 +0000 (01:38 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 2 Jun 2017 08:38:21 +0000 (01:38 -0700)
src/generate_spirv_parser/generate_spirv_parser.cpp
src/json/json.cpp
src/json/json.h

index df3b453d3ad45328678fe6b72562e8ec82a9d52d..e38b2169d8b140ea395fb2be695f5b5f447adf2e 100644 (file)
@@ -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)
index cb213aa47af8c5a8f7e156b2b1b6d29a4c2006ca..1dfad8773093e4aa5e0afd9bd62080cb098de256 100644 (file)
 #include <cstdint>
 #include <cassert>
 #include <tuple>
+#include <algorithm>
 #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<std::string, value> &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<decltype(values)::const_iterator> 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 << ']';
 }
index d54fa90bd2ee00349451208dd3d5402112e7282a..2676a4e37468ea587f5f03aa945eb140e6171e85 100644 (file)
 #include <utility>
 #include <limits>
 #include <type_traits>
+#include <cassert>
 #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<std::string, value> values;
@@ -274,7 +327,7 @@ struct object final : public composite_value
     object(std::unordered_map<std::string, value> 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<std::string, value> new_values;
@@ -295,7 +348,7 @@ struct array final : public composite_value
     array(std::vector<value> 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<value> 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);
+}
 }
 }