diff options
Diffstat (limited to 'src/formatter')
-rw-r--r-- | src/formatter/formatter.cc | 38 | ||||
-rw-r--r-- | src/formatter/formatter.h | 257 |
2 files changed, 295 insertions, 0 deletions
diff --git a/src/formatter/formatter.cc b/src/formatter/formatter.cc new file mode 100644 index 0000000..6fedf8c --- /dev/null +++ b/src/formatter/formatter.cc @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include "formatter.h" + +namespace formatter { + +std::ostream& operator<<(std::ostream& os, Unit val) { + switch (val) { + case Unit::V: + return os << "V"; + + case Unit::A: + return os << "A"; + + case Unit::Wh: + return os << "Wh"; + + case Unit::VA: + return os << "VA"; + + case Unit::Hz: + return os << "Hz"; + + case Unit::Percentage: + return os << "%"; + + case Unit::Celsius: + return os << "°C"; + + default: + break; + }; + + return os; +} + + +}
\ No newline at end of file diff --git a/src/formatter/formatter.h b/src/formatter/formatter.h new file mode 100644 index 0000000..5dfa184 --- /dev/null +++ b/src/formatter/formatter.h @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef INVERTER_TOOLS_PRINT_H +#define INVERTER_TOOLS_PRINT_H + +#include <string> +#include <vector> +#include <iostream> +#include <sstream> +#include <ios> +#include <iomanip> +#include <nlohmann/json.hpp> + +#include "src/util.h" + +namespace formatter { + +using nlohmann::json; +using nlohmann::ordered_json; + + +/** + * Enumerations + */ + +enum class Unit { + None = 0, + V, + A, + Wh, + VA, + Hz, + Percentage, + Celsius, +}; + +enum class Format { + Table, + SimpleTable, + JSON, +}; +std::ostream& operator<<(std::ostream& os, Unit val); + + +/** + * Helper functions + */ + +template <typename T> +std::string to_str(T& v) { + std::ostringstream buf; + buf << v; + return buf.str(); +} + + +/** + * Items + */ + +template <typename T> +struct TableItem { + explicit TableItem(std::string key, std::string title, T value, Unit unit = Unit::None, unsigned precision = 0) : + key(std::move(key)), + title(std::move(title)), + value(value), + unit(unit) {} + + std::string key; + std::string title; + T value; + Unit unit; +}; + +template <typename T> +struct ListItem { + explicit ListItem(T value) : value(value) {} + T value; +}; + + +/** + * Items holders + */ + +class Formattable { +protected: + Format format_; + +public: + explicit Formattable(Format format) : format_(format) {} + virtual ~Formattable() = default; + + virtual std::ostream& writeJSON(std::ostream& os) const = 0; + virtual std::ostream& writeTable(std::ostream& os) const = 0; + virtual std::ostream& writeSimpleTable(std::ostream& os) const = 0; + + friend std::ostream& operator<<(std::ostream& os, Formattable const& ref) { + switch (ref.format_) { + case Format::Table: + return ref.writeTable(os); + + case Format::SimpleTable: + return ref.writeSimpleTable(os); + + case Format::JSON: + return ref.writeJSON(os); + } + + return os; + } +}; + + +// T must have `operator<<` and `basic_json toJSON()` methods +template <typename T> +class Table : public Formattable { +protected: + std::vector<TableItem<T>> v_; + +public: + explicit Table(Format format, std::vector<TableItem<T>> v) + : Formattable(format), v_(v) {} + + std::ostream& writeSimpleTable(std::ostream& os) const override { + for (const auto& item: v_) { + os << item.key << " "; + + std::string value = to_str(item.value); + bool space = string_has(value, ' '); + if (space) + os << "\""; + os << value; + if (space) + os << "\""; + + if (item.unit != Unit::None) + os << " " << item.unit; + + if (&item != &v_.back()) + os << std::endl; + } + return os; + } + + std::ostream& writeTable(std::ostream& os) const override { + int maxWidth = 0; + for (const auto& item: v_) { + int width = item.title.size()+1 /* colon */; + if (width > maxWidth) + maxWidth = width; + } + + std::ios_base::fmtflags f(os.flags()); + os << std::left; + for (const auto &item: v_) { + os << std::setw(maxWidth) << (item.title+":") << " " << item.value; + + if (item.unit != Unit::None) + os << " " << item.unit; + + if (&item != &v_.back()) + os << std::endl; + } + + os.flags(f); + return os; + } + + std::ostream& writeJSON(std::ostream& os) const override { + ordered_json j = { + {"result", "ok"}, + {"data", {}} + }; + for (const auto &item: v_) { + if (item.unit != Unit::None) { + json jval = json::object(); + jval["value"] = item.value.toJSON(); + jval["unit"] = to_str(item.unit); + j["data"][item.key] = jval; + } else { + j["data"][item.key] = item.value.toJSON(); + } + } + return os << j.dump(); + } +}; + +template <typename T> +class List : public Formattable { +protected: + std::vector<ListItem<T>> v_; + +public: + explicit List(Format format, std::vector<ListItem<T>> v) + : Formattable(format), v_(v) {} + + std::ostream& writeSimpleTable(std::ostream& os) const override { + return writeTable(os); + } + + std::ostream& writeTable(std::ostream& os) const override { + for (const auto &item: v_) { + os << item.value; + if (&item != &v_.back()) + os << std::endl; + } + return os; + } + + std::ostream& writeJSON(std::ostream& os) const override { + json data = {}; + ordered_json j; + + j["result"] = "ok"; + + for (const auto &item: v_) + data.push_back(item.value.toJSON()); + j["data"] = data; + + return os << j.dump(); + } +}; + +class Status : public Formattable { +protected: + bool value_; + std::string message_; + +public: + explicit Status(Format format, bool value, std::string message) + : Formattable(format), value_(value), message_(std::move(message)) {} + + std::ostream& writeSimpleTable(std::ostream& os) const override { + return writeTable(os); + } + + std::ostream& writeTable(std::ostream& os) const override { + os << (value_ ? "ok" : "error"); + if (!message_.empty()) + os << ": " << message_; + return os; + } + + std::ostream& writeJSON(std::ostream& os) const override { + ordered_json j = { + {"result", (value_ ? "ok" : "error")} + }; + if (!message_.empty()) + j["message"] = message_; + return os << j.dump(); + } +}; + +} + +#endif
\ No newline at end of file |