Browse Source

Util: Add map formatting to new struct Formatter

master
Riyyi 2 years ago
parent
commit
da0954ffcc
  1. 1
      src/util/format/format.h
  2. 2
      src/util/format/formatter.cpp
  3. 28
      src/util/format/formatter.h
  4. 165
      src/util/format/toformat.h

1
src/util/format/format.h

@ -13,7 +13,6 @@
#include <string_view>
#include "util/format/formatter.h"
#include "util/format/toformat.h"
namespace Util::Format {

2
src/util/format/formatter.cpp

@ -90,6 +90,4 @@ void Formatter<std::nullptr_t>::format(Builder& builder, std::nullptr_t) const
Formatter<const void*>::format(builder, 0);
}
// Containers
} // namespace Util::Format

28
src/util/format/formatter.h

@ -114,4 +114,32 @@ struct Formatter<std::vector<T>> : Formatter<T> {
}
};
#define UTIL_FORMAT_FORMAT_AS_MAP(type) \
template<typename K, typename V> \
struct Formatter<type<K, V>> \
: Formatter<K> \
, Formatter<V> { \
void format(Builder& builder, const type<K, V>& value) const \
{ \
builder.putString("{\n"); \
auto last = value.end(); \
for (auto it = value.begin(); it != last; ++it) { \
builder.putString(R"( ")"); \
Formatter<K>::format(builder, it->first); \
builder.putString(R"(": )"); \
Formatter<V>::format(builder, it->second); \
\
/* Add comma, except after the last element */ \
if (std::next(it) != last) { \
builder.putCharacter(','); \
} \
\
builder.putCharacter('\n'); \
} \
builder.putCharacter('}'); \
} \
}
UTIL_FORMAT_FORMAT_AS_MAP(std::map);
UTIL_FORMAT_FORMAT_AS_MAP(std::unordered_map);
} // namespace Util::Format

165
src/util/format/toformat.h

@ -1,165 +0,0 @@
/*
* Copyright (C) 2022 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <cstddef> // nullptr_t, size_t
#include <cstdint> // int32_t, uint32_t, int64_t
#include <cstring> // strlen
#include <iterator> // next
#include <map>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility> // forward
#include <vector>
#include "util/meta/odr.h"
namespace Util::Format {
namespace Detail {
template<typename FormatBuilder>
void format(FormatBuilder& builder, std::nullptr_t)
{
builder.putString("(nil)");
}
template<typename FormatBuilder, typename T>
void format(FormatBuilder& builder, T* pointer)
{
builder.putPointer(static_cast<const void*>(pointer));
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, bool boolean)
{
builder.putString(boolean ? "true" : "false");
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, int32_t number) // int
{
builder.putI32(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, uint32_t number) // unsigned int
{
builder.putU32(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, int64_t number) // long int
{
builder.putI64(number);
}
template<typename FormatBuilder> // uint64_t
void format(FormatBuilder& builder, size_t number) // long unsigned int
{
builder.putU64(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, float number)
{
builder.putF32(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, double number)
{
builder.putF64(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, char character)
{
builder.putCharacter(character);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, const char* string)
{
builder.putString({ string, strlen(string) });
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, const std::string& string)
{
builder.putString(string);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, std::string_view string)
{
builder.putString(string);
}
template<typename FormatBuilder, typename T>
void format(FormatBuilder& builder, const std::vector<T>& array)
{
builder.putString("{\n");
for (auto it = array.cbegin(); it != array.cend(); ++it) {
builder.putString(" ");
format(builder, *it);
// Add comma, except after the last element
if (it != std::prev(array.end(), 1)) {
builder.putCharacter(',');
}
builder.putCharacter('\n');
}
builder.putCharacter('}');
}
#define FORMAT_MAP \
builder.putString("{\n"); \
auto last = map.end(); \
for (auto it = map.begin(); it != last; ++it) { \
builder.putString(R"( ")"); \
format(builder, it->first); \
builder.putString(R"(": )"); \
format(builder, it->second); \
\
/* Add comma, except after the last element */ \
if (std::next(it) != last) { \
builder.putCharacter(','); \
} \
\
builder.putCharacter('\n'); \
} \
builder.putCharacter('}');
template<typename FormatBuilder, typename K, typename V>
void format(FormatBuilder& builder, const std::map<K, V>& map)
{
FORMAT_MAP;
}
template<typename FormatBuilder, typename K, typename V>
void format(FormatBuilder& builder, const std::unordered_map<K, V>& map)
{
FORMAT_MAP;
}
struct formatFunction {
template<typename FormatBuilder, typename T>
auto operator()(FormatBuilder& builder, T&& value) const
{
return format(builder, std::forward<T>(value));
}
};
} // namespace Detail
namespace {
constexpr const auto& _format = Util::Detail::staticConst<Detail::formatFunction>; // NOLINT(misc-definitions-in-headers,clang-diagnostic-unused-variable)
} // namespace
} // namespace Util::Format
Loading…
Cancel
Save