header_utils
Loading...
Searching...
No Matches
stringification.h
1
4
5#pragma once
6
7#include "string_ops.h"
8
9namespace ghassanpl
10{
13
15 template <std::floating_point T>
16 [[nodiscard]] std::string to_string(T floating_point)
17 {
18 const auto len = static_cast<size_t>(::snprintf(nullptr, 0, "%g", floating_point));
19 std::string str(len, '\0');
20 ::sprintf_s(&str[0], len + 1, "%g", floating_point);
21 return str;
22 }
23
25 template <typename T>
26 requires (!std::same_as<T, char>&& std::integral<T>)
27 [[nodiscard]] std::string to_string(T integral) { return std::to_string(integral); }
28
30 template <std::same_as<char> T>
31 [[nodiscard]] std::string to_string(T c) { return std::string{c}; }
32
34 template <typename T>
35 requires std::constructible_from<std::string_view, T>
36 [[nodiscard]] std::string to_string(T&& val) { return std::string{std::string_view{std::forward<T>(val)}}; }
37
39 [[nodiscard]] inline std::string to_string(nullptr_t) { return "null"; }
40
42}
43
45
46namespace ghassanpl
47{
49
50 template <bool TO_STRING>
52 {
53 std::string& result;
54
55 template <typename T>
56 std::string str(T&& val) const;
57
58 template <typename... ARGS>
59 bool operator()(ARGS&&... args) const
60 {
61 ((result += this->str(args)), ...);
62 return true;
63 }
64 };
65
66 template <typename T>
67 concept from_charsable = requires (const char* a, T& to) { { std::from_chars(a, a, to) } -> std::same_as<std::from_chars_result>; };
68
69 template <typename T>
70 bool eat_from_string(std::string_view& from, T&& val)
71 {
72 if constexpr (std::is_reference_v<T>)
73 {
74 if constexpr (std::same_as<T, char>)
75 {
76 if (from.empty()) return false;
77 val = from[0];
78 from.remove_prefix(1);
79 return true;
80 }
81 else if constexpr (from_charsable<T>)
82 {
83 auto [ptr, ec] = string_ops::from_chars(from, val);
84 if (ec == std::errc{})
85 {
86 from = ghassanpl::string_ops::make_sv(ptr, from.end());
87 return true;
88 }
89 return false;
90 }
91 else
92 {
93 make_sv(from, val);
94 }
95 }
96 else
97 {
98 if constexpr (std::same_as<T, char> || std::convertible_to<T, std::string_view>)
99 {
100 return ghassanpl::string_ops::consume(from, val);
101 }
102 else
103 {
104 make_sv(from, val);
105 }
106 }
107 }
108
109 template <>
110 struct string_stringifier<false>
111 {
112 std::string_view from;
113
114 template <typename... ARGS>
115 bool operator()(ARGS&&... args)
116 {
117 return ((ghassanpl::eat_from_string(from, std::forward<ARGS>(args))) && ...);
118 }
119 };
120
121 template <typename T, template<bool> typename STRINGIFIER = string_stringifier>
122 requires requires (STRINGIFIER<true> str, T val) { stringify(str, val); }
123 [[nodiscard]] std::string to_string(T&& val)
124 {
125 std::string result;
126 STRINGIFIER<true> str{result};
127 stringify(str, std::forward<T>(val));
128 return result;
129 }
130
131 template <typename T, template<bool> typename STRINGIFIER = string_stringifier>
132 requires requires (STRINGIFIER<false> str, T val) { stringify(str, val); }
133 bool from_string(std::string_view val, T& target)
134 {
135 STRINGIFIER<false> str{val};
136 if (!stringify(str, target))
137 return false;
138 return true;
139 }
140
141 template <typename T, template<bool> typename STRINGIFIER = string_stringifier>
142 requires requires (STRINGIFIER<false> str, T val) { stringify(str, val); }
143 [[nodiscard]] T from_string(std::string_view val)
144 {
145 T result{};
146 STRINGIFIER<false> str{val};
147 if (!stringify(str, result))
148 return {};
149 return result;
150 }
151
152 template<bool TO_STRING>
153 template<typename T>
154 inline std::string string_stringifier<TO_STRING>::str(T&& val) const
155 {
157 return to_string(std::forward<T>(val));
158 }
159}
160
161template <typename T>
162requires requires (ghassanpl::string_stringifier<true> str, T val) { stringify(str, val); }
163struct std::formatter<T> : std::formatter<std::string>
164{
165 template<typename U, class FormatContext>
166 auto format(U&& t, FormatContext& fc) const
167 {
168 std::string result;
169 ghassanpl::string_stringifier<true> str{ result };
170 stringify(str, std::forward<U>(t));
171 return std::formatter<std::string>::format(std::move(result), fc);
172 }
173};
174
175template <typename T>
176requires requires (T val) { { (std::string_view)val } -> std::same_as<std::string_view>; } && (!std::convertible_to<T, std::string_view>)
177struct std::formatter<T> : std::formatter<std::string_view>
178{
179 template<typename U, class FormatContext>
180 auto format(U&& t, FormatContext& fc) const
181 {
182 return std::formatter<std::string_view>::format((std::string_view)std::forward<U>(t), fc);
183 }
184};
185
186/*
187template <typename T>
188requires (requires (T val) { ghassanpl::to_string(val); }) && (!requires (T val) { std::to_string(val); })
189struct std::formatter<T> : std::formatter<std::string>
190{
191 template<typename U, class FormatContext>
192 auto format(U&& t, FormatContext& fc) const
193 {
194 return std::formatter<std::string>::format(ghassanpl::to_string(std::forward<U>(t)), fc);
195 }
196};
197*/
constexpr CONTAINER to(RANGE &&range, TYPES &&... args)
to<container>();
Definition ranges.h:386
char consume(std::string_view &str)
Consumes and returns the first character in the str, or \0 if no more characters.
Definition string_ops.h:702
constexpr auto from_chars(std::string_view str, T &value, const int base=10) noexcept
A version of std::from_chars that takes a std::string_view as the first argument.
std::string to_string(T floating_point)
float overload
Primary namespace for everything in this library.
Definition align+rec2.h:10
NOTE: The below is a MAJOR WORK IN PROGRESS.