Skip to content

Commit 4c20237

Browse files
committed
Formattable types
1 parent 56a5672 commit 4c20237

10 files changed

Lines changed: 176 additions & 5 deletions

File tree

include/libhat.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "libhat/cstring_view.hpp"
77
#include "libhat/defines.hpp"
88
#include "libhat/fixed_string.hpp"
9+
#include "libhat/formatter.hpp"
910
#include "libhat/memory.hpp"
1011
#include "libhat/memory_protector.hpp"
1112
#include "libhat/process.hpp"

include/libhat/cow.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "detail/compressed_pair.hpp"
1616
#include "cstring_view.hpp"
1717
#include "export.hpp"
18+
#include "formatter.hpp"
1819

1920
LIBHAT_EXPORT namespace hat {
2021

@@ -450,4 +451,12 @@ LIBHAT_EXPORT namespace hat {
450451
template<detail::non_const T>
451452
using cow_writable_span = cow_writable_span<T, std::pmr::polymorphic_allocator<T>>;
452453
}
454+
455+
template<typename T, typename Traits, typename Allocator, typename CharT, template<typename...> class Formatter>
456+
struct formatter<cow<T, Traits, Allocator>, CharT, Formatter> : Formatter<T, CharT> {
457+
template<typename FormatContext>
458+
constexpr auto format(const cow<T, Traits, Allocator>& value, FormatContext& ctx) const {
459+
return Formatter<T, CharT>::format(value.viewed(), ctx);
460+
}
461+
};
453462
}

include/libhat/cstring_view.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#endif
88

99
#include "export.hpp"
10+
#include "formatter.hpp"
1011

