Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

utility: table_printer support output in json mode. #223

Merged
merged 9 commits into from
Mar 4, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions include/dsn/cpp/json_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <cctype>

#include <rapidjson/ostreamwrapper.h>
#include <rapidjson/prettywriter.h>
#include <rapidjson/writer.h>
#include <rapidjson/document.h>

Expand Down Expand Up @@ -200,14 +201,16 @@ namespace json {

typedef rapidjson::GenericValue<rapidjson::UTF8<>> JsonObject;
typedef rapidjson::Writer<rapidjson::OStreamWrapper> JsonWriter;
typedef rapidjson::PrettyWriter<rapidjson::OStreamWrapper> PrettyJsonWriter;

template <typename>
class json_forwarder;

// json serialization for string types.
// please notice when we call rapidjson::Writer::String, with 3rd parameter with "true",
// which means that we will COPY string to writer
inline void json_encode(JsonWriter &out, const std::string &str)
template <typename Writer>
inline void json_encode(Writer &out, const std::string &str)
acelyc111 marked this conversation as resolved.
Show resolved Hide resolved
{
out.String(str.c_str(), str.length(), true);
}
Expand Down Expand Up @@ -599,5 +602,38 @@ NON_MEMBER_JSON_SERIALIZATION(dsn::app_info,
expire_second,
create_second,
drop_second)
}
}

class JsonWriterIf
{
public:
virtual void StartObject() = 0;
virtual void EndObject() = 0;
virtual void StartArray() = 0;
virtual void EndArray() = 0;

virtual void String(const std::string &str) = 0;
};

// Could create template instantiation class with JsonWriter or PrettyJsonWriter.
template <typename Writer>
class GeneralJsonWriter : public JsonWriterIf
{
public:
explicit GeneralJsonWriter(std::ostream &os)
{
rapidjson::OStreamWrapper wrapper(os);
writer_.reset(new Writer(wrapper));
}

virtual void StartObject() { writer_->StartObject(); }
virtual void EndObject() { writer_->EndObject(); }
virtual void StartArray() { writer_->StartArray(); }
virtual void EndArray() { writer_->EndArray(); }

virtual void String(const std::string &str) { json_encode(*writer_, str); }

private:
std::shared_ptr<Writer> writer_;
acelyc111 marked this conversation as resolved.
Show resolved Hide resolved
};
} // namaspace json
} // namaspace dsn
1 change: 1 addition & 0 deletions include/dsn/dist/replication/replication_ddl_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class replication_ddl_client
dsn::error_code list_apps(const dsn::app_status::type status,
bool show_all,
bool detailed,
bool json,
const std::string &file_name);

dsn::error_code list_apps(const dsn::app_status::type status,
Expand Down
52 changes: 47 additions & 5 deletions include/dsn/utility/output_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,18 @@
#include <string>
#include <vector>

#include <dsn/cpp/json_helper.h>

namespace dsn {
namespace utils {

class table_printer;
class table_printer_container;

// Keep the same code style with dsn/cpp/json_helper.h
template <typename JsonWriter>
void json_encode(JsonWriter &out, const table_printer &tp);

/// A tool used to print data in a table form.
///
/// Example usage 1:
Expand Down Expand Up @@ -86,12 +95,22 @@ class table_printer
kRight = 1,
};

table_printer(int space_width = 2, int precision = 2)
: mode_(data_mode::kUninitialized), space_width_(space_width), precision_(precision)
enum class output_format
{
kSpace = 0,
acelyc111 marked this conversation as resolved.
Show resolved Hide resolved
kJsonCompact = 1,
kJsonPretty = 2,
};

table_printer(std::string name = "", int space_width = 2, int precision = 2)
: name_(std::move(name)),
mode_(data_mode::kUninitialized),
space_width_(space_width),
precision_(precision)
{
}

// KMultiColumns
// KMultiColumns mode.
void add_title(const std::string &title, alignment align = alignment::kLeft);
void add_column(const std::string &col_name, alignment align = alignment::kLeft);
template <typename T>
Expand All @@ -108,15 +127,16 @@ class table_printer
append_string_data(to_string(data));
}

// KSingleColumn
// KSingleColumn mode.
template <typename T>
void add_row_name_and_data(const std::string &row_name, const T &data)
{
check_mode(data_mode::KSingleColumn);
add_row_name_and_string_data(row_name, to_string(data));
}

void output(std::ostream &out, const std::string &separator = "") const;
// Output result.
void output(std::ostream &out, output_format format = output_format::kSpace) const;

private:
template <typename T>
Expand All @@ -126,10 +146,19 @@ class table_printer
}

void check_mode(data_mode mode);

void append_string_data(const std::string &data);
void add_row_name_and_string_data(const std::string &row_name, const std::string &data);

void output_in_space(std::ostream &out) const;
void output_in_json(std::ostream &out, output_format format) const;

private:
friend class table_printer_container;
template <typename Writer>
friend void json_encode(Writer &out, const table_printer &tp);

std::string name_;
acelyc111 marked this conversation as resolved.
Show resolved Hide resolved
data_mode mode_;
int space_width_;
int precision_;
Expand Down Expand Up @@ -168,5 +197,18 @@ inline std::string table_printer::to_string<const char *>(const char *data)
return std::string(data);
}

