xo-indentlog: add general-purposee pretty-printing [WIP]

This commit is contained in:
Roland Conybeare 2025-07-13 21:17:13 -05:00
commit 28172fc3d6
24 changed files with 1326 additions and 121 deletions

View file

@ -3,8 +3,8 @@
set(SELF_EXECUTABLE_NAME utest.indentlog)
set(SELF_SOURCE_FILES
fixed.test.cpp quoted.test.cpp vector.test.cpp array.test.cpp timeutil.test.cpp tag.test.cpp
filename.test.cpp code_location.test.cpp function.test.cpp
indentlog_utest_main.cpp)
filename.test.cpp code_location.test.cpp function.test.cpp pretty_vector.test.cpp
indentlog_utest_main.cpp log_streambuf.test.cpp toppstr.test.cpp)
xo_add_utest_executable(${SELF_EXECUTABLE_NAME} ${SELF_SOURCE_FILES})

View file

@ -0,0 +1,107 @@
/* @file log_streambuf.test.cpp */
#include "xo/indentlog/log_streambuf.hpp"
#include "xo/indentlog/print/tag.hpp"
#include "xo/indentlog/print/quoted.hpp"
#include <catch2/catch.hpp>
//#include <sstream>
namespace ut {
using xo::log_streambuf;
TEST_CASE("log_streamhuf", "[log_streambuf]") {
std::size_t z = 16;
log_streambuf<char, std::char_traits<char>> sbuf(z);
std::ostream ss(&sbuf);
REQUIRE(sbuf.capacity() == z);
REQUIRE(sbuf.pos() == 0);
REQUIRE(sbuf.lpos() == 0);
ss << '\n';
REQUIRE(sbuf.capacity() == z);
REQUIRE(sbuf.pos() == 1);
REQUIRE(sbuf.lpos() == 1);
}
// write test cases with some random strings.
// for each string a list of tuples {ch,pos,lpos}
struct recd {
char const * text_ = nullptr;
std::size_t expect_pos_ = 0;
std::size_t expect_lpos_ = 0;
};
struct test_case {
std::size_t buf_capacity_;
std::vector<recd> steps_;
};
std::vector<test_case> s_testcase_v = {
{64, {{"\n", 1, 0},
{"abcd", 5, 4},
{"abcd\nefg\nhij", 17, 3},
{"klmnopqrstuvwxyz", 33, 19},
}},
{32, {{"\n", 1, 0},
{"abcd", 5, 4},
{"abcd\nefg\nhij", 17, 3},
{"klmnopqrstuvwxyz", 33, 19},
}},
{16, {{"\n", 1, 0},
{"abcd", 5, 4},
{"abcd\nefg\nhij", 17, 3},
{"klmnopqrstuvwxyz", 33, 19},
}},
{8, {{"\n", 1, 0},
{"abcd", 5, 4},
{"abcd\nefg\nhij", 17, 3},
{"klmnopqrstuvwxyz", 33, 19},
}},
{4, {{"\n", 1, 0},
{"abcd", 5, 4},
{"abcd\nefg\nhij", 17, 3},
{"klmnopqrstuvwxyz", 33, 19},
}},
};
TEST_CASE("log_streambuf2", "[log_streambuf]") {
using xo::xtag;
using xo::print::quot;
using xo::print::unq;
for (std::size_t i = 0; i < s_testcase_v.size(); ++i) {
INFO(tostr(xtag("i", i)));
const test_case & tc = s_testcase_v[i];
std::size_t z = tc.buf_capacity_;
log_streambuf<char> sbuf(z, true /*debug_flag*/);
std::ostream ss(&sbuf);
REQUIRE(sbuf.capacity() == z);
REQUIRE(sbuf.pos() == 0);
REQUIRE(sbuf.lpos() == 0);
REQUIRE(sbuf.lo() + sbuf.capacity() == sbuf.hi());
std::size_t j = 0;
for (const recd & r : tc.steps_) {
INFO(tostr(xtag("j", j), xtag("text", unq(r.text_))));
ss << r.text_;
REQUIRE(ss.good());
REQUIRE(sbuf.capacity() >= z);
REQUIRE(sbuf.lo() + sbuf.capacity() == sbuf.hi());
REQUIRE(sbuf.pos() == r.expect_pos_);
REQUIRE(sbuf.lpos() == r.expect_lpos_);
++j;
}
}
}
}
/* end log_streambuf.test.cpp */

View file

