HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
format10.hpp
1// Copyright 2020 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include <fmt/format.h>
7#include <utility>
8#include <tuple>
9#include <memory>
10#include <string>
11#include <locale>
12#include "translation.hpp"
13#include "TTauri/Foundation/type_traits.hpp"
14
15namespace tt {
16
18{
19protected:
20 std::string fmt;
21
22public:
23 format10_base(std::string_view fmt) noexcept :
24 fmt(std::string{fmt}) {}
25
26 virtual ~format10_base() = default;
27
28 virtual operator std::string () const noexcept = 0;
29
30 virtual std::unique_ptr<format10_base> make_unique_copy() const noexcept = 0;
31
32 [[nodiscard]] virtual bool equal_to(format10_base &other) const noexcept = 0;
33};
34
37template<typename... Args>
38std::string cpp20_format(std::locale const &locale, std::string_view fmt, Args const &... args)
39{
40 return fmt::format(fmt, args...);
41}
42
43
44template<typename... Args>
46{
48
49 using format_func_type = std::string(*)(std::locale const &, std::string_view, remove_cvref_t<Args> const &...);
50 using make_unique_type = std::unique_ptr<format10_impl>(*)(std::string_view const &, remove_cvref_t<Args> const &...);
51
52public:
53 format10_impl(std::string_view fmt, Args const &... args) noexcept :
54 format10_base(fmt),
55 args(args...) {}
56
57 operator std::string () const noexcept override {
58 auto locale = std::locale{};
59 auto translated_fmt = get_translation(fmt);
60
61 format_func_type format_func = cpp20_format;
62 return std::apply(format_func, std::tuple_cat(std::tuple(locale, translated_fmt), args));
63 }
64
65 std::unique_ptr<format10_base> make_unique_copy() const noexcept override {
66 make_unique_type unique_constructor = std::make_unique<format10_impl>;
67 return std::apply(unique_constructor, std::tuple_cat(std::tuple(fmt), args));
68 }
69
70 [[nodiscard]] bool equal_to(format10_base &other) const noexcept override {
71 auto *other_ = dynamic_cast<format10_impl *>(&other);
72 return other_ && this->fmt == other_->fmt && this->args == other_->args;
73 }
74};
75
76template<>
78{
79public:
80
81 format10_impl(std::string_view fmt) noexcept :
82 format10_base(fmt) {}
83
84 operator std::string () const noexcept override {
85 return std::string{get_translation(fmt)};
86 }
87
88 std::unique_ptr<format10_base> make_unique_copy() const noexcept override {
89 return std::make_unique<format10_impl>(fmt);
90 }
91
92 [[nodiscard]] bool equal_to(format10_base &other) const noexcept override {
93 auto *other_ = dynamic_cast<format10_impl *>(&other);
94 return other_ && this->fmt == other_->fmt;
95 }
96};
97
98class format10 {
100
101public:
102 format10() noexcept :
103 impl(std::make_unique<format10_impl<>>(""s)) {}
104
105 template<typename... Args>
106 format10(std::string_view fmt, Args const &... args) noexcept :
107 impl(std::make_unique<format10_impl<Args...>>(fmt, args...)) {}
108
109 format10(format10 &&other) noexcept = default;
110 format10 &operator=(format10 &&other) noexcept = default;
111
112 format10(format10 const &other) noexcept :
113 impl(other.impl->make_unique_copy()) {
114 tt_assume(other.impl);
115 }
116
117 format10 &operator=(format10 const &other) noexcept {
118 tt_assume(other.impl);
119 impl = other.impl->make_unique_copy();
120 return *this;
121 }
122
123 operator std::string () const noexcept {
124 tt_assume(impl);
125 return static_cast<std::string>(*impl);
126 }
127
128 [[nodiscard]] friend bool operator==(format10 const &lhs, format10 const &rhs) noexcept {
129 tt_assume(lhs.impl);
130 tt_assume(rhs.impl);
131 return lhs.impl->equal_to(*rhs.impl);
132 }
133
134 [[nodiscard]] friend bool operator!=(format10 const &lhs, format10 const &rhs) noexcept {
135 return !(lhs == rhs);
136 }
137
138};
139
140using format10p = format10;
141
142}
143
144// Add specialization for observable_cast
145#include "detail/observable_cast_format10.hpp"
Definition format10.hpp:18
Definition format10.hpp:46
Definition format10.hpp:78
Definition format10.hpp:98
T tuple_cat(T... args)