Skip to content

Commit

Permalink
Slightly improved SimpleTable pretty print with '+' instead of '-' at…
Browse files Browse the repository at this point in the history
… intersection of columns
  • Loading branch information
sjanel committed Aug 23, 2023
1 parent 278af63 commit 3828de1
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 111 deletions.
3 changes: 2 additions & 1 deletion src/engine/src/queryresultprinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,8 @@ void QueryResultPrinter::printDustSweeper(
void QueryResultPrinter::printTable(const SimpleTable &simpleTable) const {
std::ostringstream ss;
std::ostream &os = _pOs != nullptr ? *_pOs : ss;
simpleTable.print(os);

os << simpleTable;

if (_pOs != nullptr) {
*_pOs << std::endl;
Expand Down
96 changes: 48 additions & 48 deletions src/engine/test/queryresultprinter_private_test.cpp

Large diffs are not rendered by default.

78 changes: 39 additions & 39 deletions src/engine/test/queryresultprinter_public_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class QueryResultPrinterHealthCheckTest : public QueryResultPrinterTest {
TEST_F(QueryResultPrinterHealthCheckTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable).printHealthCheck(healthCheckPerExchange);
static constexpr std::string_view kExpected = R"(
----------------------------------
+----------+---------------------+
| Exchange | Health Check status |
----------------------------------
+----------+---------------------+
| binance | OK |
| huobi | Not OK! |
----------------------------------
+----------+---------------------+
)";

expectStr(kExpected);
Expand Down Expand Up @@ -67,13 +67,13 @@ class QueryResultPrinterMarketsTest : public QueryResultPrinterTest {
TEST_F(QueryResultPrinterMarketsTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable).printMarkets(cur1, cur2, marketsPerExchange);
static constexpr std::string_view kExpected = R"(
-------------------------------
+----------+------------------+
| Exchange | Markets with XRP |
-------------------------------
+----------+------------------+
| binance | XRP-BTC |
| binance | XRP-KRW |
| huobi | XRP-EUR |
-------------------------------
+----------+------------------+
)";

expectStr(kExpected);
Expand Down Expand Up @@ -133,13 +133,13 @@ class QueryResultPrinterTickerTest : public QueryResultPrinterTest {
TEST_F(QueryResultPrinterTickerTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable).printTickerInformation(exchangeTickerMaps);
static constexpr std::string_view kExpected = R"(
------------------------------------------------------------------------------
+----------+---------+--------------+------------+--------------+------------+
| Exchange | Market | Bid price | Bid volume | Ask price | Ask volume |
------------------------------------------------------------------------------
+----------+---------+--------------+------------+--------------+------------+
| bithumb | ETH-EUR | 2301.05 EUR | 17 ETH | 2301.15 EUR | 0.4 ETH |
| huobi | BTC-EUR | 31051.01 EUR | 1.9087 BTC | 31051.02 EUR | 0.409 BTC |
| huobi | XRP-BTC | 0.36 BTC | 3494 XRP | 0.37 BTC | 916.4 XRP |
------------------------------------------------------------------------------
+----------+---------+--------------+------------+--------------+------------+
)";
expectStr(kExpected);
}
Expand Down Expand Up @@ -223,26 +223,26 @@ TEST_F(QueryResultPrinterMarketOrderBookTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable)
.printMarketOrderBooks(mk, CurrencyCode{}, d, marketOrderBookConversionRates);
static constexpr std::string_view kExpected = R"(
-----------------------------------------------------------------------------
+-----------------------+----------------------------+----------------------+
| Sellers of BTC (asks) | exchangeA BTC price in EUR | Buyers of BTC (bids) |
-----------------------------------------------------------------------------
+-----------------------+----------------------------+----------------------+
| 0.18116 | 31056.7 | |
| 0.15058 | 31056.68 | |
| 0.12 | 31056.67 | |
| | 31056.66 | 0.00234 |
| | 31056.65 | 0.03292 |
| | 31056.63 | 0.0635 |
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
+-----------------------+----------------------------+----------------------+
+-----------------------+----------------------------+----------------------+
| Sellers of BTC (asks) | exchangeD BTC price in EUR | Buyers of BTC (bids) |
-----------------------------------------------------------------------------
+-----------------------+----------------------------+----------------------+
| 0.18116 | 31056.7 | |
| 0.15058 | 31056.68 | |
| 0.12 | 31056.67 | |
| | 31056.66 | 0.00234 |
| | 31056.65 | 0.03292 |
| | 31056.63 | 0.0635 |
-----------------------------------------------------------------------------
+-----------------------+----------------------------+----------------------+
)";
expectStr(kExpected);
}
Expand Down Expand Up @@ -360,12 +360,12 @@ class QueryResultPrinterConversionPathTest : public QueryResultPrinterTest {
TEST_F(QueryResultPrinterConversionPathTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable).printConversionPath(marketForPath, conversionPathPerExchange);
static constexpr std::string_view kExpected = R"(
--------------------------------------------------
+----------+-------------------------------------+
| Exchange | Fastest conversion path for XLM-XRP |
--------------------------------------------------
+----------+-------------------------------------+
| bithumb | XLM-XRP |
| huobi | XLM-AAA,BBB-AAA,BBB-XRP |
--------------------------------------------------
+----------+-------------------------------------+
)";
expectStr(kExpected);
}
Expand Down Expand Up @@ -424,12 +424,12 @@ class QueryResultPrinterWithdrawFeeTest : public QueryResultPrinterTest {
TEST_F(QueryResultPrinterWithdrawFeeTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable).printWithdrawFees(withdrawFeePerExchange, curWithdrawFee);
static constexpr std::string_view kExpected = R"(
---------------------------
+----------+--------------+
| Exchange | Withdraw fee |
---------------------------
+----------+--------------+
| bithumb | 0.15 ETH |
| huobi | 0.05 ETH |
---------------------------
+----------+--------------+
)";
expectStr(kExpected);
}
Expand Down Expand Up @@ -483,12 +483,12 @@ TEST_F(QueryResultPrinterLast24HoursTradedVolumeTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable)
.printLast24hTradedVolume(marketLast24hTradedVolume, monetaryAmountPerExchange);
static constexpr std::string_view kExpected = R"(
---------------------------------------------
+----------+--------------------------------+
| Exchange | Last 24h BTC-EUR traded volume |
---------------------------------------------
+----------+--------------------------------+
| binance | 37.8 BTC |
| huobi | 14 BTC |
---------------------------------------------
+----------+--------------------------------+
)";
expectStr(kExpected);
}
Expand Down Expand Up @@ -559,32 +559,32 @@ TEST_F(QueryResultPrinterLastTradesVolumeTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable)
.printLastTrades(marketLastTrades, nbLastTrades, lastTradesPerExchange);
static constexpr std::string_view kExpected = R"(
--------------------------------------------------------------------------------------------
+----------------------+--------------------+--------------------------+-------------------+
| binance trades - UTC | ETH buys | Price in USDT | ETH sells |
--------------------------------------------------------------------------------------------
+----------------------+--------------------+--------------------------+-------------------+
| 1999-03-25 04:46:43 | 0.13 | 1500.5 | |
| 2002-06-23 07:58:35 | | 1500.5 | 3.7 |
| 2006-07-14 23:58:24 | 0.004 | 1501 | |
--------------------------------------------------------------------------------------------
+----------------------+--------------------+--------------------------+-------------------+
| Summary | 0.134 ETH (2 buys) | 1500.66666666666666 USDT | 3.7 ETH (1 sells) |
--------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------
+----------------------+--------------------+--------------------------+-------------------+
+---------------------+--------------------+---------------+--------------------+
| huobi trades - UTC | ETH buys | Price in USDT | ETH sells |
---------------------------------------------------------------------------------
+---------------------+--------------------+---------------+--------------------+
| 2011-10-03 06:49:36 | | 1500.5 | 0.13 |
| 2002-06-23 07:58:35 | 0.004 | 1501 | |
---------------------------------------------------------------------------------
+---------------------+--------------------+---------------+--------------------+
| Summary | 0.004 ETH (1 buys) | 1500.75 USDT | 0.13 ETH (1 sells) |
---------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
+---------------------+--------------------+---------------+--------------------+
+----------------------+---------------------+--------------------------+--------------------+
| bithumb trades - UTC | ETH buys | Price in USDT | ETH sells |
----------------------------------------------------------------------------------------------
+----------------------+---------------------+--------------------------+--------------------+
| 2011-10-03 06:49:36 | | 1500.5 | 0.13 |
| 2002-06-23 07:58:35 | 0.004 | 1501 | |
| 1999-03-25 04:46:43 | 47.78 | 1498 | |
----------------------------------------------------------------------------------------------
+----------------------+---------------------+--------------------------+--------------------+
| Summary | 47.784 ETH (2 buys) | 1499.83333333333333 USDT | 0.13 ETH (1 sells) |
----------------------------------------------------------------------------------------------
+----------------------+---------------------+--------------------------+--------------------+
)";
expectStr(kExpected);
}
Expand Down Expand Up @@ -694,13 +694,13 @@ class QueryResultPrinterLastPriceTest : public QueryResultPrinterTest {
TEST_F(QueryResultPrinterLastPriceTest, FormattedTable) {
basicQueryResultPrinter(ApiOutputType::kFormattedTable).printLastPrice(marketLastPrice, monetaryAmountPerExchange);
static constexpr std::string_view kExpected = R"(
---------------------------------
+----------+--------------------+
| Exchange | XRP-KRW last price |
---------------------------------
+----------+--------------------+
| binance | 417 KRW |
| huobi | 444 KRW |
| bithumb | 590 KRW |
---------------------------------
+----------+--------------------+
)";
expectStr(kExpected);
}
Expand Down
13 changes: 10 additions & 3 deletions src/tech/include/simpletable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <string>
#endif

