122 lines
4.6 KiB
C++
122 lines
4.6 KiB
C++
/** @file PrettySink.hpp
|
|
*
|
|
* @author Roland Conybeare, Jul 2026
|
|
**/
|
|
|
|
#pragma once
|
|
|
|
#include "PpState.hpp"
|
|
#include "PpTokenStreambuf.hpp"
|
|
#include <xo/ppsink/PpSink.hpp>
|
|
|
|
namespace xo {
|
|
namespace pp {
|
|
/**
|
|
* Use:
|
|
* @code
|
|
* PpConfig ppc;
|
|
* PrettySink pp(ppc, nullptr);
|
|
*
|
|
* @endcode
|
|
**/
|
|
class PrettySink : public PpSink {
|
|
public:
|
|
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
|
|
using uint32_t = std::uint32_t;
|
|
|
|
public:
|
|
/** @p cfg. pretty-printing configuration.
|
|
* @p out. if non-null, forward output to this streambuf.
|
|
**/
|
|
PrettySink(const PpConfig & cfg, std::streambuf * out);
|
|
|
|
/** move ctor.
|
|
* Needs special treatment for self-referencing pointers
|
|
* involving @ref sbuf_ and @ref pps_.
|
|
**/
|
|
PrettySink(PrettySink && rhs) noexcept;
|
|
|
|
/** move assignment disabled for now **/
|
|
PrettySink & operator=(PrettySink &&) = delete;
|
|
|
|
/** create pretty sink that writes to string **/
|
|
static PrettySink make2str(const PpConfig & cfg);
|
|
|
|
/** create pretty sink that writes to cout **/
|
|
static PrettySink make2cout(const PpConfig & cfg);
|
|
|
|
/** create temporary pretty sink, intended for a unit test **/
|
|
static PrettySink scratch_plain(std::string basename,
|
|
uint32_t logbuf_z,
|
|
uint32_t margin);
|
|
/** create temporary pretty sink **/
|
|
static PrettySink scratch_aux(std::string basename,
|
|
uint32_t logbuf_z,
|
|
uint32_t margin,
|
|
const PpStyle & style);
|
|
|
|
/** verify internal state appears consistent. **/
|
|
bool verify_ok(bool throw_flag = true) const;
|
|
|
|
/** attach (or detach, with nullptr) a streambuf that completed
|
|
* records are drained to (e.g. @c std::clog.rdbuf()).
|
|
* Forwards to the underlying @ref logbuf_.
|
|
**/
|
|
void set_dest_sbuf(std::streambuf * sb);
|
|
|
|
LogBuffer & logbuf() { return logbuf_; }
|
|
|
|
/** pretty-printed output flushed to @ref logbuf_ so far.
|
|
* Excludes content still buffered in @ref pps_.
|
|
* Valid until the next write or logbuf reset.
|
|
**/
|
|
std::string_view output() const {
|
|
auto s = logbuf_.char_used_span();
|
|
return std::string_view(s.lo(), s.hi());
|
|
}
|
|
|
|
/** visit mapped storage pools **/
|
|
void visit_pools(const MemorySizeVisitor & fn) const;
|
|
|
|
// inherited from PpSink
|
|
|
|
/* keep the inherited split()/split(spaces) and newline()
|
|
* convenience overloads visible alongside the overrides below
|
|
*/
|
|
using PpSink::split;
|
|
using PpSink::newline;
|
|
|
|
virtual std::pair<bool, std::string> copy_output() override final;
|
|
virtual PpSink & put(std::string_view x) override final;
|
|
virtual PpSink & put_with_escape(std::string_view x, bool quote_flag) override final;
|
|
virtual PpSink & begin() override final;
|
|
virtual PpSink & begin(std::int32_t offset) override final;
|
|
virtual PpSink & begin_here(std::int32_t offset) override final;
|
|
virtual PpSink & split(std::uint32_t spaces, std::int32_t offset) override final;
|
|
virtual PpSink & newline(std::int32_t offset) override final;
|
|
virtual PpSink & end() override final;
|
|
/** record boundary: emit the terminating newline, then drain the
|
|
* completed record to the attached streambuf and reclaim logbuf_.
|
|
**/
|
|
virtual PpSink & complete() override final;
|
|
/** current visible output column (enables right-aligned fields) **/
|
|
virtual std::optional<std::size_t> lpos() const override final {
|
|
return logbuf_.viz_lpos();
|
|
}
|
|
virtual PpSinkInserter stream_open(uint32_t min_z) override final;
|
|
virtual void stream_commit() override;
|
|
|
|
private:
|
|
/** Pretty printer state (+ driver) **/
|
|
PpState pps_;
|
|
|
|
/** stream buffer for writing into @ref pps_ (at the scan endpoint) **/
|
|
PpTokenStreambuf sbuf_;
|
|
|
|
/** Buffer for pretty-printed output **/
|
|
LogBuffer logbuf_;
|
|
};
|
|
} /*namespace pp*/
|
|
} /*namespace xo*/
|
|
|
|
/* end PrettySink.hpp */
|