1 #ifndef LIBFILEZILLA_FORMAT_HEADER
2 #define LIBFILEZILLA_FORMAT_HEADER
35 explicit operator bool()
const {
return type != 0; }
40 template<
typename String,
bool Un
signed,
typename Arg>
41 typename std::enable_if_t<std::is_integral<std::decay_t<Arg>>::value && !std::is_enum<std::decay_t<Arg>>::value, String> integral_to_string(field
const& f, Arg && arg)
43 std::decay_t<Arg> v = arg;
47 assert(!Unsigned || !std::is_signed<std::decay_t<Arg>>::value || arg >= 0);
49 if (std::is_signed<std::decay_t<Arg>>::value && !(arg >= 0)) {
52 else if (std::is_signed<std::decay_t<Arg>>::value && f.flags & always_sign) {
55 else if (f.flags & pad_blank && arg >= 0) {
60 typename String::value_type buf[
sizeof(v) * 4 + 1];
61 auto *
const end = buf +
sizeof(v) * 4 + 1;
65 int const mod = std::abs(static_cast<int>(v % 10));
71 if (f.flags & with_width) {
72 if (lead && width > 0) {
78 if (f.flags & pad_0) {
82 if (static_cast<size_t>(end - p) < width) {
83 ret.append(width - (end - p),
'0');
88 if (static_cast<size_t>(end - p) < width && !(f.flags & left_align)) {
89 ret.append(width - (end - p),
' ');
95 if (static_cast<size_t>(end - p) < width && f.flags & left_align) {
96 ret.append(width - (end - p),
' ');
106 return String(p, end);
111 template<
typename String,
bool Un
signed,
typename Arg>
112 typename std::enable_if_t<std::is_enum<std::decay_t<Arg>>::value, String> integral_to_string(field
const& f, Arg && arg)
114 return integral_to_string<String, Unsigned>(f,
static_cast<std::underlying_type_t<std::decay_t<Arg>
>>(arg));
118 template<
typename String,
bool Un
signed,
typename Arg>
119 typename std::enable_if_t<!std::is_integral<std::decay_t<Arg>>::value && !std::is_enum<std::decay_t<Arg>>::value, String> integral_to_string(field
const&, Arg &&)
125 template<
typename String,
class Arg,
typename =
void>
126 struct has_toString : std::false_type {};
128 template<
typename String,
class Arg>
129 struct has_toString<String, Arg, std::void_t<decltype(toString<String>(std::declval<Arg>()))>> : std::true_type {};
131 template<
typename String,
typename Arg>
132 String arg_to_string(Arg&& arg)
134 if constexpr (has_toString<String, Arg>::value) {
137 return toString<String>(std::forward<Arg>(arg));
147 template<
typename String,
bool Lowercase,
typename Arg>
148 String integral_to_hex_string(Arg && arg)
150 if constexpr (std::is_enum_v<std::decay_t<Arg>>) {
152 return integral_to_hex_string<String, Lowercase>(
static_cast<std::underlying_type_t<std::decay_t<Arg>
>>(arg));
154 else if constexpr (std::is_integral_v<std::decay_t<Arg>>) {
155 std::decay_t<Arg> v = arg;
156 typename String::value_type buf[
sizeof(v) * 2];
157 auto*
const end = buf +
sizeof(v) * 2;
161 *(--p) = fz::int_to_hex_char<typename String::value_type, Lowercase>(v & 0xf);
165 return String(p, end);
174 template<
typename String,
typename Arg>
175 String pointer_to_string(Arg&& arg)
177 if constexpr (std::is_pointer_v<std::decay_t<Arg>>) {
178 return String({
'0',
'x'}) + integral_to_hex_string<String, true>(reinterpret_cast<uintptr_t>(arg));
186 template<
typename String,
typename Arg>
187 String char_to_string(Arg&& arg)
189 if constexpr (std::is_integral_v<std::decay_t<Arg>>) {
190 return String({
static_cast<typename String::value_type
>(
static_cast<unsigned char>(arg))});
199 template<
typename String>
200 void pad_arg(String& s, field
const& f)
202 if (f.flags & with_width && s.size() < f.width) {
203 if (f.flags & left_align) {
204 s += String(f.width - s.size(),
' ');
207 s = String(f.width - s.size(), (f.flags & pad_0) ?
'0' :
' ') + s;
212 template<
typename String,
typename Arg>
213 String format_arg(field
const& f, Arg&& arg)
217 ret = arg_to_string<String>(std::forward<Arg>(arg));
220 else if (f.type ==
'd' || f.type ==
'i') {
221 ret = integral_to_string<String, false>(f, std::forward<Arg>(arg));
223 else if (f.type ==
'u') {
224 ret = integral_to_string<String, true>(f, std::forward<Arg>(arg));
226 else if (f.type ==
'x') {
227 ret = integral_to_hex_string<String, true>(std::forward<Arg>(arg));
230 else if (f.type ==
'X') {
231 ret = integral_to_hex_string<String, false>(std::forward<Arg>(arg));
234 else if (f.type ==
'p') {
235 ret = pointer_to_string<String>(std::forward<Arg>(arg));
238 else if (f.type ==
'c') {
239 ret = char_to_string<String>(std::forward<Arg>(arg));
247 template<
typename String,
typename... Args>
248 String extract_arg(field
const&,
size_t)
254 template<
typename String,
typename Arg,
typename... Args>
255 String extract_arg(field
const& f,
size_t arg_n, Arg&& arg, Args&&...args)
260 ret = format_arg<String>(f, std::forward<Arg>(arg));
263 ret = extract_arg<String>(f, arg_n - 1, std::forward<Args>(args)...);
269 template<
typename InString,
typename OutString,
typename... Args>
270 field get_field(InString
const& fmt,
typename InString::size_type & pos,
size_t& arg_n, OutString & ret)
273 if (++pos >= fmt.size()) {
279 if (fmt[pos] ==
'%') {
287 if (fmt[pos] ==
'0') {
290 else if (fmt[pos] ==
' ') {
291 f.flags |= pad_blank;
293 else if (fmt[pos] ==
'-') {
295 f.flags |= left_align;
297 else if (fmt[pos] ==
'+') {
298 f.flags &= ~pad_blank;
299 f.flags |= always_sign;
304 if (++pos >= fmt.size()) {
311 while (fmt[pos] >=
'0' && fmt[pos] <=
'9') {
312 f.flags |= with_width;
314 f.width += fmt[pos] -
'0';
315 if (++pos >= fmt.size()) {
320 if (f.width > 10000) {
325 if (fmt[pos] ==
'$') {
328 if (++pos >= fmt.size()) {
338 if (c ==
'h' || c ==
'l' || c ==
'L' || c ==
'j' || c ==
'z' || c ==
't') {
339 if (++pos >= fmt.size()) {
349 f.type =
static_cast<char>(fmt[pos++]);
353 template<
typename InString,
typename CharType =
typename InString::value_type,
typename OutString = std::basic_
string<CharType>,
typename... Args>
354 OutString do_sprintf(InString
const& fmt, Args&&... args)
359 typename InString::size_type start = 0, pos;
362 while ((pos = fmt.find(
'%', start)) != InString::npos) {
365 ret += fmt.substr(start, pos - start);
367 field f = detail::get_field(fmt, pos, arg_n, ret);
369 assert(arg_n <
sizeof...(args));
370 ret += detail::extract_arg<OutString>(f, arg_n++, std::forward<Args>(args)...);
377 ret += fmt.substr(start);
405 template<
typename... Args>
406 std::string
sprintf(std::string_view
const& fmt, Args&&... args)
408 return detail::do_sprintf(fmt, std::forward<Args>(args)...);
411 template<
typename... Args>
412 std::wstring
sprintf(std::wstring_view
const& fmt, Args&&... args)
414 return detail::do_sprintf(fmt, std::forward<Args>(args)...);
std::string sprintf(std::string_view const &fmt, Args &&...args)
A simple type-safe sprintf replacement.
Definition: format.hpp:406
Functions to encode/decode strings.
String types and assorted functions.
The namespace used by libfilezilla.
Definition: apply.hpp:16