JH-Toolkit v1.4.1
An engineering-oriented C++20 toolkit with duck-typed concepts, static design, async coroutines, and semantic containers — header-only, RTTI-free, and concurrency-friendly.
Loading...
Searching...
No Matches
stringify.h File Reference

Stream output adapters (operator<<) for POD containers and utilities. More...

#include "jh/pods/pod_like.h"
#include <ostream>
#include <sstream>
#include <iomanip>
#include "jh/typing/monostate.h"
#include "jh/serialize_io/base64.h"
#include "jh/macros/type_name.h"
#include "jh/pods/array.h"
#include "jh/pods/bits.h"
#include "jh/pods/bytes_view.h"
#include "jh/pods/optional.h"
#include "jh/pods/pair.h"
#include "jh/pods/span.h"
#include "jh/pods/string_view.h"
#include "jh/pods/tuple.h"

Go to the source code of this file.

Namespaces

namespace  jh::pod
 Aggregated entry point for Plain-Old-Data and layout-stable value utilities.
namespace  jh::typed
 Aggregated entry point for lightweight typing and semantic placeholder utilities.

Concepts

concept  jh::pod::streamable
 Checks whether a type can be streamed to std::ostream.
concept  jh::pod::streamable_pod
 Debug-only constraint for POD-like types printable to std::ostream.

Functions

template<streamable T, std::uint16_t N>
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::array< T, N > &arr)
template<std::uint16_t N>
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::array< char, N > &str)
std::ostream & jh::pod::operator<< (std::ostream &os, jh::typed::monostate &)
template<streamable T1, streamable T2>
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::pair< T1, T2 > &t)
template<streamable T>
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::optional< T > &opt)
template<std::uint16_t N>
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::bitflags< N > &flags)
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::bytes_view bv)
template<streamable T>
std::ostream & jh::pod::operator<< (std::ostream &os, const span< T > &sp)
std::ostream & jh::pod::operator<< (std::ostream &os, const string_view &sv)
template<streamable_pod Pod>
std::string jh::pod::to_string (const Pod &p)
template<streamable... Ts>
std::ostream & jh::pod::operator<< (std::ostream &os, const jh::pod::tuple< Ts... > &t)
std::ostream & jh::typed::operator<< (std::ostream &os, const jh::typed::monostate &)

Detailed Description

Stream output adapters (operator<<) for POD containers and utilities.

This header provides inline operator<< overloads for types in jh::pod, producing human-readable, debug-friendly representations on std::ostream.

Important Notes:

  • These outputs are intended for debugging, inspection, and logging.
  • They do not define a stable serialization format — output may change across compiler, platform, or version differences.
  • Do not use these printers for persistence, network protocols, or ABI-sensitive data.
  • If you need true serialization:
    • Implement your own operator<< / to_string overloads.
    • Or use jh::utils::base64 helpers, which provide proper encode/decode.
  • All overloads are declared inline. In C++17+, this does not force inlining, but provides weak linkage semantics, allowing safe inclusion in multiple translation units without ODR violations, and optional overriding elsewhere.

jh::utils::base64 (recommended for serialization)

Provides a minimal and consistent interface for encoding and decoding binary data.

  • std::string encode(const std::uint8_t *data, std::size_t len) noexcept;
    Encode raw bytes into a Base64 string.

  • std::vector<std::uint8_t> decode(const std::string &input);
    Decode a Base64 string into a new byte buffer.

  • jh::pod::bytes_view decode(const std::string &input, std::vector<std::uint8_t>& buffer);
    Decode into a provided std::vector<std::uint8_t> and return a bytes_view pointing into it (useful for flat binary operations).

  • jh::pod::string_view decode(const std::string &input, std::string& buffer);
    Decode into a provided std::string and return a string_view pointing into it (useful for text-like operations).

These APIs are suitable for real serialization and deserialization, unlike the human-readable printers in this file.

These APIs provide predictable serialization and deserialization. Use them if you need to persist or exchange data between systems.

Examples of Debug Printers

Stream adapters (operator<<) follow a layered visual convention distinguishing between owning types, view types, and semantic wrappers.

  1. Owning Types (Value Containers) — use bare structural delimiters.
    • pod::array<T, N>[1, 2, 3]
    • pod::array<char, N>"escaped\tstring"
    • pod::pair<T1, T2>{a, b}
    • pod::tuple<Ts...>(), (1,), (1, 2, 3)
  2. View Types (Non-owning References) — prefixed with their type name to clarify borrowed semantics.
    • pod::span<T>span<int>[1, 2, 3]
    • pod::string_viewstring_view"hello"
    • pod::bytes_viewbase64'...'
  3. Semantic Wrappers — printed with keywords to express meaning rather than structure.
    • pod::optional<T>value or nullopt
    • typed::monostatenull
    • pod::bitflags<N>0x'ABCD' or 0b'0101'
  4. Nesting — all printers are composable: nested POD types print recursively, preserving their delimiters at each layer.
    Example: pod::array<pod::tuple<int, int>, 2>[(1, 2), (3, 4)]