class table_printer_container
acelyc111 marked this conversation as resolved.
Show resolved Hide resolved
{
public:
void add(table_printer &&tp);
void output(std::ostream &out, table_printer::output_format format) const;

private:
void output_in_space(std::ostream &out) const;
void output_in_json(std::ostream &out, table_printer::output_format format) const;

private:
std::vector<table_printer> tps_;
};
} // namespace utils
} // namespace dsn
126 changes: 121 additions & 5 deletions src/core/core/output_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,62 @@ void table_printer::add_row_name_and_string_data(const std::string &row_name,
append_string_data(data);
}

void table_printer::output(std::ostream &out, const std::string &separator) const
void table_printer::output(std::ostream &out, output_format format) const
{
switch (format) {
case output_format::kSpace:
output_in_space(out);
break;
case output_format::kJsonCompact:
case output_format::kJsonPretty:
output_in_json(out, format);
break;
default:
dassert(false, "Unknown format");
}
}

void table_printer::output_in_space(std::ostream &out) const
{
if (max_col_width_.empty()) {
return;
}

std::string separator;
if (mode_ == data_mode::KSingleColumn) {
separator = ": ";
} else {
dassert(mode_ == data_mode::KMultiColumns, "Unknown mode");
}

out << name_ << std::endl;
for (const auto &row : matrix_data_) {
for (size_t i = 0; i < row.size(); ++i) {
auto data = (i == 0 ? "" : separator) + row[i];
out << std::setw(max_col_width_[i] + space_width_)
<< (align_left_[i] ? std::left : std::right) << data;
for (size_t col = 0; col < row.size(); ++col) {
auto data = (col == 0 ? "" : separator) + row[col];
out << std::setw(max_col_width_[col] + space_width_)
<< (align_left_[col] ? std::left : std::right) << data;
}
out << std::endl;
}
}

void table_printer::output_in_json(std::ostream &out, output_format format) const
acelyc111 marked this conversation as resolved.
Show resolved Hide resolved
{
std::unique_ptr<dsn::json::JsonWriterIf> writer;
switch (format) {
case output_format::kJsonCompact:
writer.reset(new dsn::json::GeneralJsonWriter<dsn::json::JsonWriter>(out));
break;
case output_format::kJsonPretty:
writer.reset(new dsn::json::GeneralJsonWriter<dsn::json::PrettyJsonWriter>(out));
break;
default:
dassert(false, "Unknown format");
}

json_encode(*writer, *this);
}

void table_printer::append_string_data(const std::string &data)
{
matrix_data_.rbegin()->emplace_back(data);
Expand All @@ -101,5 +141,81 @@ void table_printer::check_mode(data_mode mode)
dassert(mode_ == mode, "");
}

template <typename Writer>
void json_encode(Writer &writer, const table_printer &tp)
{
writer.String(tp.name_); // table_printer name
if (tp.mode_ == table_printer::data_mode::KMultiColumns) {
writer.StartObject();
// The 1st row elements are column names, skip it.
for (size_t row = 1; row < tp.matrix_data_.size(); ++row) {
writer.String(tp.matrix_data_[row][0]); // row name
writer.StartObject();
for (int col = 0; col < tp.matrix_data_[row].size(); col++) {
writer.String(tp.matrix_data_[0][col]); // column name
writer.String(tp.matrix_data_[row][col]); // column data
}
writer.EndObject();
}
writer.EndObject();
} else if (tp.mode_ == table_printer::data_mode::KSingleColumn) {
writer.StartObject();
for (size_t row = 0; row < tp.matrix_data_.size(); ++row) {
writer.String(tp.matrix_data_[row][0]); // row name
writer.String(tp.matrix_data_[row][1]); // row data
}
writer.EndObject();
} else {
dassert(false, "Unknown mode");
}
}

void table_printer_container::add(table_printer &&tp) { tps_.emplace_back(std::move(tp)); }

void table_printer_container::output(std::ostream &out,
table_printer::table_printer::output_format format) const
{
switch (format) {
case table_printer::output_format::kSpace:
output_in_space(out);
break;
case table_printer::output_format::kJsonCompact:
case table_printer::output_format::kJsonPretty:
output_in_json(out, format);
break;
default:
dassert(false, "Unknown format");
}
}

void table_printer_container::output_in_space(std::ostream &out) const
{
for (const auto &tp : tps_) {
tp.output_in_space(out);
}
}

void table_printer_container::output_in_json(std::ostream &out,
table_printer::output_format format) const
{
std::unique_ptr<dsn::json::JsonWriterIf> writer;
switch (format) {
case table_printer::output_format::kJsonCompact:
writer.reset(new dsn::json::GeneralJsonWriter<dsn::json::JsonWriter>(out));
break;
case table_printer::output_format::kJsonPretty:
writer.reset(new dsn::json::GeneralJsonWriter<dsn::json::PrettyJsonWriter>(out));
break;
default:
dassert(false, "Unknown format");
}

writer->StartObject();
for (const auto &tp : tps_) {
json_encode(*writer, tp);
}
writer->EndObject();
}

} // namespace utils
} // namespace dsn
Loading