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

Commit

Permalink
shell: refactor table data output method (#220)
Browse files Browse the repository at this point in the history
  • Loading branch information
acelyc111 authored and qinzuoyan committed Feb 11, 2019
1 parent fa31386 commit 38df49e
Show file tree
Hide file tree
Showing 4 changed files with 412 additions and 223 deletions.
6 changes: 0 additions & 6 deletions include/dsn/dist/replication/replication_ddl_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,6 @@ class replication_ddl_client
dsn::error_code
clear_app_envs(const std::string &app_name, bool clear_all, const std::string &prefix);

// print table to format columns as the same width.
// return false if column count is not the same for all rows.
bool print_table(const std::vector<std::vector<std::string>> &table,
std::ostream &output,
const std::string &column_delimiter = " ");

dsn::error_code ddd_diagnose(gpid pid, std::vector<ddd_partition_info> &ddd_partitions);

private:
Expand Down
165 changes: 165 additions & 0 deletions include/dsn/utility/output_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Microsoft Corporation
*
* -=- Robust Distributed System Nucleus (rDSN) -=-
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#pragma once

#include <cmath>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

namespace dsn {
namespace utils {

/// A tool used to print data in a table form.
///
/// Example usage 1:
/// table_printer tp;
/// tp.add_title("table_title");
/// tp.add_column("column_name1");
/// tp.add_column("column_name2");
/// for (...) {
/// tp.add_row("row_name_i");
/// tp.append_data(int_data);
/// tp.append_data(double_data);
/// }
///
/// std::ostream out(...);
/// tp.output(out);
///
/// Output looks like:
/// table_title column_name1 column_name2
/// row_name_1 123 45.67
/// row_name_2 456 45.68
///
/// Example usage 2:
/// table_printer tp;
/// 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, ": ");
///
/// Output looks like:
/// row_name_1 : 4567
/// row_name_2 : hello
///
class table_printer
{
private:
enum class data_mode
{
kUninitialized = 0,
KSingleColumn = 1,
KMultiColumns = 2
};

public:
table_printer(int space_width = 2, int precision = 2)
: mode_(data_mode::kUninitialized), space_width_(space_width), precision_(precision)
{
}

// KMultiColumns
void add_title(const std::string &title);
void add_column(const std::string &col_name);
template <typename T>
void add_row(const T &row_name)
{
check_mode(data_mode::KMultiColumns);
matrix_data_.emplace_back(std::vector<std::string>());
append_data(row_name);
}
template <typename T>
void append_data(const T &data)
{
check_mode(data_mode::KMultiColumns);
append_string_data(to_string(data));
}

// KSingleColumn
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;

private:
template <typename T>
std::string to_string(T data)
{
return std::to_string(data);
}

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);

private:
data_mode mode_;
int space_width_;
int precision_;
std::vector<int> max_col_width_;
std::vector<std::vector<std::string>> matrix_data_;
};

template <>
inline std::string table_printer::to_string<bool>(bool data)
{
return data ? "true" : "false";
}

template <>
inline std::string table_printer::to_string<double>(double data)
{
if (std::abs(data) < 1e-6) {
return "0.00";
} else {
std::stringstream s;
s << std::fixed << std::setprecision(precision_) << data;
return s.str();
}
}

template <>
inline std::string table_printer::to_string<std::string>(std::string data)
{
return data;
}

template <>
inline std::string table_printer::to_string<const char *>(const char *data)
{
return std::string(data);
}

} // namespace utils
} // namespace dsn
97 changes: 97 additions & 0 deletions src/core/core/output_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Microsoft Corporation
*
* -=- Robust Distributed System Nucleus (rDSN) -=-
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "dsn/utility/output_utils.h"

#include <dsn/c/api_utilities.h>

namespace dsn {
namespace utils {

void table_printer::add_title(const std::string &title)
{
check_mode(data_mode::KMultiColumns);
dassert(matrix_data_.empty() && max_col_width_.empty(), "`add_title` must be called only once");
max_col_width_.push_back(title.length());
add_row(title);
}

void table_printer::add_column(const std::string &col_name)
{
check_mode(data_mode::KMultiColumns);
dassert(matrix_data_.size() == 1, "`add_column` must be called before real data appendding");
max_col_width_.emplace_back(col_name.length());
append_data(col_name);
}

void table_printer::add_row_name_and_string_data(const std::string &row_name,
const std::string &data)
{
max_col_width_.push_back(row_name.length());
max_col_width_.push_back(data.length());

matrix_data_.emplace_back(std::vector<std::string>());
append_string_data(row_name);
append_string_data(data);
}

void table_printer::output(std::ostream &out, const std::string &separator) const
{
if (max_col_width_.empty()) {
return;
}

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_) << std::left << data;
}
out << std::endl;
}
}

void table_printer::append_string_data(const std::string &data)
{
matrix_data_.rbegin()->emplace_back(data);

// update column max length
int &cur_len = max_col_width_[matrix_data_.rbegin()->size() - 1];
if (cur_len < data.size()) {
cur_len = data.size();
}
}

void table_printer::check_mode(data_mode mode)
{
if (mode_ == data_mode::kUninitialized) {
mode_ = mode;
return;
}
dassert(mode_ == mode, "");
}

} // namespace utils
} // namespace dsn
Loading

0 comments on commit 38df49e

Please sign in to comment.