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 5 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
31 changes: 28 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>
void json_encode(Writer &out, const std::string &str)
{
out.String(str.c_str(), str.length(), true);
}
Expand Down Expand Up @@ -599,5 +602,27 @@ NON_MEMBER_JSON_SERIALIZATION(dsn::app_info,
expire_second,
create_second,
drop_second)
}
}

// Could create template instantiation class with JsonWriter or PrettyJsonWriter.
template <typename Writer>
class json_writer
{
public:
explicit json_writer(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::unique_ptr<Writer> _writer;
};
} // 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
93 changes: 76 additions & 17 deletions include/dsn/utility/output_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,22 @@
#include <string>
#include <vector>

#include <dsn/cpp/json_helper.h>

namespace dsn {
namespace utils {

class table_printer;
class multi_table_printer;

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

/// A tool used to print data in a table form.
///
/// Example usage 1:
/// table_printer tp;
/// table_printer tp("sample_data");
/// tp.add_title("table_title");
/// tp.add_column("column_name1");
/// tp.add_column("column_name2");
Expand All @@ -50,22 +59,24 @@ namespace utils {
/// }
///
/// std::ostream out(...);
/// tp.output(out);
/// tp.output(out, output_format::kTabular);
///
/// Output looks like:
/// sample_data
/// table_title column_name1 column_name2
/// row_name_1 123 45.67
/// row_name_2 456 45.68
///
/// Example usage 2:
/// table_printer tp;
/// table_printer tp("sample_data_2");
/// tp.add_row_name_and_data("row_name_1", int_value);
/// tp.add_row_name_and_data("row_name_2", string_value);
///
/// std::ostream out(...);
/// tp.output(out, ": ");
/// tp.output(out);
///
/// Output looks like:
/// sample_data_2
/// row_name_1 : 4567
/// row_name_2 : hello
///
Expand All @@ -86,19 +97,29 @@ 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
{
kTabular = 0,
kJsonCompact = 1,
kJsonPretty = 2,
};

table_printer(std::string name = "", int tabular_width = 2, int precision = 2)
: _name(std::move(name)),
_mode(data_mode::kUninitialized),
_tabular_width(tabular_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>
void add_row(const T &row_name)
{
check_mode(data_mode::KMultiColumns);
matrix_data_.emplace_back(std::vector<std::string>());
_matrix_data.emplace_back(std::vector<std::string>());
append_data(row_name);
}
template <typename T>
Expand All @@ -108,15 +129,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::kTabular) const;

private:
template <typename T>
Expand All @@ -126,16 +148,30 @@ 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_tabular(std::ostream &out) const;
template <typename Writer>
void output_in_json(std::ostream &out) const
{
Writer writer(out);
json_encode(writer, *this);
}

private:
data_mode mode_;
int space_width_;
int precision_;
std::vector<bool> align_left_;
std::vector<int> max_col_width_;
std::vector<std::vector<std::string>> matrix_data_;
friend class multi_table_printer;
template <typename Writer>
friend void json_encode(Writer &out, const table_printer &tp);

std::string _name;
data_mode _mode;
int _tabular_width;
int _precision;
std::vector<bool> _align_left;
std::vector<int> _max_col_width;
std::vector<std::vector<std::string>> _matrix_data;
};

template <>
Expand All @@ -151,7 +187,7 @@ inline std::string table_printer::to_string<double>(double data)
return "0.00";
} else {
std::stringstream s;
s << std::fixed << std::setprecision(precision_) << data;
s << std::fixed << std::setprecision(_precision) << data;
return s.str();
}
}
Expand All @@ -168,5 +204,28 @@ inline std::string table_printer::to_string<const char *>(const char *data)
return std::string(data);
}

// Helper to output multiple tables into one large table.
class multi_table_printer
{
public:
void add(table_printer &&tp);
void output(std::ostream &out, table_printer::output_format format) const;

private:
void output_in_tabular(std::ostream &out) const;
template <typename Writer>
void output_in_json(std::ostream &out) const
{
Writer writer(out);
writer.StartObject();
for (const auto &tp : _tps) {
json_encode(writer, tp);
}
writer.EndObject();
}

private:
std::vector<table_printer> _tps;
};
} // namespace utils
} // namespace dsn
Loading