mirror of
https://github.com/tdulcet/Table-and-Graph-Libs.git
synced 2025-05-05 21:41:12 +08:00
Updated to require C++17 and use exceptions.
This commit is contained in:
parent
370dde9025
commit
8fa05e23c8
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
$CXX --version
|
||||
- name: Script
|
||||
run: |
|
||||
ARGS=( -std=gnu++14 -Wall -g -Og )
|
||||
ARGS=( -std=gnu++17 -Wall -g -Og )
|
||||
if [[ $CXX == clang* ]]; then
|
||||
ARGS+=( -fsanitize=address,undefined,integer )
|
||||
else
|
||||
|
@ -21,7 +21,7 @@ target_sources(tglib_tables PUBLIC
|
||||
|
||||
# compile example binaries as executables
|
||||
if (PROJECT_IS_TOP_LEVEL)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
add_executable(tglib_graphs_example "${CMAKE_CURRENT_SOURCE_DIR}/graphs.cpp")
|
||||
target_link_libraries(tglib_graphs_example PRIVATE tglib::graphs)
|
||||
|
42
README.md
42
README.md
@ -38,13 +38,13 @@ For command-line tools using these respective libraries, see the [Tables and Gra
|
||||
|
||||
### Usage
|
||||
|
||||
Requires support for C++14. See the [tables.hpp](tables.hpp) file for full usage information.
|
||||
Requires support for C++17. See the [tables.hpp](tables.hpp) file for full usage information.
|
||||
|
||||
Complete versions of all of the examples below and more can be found in the [tables.cpp](tables.cpp) file.
|
||||
|
||||
Compile with:
|
||||
* GCC: `g++ -std=c++14 -Wall -g -O3 tables.cpp -o tables`
|
||||
* Clang: `clang++ -std=c++14 -Wall -g -O3 tables.cpp -o tables`
|
||||
* GCC: `g++ -std=c++17 -Wall -g -O3 tables.cpp -o tables`
|
||||
* Clang: `clang++ -std=c++17 -Wall -g -O3 tables.cpp -o tables`
|
||||
|
||||
Other compilers should work as well, but are not (yet) tested.
|
||||
|
||||
@ -68,9 +68,7 @@ int main()
|
||||
|
||||
// Allocate and set array
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
tables::array(rows, columns, array, nullptr, nullptr, aoptions);
|
||||
|
||||
@ -99,9 +97,7 @@ int main()
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
tables::array(array, headerrow, headercolumn, aoptions);
|
||||
|
||||
@ -134,9 +130,7 @@ int main()
|
||||
|
||||
// Allocate and set array
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
tables::array(rows, columns, array, headerrow, headercolumn, aoptions);
|
||||
|
||||
@ -165,11 +159,7 @@ int main()
|
||||
|
||||
// Set array
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// or with C++20:
|
||||
// tables::options aoptions{.headerrow = true, .headercolumn = true};
|
||||
tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
tables::array(array, headerrow, headercolumn, aoptions);
|
||||
|
||||
@ -337,8 +327,7 @@ int main()
|
||||
double xmax = 10;
|
||||
double xstep = 0.5;
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
tables::function(xmin, xmax, xstep, afunction, aoptions);
|
||||
|
||||
@ -362,8 +351,7 @@ int main()
|
||||
function<double(double)> afunction = [](auto x)
|
||||
{ return x + 1; };
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
tables::function(xmin, xmax, xstep, afunction, aoptions);
|
||||
|
||||
@ -404,8 +392,7 @@ int main()
|
||||
// Function parameter and return value can be any data type, as long as they are the same
|
||||
function<double(double)> functions[] = {function1, function2};
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
tables::functions(xmin, xmax, xstep, numfunctions, functions, aoptions);
|
||||
|
||||
@ -435,8 +422,7 @@ int main()
|
||||
[](auto x)
|
||||
{ return pow(x, 2); }};
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
tables::functions(xmin, xmax, xstep, numfunctions, functions, aoptions);
|
||||
|
||||
@ -538,13 +524,13 @@ Check that the width of the table is not greater then the width of the terminal.
|
||||
|
||||
### Usage
|
||||
|
||||
Requires support for C++14. See the [graphs.hpp](graphs.hpp) file for full usage information.
|
||||
Requires support for C++17. See the [graphs.hpp](graphs.hpp) file for full usage information.
|
||||
|
||||
Complete versions of all of the examples below and more can be found in the [graphs.cpp](graphs.cpp) file.
|
||||
|
||||
Compile with:
|
||||
* GCC: `g++ -std=c++14 -Wall -g -O3 graphs.cpp -o graphs`
|
||||
* Clang: `clang++ -std=c++14 -Wall -g -O3 graphs.cpp -o graphs`
|
||||
* GCC: `g++ -std=c++17 -Wall -g -O3 graphs.cpp -o graphs`
|
||||
* Clang: `clang++ -std=c++17 -Wall -g -O3 graphs.cpp -o graphs`
|
||||
|
||||
Other compilers should work as well, but are not (yet) tested.
|
||||
|
||||
|
12
graphs.cpp
12
graphs.cpp
@ -1,6 +1,6 @@
|
||||
// Teal Dulcet, CS546
|
||||
|
||||
// Compile: g++ -std=c++14 -Wall -g -O3 graphs.cpp -o graphs
|
||||
// Compile: g++ -std=gnu++17 -Wall -g -O3 graphs.cpp -o graphs
|
||||
|
||||
// Run: ./graphs
|
||||
|
||||
@ -242,7 +242,7 @@ int main()
|
||||
{
|
||||
aoptions.style = style;
|
||||
|
||||
graphs::functions(height, width, xmin, xmax, ymin, ymax, graphs::size(functions), functions, aoptions);
|
||||
graphs::functions(height, width, xmin, xmax, ymin, ymax, size(functions), functions, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -257,7 +257,7 @@ int main()
|
||||
{
|
||||
aoptions.style = style;
|
||||
|
||||
graphs::functions(height, width, xmin, xmax, ymin, ymax, graphs::size(functions), functions, aoptions);
|
||||
graphs::functions(height, width, xmin, xmax, ymin, ymax, size(functions), functions, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -270,13 +270,13 @@ int main()
|
||||
|
||||
graphs::options aoptions;
|
||||
aoptions.axisunitslabel = false;
|
||||
// graphs::options aoptions{.axisunitslabel = false};
|
||||
// graphs::options aoptions = {.axisunitslabel = false};
|
||||
|
||||
for (const graphs::style_type style : graphs::style_types)
|
||||
{
|
||||
aoptions.style = style;
|
||||
|
||||
graphs::functions(height, width, xmin, xmax, ymin, ymax, graphs::size(functions), functions, aoptions);
|
||||
graphs::functions(height, width, xmin, xmax, ymin, ymax, size(functions), functions, aoptions);
|
||||
}
|
||||
|
||||
/* aoptions.style = 2;
|
||||
@ -286,7 +286,7 @@ int main()
|
||||
cout << "\e[1;1H"
|
||||
<< "\e[2J";
|
||||
|
||||
graphs::functions(k, k, xmin, xmax, ymin, ymax, graphs::size(functions), functions, aoptions);
|
||||
graphs::functions(k, k, xmin, xmax, ymin, ymax, size(functions), functions, aoptions);
|
||||
|
||||
usleep(200000);
|
||||
} */
|
||||
|
157
graphs.hpp
157
graphs.hpp
@ -168,52 +168,30 @@ namespace graphs
|
||||
bool check = true;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t size(const T &array)
|
||||
{
|
||||
return distance(cbegin(array), cend(array));
|
||||
}
|
||||
|
||||
// Number of columns needed to represent the string
|
||||
// Adapted from: https://stackoverflow.com/a/31124065
|
||||
inline int strcol(const char *const str)
|
||||
inline int strcol(const string &str)
|
||||
{
|
||||
size_t length = strlen(str);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
if (iscntrl(str[i]))
|
||||
for (const char c : str)
|
||||
if (iscntrl(c))
|
||||
{
|
||||
cerr << "\nError! Control character in string.\n";
|
||||
cout << "Control character: " << (int)str[i] << '\n';
|
||||
cerr << "\nError: Control character in string.\n";
|
||||
cout << "Control character: " << (int)c << '\n';
|
||||
}
|
||||
|
||||
length = mbstowcs(nullptr, str, 0);
|
||||
size_t length = mbstowcs(nullptr, str.c_str(), 0);
|
||||
if (length == static_cast<size_t>(-1))
|
||||
{
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
exit(1);
|
||||
}
|
||||
throw range_error("Error: mbstowcs failed. Invalid multibyte character.");
|
||||
++length;
|
||||
|
||||
auto *wcstring = new wchar_t[length];
|
||||
wstring wcstring(length, L'\0');
|
||||
|
||||
if (mbstowcs(wcstring, str, length) == static_cast<size_t>(-1))
|
||||
{
|
||||
if (wcstring)
|
||||
delete[] wcstring;
|
||||
if (mbstowcs(wcstring.data(), str.c_str(), length) == static_cast<size_t>(-1))
|
||||
throw range_error("Error: mbstowcs failed. Invalid multibyte character.");
|
||||
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const int width = wcswidth(wcstring, length);
|
||||
const int width = wcswidth(wcstring.c_str(), length);
|
||||
if (width == -1)
|
||||
{
|
||||
cerr << "\nError! wcswidth failed. Nonprintable wide character.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (wcstring)
|
||||
delete[] wcstring;
|
||||
throw range_error("Error: wcswidth failed. Nonprintable wide character.");
|
||||
|
||||
return width;
|
||||
}
|
||||
@ -221,7 +199,7 @@ namespace graphs
|
||||
// Word wrap
|
||||
// Source: https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0
|
||||
// Adapted from: https://stackoverflow.com/a/42016346 and https://stackoverflow.com/a/13094734
|
||||
inline string wrap(const char *const str, const size_t line_length)
|
||||
inline string wrap(const string &str, const size_t line_length)
|
||||
{
|
||||
string words = str;
|
||||
string wrapped;
|
||||
@ -245,9 +223,7 @@ namespace graphs
|
||||
++tempindex;
|
||||
}
|
||||
|
||||
const string temp = words.substr(index - linelen, templinelen);
|
||||
|
||||
const size_t width = strcol(temp.c_str());
|
||||
const size_t width = strcol(words.substr(index - linelen, templinelen));
|
||||
|
||||
if (width >= line_length)
|
||||
{
|
||||
@ -343,7 +319,8 @@ namespace graphs
|
||||
strm << setprecision(0) << fixed << number;
|
||||
}
|
||||
|
||||
strm << (power < graphs::size(suffix_power_char) ? suffix_power_char[power] : "(error)");
|
||||
// power == 1 and scale == units_scale_SI ? "k" :
|
||||
strm << (power < size(suffix_power_char) ? suffix_power_char[power] : "(error)");
|
||||
|
||||
if (scale == units_scale_IEC_I and power > 0)
|
||||
strm << "i";
|
||||
@ -360,7 +337,7 @@ namespace graphs
|
||||
long double intpart = 0;
|
||||
const long double fractionpart = abs(modf(number, &intpart));
|
||||
|
||||
for (size_t i = 0; i < graphs::size(fractions) and !output; ++i)
|
||||
for (size_t i = 0; i < size(fractions) and !output; ++i)
|
||||
{
|
||||
if (abs(fractionpart - fractionvalues[i]) <= DBL_EPSILON * n)
|
||||
{
|
||||
@ -377,7 +354,7 @@ namespace graphs
|
||||
|
||||
if (n > DBL_EPSILON)
|
||||
{
|
||||
for (size_t i = 0; i < graphs::size(constants) and !output; ++i)
|
||||
for (size_t i = 0; i < size(constants) and !output; ++i)
|
||||
{
|
||||
if (abs(fmod(number, constantvalues[i])) <= DBL_EPSILON * n)
|
||||
{
|
||||
@ -442,7 +419,7 @@ namespace graphs
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t length = strcol(strm.str().c_str());
|
||||
const size_t length = strcol(strm.str());
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -450,7 +427,7 @@ namespace graphs
|
||||
// Output graph
|
||||
inline int graph(const size_t height, const size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const vector<vector<unsigned short>> &array, const options &aoptions)
|
||||
{
|
||||
if (!graphs::size(array))
|
||||
if (!size(array))
|
||||
return 1;
|
||||
|
||||
const bool border = aoptions.border;
|
||||
@ -461,10 +438,10 @@ namespace graphs
|
||||
const type_type type = aoptions.type;
|
||||
const char *const title = aoptions.title;
|
||||
|
||||
if (height == 0)
|
||||
if (!height)
|
||||
return 1;
|
||||
|
||||
if (width == 0)
|
||||
if (!width)
|
||||
return 1;
|
||||
|
||||
struct winsize w;
|
||||
@ -580,7 +557,7 @@ namespace graphs
|
||||
}
|
||||
else if (axaxis)
|
||||
{
|
||||
if (i == 0)
|
||||
if (!i)
|
||||
{
|
||||
cout << astyle[4];
|
||||
output = true;
|
||||
@ -611,7 +588,7 @@ namespace graphs
|
||||
}
|
||||
else if (ayaxis)
|
||||
{
|
||||
if (j == 0)
|
||||
if (!j)
|
||||
{
|
||||
cout << astyle[2];
|
||||
output = true;
|
||||
@ -645,7 +622,7 @@ namespace graphs
|
||||
cout << '0';
|
||||
output = true;
|
||||
}
|
||||
else if ((xaxis <= (width - aj) ? j >= (width - aj) : j == 0) and yaxislabel and axislabel)
|
||||
else if ((xaxis <= (width - aj) ? j >= (width - aj) : !j) and yaxislabel and axislabel)
|
||||
{
|
||||
cout << 'x';
|
||||
output = true;
|
||||
@ -691,7 +668,7 @@ namespace graphs
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((yaxis >= ai ? i == 0 : i >= (height - ai)) and xaxislabel and axislabel)
|
||||
else if ((yaxis >= ai ? !i : i >= (height - ai)) and xaxislabel and axislabel)
|
||||
{
|
||||
cout << 'y';
|
||||
output = true;
|
||||
@ -720,7 +697,7 @@ namespace graphs
|
||||
if (type == type_histogram)
|
||||
{
|
||||
if (!dot)
|
||||
dot = (graphs::size(bars) - l) - 1;
|
||||
dot = (size(bars) - l) - 1;
|
||||
}
|
||||
else if (type == type_block)
|
||||
dot += blockvalues[k][l];
|
||||
@ -776,7 +753,7 @@ namespace graphs
|
||||
template <typename T>
|
||||
int histogram(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const T &aarray, const options &aoptions = {})
|
||||
{
|
||||
if (!graphs::size(aarray))
|
||||
if (!size(aarray))
|
||||
return 1;
|
||||
|
||||
const color_type color = aoptions.color;
|
||||
@ -784,10 +761,10 @@ namespace graphs
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
if (height == 0)
|
||||
if (!height)
|
||||
height = w.ws_row * 4;
|
||||
|
||||
if (width == 0)
|
||||
if (!width)
|
||||
width = w.ws_col * 2;
|
||||
|
||||
if (aoptions.check)
|
||||
@ -811,12 +788,12 @@ namespace graphs
|
||||
height *= 2;
|
||||
width /= 2;
|
||||
|
||||
if (xmin == 0 and xmax == 0)
|
||||
if (!xmin and !xmax)
|
||||
{
|
||||
const auto &minmax = minmax_element(begin(aarray), end(aarray));
|
||||
const auto &[amin, amax] = minmax_element(cbegin(aarray), cend(aarray));
|
||||
|
||||
xmin = *minmax.first;
|
||||
xmax = *minmax.second;
|
||||
xmin = *amin;
|
||||
xmax = *amax;
|
||||
}
|
||||
|
||||
if (xmin >= xmax)
|
||||
@ -838,12 +815,12 @@ namespace graphs
|
||||
}
|
||||
}
|
||||
|
||||
if (ymin == 0 and ymax == 0)
|
||||
if (!ymin and !ymax)
|
||||
{
|
||||
const auto &minmax = minmax_element(histogram.begin(), histogram.end());
|
||||
const auto &[amin, amax] = minmax_element(histogram.cbegin(), histogram.cend());
|
||||
|
||||
ymin = *minmax.first;
|
||||
ymax = *minmax.second;
|
||||
ymin = *amin;
|
||||
ymax = *amax;
|
||||
}
|
||||
|
||||
if (ymin >= ymax)
|
||||
@ -859,7 +836,7 @@ namespace graphs
|
||||
|
||||
const unsigned acolor = color + 1;
|
||||
|
||||
for (size_t x = 0; x < graphs::size(histogram); ++x)
|
||||
for (size_t x = 0; x < size(histogram); ++x)
|
||||
{
|
||||
const size_t ay = histogram[x];
|
||||
|
||||
@ -867,7 +844,8 @@ namespace graphs
|
||||
aaarray[x][y] = acolor;
|
||||
}
|
||||
|
||||
if (aoptions.type != type_histogram) {
|
||||
if (aoptions.type != type_histogram)
|
||||
{
|
||||
options hist_options = aoptions;
|
||||
hist_options.type = type_histogram;
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, hist_options);
|
||||
@ -878,7 +856,7 @@ namespace graphs
|
||||
template <typename T>
|
||||
int histogram(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const size_t rows, T *aarray, const options &aoptions = {})
|
||||
{
|
||||
if (rows == 0)
|
||||
if (!rows)
|
||||
return 1;
|
||||
|
||||
vector<T> aaarray(rows);
|
||||
@ -891,12 +869,12 @@ namespace graphs
|
||||
template <typename T>
|
||||
int plots(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const T &arrays, const options &aoptions = {})
|
||||
{
|
||||
if (!graphs::size(arrays))
|
||||
if (!size(arrays))
|
||||
return 1;
|
||||
|
||||
if (!all_of(cbegin(arrays), cend(arrays), [](const auto &array)
|
||||
{ return all_of(cbegin(array), cend(array), [](const auto &x)
|
||||
{ return graphs::size(x) == 2; }); }))
|
||||
{ return size(x) == 2; }); }))
|
||||
{
|
||||
cerr << "Error: The arrays must have two columns.\n";
|
||||
return 1;
|
||||
@ -907,10 +885,10 @@ namespace graphs
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
if (height == 0)
|
||||
if (!height)
|
||||
height = w.ws_row * 4;
|
||||
|
||||
if (width == 0)
|
||||
if (!width)
|
||||
width = w.ws_col * 2;
|
||||
|
||||
if (aoptions.check)
|
||||
@ -934,24 +912,24 @@ namespace graphs
|
||||
if (aoptions.type == type_block)
|
||||
height /= 2;
|
||||
|
||||
if (xmin == 0 and xmax == 0)
|
||||
if (!xmin and !xmax)
|
||||
{
|
||||
const auto compare = [](const auto &a, const auto &b)
|
||||
{ return a[0] < b[0]; };
|
||||
const auto &result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto ¤t, const auto &array)
|
||||
{ const auto &minmax = minmax_element(begin(array), end(array), compare); return make_pair(min(current.first, *minmax.first, compare), max(current.second, *minmax.second, compare)); });
|
||||
xmin = result.first[0];
|
||||
xmax = result.second[0];
|
||||
const auto &[amin, amax] = accumulate(cbegin(arrays), cend(arrays), make_pair(arrays[0][0], arrays[0][0]), [&compare](const auto ¤t, const auto &array)
|
||||
{ const auto &[amin, amax] = minmax_element(cbegin(array), cend(array), compare); return make_pair(min(current.first, *amin, compare), max(current.second, *amax, compare)); });
|
||||
xmin = amin[0];
|
||||
xmax = amax[0];
|
||||
}
|
||||
|
||||
if (ymin == 0 and ymax == 0)
|
||||
if (!ymin and !ymax)
|
||||
{
|
||||
const auto compare = [](const auto &a, const auto &b)
|
||||
{ return a[1] < b[1]; };
|
||||
const auto &result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto ¤t, const auto &array)
|
||||
{ const auto &minmax = minmax_element(begin(array), end(array), compare); return make_pair(min(current.first, *minmax.first, compare), max(current.second, *minmax.second, compare)); });
|
||||
ymin = result.first[1];
|
||||
ymax = result.second[1];
|
||||
const auto &[amin, amax] = accumulate(cbegin(arrays), cend(arrays), make_pair(arrays[0][0], arrays[0][0]), [&compare](const auto ¤t, const auto &array)
|
||||
{ const auto &[amin, amax] = minmax_element(cbegin(array), cend(array), compare); return make_pair(min(current.first, *amin, compare), max(current.second, *amax, compare)); });
|
||||
ymin = amin[1];
|
||||
ymax = amax[1];
|
||||
}
|
||||
|
||||
if (xmin >= xmax)
|
||||
@ -973,12 +951,12 @@ namespace graphs
|
||||
|
||||
vector<vector<unsigned short>> aarray(width, vector<unsigned short>(height, 0));
|
||||
|
||||
for (size_t j = 0; j < graphs::size(arrays); ++j)
|
||||
for (size_t j = 0; j < size(arrays); ++j)
|
||||
{
|
||||
const auto &array = arrays[j];
|
||||
const unsigned acolor = graphs::size(arrays) == 1 ? color + 1 : (j % (graphs::size(colors) - 2)) + 3;
|
||||
const unsigned acolor = size(arrays) == 1 ? color + 1 : (j % (size(colors) - 2)) + 3;
|
||||
|
||||
for (size_t i = 0; i < graphs::size(array); ++i)
|
||||
for (size_t i = 0; i < size(array); ++i)
|
||||
{
|
||||
const auto &x = array[i][0], &y = array[i][1];
|
||||
|
||||
@ -987,10 +965,10 @@ namespace graphs
|
||||
const size_t ax = (x / xstep) + xaxis;
|
||||
const size_t ay = (yaxis - (y / ystep)) - 1;
|
||||
|
||||
for (const auto &mark : marks[aoptions.mark])
|
||||
for (const auto &[ix, iy] : marks[aoptions.mark])
|
||||
{
|
||||
const size_t x = ax + mark[0];
|
||||
const size_t y = ay + mark[1];
|
||||
const size_t x = ax + ix;
|
||||
const size_t y = ay + iy;
|
||||
|
||||
if (x < width and y < height)
|
||||
{
|
||||
@ -1023,7 +1001,7 @@ namespace graphs
|
||||
template <typename T>
|
||||
int plot(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const size_t rows, T **aarray, const options &aoptions = {})
|
||||
{
|
||||
if (rows == 0)
|
||||
if (!rows)
|
||||
return 1;
|
||||
|
||||
const size_t columns = 2;
|
||||
@ -1040,16 +1018,16 @@ namespace graphs
|
||||
{
|
||||
const color_type color = aoptions.color;
|
||||
|
||||
if (numfunctions == 0)
|
||||
if (!numfunctions)
|
||||
return 1;
|
||||
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
if (height == 0)
|
||||
if (!height)
|
||||
height = w.ws_row * 4;
|
||||
|
||||
if (width == 0)
|
||||
if (!width)
|
||||
width = w.ws_col * 2;
|
||||
|
||||
if (aoptions.check)
|
||||
@ -1097,7 +1075,7 @@ namespace graphs
|
||||
|
||||
for (size_t j = 0; j < numfunctions; ++j)
|
||||
{
|
||||
const unsigned short acolor = numfunctions == 1 ? color + 1 : (j % (graphs::size(colors) - 2)) + 3;
|
||||
const unsigned short acolor = numfunctions == 1 ? color + 1 : (j % (size(colors) - 2)) + 3;
|
||||
|
||||
for (size_t i = 0; i < rows * xres; ++i)
|
||||
{
|
||||
@ -1140,5 +1118,4 @@ namespace graphs
|
||||
|
||||
return functions(height, width, xmin, xmax, ymin, ymax, 1, afunctions, aoptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -173,10 +173,8 @@ def strcol(astr: str) -> int:
|
||||
"""Returns the number of columns that the given string would take up if printed."""
|
||||
width = wcswidth(astr)
|
||||
if width == -1:
|
||||
print(
|
||||
"\nError! wcswidth failed. Nonprintable wide character.",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
msg = "wcswidth failed. Nonprintable wide character."
|
||||
raise ValueError(msg)
|
||||
return width
|
||||
# return len(astr)
|
||||
|
||||
@ -305,10 +303,10 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
if not array:
|
||||
return 1
|
||||
|
||||
if height == 0:
|
||||
if not height:
|
||||
return 1
|
||||
|
||||
if width == 0:
|
||||
if not width:
|
||||
return 1
|
||||
|
||||
w = shutil.get_terminal_size()
|
||||
@ -395,7 +393,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
strm += astyle[6]
|
||||
output = True
|
||||
elif axaxis:
|
||||
if i == 0:
|
||||
if not i:
|
||||
strm += astyle[4]
|
||||
output = True
|
||||
elif i >= height - ai:
|
||||
@ -414,7 +412,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
strm += astyle[1]
|
||||
output = True
|
||||
elif ayaxis:
|
||||
if j == 0:
|
||||
if not j:
|
||||
strm += astyle[2]
|
||||
output = True
|
||||
elif j >= width - aj:
|
||||
@ -435,7 +433,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
elif yaxislabel and xaxislabel and axistick and axisunitslabel and ymin <= 0 <= ymax and xmin <= 0 <= xmax:
|
||||
strm += "0"
|
||||
output = True
|
||||
elif (j >= width - aj if xaxis <= width - aj else j == 0) and yaxislabel and axislabel:
|
||||
elif (j >= width - aj if xaxis <= width - aj else not j) and yaxislabel and axislabel:
|
||||
strm += "x"
|
||||
output = True
|
||||
elif yaxislabel and axistick and axisunitslabel:
|
||||
@ -470,7 +468,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
output = True
|
||||
else:
|
||||
j += aj
|
||||
elif (i == 0 if yaxis >= ai else i >= height - ai) and xaxislabel and axislabel:
|
||||
elif (not i if yaxis >= ai else i >= height - ai) and xaxislabel and axislabel:
|
||||
strm += "y"
|
||||
output = True
|
||||
elif ylabellength and (xaxislabel if xaxis < aj else j < xaxis - ylabellength and j + aj >= xaxis - ylabellength) and (yaxis >= ai or i < height - ai) and axistick and axisunitslabel:
|
||||
@ -535,10 +533,10 @@ def histogram(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
||||
|
||||
w = shutil.get_terminal_size()
|
||||
|
||||
if height == 0:
|
||||
if not height:
|
||||
height = w.lines * 4
|
||||
|
||||
if width == 0:
|
||||
if not width:
|
||||
width = w.columns * 2
|
||||
|
||||
if check:
|
||||
@ -558,7 +556,7 @@ def histogram(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
||||
height *= 2
|
||||
width //= 2
|
||||
|
||||
if xmin == xmax == 0:
|
||||
if not xmin and not xmax:
|
||||
xmin = min(aarray)
|
||||
xmax = max(aarray)
|
||||
|
||||
@ -575,7 +573,7 @@ def histogram(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
||||
index = int((x - xmin) / xstep)
|
||||
histogram[index] += 1
|
||||
|
||||
if ymin == ymax == 0:
|
||||
if not ymin and not ymax:
|
||||
ymin = min(histogram)
|
||||
ymax = max(histogram)
|
||||
|
||||
@ -610,10 +608,10 @@ def plots(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
|
||||
w = shutil.get_terminal_size()
|
||||
|
||||
if height == 0:
|
||||
if not height:
|
||||
height = w.lines * 4
|
||||
|
||||
if width == 0:
|
||||
if not width:
|
||||
width = w.columns * 2
|
||||
|
||||
if check:
|
||||
@ -633,11 +631,11 @@ def plots(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
if atype == type_types.block:
|
||||
height //= 2
|
||||
|
||||
if xmin == xmax == 0:
|
||||
if not xmin and not xmax:
|
||||
xmin = min(x for aarray in aarrays for x, y in aarray)
|
||||
xmax = max(x for aarray in aarrays for x, y in aarray)
|
||||
|
||||
if ymin == ymax == 0:
|
||||
if not ymin and not ymax:
|
||||
ymin = min(y for aarray in aarrays for x, y in aarray)
|
||||
ymax = max(y for aarray in aarrays for x, y in aarray)
|
||||
|
||||
@ -690,10 +688,10 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
||||
|
||||
w = shutil.get_terminal_size()
|
||||
|
||||
if height == 0:
|
||||
if not height:
|
||||
height = w.lines * 4
|
||||
|
||||
if width == 0:
|
||||
if not width:
|
||||
width = w.columns * 2
|
||||
|
||||
if check:
|
||||
|
@ -59,10 +59,8 @@ def strcol(astr: str) -> int:
|
||||
astr = ansi.sub("", astr)
|
||||
width = wcswidth(astr)
|
||||
if width == -1:
|
||||
print(
|
||||
"\nError! wcswidth failed. Nonprintable wide character.",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
msg = "wcswidth failed. Nonprintable wide character."
|
||||
raise ValueError(msg)
|
||||
return width
|
||||
# return len(astr)
|
||||
|
||||
@ -106,7 +104,7 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
|
||||
strm += astyle[0] * (2 * padding + columnwidth[j])
|
||||
|
||||
if j < columns - 1:
|
||||
if cellborder or headerrow or (j == 0 and headercolumn):
|
||||
if cellborder or headerrow or (not j and headercolumn):
|
||||
strm += astyle[3]
|
||||
else:
|
||||
strm += astyle[0]
|
||||
@ -118,14 +116,14 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
|
||||
strm += astyle[1]
|
||||
|
||||
for j in range(columns):
|
||||
if (j > 0 and cellborder) or (i == 0 and j > 0 and headerrow) or (j == 1 and headercolumn):
|
||||
if (j > 0 and cellborder) or (not i and j > 0 and headerrow) or (j == 1 and headercolumn):
|
||||
strm += astyle[1]
|
||||
elif j > 0 and (tableborder or (i > 0 and headerrow) or headercolumn):
|
||||
strm += " "
|
||||
|
||||
awidth = columnwidth[j] - (strcol(array[i][j]) - len(array[i][j]))
|
||||
|
||||
if (i == 0 and headerrow) or (j == 0 and headercolumn):
|
||||
if (not i and headerrow) or (not j and headercolumn):
|
||||
strm += (" " * padding) + "\033[1m" + array[i][j].center(awidth) + "\033[22m" + (" " * padding)
|
||||
else:
|
||||
strm += (" " * padding) + (f"{array[i][j]:{awidth}}" if alignment is None else array[i][j].rjust(awidth) if alignment else array[i][j].ljust(awidth)) + (" " * padding)
|
||||
@ -136,29 +134,29 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
|
||||
if i < rows - 1 or tableborder:
|
||||
strm += "\n"
|
||||
|
||||
if (i < rows - 1 and cellborder) or (i == 0 and headerrow) or (i < rows - 1 and headercolumn):
|
||||
if tableborder and (cellborder or (i == 0 and headerrow) or headercolumn):
|
||||
if (i < rows - 1 and cellborder) or (not i and headerrow) or (i < rows - 1 and headercolumn):
|
||||
if tableborder and (cellborder or (not i and headerrow) or headercolumn):
|
||||
strm += astyle[5]
|
||||
|
||||
for j in range(columns):
|
||||
if cellborder or (i == 0 and headerrow) or (j == 0 and headercolumn):
|
||||
if cellborder or (not i and headerrow) or (not j and headercolumn):
|
||||
strm += astyle[0] * (2 * padding + columnwidth[j])
|
||||
elif headercolumn:
|
||||
strm += " " * (2 * padding + columnwidth[j])
|
||||
|
||||
if j < columns - 1:
|
||||
if cellborder or ((i == 0 and headerrow) and (j == 0 and headercolumn)):
|
||||
if cellborder or ((not i and headerrow) and (not j and headercolumn)):
|
||||
strm += astyle[6]
|
||||
elif i == 0 and headerrow:
|
||||
elif not i and headerrow:
|
||||
strm += astyle[9]
|
||||
elif headercolumn:
|
||||
if j == 0:
|
||||
if not j:
|
||||
strm += astyle[7]
|
||||
else:
|
||||
strm += " "
|
||||
|
||||
if tableborder:
|
||||
if cellborder or (i == 0 and headerrow):
|
||||
if cellborder or (not i and headerrow):
|
||||
strm += astyle[7]
|
||||
elif headercolumn:
|
||||
strm += astyle[1]
|
||||
@ -172,7 +170,7 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
|
||||
strm += astyle[0] * (2 * padding + columnwidth[j])
|
||||
|
||||
if j < columns - 1:
|
||||
if cellborder or (j == 0 and headercolumn):
|
||||
if cellborder or (not j and headercolumn):
|
||||
strm += astyle[9]
|
||||
else:
|
||||
strm += astyle[0]
|
||||
|
@ -5,6 +5,7 @@
|
||||
# Run: python3 -OO test.py
|
||||
|
||||
import math
|
||||
import operator
|
||||
import random
|
||||
import sys
|
||||
|
||||
@ -87,7 +88,7 @@ print("\nOutput sorted array as table\n")
|
||||
array = ([random.randint(0, sys.maxsize)
|
||||
for j in range(columns)] for i in range(rows))
|
||||
sortdimension = 0
|
||||
array = sorted(array, key=lambda x: x[sortdimension])
|
||||
array = sorted(array, key=operator.itemgetter(sortdimension))
|
||||
for style in tables.style_types:
|
||||
tables.array(array, None, None, style=style)
|
||||
|
||||
|
56
tables.cpp
56
tables.cpp
@ -1,6 +1,6 @@
|
||||
// Teal Dulcet, CS546
|
||||
|
||||
// Compile: g++ -std=c++14 -Wall -g -O3 tables.cpp -o tables
|
||||
// Compile: g++ -std=gnu++17 -Wall -g -O3 tables.cpp -o tables
|
||||
|
||||
// Run: ./tables
|
||||
|
||||
@ -216,7 +216,7 @@ int main()
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// tables::options aoptions{.headerrow = true, .headercolumn = true};
|
||||
// tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
@ -232,10 +232,7 @@ int main()
|
||||
{"Header column 4", "Data 9", "Data 10", "Data 11", "Data 12"},
|
||||
{"Header column 5", "Data 13", "Data 14", "Data 15", "Data 16"}}};
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// tables::options aoptions{.headerrow = true, .headercolumn = true};
|
||||
tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
@ -259,10 +256,7 @@ int main()
|
||||
const char *const headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
||||
const char *const headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// tables::options aoptions{.headerrow = true, .headercolumn = true};
|
||||
tables::options aoptions = {.headerrow = true, .headercolumn = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
@ -295,7 +289,7 @@ int main()
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.cellborder = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.headerrow = true, .headercolumn = true, .cellborder = true, .style = style};
|
||||
// tables::options aoptions = {.headerrow = true, .headercolumn = true, .cellborder = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -304,7 +298,7 @@ int main()
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.headerrow = true, .headercolumn = true, .style = style};
|
||||
// tables::options aoptions = {.headerrow = true, .headercolumn = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -315,7 +309,7 @@ int main()
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.headerrow = true, .style = style};
|
||||
// tables::options aoptions = {.headerrow = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -326,7 +320,7 @@ int main()
|
||||
tables::options aoptions;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.headercolumn = true, .style = style};
|
||||
// tables::options aoptions = {.headercolumn = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -337,7 +331,7 @@ int main()
|
||||
tables::options aoptions;
|
||||
aoptions.cellborder = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.cellborder = true, .style = style};
|
||||
// tables::options aoptions = {.cellborder = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -348,7 +342,7 @@ int main()
|
||||
tables::options aoptions;
|
||||
aoptions.tableborder = false;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.tableborder = false, .style = style};
|
||||
// tables::options aoptions = {.tableborder = false, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -358,7 +352,7 @@ int main()
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.tableborder = false, .headerrow = true, .headercolumn = true, .style = style};
|
||||
// tables::options aoptions = {.tableborder = false, .headerrow = true, .headercolumn = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -370,7 +364,7 @@ int main()
|
||||
aoptions.tableborder = false;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.tableborder = false, .headerrow = true, .style = style};
|
||||
// tables::options aoptions = {.tableborder = false, .headerrow = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -382,7 +376,7 @@ int main()
|
||||
aoptions.tableborder = false;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.tableborder = false, .headercolumn = true, .style = style};
|
||||
// tables::options aoptions = {.tableborder = false, .headercolumn = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -394,7 +388,7 @@ int main()
|
||||
aoptions.tableborder = false;
|
||||
aoptions.cellborder = true;
|
||||
aoptions.style = style;
|
||||
// tables::options aoptions{.tableborder = false, .cellborder = true, .style = style};
|
||||
// tables::options aoptions = {.tableborder = false, .cellborder = true, .style = style};
|
||||
|
||||
tables::array(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
@ -412,7 +406,7 @@ int main()
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.boolalpha = true;
|
||||
// tables::options aoptions{.boolalpha = true};
|
||||
// tables::options aoptions = {.boolalpha = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
@ -509,9 +503,7 @@ int main()
|
||||
// Output single function as table
|
||||
cout << "\nOutput single function as table\n\n";
|
||||
{
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tables::options aoptions{.headerrow = true};
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
@ -524,9 +516,7 @@ int main()
|
||||
const function<long double(long double)> afunction = [](auto x)
|
||||
{ return x + 1; };
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tables::options aoptions{.headerrow = true};
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
@ -540,15 +530,13 @@ int main()
|
||||
{
|
||||
function<long double(long double)> functions[] = {function1, function2};
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tables::options aoptions{.headerrow = true};
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
aoptions.style = style;
|
||||
|
||||
tables::functions(xmin, xmax, xstep, tables::size(functions), functions, aoptions);
|
||||
tables::functions(xmin, xmax, xstep, size(functions), functions, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -557,15 +545,13 @@ int main()
|
||||
[](auto x)
|
||||
{ return pow(x, 2); }};
|
||||
|
||||
tables::options aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tables::options aoptions{.headerrow = true};
|
||||
tables::options aoptions = {.headerrow = true};
|
||||
|
||||
for (const tables::style_type style : tables::style_types)
|
||||
{
|
||||
aoptions.style = style;
|
||||
|
||||
tables::functions(xmin, xmax, xstep, tables::size(functions), functions, aoptions);
|
||||
tables::functions(xmin, xmax, xstep, size(functions), functions, aoptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
113
tables.hpp
113
tables.hpp
@ -65,55 +65,33 @@ namespace tables
|
||||
bool check = true;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t size(const T &array)
|
||||
{
|
||||
return distance(cbegin(array), cend(array));
|
||||
}
|
||||
|
||||
// Number of columns needed to represent the string
|
||||
// Adapted from: https://stackoverflow.com/a/31124065
|
||||
inline int strcol(const char *str)
|
||||
inline int strcol(const string &astr)
|
||||
{
|
||||
const string astr = regex_replace(str, ansi, "");
|
||||
str = astr.c_str();
|
||||
const string str = regex_replace(astr, ansi, "");
|
||||
|
||||
size_t length = strlen(str);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
if (iscntrl(str[i]))
|
||||
for (const char c : str)
|
||||
if (iscntrl(c))
|
||||
{
|
||||
cerr << "\nError! Control character in string.\n";
|
||||
cout << "Control character: " << (int)str[i] << '\n';
|
||||
cerr << "\nError: Control character in string.\n";
|
||||
cout << "Control character: " << (int)c << '\n';
|
||||
}
|
||||
|
||||
length = mbstowcs(nullptr, str, 0);
|
||||
size_t length = mbstowcs(nullptr, str.c_str(), 0);
|
||||
if (length == static_cast<size_t>(-1))
|
||||
{
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
exit(1);
|
||||
}
|
||||
throw range_error("Error: mbstowcs failed. Invalid multibyte character.");
|
||||
++length;
|
||||
|
||||
auto *wcstring = new wchar_t[length];
|
||||
wstring wcstring(length, L'\0');
|
||||
|
||||
if (mbstowcs(wcstring, str, length) == static_cast<size_t>(-1))
|
||||
{
|
||||
if (wcstring)
|
||||
delete[] wcstring;
|
||||
if (mbstowcs(wcstring.data(), str.c_str(), length) == static_cast<size_t>(-1))
|
||||
throw range_error("Error: mbstowcs failed. Invalid multibyte character.");
|
||||
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const int width = wcswidth(wcstring, length);
|
||||
const int width = wcswidth(wcstring.c_str(), length);
|
||||
if (width == -1)
|
||||
{
|
||||
cerr << "\nError! wcswidth failed. Nonprintable wide character.\n";
|
||||
exit(1);
|
||||
}
|
||||
throw range_error("Error: wcswidth failed. Nonprintable wide character.");
|
||||
|
||||
if (wcstring)
|
||||
delete[] wcstring;
|
||||
|
||||
return width;
|
||||
}
|
||||
@ -121,7 +99,7 @@ namespace tables
|
||||
// Word wrap
|
||||
// Source: https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0
|
||||
// Adapted from: https://stackoverflow.com/a/42016346 and https://stackoverflow.com/a/13094734
|
||||
inline string wrap(const char *const str, const size_t line_length)
|
||||
inline string wrap(const string &str, const size_t line_length)
|
||||
{
|
||||
string words = str;
|
||||
string wrapped;
|
||||
@ -145,9 +123,7 @@ namespace tables
|
||||
++tempindex;
|
||||
}
|
||||
|
||||
const string temp = words.substr(index - linelen, templinelen);
|
||||
|
||||
const size_t width = strcol(temp.c_str());
|
||||
const size_t width = strcol(words.substr(index - linelen, templinelen));
|
||||
|
||||
if (width >= line_length)
|
||||
{
|
||||
@ -171,7 +147,7 @@ namespace tables
|
||||
template <typename T>
|
||||
int table(const vector<vector<basic_string<T>>> &array, const options &aoptions)
|
||||
{
|
||||
if (!tables::size(array))
|
||||
if (!size(array))
|
||||
return 1;
|
||||
|
||||
const bool headerrow = aoptions.headerrow;
|
||||
@ -192,7 +168,7 @@ namespace tables
|
||||
{
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
{
|
||||
const int cellwidth = strcol(array[i][j].c_str());
|
||||
const int cellwidth = strcol(array[i][j]);
|
||||
if (cellwidth > columnwidth[j])
|
||||
columnwidth[j] = cellwidth;
|
||||
}
|
||||
@ -236,7 +212,7 @@ namespace tables
|
||||
|
||||
if (j < (columns - 1))
|
||||
{
|
||||
if (cellborder or headerrow or (j == 0 and headercolumn))
|
||||
if (cellborder or headerrow or (!j and headercolumn))
|
||||
cout << astyle[3];
|
||||
else
|
||||
cout << astyle[0];
|
||||
@ -253,14 +229,14 @@ namespace tables
|
||||
|
||||
for (size_t j = 0; j < columns; ++j)
|
||||
{
|
||||
if ((j and cellborder) or (i == 0 and j and headerrow) or (j == 1 and headercolumn))
|
||||
if ((j and cellborder) or (!i and j and headerrow) or (j == 1 and headercolumn))
|
||||
cout << astyle[1];
|
||||
else if (j and (tableborder or (i and headerrow) or headercolumn))
|
||||
cout << ' ';
|
||||
|
||||
const int difference = columnwidth[j] - strcol(array[i][j].c_str());
|
||||
const int difference = columnwidth[j] - strcol(array[i][j]);
|
||||
|
||||
if ((i == 0 and headerrow) or (j == 0 and headercolumn))
|
||||
if ((!i and headerrow) or (!j and headercolumn))
|
||||
{
|
||||
const int apadding = (difference / 2);
|
||||
|
||||
@ -278,17 +254,17 @@ namespace tables
|
||||
if (i < (rows - 1) or tableborder)
|
||||
cout << '\n';
|
||||
|
||||
if ((i < (rows - 1) and cellborder) or (i == 0 and headerrow) or (i < (rows - 1) and headercolumn))
|
||||
if ((i < (rows - 1) and cellborder) or (!i and headerrow) or (i < (rows - 1) and headercolumn))
|
||||
{
|
||||
if (tableborder)
|
||||
{
|
||||
if (cellborder or (i == 0 and headerrow) or headercolumn)
|
||||
if (cellborder or (!i and headerrow) or headercolumn)
|
||||
cout << astyle[5];
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < columns; ++j)
|
||||
{
|
||||
if (cellborder or (i == 0 and headerrow) or (j == 0 and headercolumn))
|
||||
if (cellborder or (!i and headerrow) or (!j and headercolumn))
|
||||
for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k)
|
||||
cout << astyle[0];
|
||||
else if (headercolumn)
|
||||
@ -296,13 +272,13 @@ namespace tables
|
||||
|
||||
if (j < (columns - 1))
|
||||
{
|
||||
if (cellborder or ((i == 0 and headerrow) and (j == 0 and headercolumn)))
|
||||
if (cellborder or ((!i and headerrow) and (!j and headercolumn)))
|
||||
cout << astyle[6];
|
||||
else if (i == 0 and headerrow)
|
||||
else if (!i and headerrow)
|
||||
cout << astyle[9];
|
||||
else if (headercolumn)
|
||||
{
|
||||
if (j == 0)
|
||||
if (!j)
|
||||
cout << astyle[7];
|
||||
else
|
||||
cout << ' ';
|
||||
@ -312,7 +288,7 @@ namespace tables
|
||||
|
||||
if (tableborder)
|
||||
{
|
||||
if (cellborder or (i == 0 and headerrow))
|
||||
if (cellborder or (!i and headerrow))
|
||||
cout << astyle[7];
|
||||
else if (headercolumn)
|
||||
cout << astyle[1];
|
||||
@ -333,7 +309,7 @@ namespace tables
|
||||
|
||||
if (j < (columns - 1))
|
||||
{
|
||||
if (cellborder or (j == 0 and headercolumn))
|
||||
if (cellborder or (!j and headercolumn))
|
||||
cout << astyle[9];
|
||||
else
|
||||
cout << astyle[0];
|
||||
@ -352,17 +328,17 @@ namespace tables
|
||||
template <typename T1, typename T2>
|
||||
int array(const T1 &aarray, T2 headerrow[] = nullptr, T2 headercolumn[] = nullptr, const options &aoptions = {})
|
||||
{
|
||||
if (!tables::size(aarray))
|
||||
if (!size(aarray))
|
||||
return 1;
|
||||
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
size_t rows = tables::size(aarray);
|
||||
size_t columns = tables::size(aarray[0]);
|
||||
size_t rows = size(aarray);
|
||||
size_t columns = size(aarray[0]);
|
||||
|
||||
if (!all_of(cbegin(aarray), cend(aarray), [&columns](const auto &x)
|
||||
{ return tables::size(x) == columns; }))
|
||||
{ return size(x) == columns; }))
|
||||
{
|
||||
cerr << "Error: The rows of the array must have the same number of columns.\n";
|
||||
return 1;
|
||||
@ -460,7 +436,7 @@ namespace tables
|
||||
template <typename T>
|
||||
int functions(const long double xmin, const long double xmax, const long double xstep, const size_t numfunctions, function<T(T)> functions[], const options &aoptions = {})
|
||||
{
|
||||
if (numfunctions == 0)
|
||||
if (!numfunctions)
|
||||
return 1;
|
||||
|
||||
if (xmin >= xmax)
|
||||
@ -481,9 +457,9 @@ namespace tables
|
||||
const char *const aheaderrow[] = {"x", "y"};
|
||||
// const char* const aheaderrow[] = {"", "x", "y"};
|
||||
|
||||
const size_t length = tables::size(aheaderrow);
|
||||
const size_t length = size(aheaderrow);
|
||||
|
||||
auto *headerrow = new string[columns];
|
||||
vector<string> headerrow(columns);
|
||||
|
||||
for (size_t j = 0; j < columns; ++j)
|
||||
{
|
||||
@ -500,7 +476,7 @@ namespace tables
|
||||
}
|
||||
|
||||
string *headercolumn = nullptr;
|
||||
// headercolumn = new string[rows + 1];
|
||||
// vector<string> headercolumn(rows + 1);
|
||||
|
||||
// for (size_t i = 0; i < rows + 1; ++i)
|
||||
// {
|
||||
@ -519,19 +495,7 @@ namespace tables
|
||||
aarray[i][j + 1] = (functions[j])(aarray[i][0]);
|
||||
}
|
||||
|
||||
const int code = array(aarray, headerrow, headercolumn, aoptions);
|
||||
|
||||
if (headerrow)
|
||||
{
|
||||
delete[] headerrow;
|
||||
}
|
||||
|
||||
// if (headercolumn)
|
||||
// {
|
||||
// delete[] headercolumn;
|
||||
// }
|
||||
|
||||
return code;
|
||||
return array(aarray, headerrow.data(), headercolumn, aoptions);
|
||||
}
|
||||
|
||||
// Convert single function to array and output as table
|
||||
@ -551,5 +515,4 @@ namespace tables
|
||||
|
||||
return functions(xmin, xmax, xstep, 1, afunctions, aoptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user