@ -0,0 +1,97 @@
/* @file pretty_vector.test.cpp */
#include "xo/indentlog/print/pretty.hpp"
#include "xo/indentlog/print/pretty_vector.hpp"
#include <catch2/catch.hpp>
#include <sstream>
namespace ut {
using xo::print::ppconfig;
using xo::print::ppstate_standalone;
TEST_CASE("print-upto", "[pretty]") {
std::stringstream ss;
ppconfig cfg;
ppstate_standalone pps(&ss, 0, &cfg);
REQUIRE(pps.pos() == 0);
REQUIRE(pps.lpos() == 0);
REQUIRE(pps.avail_margin() == cfg.right_margin_);
REQUIRE(pps.has_margin());
REQUIRE(pps.has_budget(cfg.right_margin_));
REQUIRE(pps.scan_no_newline(0));
}
TEST_CASE("pretty", "[pretty]") {
ppconfig ppc;
ppc.right_margin_ = 40;
ppc.indent_width_ = 2;
std::stringstream ss;
ppstate_standalone pps(&ss, 0, &ppc);
pps.pretty("hello");
REQUIRE(ss.str() == "hello");
}
TEST_CASE("prettyvec", "[pretty]") {
ppconfig ppc;
ppc.right_margin_ = 20;
ppc.indent_width_ = 2;
std::stringstream ss;
ppstate_standalone pps(&ss, 0, &ppc);
std::vector<int64_t> test = {1, 2, 3, 4, 5, 6};
pps.pretty(test);
REQUIRE(ss.str() == "[1, 2, 3, 4, 5, 6]");
}
TEST_CASE("prettyvec2", "[pretty]") {
ppconfig ppc;
ppc.right_margin_ = 10;
ppc.indent_width_ = 2;
std::stringstream ss;
ppstate_standalone pps(&ss, 0, &ppc);
std::vector<int64_t> test = {1, 2, 3, 4, 5, 6};
pps.pretty(test);
REQUIRE(ss.str() == "[\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n]");
}
TEST_CASE("prettyvec3", "[pretty]") {
ppconfig ppc;
ppc.right_margin_ = 20;
ppc.indent_width_ = 2;
std::stringstream ss;
ppstate_standalone pps(&ss, 0, &ppc);
std::vector<std::vector<int64_t>> test = {{1, 2, 3, 4}, {4, 5, 6, 7}};
pps.pretty(test);
REQUIRE(ss.str() == "[\n [1, 2, 3, 4],\n [4, 5, 6, 7]\n]");
}
TEST_CASE("prettyvec4", "[pretty]") {
ppconfig ppc;
ppc.right_margin_ = 10;
ppc.indent_width_ = 2;
std::stringstream ss;
ppstate_standalone pps(&ss, 0, &ppc);
std::vector<std::vector<int64_t>> test = {{1, 2, 3, 4}, {4, 5, 6, 7}};
pps.pretty(test);
REQUIRE(ss.str() == "[\n [\n 1,\n 2,\n 3,\n 4\n ],\n [\n 4,\n 5,\n 6,\n 7\n ]\n]");
}
}

55
utest/toppstr.test.cpp Normal file
View file

@ -0,0 +1,55 @@
/* @file toppstr.cpp */
#include "xo/indentlog/print/ppstr.hpp"
#include "xo/indentlog/print/tag.hpp"
#include <catch2/catch.hpp>
#include <sstream>
namespace ut {
using xo::toppstr;
using xo::toppstr2;
using xo::print::ppconfig;
using xo::print::ppstate;
TEST_CASE("toppstr_1", "[toppstr]") {
std::string s = toppstr();
REQUIRE(s.empty());
}
TEST_CASE("toppstr_2", "[toppstr]") {
std::string s = toppstr("hello");
REQUIRE(s == "hello");
}
TEST_CASE("toppstr_3", "[toppstr]") {
std::string s = toppstr("the", " quick", " brown", " fox", " jumps", " over", " the", " lazy", " dog");
REQUIRE(s == "the quick brown fox jumps over the lazy dog");
}
TEST_CASE("toppstr2_0", "[toppstr2]") {
ppconfig ppc;
ppc.right_margin_ = 40;
ppc.indent_width_ = 0;
std::string s = toppstr2(ppc, "the", " quick", " brown", " fox", " jumps", " over", " the", " lazy", " dog");
REQUIRE(s == "the\n quick\n brown\n fox\n jumps\n over\n the\n lazy\n dog");
}
TEST_CASE("toppstr2_1", "[toppstr2]") {
ppconfig ppc;
ppc.right_margin_ = 40;
ppc.indent_width_ = 2;
std::string s = toppstr2(ppc, "the", " quick", " brown", " fox", " jumps", " over", " the", " lazy", " dog");
REQUIRE(s == "the\n quick\n brown\n fox\n jumps\n over\n the\n lazy\n dog");
}
TEST_CASE("toppstr2_2", "[toppstr2]") {
ppconfig ppc;
ppc.right_margin_ = 40;
ppc.indent_width_ = 4;
std::string s = toppstr2(ppc, "the", " quick", " brown", " fox", " jumps", " over", " the", " lazy", " dog");
REQUIRE(s == "the\n quick\n brown\n fox\n jumps\n over\n the\n lazy\n dog");
}
}