#include "cct_smallvector.hpp"
#include "cct_string.hpp"
#include "cct_type_traits.hpp"
#include "cct_vector.hpp"
Expand Down Expand Up @@ -120,11 +121,11 @@ class SimpleTable {

bool operator==(const Row &) const = default;

// TODO: to be replaced by spaceship defaulted operator once vector supports it
bool operator<(const Row &o) const { return _cells < o._cells; }
auto operator<=>(const Row &) const = default;

private:
friend class SimpleTable;
friend std::ostream &operator<<(std::ostream &, const SimpleTable &);

void print(std::ostream &os, std::span<const uint16_t> maxWidthPerColumn) const;

Expand Down Expand Up @@ -167,11 +168,17 @@ class SimpleTable {

void reserve(size_type s) { _rows.reserve(s); }

void print(std::ostream &os = std::cout) const;
friend std::ostream &operator<<(std::ostream &os, const SimpleTable &t);

using trivially_relocatable = is_trivially_relocatable<vector<Row>>::type;

private:
using MaxWidthPerColumnVector = SmallVector<uint16_t, 8>;

MaxWidthPerColumnVector computeMaxWidthPerColumn() const;

Cell::string_type computeLineSep(std::span<const uint16_t> maxWidthPerColumnVector) const;

vector<Row> _rows;
};
} // namespace cct
47 changes: 31 additions & 16 deletions src/tech/src/simpletable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <iomanip>
#include <numeric>