1112
LIBHAT_EXPORT namespace hat {
1213

@@ -308,6 +309,17 @@ LIBHAT_EXPORT namespace hat {
308309
#endif
309310
using u16cstring_view = basic_cstring_view<char16_t>;
310311
using u32cstring_view = basic_cstring_view<char32_t>;
312+
313+
template<typename CharT, typename Traits, template<typename...> class Formatter>
314+
struct formatter<basic_cstring_view<CharT, Traits>, CharT, Formatter> : Formatter<std::basic_string_view<CharT, Traits>, CharT> {
315+
template<typename FormatContext>
316+
constexpr auto format(const basic_cstring_view<CharT, Traits>& value, FormatContext& ctx) const {
317+
return Formatter<std::basic_string_view<CharT, Traits>, CharT>::format(value, ctx);
318+
}
319+
};
320+
321+
template<typename CharT, typename Traits>
322+
constexpr bool disable_range_formatter<basic_cstring_view<CharT, Traits>> = true;
311323
}
312324

313325
namespace hat::detail {

include/libhat/fixed_string.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "cstring_view.hpp"
1111
#include "export.hpp"
12+
#include "formatter.hpp"
1213

1314
LIBHAT_EXPORT namespace hat {
1415

@@ -174,16 +175,25 @@ LIBHAT_EXPORT namespace hat {
174175
};
175176

176177
#define LIBHAT_DEFINE_FIXED_STRING(name, type) \
177-
template<std::size_t N> \
178+
template<std::size_t N> \
178179
struct name : public basic_fixed_string<type, N, name> { \
179180
using basic_fixed_string<type, N, name>::basic_fixed_string; \
180181
}; \
181-
template<std::size_t N> \
182+
template<std::size_t N> \
182183
name(const type(&str)[N]) -> name<N - 1>; \
183-
template<std::size_t N, std::size_t M> \
184+
template<std::size_t N, std::size_t M> \
184185
constexpr inline auto operator+(const type (&cstr)[N], const basic_fixed_string<type, M, name>& lstr) { \
185186
return name{cstr} + lstr; \
186-
}
187+
} \
188+
template<std::size_t N, template<typename...> class Formatter> \
189+
struct formatter<name<N>, type, Formatter> : Formatter<std::basic_string_view<type>, type> { \
190+
template<typename FormatContext> \
191+
constexpr auto format(const name<N>& value, FormatContext& ctx) const { \
192+
return Formatter<std::basic_string_view<type>, type>::format(value.to_view(), ctx); \
193+
} \
194+
}; \
195+
template<std::size_t N> \
196+
constexpr bool disable_range_formatter<name<N>> = true;
187197

188198
LIBHAT_DEFINE_FIXED_STRING(fixed_string, char)
189199
LIBHAT_DEFINE_FIXED_STRING(wfixed_string, wchar_t)

include/libhat/formatter.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#ifndef LIBHAT_MODULE
4+
#include <concepts>
5+
#include <format>
6+
#include <type_traits>
7+
#endif
8+
9+
#include "export.hpp"
10+
11+
LIBHAT_EXPORT namespace hat {
12+
13+
template<typename T, typename CharT, template<typename...> class Formatter>
14+
struct formatter {
15+
formatter() = delete;
16+
formatter(const formatter&) = delete;
17+
formatter& operator=(const formatter&) = delete;
18+
};
19+
20+
template<typename T, typename CharT, template<typename...> class Formatter>
21+
concept formattable = std::semiregular<formatter<std::remove_reference_t<T>, CharT, Formatter>>;
22+
23+
template<typename T>
24+
constexpr bool disable_range_formatter = false;
25+
}
26+
27+
template<typename T, typename CharT>
28+
requires(hat::formattable<T, CharT, std::formatter>)
29+
struct std::formatter<T, CharT> : hat::formatter<T, CharT, std::formatter> {};
30+
31+
#if __cpp_lib_format_ranges >= 202207L
32+
template<typename T>
33+
requires(hat::disable_range_formatter<T>)
34+
constexpr auto std::format_kind<T> = std::range_format::disabled;
35+
#endif

include/libhat/signature.hpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212

1313
#include "defines.hpp"
1414
#include "export.hpp"
15-
#include "strconv.hpp"
1615
#include "fixed_string.hpp"
16+
#include "formatter.hpp"
17+
#include "strconv.hpp"
1718

1819
LIBHAT_EXPORT namespace hat {
1920

@@ -286,6 +287,47 @@ LIBHAT_EXPORT namespace hat {
286287
ret.pop_back();
287288
return ret;
288289
}
290+
291+
template<template<typename...> class Formatter>
292+
struct formatter<signature_element, char, Formatter> : Formatter<std::string, char> {
293+
template<typename FormatContext>
294+
constexpr auto format(const signature_element& value, FormatContext& ctx) const {
295+
return Formatter<std::string, char>::format(to_string(signature_view{&value, 1}), ctx);
296+
}
297+
};
298+
299+
template<template<typename...> class Formatter>
300+
struct formatter<signature, char, Formatter> : Formatter<std::string, char> {
301+
template<typename FormatContext>
302+
constexpr auto format(const signature& value, FormatContext& ctx) const {
303+
return Formatter<std::string, char>::format(to_string(value), ctx);
304+
}
305+
};
306+
307+
template<>
308+
constexpr bool disable_range_formatter<signature> = true;
309+
310+
template<template<typename...> class Formatter>
311+
struct formatter<signature_view, char, Formatter> : Formatter<std::string, char> {
312+
template<typename FormatContext>
313+
constexpr auto format(const signature_view& value, FormatContext& ctx) const {
314+
return Formatter<std::string, char>::format(to_string(value), ctx);
315+
}
316+
};
317+
318+
template<>
319+
constexpr bool disable_range_formatter<signature_view> = true;
320+
321+
template<std::size_t N, template<typename...> class Formatter>
322+
struct formatter<fixed_signature<N>, char, Formatter> : Formatter<std::string, char> {
323+
template<typename FormatContext>
324+
constexpr auto format(const fixed_signature<N>& value, FormatContext& ctx) const {
325+
return Formatter<std::string, char>::format(to_string(value), ctx);
326+
}
327+
};
328+
329+
template<std::size_t N>
330+
constexpr bool disable_range_formatter<fixed_signature<N>> = true;
289331
}
290332

291333
LIBHAT_EXPORT namespace hat::inline literals::inline signature_literals {

include/libhat/string_literal.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "export.hpp"
44
#include "fixed_string.hpp"
5+
#include "formatter.hpp"
56

67
LIBHAT_EXPORT namespace hat {
78

@@ -26,6 +27,14 @@ LIBHAT_EXPORT namespace hat {
2627

2728
template<hat::u32fixed_string str>
2829
using u32string_literal = basic_string_literal<str>;
30+
31+
template<auto str, template<typename...> class Formatter>
32+
struct formatter<basic_string_literal<str>, typename decltype(str)::value_type, Formatter> : Formatter<decltype(str), typename decltype(str)::value_type> {
33+
template<typename FormatContext>
34+
constexpr auto format(const string_literal<str>&, FormatContext& ctx) const {
35+
return Formatter<decltype(str), typename decltype(str)::value_type>::format(str, ctx);
36+
}
37+
};
2938
}
3039

3140
LIBHAT_EXPORT namespace hat::inline literals::inline string_literals {

module/libhat.cppm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module;
1616
#include <cstdlib>
1717
#include <cstring>
1818
#include <execution>
19+
#include <format>
1920
#include <functional>
2021
#include <iterator>
2122
#include <memory>

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ register_test(libhat_benchmark_compare benchmark/Compare.cpp)
6262
register_test(libhat_benchmark_compare_impl benchmark/CompareImpl.cpp)
6363
register_test(libhat_test_scanner tests/Scanner.cpp)
6464
register_test(libhat_test_process tests/Process.cpp)
65+
register_test(libhat_test_formatter tests/Formatter.cpp)
6566

6667
if(LIBHAT_TESTING_SAMPLE_BIN)
6768
CPMAddPackage(

test/tests/Formatter.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <gtest/gtest.h>
2+
#include <libhat/cow.hpp>
3+
#include <libhat/cstring_view.hpp>
4+
#include <libhat/fixed_string.hpp>
5+
#include <libhat/signature.hpp>
6+
#include <libhat/string_literal.hpp>
7+
#include <format>
8+
9+
using namespace std::literals;
10+
using namespace hat::literals;
11+
12+
TEST(FormatterTest, FixedString) {
13+
ASSERT_EQ(std::format("{}", hat::fixed_string{"abc"}), "abc"sv);
14+
}
15+
16+
TEST(FormatterTest, StringLiteral) {
17+
ASSERT_EQ(std::format("{}", "abc"_s), "abc"sv);
18+
}
19+
20+
TEST(FormatterTest, CStringView) {
21+
ASSERT_EQ(std::format("{}", "abc"_csv), "abc"sv);
22+
}
23+
24+
TEST(FormatterTest, CowString) {
25+
ASSERT_EQ(std::format("{}", hat::cow_string{"abc"s}), "abc"sv);
26+
ASSERT_EQ(std::format("{}", hat::cow_string{"abc"sv}), "abc"sv);
27+
}
28+
29+
TEST(FormatterTest, CowCString) {
30+
ASSERT_EQ(std::format("{}", hat::cow_cstring{"abc"s}), "abc"sv);
31+
ASSERT_EQ(std::format("{}", hat::cow_cstring{"abc"_csv}), "abc"sv);
32+
}
33+
34+
TEST(FormatterTest, CowSpan) {
35+
std::vector data{1, 2, 3};
36+
ASSERT_EQ(std::format("{}", hat::cow_span<int>{data}), "[1, 2, 3]"sv);
37+
ASSERT_EQ(std::format("{}", hat::cow_span<int>{std::span{data}}), "[1, 2, 3]"sv);
38+
// ASSERT_EQ(std::format("{}", hat::cow_writable_span<int>{data}), "[1, 2, 3]"sv);
39+
// ASSERT_EQ(std::format("{}", hat::cow_writable_span<int>{std::span{data}}), "[1, 2, 3]"sv);
40+
}
41+
42+
TEST(FormatterTest, SignatureElement) {
43+
ASSERT_EQ(std::format("{}", hat::signature_element{std::byte{0x10}, std::byte{0xF0}}), "1?"sv);
44+
}
45+
46+
TEST(FormatterTest, Signature) {
47+
constexpr auto sig = "11 22 33"_sig;
48+
ASSERT_EQ(std::format("{}", hat::signature(sig.begin(), sig.end())), "11 22 33"sv);
49+
ASSERT_EQ(std::format("{}", hat::signature_view{sig}), "11 22 33"sv);
50+
ASSERT_EQ(std::format("{}", sig), "11 22 33"sv);
51+
}

0 commit comments

Comments
 (0)