38 static constexpr auto DYNAMIC = std::numeric_limits<size_t>::max();
69 template<Specifier __spec>
72 static constexpr auto spec = __spec;
74 template<
typename TArg,
Specifier _config =
spec, std::enable_if_t<_config.n_dynamic_args() == 1,
int> = 0>
75 static constexpr auto arg_tuple() -> std::tuple<TArg>;
77 template<
typename TArg,
Specifier _config =
spec, std::enable_if_t<_config.n_dynamic_args() == 2,
int> = 0>
78 static constexpr auto arg_tuple() -> std::tuple<TArg, size_t>;
80 template<
typename TArg,
Specifier _config =
spec, std::enable_if_t<_config.n_dynamic_args() == 3,
int> = 0>
81 static constexpr auto arg_tuple() -> std::tuple<TArg, size_t, size_t>;
83 template<
typename TArg,
typename Stream>
86 if constexpr (
spec.n_dynamic_args() == 1)
88 const auto &[arg] =
args;
91 else if constexpr (
spec.n_dynamic_args() == 2)
93 const auto &[arg, n1] =
args;
94 os <<
'[' << arg <<
" " << n1 <<
']';
96 else if constexpr (
spec.n_dynamic_args() == 3)
98 const auto &[arg, n1, n2] =
args;
99 os <<
'[' << arg <<
" " << n1 <<
" " << n2 <<
']';
106 template<Specifier orig>
115 template<Specifier orig>
119 config.
width = width;
125 template<Specifier orig>
135 template<Specifier orig>
144 template<Specifier orig>
147 static_assert(orig.filler ==
'\0',
"Fill already set");
153 template<Specifier orig>
156 static_assert(orig.debug ==
false,
"Debug format already set");
158 config.
debug = debug_format;
162 template<Specifier orig>
165 static_assert(orig.alternative ==
false,
"Alternative form already set");
174 return std::tuple_cat(std::make_tuple(a), b);
192 template<
typename... Type>
198 template<
typename... Type>
204 template<
string_literal view,
size_t I,
size_t End,
size_t Result = 0>
207 if constexpr (view[I] <
'0' || view[I] >
'9' || I == view.strlen || I == End)
210 return __do_parse_int<view, I + 1, End, Result * 10 + (view[I] -
'0')>();
213 template<
string_literal view,
size_t IStart>
216 if constexpr (view[IStart] <
'0' || view[IStart] >
'9' || IStart == view.strlen)
222 template<
string_literal view,
size_t I,
size_t StartI, Specifier config>
225 if constexpr (view[I] ==
'}')
227 else if constexpr (view[I] ==
'{')
230 static_assert(view[I + 1] ==
'}',
"Invalid dynamic width specifier");
233 else if constexpr (view[I] ==
'.')
235 if constexpr (view[I + 1] ==
'{')
238 static_assert(view[I + 2] ==
'}',
"Invalid dynamic precision specifier");
241 else if constexpr (view[I + 1] >=
'0' && view[I + 1] <=
'9')
249 static_assert(
false,
"Invalid precision specifier");
255 if constexpr (view[I] ==
'<')
257 else if constexpr (view[I] ==
'>')
259 else if constexpr (view[I] ==
'^')
261 else if constexpr (view[I] ==
'+')
263 else if constexpr (view[I] ==
'-')
265 else if constexpr (view[I] ==
' ')
267 else if constexpr (view[I] ==
'?')
269 else if constexpr (view[I] ==
'#')
271 else if constexpr (view[I] ==
':')
273 else if constexpr (view[I] >=
'0' && view[I] <=
'9')
285 template<
size_t StartI,
size_t N,
typename... Args>
288 if constexpr (StartI == N || StartI >= std::tuple_size_v<std::remove_cvref_t<
decltype(
args)>>)
294 template<
typename... TArgs>
297 return std::get<0>(
args);
300 template<
size_t N,
typename... TArgs>
306 template<
typename... TArgs>
309 return get_slice<1, std::tuple_size_v<std::remove_cvref_t<
decltype(
args)>>>(
args);
312 template<
size_t N,
typename... TArgs>
315 return get_slice<N, std::tuple_size_v<std::remove_cvref_t<
decltype(
args)>>>(
args);
318 template<
typename Stream,
typename... TArgs>
319 static inline constexpr auto do_next_print(Stream &stream, std::tuple<TArgs...> str_format_tuple)
321 constexpr auto rest_specifier_size = std::tuple_size_v<std::remove_cvref_t<
decltype(str_format_tuple)>>;
322 static_assert(rest_specifier_size == 0 || rest_specifier_size == 1,
"Invalid format string");
324 if constexpr (rest_specifier_size == 1)
328 template<
typename Stream,
typename... TSpecs,
typename TSpec,
typename TArg,
typename... TArgs>
329 static inline constexpr auto do_next_print(Stream &stream, TSpec spec,
const std::tuple<TSpecs...> &specs,
const TArg &arg,
const std::tuple<TArgs...> &
args)
331 constexpr auto rest_specifier_size = std::tuple_size_v<std::remove_cvref_t<
decltype(specs)>>;
332 constexpr auto rest_arg_size = std::tuple_size_v<std::remove_cvref_t<
decltype(
args)>>;
334 if constexpr (std::is_same_v<TSpec, mos::string_view>)
341 using TArgTuple =
decltype(TSpec::template arg_tuple<TArg>());
342 constexpr auto TArgTupleSize = std::tuple_size_v<TArgTuple>;
343 static_assert(TArgTupleSize == 1 || TArgTupleSize == 2 || TArgTupleSize == 3,
"Invalid number of arguments");
345 static_assert(TArgTupleSize - 1 <= rest_arg_size,
"Not enough arguments");
349 if constexpr (rest_arg_size - (TArgTupleSize - 1) > 0)
356 static_assert(rest_specifier_size == 0 || rest_specifier_size == 1,
"Invalid number of arguments");
362 static_assert(
false,
"Invalid specifier");
367 template<
string_literal view,
size_t I = 0,
size_t StartI = 0>
370 if constexpr (I == view.strlen)
372 if constexpr (StartI == I)
373 return std::make_tuple();
377 else if constexpr (view[I] ==
'{' && (I < 1 || view[I - 1] !=
'\\'))
381 if constexpr (StartI == I)
388 constexpr bool escaped = view[I] ==
'{' && (I >= 1 && view[I - 1] ==
'\\');
398 static_assert(args_expected ==
sizeof...(args),
"Number of arguments does not match format string");
400 if constexpr (args_expected == 0)
406 const auto args_tuple = std::make_tuple(
args...);
412 template<
typename M,
typename Stream,
typename... TArgs>
413 static inline constexpr Stream &
print_m(Stream &stream, std::tuple<TArgs...>
args)
417 static_assert(args_expected ==
sizeof...(TArgs),
"Number of arguments does not match format string");
419 if constexpr (args_expected == 0)
438#define formatted_type(literal) \
441 struct M : mos::FormatImpl::formatted_string \
443 static consteval auto string_value() \
445 return ::mos::string_literal{ literal }; \
458inline auto FakeStream = FakeStreamType();
MOSAPI const char *__restrict format
mos::SyslogStreamWriter operator<<(mos::SyslogStreamWriter stream, VMFlags flags)
basic_string_view< char > string_view
@ NEGATIVE
only negative numbers are prefixed with a sign
@ BOTH
both native and positive numbers are prefixed with a sign
@ LEADING_SPACE
positive numbers are prefixed with a leading space
@ _DEFAULT
default, negative
consteval size_t n_dynamic_args() const
number of runtime arguments required to print this item.
FormatAlignment alignment
WidthPrecisionOrder order
static constexpr auto DYNAMIC