#include "cct_smallvector.hpp"
#include "mathhelpers.hpp"
#include "unreachable.hpp"

Expand All @@ -17,7 +16,6 @@ const SimpleTable::Row SimpleTable::Row::kDivider;

namespace {
constexpr char kColumnSep = '|';
constexpr char kLineSep = '-';

enum class AlignTo : int8_t { kLeft, kRight };

Expand Down Expand Up @@ -76,40 +74,57 @@ void SimpleTable::Row::print(std::ostream &os, std::span<const uint16_t> maxWidt
os << std::endl;
}

void SimpleTable::print(std::ostream &os) const {
if (_rows.empty()) {
return;
}
SimpleTable::MaxWidthPerColumnVector SimpleTable::computeMaxWidthPerColumn() const {
// We assume that each row has same number of cells, no silly checks here
const size_type nbColumns = _rows.front().size();
SmallVector<uint16_t, 8> maxWidthPerColumn(nbColumns, 0);
SmallVector<uint16_t, 8> res(nbColumns, 0);
for (const Row &row : _rows) {
if (!row.isDivider()) {
for (size_type columnPos = 0; columnPos < nbColumns; ++columnPos) {
maxWidthPerColumn[columnPos] =
std::max(maxWidthPerColumn[columnPos], static_cast<uint16_t>(row[columnPos].size()));
res[columnPos] = std::max(res[columnPos], static_cast<uint16_t>(row[columnPos].size()));
}
}
}
const size_type sumWidths = std::accumulate(maxWidthPerColumn.begin(), maxWidthPerColumn.end(), 0U);
const size_type maxTableWidth = sumWidths + nbColumns * 3 + 1;
const Cell::string_type lineSep(maxTableWidth, kLineSep);
return res;
}

SimpleTable::Cell::string_type SimpleTable::computeLineSep(std::span<const uint16_t> maxWidthPerColumnVector) const {
const size_type sumWidths = std::accumulate(maxWidthPerColumnVector.begin(), maxWidthPerColumnVector.end(), 0U);
const size_type maxTableWidth = sumWidths + maxWidthPerColumnVector.size() * 3 + 1;
Cell::string_type lineSep(maxTableWidth, '-');

size_type curWidth = 0;
lineSep[curWidth] = '+';
for (auto maxWidth : maxWidthPerColumnVector) {
curWidth += maxWidth + 3;
lineSep[curWidth] = '+';
}

return lineSep;
}

std::ostream &operator<<(std::ostream &os, const SimpleTable &t) {
if (t._rows.empty()) {
return os;
}
const auto maxWidthPerColumnVector = t.computeMaxWidthPerColumn();
const auto lineSep = t.computeLineSep(maxWidthPerColumnVector);

os << lineSep << std::endl;

bool printHeader = _rows.size() > 1U;
for (const Row &row : _rows) {
bool printHeader = t._rows.size() > 1U;
for (const auto &row : t._rows) {
if (row.isDivider()) {
os << lineSep << std::endl;
} else {
row.print(os, maxWidthPerColumn);
row.print(os, maxWidthPerColumnVector);
}
if (printHeader) {
os << lineSep << std::endl;
printHeader = false;
}
}

os << lineSep;
return os << lineSep;
}
} // namespace cct
12 changes: 8 additions & 4 deletions src/tech/test/simpletable_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ namespace cct {
TEST(SimpleTable, DefaultConstructor) {
SimpleTable table;
EXPECT_TRUE(table.empty());
table.print(std::cout);

std::cout << table;
}

TEST(SimpleTable, OneLinePrint) {
SimpleTable table;
string str("I am a string");
table.emplace_back("Header 1", 42, std::move(str));
EXPECT_EQ(table.size(), 1U);
table.print(std::cout);

std::cout << table;
}

TEST(SimpleTable, SimplePrint) {
Expand All @@ -32,7 +34,8 @@ TEST(SimpleTable, SimplePrint) {
row3.emplace_back("BTC");
table.push_back(std::move(row3));
EXPECT_EQ(table.size(), 3U);
table.print(std::cout);

std::cout << table;
}

TEST(SimpleTable, SettingRowDirectly) {
Expand All @@ -44,6 +47,7 @@ TEST(SimpleTable, SettingRowDirectly) {
table.emplace_back(-677256340000, "KEBAB", "-34.09");
EXPECT_EQ(table[2].front().size(), 7U);
EXPECT_EQ(table.back().front().size(), 13U);
table.print(std::cout);

std::cout << table;
}
} // namespace cct

0 comments on commit 3828de1

Please sign in to comment.