Files
scylladb/utils/to_string.hh
Kefu Chai c980bd54ad utils: specialize fmt::formatter<optional<>>
this is a part of a series to migrating from `operator<<(ostream&, ..)`
based formatting to fmtlib based formatting. the goal here is to enable
fmtlib to print `optional<T>` without the help of `operator<<()`.

this change also enables us to ditch more `operator<<()`s in future.
as we are relying on `operator<<(ostream&, const optional<T>&)` for
printing instances of `optional<T>`, and `operator<<(ostream&, const optional<T>&)`
in turn uses the `operator<<(ostream&, const T&)`. so, the new
specialization of `fmt::formatter<optional<>>` will remove yet
another caller of these operators.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2023-04-12 10:57:03 +08:00

179 lines
4.5 KiB
C++

/*
* Copyright (C) 2015-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <seastar/core/sstring.hh>
#include <vector>
#include <sstream>
#include <unordered_set>
#include <set>
#include <optional>
#include <list>
#include <map>
#include "seastarx.hh"
#include "utils/chunked_vector.hh"
namespace utils {
template<typename Iterator>
static inline
sstring join(sstring delimiter, Iterator begin, Iterator end) {
std::ostringstream oss;
while (begin != end) {
oss << *begin;
++begin;
if (begin != end) {
oss << delimiter;
}
}
return oss.str();
}
template<typename PrintableRange>
static inline
sstring join(sstring delimiter, const PrintableRange& items) {
return join(delimiter, items.begin(), items.end());
}
namespace internal {
template<bool NeedsComma, typename Printable>
struct print_with_comma {
const Printable& v;
};
template<bool NeedsComma, typename Printable>
std::ostream& operator<<(std::ostream& os, const print_with_comma<NeedsComma, Printable>& x) {
os << x.v;
if (NeedsComma) {
os << ", ";
}
return os;
}
} // namespace internal
} // namespace utils
namespace std {
template<typename Printable>
static inline
sstring
to_string(const std::vector<Printable>& items) {
return "[" + utils::join(", ", items) + "]";
}
template<typename Printable>
static inline
sstring
to_string(const std::set<Printable>& items) {
return "{" + utils::join(", ", items) + "}";
}
template<typename Printable>
static inline
sstring
to_string(const std::unordered_set<Printable>& items) {
return "{" + utils::join(", ", items) + "}";
}
template<typename Printable>
static inline
sstring
to_string(std::initializer_list<Printable> items) {
return "[" + utils::join(", ", std::begin(items), std::end(items)) + "]";
}
template <typename K, typename V>
std::ostream& operator<<(std::ostream& os, const std::pair<K, V>& p) {
os << "{" << p.first << ", " << p.second << "}";
return os;
}
template<typename... T, size_t... I>
std::ostream& print_tuple(std::ostream& os, const std::tuple<T...>& p, std::index_sequence<I...>) {
return ((os << "{" ) << ... << utils::internal::print_with_comma<I < sizeof...(I) - 1, T>{std::get<I>(p)}) << "}";
}
template <typename... T>
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& p) {
return print_tuple(os, p, std::make_index_sequence<sizeof...(T)>());
}
template <typename T, typename... Args>
std::ostream& operator<<(std::ostream& os, const std::unordered_set<T, Args...>& items) {
os << "{" << utils::join(", ", items) << "}";
return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& items) {
os << "{" << utils::join(", ", items) << "}";
return os;
}
template<typename T, size_t N>
std::ostream& operator<<(std::ostream& os, const std::array<T, N>& items) {
os << "{" << utils::join(", ", items) << "}";
return os;
}
template <typename K, typename V, typename... Args>
std::ostream& operator<<(std::ostream& os, const std::unordered_map<K, V, Args...>& items) {
os << "{" << utils::join(", ", items) << "}";
return os;
}
template <typename K, typename V, typename... Args>
std::ostream& operator<<(std::ostream& os, const std::map<K, V, Args...>& items) {
os << "{" << utils::join(", ", items) << "}";
return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const utils::chunked_vector<T>& items) {
os << "[" << utils::join(", ", items) << "]";
return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::list<T>& items) {
os << "[" << utils::join(", ", items) << "]";
return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::optional<T>& opt) {
if (opt) {
os << "{" << *opt << "}";
} else {
os << "{}";
}
return os;
}
std::ostream& operator<<(std::ostream& os, const std::strong_ordering& order);
std::ostream& operator<<(std::ostream& os, const std::weak_ordering& order);
std::ostream& operator<<(std::ostream& os, const std::partial_ordering& order);
} // namespace std
template<typename T>
struct fmt::formatter<std::optional<T>> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const std::optional<T>& opt, FormatContext& ctx) const {
if (opt) {
return fmt::format_to(ctx.out(), "{}", *opt);
} else {
return fmt::format_to(ctx.out(), "{{}}");
}
}
};