Browse Source

Util: Add format specifier logic to container types

master
Riyyi 2 years ago
parent
commit
14e57acfd8
  1. 98
      src/util/format/formatter.h

98
src/util/format/formatter.h

@ -8,7 +8,7 @@
#include <cassert> #include <cassert>
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstdint> // int8_t, int32_t, int64_t, uint8_t, uint32_t, uintptr_t #include <cstdint> // int8_t, uint8_t, uintptr_t
#include <map> #include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
@ -66,7 +66,7 @@ template<typename T>
struct Formatter { struct Formatter {
Specifier specifier; Specifier specifier;
constexpr void parse(Parser& parser) void parse(Parser& parser)
{ {
if constexpr (std::is_same_v<T, char>) { if constexpr (std::is_same_v<T, char>) {
parser.parseSpecifier(specifier, Parser::ParameterType::Char); parser.parseSpecifier(specifier, Parser::ParameterType::Char);
@ -197,7 +197,7 @@ struct Formatter<char[N]> : Formatter<const char*> {
template<typename T> template<typename T>
struct Formatter<T*> : Formatter<uintptr_t> { struct Formatter<T*> : Formatter<uintptr_t> {
constexpr void parse(Parser& parser) void parse(Parser& parser)
{ {
parser.parseSpecifier(specifier, Parser::ParameterType::Pointer); parser.parseSpecifier(specifier, Parser::ParameterType::Pointer);
specifier.alternativeForm = true; specifier.alternativeForm = true;
@ -219,47 +219,85 @@ struct Formatter<std::nullptr_t> : Formatter<const void*> {
template<typename T> template<typename T>
struct Formatter<std::vector<T>> : Formatter<T> { struct Formatter<std::vector<T>> : Formatter<T> {
Specifier specifier;
void parse(Parser& parser)
{
parser.parseSpecifier(specifier, Parser::ParameterType::Container);
}
void format(Builder& builder, const std::vector<T>& value) const void format(Builder& builder, const std::vector<T>& value) const
{ {
builder.putString("{\n"); std::string indent = std::string(specifier.width, specifier.fill);
builder.putCharacter('{');
if (specifier.alternativeForm) {
builder.putCharacter('\n');
}
for (auto it = value.cbegin(); it != value.cend(); ++it) { for (auto it = value.cbegin(); it != value.cend(); ++it) {
builder.putString(" "); builder.putString(indent);
Formatter<T>::format(builder, *it); Formatter<T>::format(builder, *it);
// Add comma, except after the last element // Add comma, except after the last element
if (it != std::prev(value.end(), 1)) { if (it != std::prev(value.end(), 1)) {
builder.putCharacter(','); builder.putCharacter(',');
} }
builder.putCharacter('\n'); else if (!specifier.alternativeForm) {
builder.putString(indent);
}
if (specifier.alternativeForm) {
builder.putCharacter('\n');
}
} }
builder.putCharacter('}'); builder.putCharacter('}');
} }
}; };
#define UTIL_FORMAT_FORMAT_AS_MAP(type) \ #define UTIL_FORMAT_FORMAT_AS_MAP(type) \
template<typename K, typename V> \ template<typename K, typename V> \
struct Formatter<type<K, V>> \ struct Formatter<type<K, V>> \
: Formatter<K> \ : Formatter<K> \
, Formatter<V> { \ , Formatter<V> { \
void format(Builder& builder, const type<K, V>& value) const \ Specifier specifier; \
{ \ \
builder.putString("{\n"); \ void parse(Parser& parser) \
auto last = value.end(); \ { \
for (auto it = value.begin(); it != last; ++it) { \ parser.parseSpecifier(specifier, Parser::ParameterType::Container); \
builder.putString(R"( ")"); \ } \
Formatter<K>::format(builder, it->first); \ \
builder.putString(R"(": )"); \ void format(Builder& builder, const type<K, V>& value) const \
Formatter<V>::format(builder, it->second); \ { \
\ std::string indent = std::string(specifier.width, specifier.fill); \
/* Add comma, except after the last element */ \ \
if (std::next(it) != last) { \ builder.putCharacter('{'); \
builder.putCharacter(','); \ if (specifier.alternativeForm) { \
} \ builder.putCharacter('\n'); \
\ } \
builder.putCharacter('\n'); \ auto last = value.end(); \
} \ for (auto it = value.begin(); it != last; ++it) { \
builder.putCharacter('}'); \ builder.putString(indent); \
} \ builder.putCharacter('"'); \
Formatter<K>::format(builder, it->first); \
builder.putCharacter('"'); \
builder.putString((specifier.width > 0) ? ": " : ":"); \
Formatter<V>::format(builder, it->second); \
\
/* Add comma, except after the last element */ \
if (std::next(it) != last) { \
builder.putCharacter(','); \
} \
else if (!specifier.alternativeForm) { \
builder.putString(indent); \
} \
\
if (specifier.alternativeForm) { \
builder.putCharacter('\n'); \
} \
} \
builder.putCharacter('}'); \
} \
} }
UTIL_FORMAT_FORMAT_AS_MAP(std::map); UTIL_FORMAT_FORMAT_AS_MAP(std::map);

Loading…
Cancel
Save