parent
d589056a8d
commit
da32f9b98a
|
@ -13,40 +13,66 @@
|
||||||
#include <blt/math/math.h>
|
#include <blt/math/math.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace blt::string {
|
namespace blt::string
|
||||||
|
{
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline std::string withGrouping(T t, size_t group = 3){
|
static inline std::string withGrouping(T t, size_t group = 3)
|
||||||
|
{
|
||||||
// TODO: all this + make it faster
|
// TODO: all this + make it faster
|
||||||
static_assert(std::is_integral_v<T>, "Must be integer type! (Floats currently not supported!)");
|
static_assert(std::is_integral_v<T>, "Must be integer type! (Floats currently not supported!)");
|
||||||
auto str = std::to_string(t);
|
auto str = std::to_string(t);
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.reserve(str.size());
|
ret.reserve(str.size());
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
for (int64_t i = str.size() - 1; i >= 0; i--){
|
for (int64_t i = str.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
ret += str[i];
|
ret += str[i];
|
||||||
if (count++ % (group) == group-1 && i != 0)
|
if (count++ % (group) == group - 1 && i != 0)
|
||||||
ret += ',';
|
ret += ',';
|
||||||
}
|
}
|
||||||
std::reverse(ret.begin(), ret.end());
|
std::reverse(ret.begin(), ret.end());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline std::string fromBytes(unsigned long bytes){
|
static inline std::string fromBytes(unsigned long bytes)
|
||||||
if (bytes > 1073741824) {
|
{
|
||||||
|
if (bytes > 1073741824)
|
||||||
|
{
|
||||||
// gigabyte
|
// gigabyte
|
||||||
return std::to_string(round_up<3>((double) bytes / 1024.0 / 1024.0 / 1024.0)) += "gb";
|
return std::to_string(round_up<3>((double) bytes / 1024.0 / 1024.0 / 1024.0)) += "gb";
|
||||||
} else if (bytes > 1048576) {
|
} else if (bytes > 1048576)
|
||||||
|
{
|
||||||
// megabyte
|
// megabyte
|
||||||
return std::to_string(round_up<3>((double)bytes / 1024.0 / 1024.0)) += "mb";
|
return std::to_string(round_up<3>((double) bytes / 1024.0 / 1024.0)) += "mb";
|
||||||
} else if (bytes > 1024) {
|
} else if (bytes > 1024)
|
||||||
|
{
|
||||||
// kilobyte
|
// kilobyte
|
||||||
return std::to_string(round_up<3>((double)bytes / 1024.0)) += "kb";
|
return std::to_string(round_up<3>((double) bytes / 1024.0)) += "kb";
|
||||||
} else {
|
} else
|
||||||
|
{
|
||||||
return std::to_string(bytes) += "b";
|
return std::to_string(bytes) += "b";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: update table formatter to use these!
|
||||||
|
/**
|
||||||
|
* creates a line starting/ending with ending char filled between with spacing char
|
||||||
|
* @param totalLength total length to generate
|
||||||
|
* @param endingChar beginning and ending char to use
|
||||||
|
* @param spacingChar char to use for spacing
|
||||||
|
* @return a generated line string eg: +--------+
|
||||||
|
*/
|
||||||
|
std::string createLine(size_t totalLength, char endingChar, char spacingChar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a padding string using length and spacing char
|
||||||
|
* @param length length of string to generate
|
||||||
|
* @param spacing char to use to generate padding
|
||||||
|
* @return a padding string
|
||||||
|
*/
|
||||||
|
std::string createPadding(size_t length, char spacing = ' ');
|
||||||
|
|
||||||
// TODO template the padding functions:
|
// TODO template the padding functions:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,13 +81,13 @@ namespace blt::string {
|
||||||
* @param expectedLength expected length of the string.
|
* @param expectedLength expected length of the string.
|
||||||
* @return a space padded string
|
* @return a space padded string
|
||||||
*/
|
*/
|
||||||
static inline std::string postPadWithSpaces(const std::string& str, size_t expectedLength) {
|
static inline std::string postPadWithSpaces(const std::string& str, size_t expectedLength)
|
||||||
|
{
|
||||||
auto currentSize = (int) (str.length() - 1);
|
auto currentSize = (int) (str.length() - 1);
|
||||||
if ((int) expectedLength - currentSize <= 0)
|
if ((int) expectedLength - currentSize <= 0)
|
||||||
return str;
|
return str;
|
||||||
auto paddedString = str;
|
auto paddedString = str;
|
||||||
for (size_t i = 0; i < expectedLength - currentSize; i++)
|
paddedString += createPadding(expectedLength - currentSize);
|
||||||
paddedString += " ";
|
|
||||||
return paddedString;
|
return paddedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,26 +97,29 @@ namespace blt::string {
|
||||||
* @param expectedLength expected length of the string.
|
* @param expectedLength expected length of the string.
|
||||||
* @return a space padded string
|
* @return a space padded string
|
||||||
*/
|
*/
|
||||||
static inline std::string prePadWithSpaces(const std::string& str, size_t expectedLength) {
|
static inline std::string prePadWithSpaces(const std::string& str, size_t expectedLength)
|
||||||
|
{
|
||||||
auto currentSize = str.length() - 1;
|
auto currentSize = str.length() - 1;
|
||||||
auto paddedString = std::string();
|
auto paddedString = std::string();
|
||||||
for (unsigned int i = 0; i < expectedLength - currentSize; i++)
|
paddedString += createPadding(expectedLength - currentSize);
|
||||||
paddedString += " ";
|
|
||||||
paddedString += str;
|
paddedString += str;
|
||||||
return paddedString;
|
return paddedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct utf8_string {
|
struct utf8_string
|
||||||
|
{
|
||||||
char* characters;
|
char* characters;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
// taken from java, adapted for c++.
|
// taken from java, adapted for c++.
|
||||||
static inline utf8_string createUTFString(const std::string& str) {
|
static inline utf8_string createUTFString(const std::string& str)
|
||||||
|
{
|
||||||
const auto strlen = (unsigned int) str.size();
|
const auto strlen = (unsigned int) str.size();
|
||||||
unsigned int utflen = strlen;
|
unsigned int utflen = strlen;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < strlen; i++) {
|
for (unsigned int i = 0; i < strlen; i++)
|
||||||
|
{
|
||||||
unsigned char c = str[i];
|
unsigned char c = str[i];
|
||||||
if (c >= 0x80 || c == 0)
|
if (c >= 0x80 || c == 0)
|
||||||
utflen += 1;
|
utflen += 1;
|
||||||
|
@ -108,21 +137,26 @@ namespace blt::string {
|
||||||
chars.characters[count++] = (char) ((utflen >> 0) & 0xFF);
|
chars.characters[count++] = (char) ((utflen >> 0) & 0xFF);
|
||||||
|
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
for (i = 0; i < strlen; i++) { // optimized for initial run of ASCII
|
for (i = 0; i < strlen; i++)
|
||||||
|
{ // optimized for initial run of ASCII
|
||||||
int c = (unsigned char) str[i];
|
int c = (unsigned char) str[i];
|
||||||
if (c >= 0x80 || c == 0) break;
|
if (c >= 0x80 || c == 0) break;
|
||||||
chars.characters[count++] = (char) c;
|
chars.characters[count++] = (char) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < strlen; i++) {
|
for (; i < strlen; i++)
|
||||||
|
{
|
||||||
int c = (unsigned char) str[i];
|
int c = (unsigned char) str[i];
|
||||||
if (c < 0x80 && c != 0) {
|
if (c < 0x80 && c != 0)
|
||||||
|
{
|
||||||
chars.characters[count++] = (char) c;
|
chars.characters[count++] = (char) c;
|
||||||
} else if (c >= 0x800) {
|
} else if (c >= 0x800)
|
||||||
|
{
|
||||||
chars.characters[count++] = (char) (0xE0 | ((c >> 12) & 0x0F));
|
chars.characters[count++] = (char) (0xE0 | ((c >> 12) & 0x0F));
|
||||||
chars.characters[count++] = (char) (0x80 | ((c >> 6) & 0x3F));
|
chars.characters[count++] = (char) (0x80 | ((c >> 6) & 0x3F));
|
||||||
chars.characters[count++] = (char) (0x80 | ((c >> 0) & 0x3F));
|
chars.characters[count++] = (char) (0x80 | ((c >> 0) & 0x3F));
|
||||||
} else {
|
} else
|
||||||
|
{
|
||||||
chars.characters[count++] = (char) (0xC0 | ((c >> 6) & 0x1F));
|
chars.characters[count++] = (char) (0xC0 | ((c >> 6) & 0x1F));
|
||||||
chars.characters[count++] = (char) (0x80 | ((c >> 0) & 0x3F));
|
chars.characters[count++] = (char) (0x80 | ((c >> 0) & 0x3F));
|
||||||
}
|
}
|
||||||
|
@ -130,7 +164,8 @@ namespace blt::string {
|
||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline std::string getStringFromUTF8(const utf8_string& str) {
|
static inline std::string getStringFromUTF8(const utf8_string& str)
|
||||||
|
{
|
||||||
int utflen = (int) str.size;
|
int utflen = (int) str.size;
|
||||||
int c, char2, char3;
|
int c, char2, char3;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -138,16 +173,19 @@ namespace blt::string {
|
||||||
|
|
||||||
auto chararr = new char[utflen + 1];
|
auto chararr = new char[utflen + 1];
|
||||||
|
|
||||||
while (count < utflen) {
|
while (count < utflen)
|
||||||
|
{
|
||||||
c = (int) str.characters[count] & 0xff;
|
c = (int) str.characters[count] & 0xff;
|
||||||
if (c > 127) break;
|
if (c > 127) break;
|
||||||
count++;
|
count++;
|
||||||
chararr[chararr_count++] = (char) c;
|
chararr[chararr_count++] = (char) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count < utflen) {
|
while (count < utflen)
|
||||||
|
{
|
||||||
c = (int) str.characters[count] & 0xff;
|
c = (int) str.characters[count] & 0xff;
|
||||||
switch (c >> 4) {
|
switch (c >> 4)
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -192,23 +230,27 @@ namespace blt::string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chararr[utflen] = '\0';
|
chararr[utflen] = '\0';
|
||||||
std::string strs {chararr};
|
std::string strs{chararr};
|
||||||
delete[] chararr;
|
delete[] chararr;
|
||||||
return strs;
|
return strs;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TableColumn {
|
struct TableColumn
|
||||||
|
{
|
||||||
std::string columnName;
|
std::string columnName;
|
||||||
size_t maxColumnLength = 0;
|
size_t maxColumnLength = 0;
|
||||||
|
|
||||||
TableColumn(std::string columnName): columnName(std::move(columnName)) {}
|
TableColumn(std::string columnName): columnName(std::move(columnName))
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TableRow {
|
struct TableRow
|
||||||
|
{
|
||||||
std::vector<std::string> rowValues;
|
std::vector<std::string> rowValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TableFormatter {
|
class TableFormatter
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
std::string m_tableName;
|
std::string m_tableName;
|
||||||
int m_columnPadding;
|
int m_columnPadding;
|
||||||
|
@ -224,19 +266,23 @@ namespace blt::string {
|
||||||
|
|
||||||
void updateMaxColumnLengths();
|
void updateMaxColumnLengths();
|
||||||
|
|
||||||
[[nodiscard]] inline size_t columnSize(const TableColumn& column) const {
|
[[nodiscard]] inline size_t columnSize(const TableColumn& column) const
|
||||||
|
{
|
||||||
return column.columnName.size() + m_columnPadding * 2;
|
return column.columnName.size() + m_columnPadding * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TableFormatter(std::string tableName = "", int columnPadding = 2, int maxColumnWidth = 500):
|
explicit TableFormatter(std::string tableName = "", int columnPadding = 2, int maxColumnWidth = 500):
|
||||||
m_tableName(std::move(tableName)), m_columnPadding(columnPadding), m_maxColumnWidth(maxColumnWidth) {}
|
m_tableName(std::move(tableName)), m_columnPadding(columnPadding), m_maxColumnWidth(maxColumnWidth)
|
||||||
|
{}
|
||||||
|
|
||||||
inline void addColumn(const TableColumn& column) {
|
inline void addColumn(const TableColumn& column)
|
||||||
|
{
|
||||||
columns.push_back(column);
|
columns.push_back(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void addRow(TableRow row) {
|
inline void addRow(TableRow row)
|
||||||
|
{
|
||||||
if (row.rowValues.size() > columns.size())
|
if (row.rowValues.size() > columns.size())
|
||||||
throw "Cannot insert more rows than columns!\n";
|
throw "Cannot insert more rows than columns!\n";
|
||||||
// ensure every row populates every column. This is important as the table generator assumes that all rows are complete!
|
// ensure every row populates every column. This is important as the table generator assumes that all rows are complete!
|
||||||
|
@ -246,7 +292,8 @@ namespace blt::string {
|
||||||
rows.push_back(std::move(row));
|
rows.push_back(std::move(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void addRow(const std::initializer_list<std::string>& values) {
|
inline void addRow(const std::initializer_list<std::string>& values)
|
||||||
|
{
|
||||||
TableRow row;
|
TableRow row;
|
||||||
for (const auto& value : values)
|
for (const auto& value : values)
|
||||||
row.rowValues.push_back(value);
|
row.rowValues.push_back(value);
|
||||||
|
@ -256,5 +303,65 @@ namespace blt::string {
|
||||||
std::vector<std::string> createTable(bool top = false, bool bottom = false);
|
std::vector<std::string> createTable(bool top = false, bool bottom = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TreeFormatter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
std::string data;
|
||||||
|
Node* left = nullptr;
|
||||||
|
Node* right = nullptr;
|
||||||
|
|
||||||
|
explicit Node(std::string data): data(std::move(data))
|
||||||
|
{}
|
||||||
|
|
||||||
|
Node* with(Node* l, Node* r = nullptr)
|
||||||
|
{
|
||||||
|
left = l;
|
||||||
|
right = r;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Node()
|
||||||
|
{
|
||||||
|
delete left;
|
||||||
|
delete right;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
// data classes
|
||||||
|
struct TreeFormat
|
||||||
|
{
|
||||||
|
int verticalSpacing;
|
||||||
|
int horizontalSpacing;
|
||||||
|
|
||||||
|
int verticalPadding;
|
||||||
|
int horizontalPadding;
|
||||||
|
|
||||||
|
TreeFormat(): verticalSpacing(2), horizontalSpacing(4), verticalPadding(1), horizontalPadding(4)
|
||||||
|
{}
|
||||||
|
} format;
|
||||||
|
|
||||||
|
Node* root;
|
||||||
|
public:
|
||||||
|
explicit TreeFormatter(std::string rootData, TreeFormat format = {}): format(format), root(new Node(std::move(rootData)))
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::vector<std::string> generateBox(Node* node) const;
|
||||||
|
|
||||||
|
inline Node* getRoot()
|
||||||
|
{
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> construct();
|
||||||
|
|
||||||
|
~TreeFormatter()
|
||||||
|
{
|
||||||
|
delete root;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //BLT_TESTS_FORMAT_H
|
#endif //BLT_TESTS_FORMAT_H
|
||||||
|
|
|
@ -6,15 +6,19 @@
|
||||||
#include <blt/std/format.h>
|
#include <blt/std/format.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "blt/std/logging.h"
|
#include "blt/std/logging.h"
|
||||||
|
#include <stack>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
std::string createPadding(int padAmount) {
|
std::string createPadding(int padAmount)
|
||||||
|
{
|
||||||
std::string padStr;
|
std::string padStr;
|
||||||
for (int i = 0; i < padAmount; i++)
|
for (int i = 0; i < padAmount; i++)
|
||||||
padStr += " ";
|
padStr += " ";
|
||||||
return padStr;
|
return padStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> blt::string::TableFormatter::createTable(bool top, bool bottom) {
|
std::vector<std::string> blt::string::TableFormatter::createTable(bool top, bool bottom)
|
||||||
|
{
|
||||||
std::vector<std::string> table;
|
std::vector<std::string> table;
|
||||||
const auto& tableHeader = generateColumnHeader();
|
const auto& tableHeader = generateColumnHeader();
|
||||||
const auto& topSeparator = generateTopSeparator(tableHeader.size());
|
const auto& topSeparator = generateTopSeparator(tableHeader.size());
|
||||||
|
@ -26,16 +30,18 @@ std::vector<std::string> blt::string::TableFormatter::createTable(bool top, bool
|
||||||
table.push_back(tableHeader);
|
table.push_back(tableHeader);
|
||||||
table.push_back(lineSeparator);
|
table.push_back(lineSeparator);
|
||||||
|
|
||||||
for (const auto& row : rows) {
|
for (const auto& row : rows)
|
||||||
|
{
|
||||||
std::string rowString = "|";
|
std::string rowString = "|";
|
||||||
for (unsigned int i = 0; i < row.rowValues.size(); i++) {
|
for (unsigned int i = 0; i < row.rowValues.size(); i++)
|
||||||
|
{
|
||||||
const auto& rowValue = row.rowValues[i];
|
const auto& rowValue = row.rowValues[i];
|
||||||
const auto& column = columns[i];
|
const auto& column = columns[i];
|
||||||
const int spaceLeft = int(column.maxColumnLength) - int(rowValue.size());
|
const int spaceLeft = int(column.maxColumnLength) - int(rowValue.size());
|
||||||
// we want to prefer putting the space on the right size, flooring left and ceiling right ensures this.
|
// we want to prefer putting the space on the right size, flooring left and ceiling right ensures this.
|
||||||
rowString += createPadding((int)std::floor(spaceLeft/2.0) + m_columnPadding);
|
rowString += createPadding((int) std::floor(spaceLeft / 2.0) + m_columnPadding);
|
||||||
rowString += rowValue;
|
rowString += rowValue;
|
||||||
rowString += createPadding((int)std::ceil(spaceLeft/2.0) + m_columnPadding);
|
rowString += createPadding((int) std::ceil(spaceLeft / 2.0) + m_columnPadding);
|
||||||
rowString += "|";
|
rowString += "|";
|
||||||
}
|
}
|
||||||
table.push_back(rowString);
|
table.push_back(rowString);
|
||||||
|
@ -47,19 +53,21 @@ std::vector<std::string> blt::string::TableFormatter::createTable(bool top, bool
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string blt::string::TableFormatter::generateColumnHeader() {
|
std::string blt::string::TableFormatter::generateColumnHeader()
|
||||||
|
{
|
||||||
updateMaxColumnLengths();
|
updateMaxColumnLengths();
|
||||||
std::string header = "|";
|
std::string header = "|";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < columns.size(); i++) {
|
for (unsigned int i = 0; i < columns.size(); i++)
|
||||||
|
{
|
||||||
const auto& column = columns[i];
|
const auto& column = columns[i];
|
||||||
auto columnPaddingLength = (int(column.maxColumnLength) - int(column.columnName.size()))/2.0;
|
auto columnPaddingLength = (int(column.maxColumnLength) - int(column.columnName.size())) / 2.0;
|
||||||
header += createPadding(int(m_columnPadding + (int)std::floor(columnPaddingLength)));
|
header += createPadding(int(m_columnPadding + (int) std::floor(columnPaddingLength)));
|
||||||
|
|
||||||
header += column.columnName;
|
header += column.columnName;
|
||||||
|
|
||||||
header += createPadding(int(m_columnPadding + (int)std::ceil(columnPaddingLength)));
|
header += createPadding(int(m_columnPadding + (int) std::ceil(columnPaddingLength)));
|
||||||
if (i < columns.size()-1)
|
if (i < columns.size() - 1)
|
||||||
header += "|";
|
header += "|";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,15 +75,16 @@ std::string blt::string::TableFormatter::generateColumnHeader() {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string blt::string::TableFormatter::generateTopSeparator(size_t size) {
|
std::string blt::string::TableFormatter::generateTopSeparator(size_t size)
|
||||||
|
{
|
||||||
auto sizeOfName = m_tableName.empty() ? 0 : m_tableName.size() + 4;
|
auto sizeOfName = m_tableName.empty() ? 0 : m_tableName.size() + 4;
|
||||||
auto sizeNameRemoved = size - sizeOfName;
|
auto sizeNameRemoved = size - sizeOfName;
|
||||||
|
|
||||||
std::string halfWidthLeftSeparator;
|
std::string halfWidthLeftSeparator;
|
||||||
std::string halfWidthRightSeparator;
|
std::string halfWidthRightSeparator;
|
||||||
|
|
||||||
auto sizeNameFloor = (size_t) std::floor((double)sizeNameRemoved/2.0);
|
auto sizeNameFloor = (size_t) std::floor((double) sizeNameRemoved / 2.0);
|
||||||
auto sizeNameCeil = (size_t) std::ceil((double)sizeNameRemoved/2.0);
|
auto sizeNameCeil = (size_t) std::ceil((double) sizeNameRemoved / 2.0);
|
||||||
|
|
||||||
halfWidthLeftSeparator.reserve(sizeNameCeil);
|
halfWidthLeftSeparator.reserve(sizeNameCeil);
|
||||||
halfWidthRightSeparator.reserve(sizeNameFloor);
|
halfWidthRightSeparator.reserve(sizeNameFloor);
|
||||||
|
@ -92,7 +101,8 @@ std::string blt::string::TableFormatter::generateTopSeparator(size_t size) {
|
||||||
|
|
||||||
std::string separator;
|
std::string separator;
|
||||||
separator += halfWidthLeftSeparator;
|
separator += halfWidthLeftSeparator;
|
||||||
if (sizeOfName != 0) {
|
if (sizeOfName != 0)
|
||||||
|
{
|
||||||
separator += "{ ";
|
separator += "{ ";
|
||||||
separator += m_tableName;
|
separator += m_tableName;
|
||||||
separator += " }";
|
separator += " }";
|
||||||
|
@ -101,13 +111,16 @@ std::string blt::string::TableFormatter::generateTopSeparator(size_t size) {
|
||||||
return separator;
|
return separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string blt::string::TableFormatter::generateSeparator(size_t size) {
|
std::string blt::string::TableFormatter::generateSeparator(size_t size)
|
||||||
|
{
|
||||||
size_t nextIndex = 0;
|
size_t nextIndex = 0;
|
||||||
size_t currentColumnIndex = 0;
|
size_t currentColumnIndex = 0;
|
||||||
std::string wholeWidthSeparator;
|
std::string wholeWidthSeparator;
|
||||||
for (unsigned int i = 0; i < size; i++) {
|
for (unsigned int i = 0; i < size; i++)
|
||||||
if (i == nextIndex) {
|
{
|
||||||
auto currentColumnSize = columns[currentColumnIndex++].maxColumnLength + m_columnPadding*2;
|
if (i == nextIndex)
|
||||||
|
{
|
||||||
|
auto currentColumnSize = columns[currentColumnIndex++].maxColumnLength + m_columnPadding * 2;
|
||||||
nextIndex += currentColumnSize + 1;
|
nextIndex += currentColumnSize + 1;
|
||||||
wholeWidthSeparator += "+";
|
wholeWidthSeparator += "+";
|
||||||
} else
|
} else
|
||||||
|
@ -117,13 +130,113 @@ std::string blt::string::TableFormatter::generateSeparator(size_t size) {
|
||||||
return wholeWidthSeparator;
|
return wholeWidthSeparator;
|
||||||
}
|
}
|
||||||
|
|
||||||
void blt::string::TableFormatter::updateMaxColumnLengths() {
|
void blt::string::TableFormatter::updateMaxColumnLengths()
|
||||||
for (unsigned int i = 0; i < columns.size(); i++) {
|
{
|
||||||
|
for (unsigned int i = 0; i < columns.size(); i++)
|
||||||
|
{
|
||||||
auto& column = columns[i];
|
auto& column = columns[i];
|
||||||
column.maxColumnLength = column.columnName.size();
|
column.maxColumnLength = column.columnName.size();
|
||||||
for (const auto& row : rows) {
|
for (const auto& row : rows)
|
||||||
|
{
|
||||||
column.maxColumnLength = std::max(column.maxColumnLength, row.rowValues[i].size());
|
column.maxColumnLength = std::max(column.maxColumnLength, row.rowValues[i].size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -----------------------
|
||||||
|
* Tree Formatter
|
||||||
|
* -----------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct node_data
|
||||||
|
{
|
||||||
|
blt::string::TreeFormatter::Node* node;
|
||||||
|
size_t level;
|
||||||
|
|
||||||
|
node_data(blt::string::TreeFormatter::Node* node, size_t level): node(node), level(level)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> blt::string::TreeFormatter::construct()
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
std::stack<node_data> nodes;
|
||||||
|
|
||||||
|
std::queue<node_data> bfs;
|
||||||
|
bfs.emplace(root, 0);
|
||||||
|
while (!bfs.empty())
|
||||||
|
{
|
||||||
|
auto n = bfs.front();
|
||||||
|
nodes.push(n);
|
||||||
|
std::cout << "Node at level " << n.level << " " << bfs.size() << "\n";
|
||||||
|
if (n.node->left != nullptr)
|
||||||
|
bfs.emplace(n.node->left, n.level + 1);
|
||||||
|
if (n.node->right != nullptr)
|
||||||
|
bfs.emplace(n.node->right, n.level + 1);
|
||||||
|
bfs.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> blt::string::TreeFormatter::generateBox(blt::string::TreeFormatter::Node* node) const
|
||||||
|
{
|
||||||
|
if (node == nullptr)
|
||||||
|
return {};
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
auto& data = node->data;
|
||||||
|
auto dataLength = data.length();
|
||||||
|
auto paddingLeft = format.horizontalPadding;
|
||||||
|
auto paddingRight = format.horizontalPadding;
|
||||||
|
auto totalLength = paddingLeft + paddingRight + dataLength;
|
||||||
|
|
||||||
|
if (totalLength % 2 != 0)
|
||||||
|
{
|
||||||
|
paddingRight += 1;
|
||||||
|
totalLength += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create horizontal line based on the calculated length
|
||||||
|
std::string hline = createLine(totalLength, '+', '-');
|
||||||
|
std::string paddedLine = createLine(totalLength, '|', ' ');
|
||||||
|
std::string dataStr;
|
||||||
|
dataStr.reserve(totalLength);
|
||||||
|
dataStr += '|';
|
||||||
|
dataStr += createPadding(paddingLeft - 1);
|
||||||
|
dataStr += data;
|
||||||
|
dataStr += createPadding(paddingRight - 1);
|
||||||
|
dataStr += '|';
|
||||||
|
|
||||||
|
lines.push_back(hline);
|
||||||
|
for (int i = 0; i < format.verticalPadding; i++)
|
||||||
|
lines.push_back(paddedLine);
|
||||||
|
lines.push_back(std::move(dataStr));
|
||||||
|
for (int i = 0; i < format.verticalPadding; i++)
|
||||||
|
lines.push_back(paddedLine);
|
||||||
|
|
||||||
|
lines.push_back(std::move(hline));
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string blt::string::createLine(size_t totalLength, char endingChar, char spacingChar)
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
line.reserve(totalLength);
|
||||||
|
line += endingChar;
|
||||||
|
line += createPadding(totalLength - 2, spacingChar);
|
||||||
|
line += endingChar;
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string blt::string::createPadding(size_t length, char spacing)
|
||||||
|
{
|
||||||
|
std::string padding;
|
||||||
|
padding.reserve(length);
|
||||||
|
for (size_t i = 0; i < length; i++)
|
||||||
|
padding += spacing;
|
||||||
|
return padding;
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <blt/std/utility.h>
|
#include <blt/std/utility.h>
|
||||||
|
#include <blt/std/format.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
#include <utility_test.h>
|
#include <utility_test.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -23,12 +24,17 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
std::optional<int> get()
|
std::optional<int> get()
|
||||||
{
|
{
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printLines(const std::vector<std::string>& lines)
|
||||||
|
{
|
||||||
|
for (const auto& v : lines)
|
||||||
|
std::cout << v << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
void blt::test::utility::run()
|
void blt::test::utility::run()
|
||||||
{
|
{
|
||||||
//std::vector<int> temp;
|
//std::vector<int> temp;
|
||||||
|
@ -37,4 +43,54 @@ void blt::test::utility::run()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blt::string::TableFormatter parkerLove("Intrinsic Action Value Table");
|
||||||
|
parkerLove.addColumn({"Thing"});
|
||||||
|
parkerLove.addColumn({"Value"});
|
||||||
|
|
||||||
|
parkerLove.addRow({"Cuddles", "1 / minute"});
|
||||||
|
parkerLove.addRow({"Hand Job", "10"});
|
||||||
|
parkerLove.addRow({"Head", "100"});
|
||||||
|
parkerLove.addRow({"Sleeping Together (Non-Sexual)", "1,000"});
|
||||||
|
parkerLove.addRow({"Actual Sex", "5,000"});
|
||||||
|
parkerLove.addRow({"Sleeping Together (Sexual)", "10,000"});
|
||||||
|
parkerLove.addRow({"Relationship (I would do anything for you)", "1,000,000,000,000"});
|
||||||
|
|
||||||
|
|
||||||
|
printLines(parkerLove.createTable(true, true));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
blt::string::TreeFormatter treeFormatter("I love Men");
|
||||||
|
treeFormatter.getRoot()->with(
|
||||||
|
new string::TreeFormatter::Node("Guys"),
|
||||||
|
new string::TreeFormatter::Node("Femboys"));
|
||||||
|
printLines(treeFormatter.construct());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue