From aad95de5fd2a82dc2bed1782f3efba24a9b43231 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Wed, 22 Jun 2022 14:23:29 +0200 Subject: [PATCH] Util: Add a JSON stringifier --- src/util/json/stringify.cpp | 140 ++++++++++++++++++++++++++++++++++++ src/util/json/stringify.h | 37 ++++++++++ src/util/json/value.h | 2 + 3 files changed, 179 insertions(+) create mode 100644 src/util/json/stringify.cpp create mode 100644 src/util/json/stringify.h diff --git a/src/util/json/stringify.cpp b/src/util/json/stringify.cpp new file mode 100644 index 0000000..3620c6f --- /dev/null +++ b/src/util/json/stringify.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2022 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#include // uint32_t +#include // prev +#include // ostringstream +#include + +#include "util/json/array.h" +#include "util/json/lexer.h" +#include "util/json/object.h" +#include "util/json/stringify.h" + +namespace Json { + +Stringify::Stringify(const Value& value, const uint32_t indent, const char indentCharacter) + : m_value(value) + , m_indent(indent) + , m_indentCharacter(indentCharacter) +{ +} + +Stringify::~Stringify() +{ +} + +// ------------------------------------------ + +std::string Stringify::dump() +{ + return dumpHelper(m_value); +} + +// ------------------------------------------ + +std::string Stringify::dumpHelper(const Value& value, const uint32_t indentLevel) +{ + switch (value.type()) { + case Value::Type::Null: + return "null"; + break; + case Value::Type::Bool: + return value.asBool() ? "true" : "false"; + break; + case Value::Type::Number: { + std::ostringstream os; + os << value.asDouble(); + return os.str(); + break; + } + case Value::Type::String: + return "\"" + value.asString() + "\""; + break; + case Value::Type::Array: + return dumpArray(value, indentLevel); + break; + case Value::Type::Object: + return dumpObject(value, indentLevel); + break; + default: + break; + } + + return ""; +} + +std::string Stringify::dumpArray(const Value& value, const uint32_t indentLevel) +{ + std::string result; + + // Append [ + result += "["; + if (m_indent > 0) { + result += '\n'; + } + + auto values = value.asArray().values(); + for (auto it = values.begin(); it != values.end(); ++it) { + result += std::string(m_indent * (indentLevel + 1), m_indentCharacter); + result += dumpHelper(*it, indentLevel + 1); + + // Add comma, except after the last element + if (it != std::prev(values.end(), 1)) { + result += ","; + } + if (m_indent > 0) { + result += '\n'; + } + } + + // Append indentation + result += std::string(m_indent * indentLevel, m_indentCharacter); + + // Append ] + result += "]"; + + return result; +} + +std::string Stringify::dumpObject(const Value& value, const uint32_t indentLevel) +{ + std::string result; + + // Append { + result += "{"; + if (m_indent > 0) { + result += '\n'; + } + + auto members = value.asObject().members(); + for (auto it = members.begin(); it != members.end(); ++it) { + result += std::string(m_indent * (indentLevel + 1), m_indentCharacter); + result += "\"" + it->first + "\":"; + if (m_indent > 0) { + result += ' '; + } + result += dumpHelper(it->second, indentLevel + 1); + + // Add comma, except after the last element + if (it != std::prev(members.end(), 1)) { + result += ","; + } + if (m_indent > 0) { + result += '\n'; + } + } + + // Append indentation + result += std::string(m_indent * indentLevel, m_indentCharacter); + + // Append } + result += "}"; + + return result; +} + +} // namespace Json diff --git a/src/util/json/stringify.h b/src/util/json/stringify.h new file mode 100644 index 0000000..3ab8c0b --- /dev/null +++ b/src/util/json/stringify.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#ifndef JSON_STRINGIFY_H +#define JSON_STRINGIFY_H + +#include // uint32_t +#include + +#include "util/json/value.h" + +namespace Json { + +class Stringify { +public: + Stringify(const Value& value, const uint32_t indent = 0, const char indentCharacter = ' '); + virtual ~Stringify(); + + std::string dump(); + +private: + std::string dumpHelper(const Value& value, const uint32_t indentLevel = 0); + std::string dumpArray(const Value& value, const uint32_t indentLevel = 0); + std::string dumpObject(const Value& value, const uint32_t indentLevel = 0); + + Value m_value; + + uint32_t m_indent { 0 }; + char m_indentCharacter { ' ' }; +}; + +} // namespace Json + +#endif // JSON_STRINGIFY_H diff --git a/src/util/json/value.h b/src/util/json/value.h index 0d9cf9b..6b68be1 100644 --- a/src/util/json/value.h +++ b/src/util/json/value.h @@ -44,6 +44,8 @@ public: Value operator[](size_t index); Value operator[](const std::string& key); + Type type() const { return m_type; } + bool asBool() const { return m_value.asBool; } double asDouble() const { return m_value.asDouble; } const std::string& asString() const { return *m_value.asString; }