1 #ifndef LIBFILEZILLA_FORMAT_HEADER
2 #define LIBFILEZILLA_FORMAT_HEADER
31 template<
typename String,
bool Un
signed,
typename Arg>
32 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(
char flags,
size_t width, Arg && arg)
34 std::decay_t<Arg> v = arg;
38 assert(!Unsigned || !std::is_signed<std::decay_t<Arg>>::value || arg >= 0);
40 if (std::is_signed<std::decay_t<Arg>>::value && !(arg >= 0)) {
43 else if (std::is_signed<std::decay_t<Arg>>::value && flags & always_sign) {
46 else if (flags & pad_blank && arg >= 0) {
51 typename String::value_type buf[
sizeof(v) * 4 + 1];
52 auto *
const end = buf +
sizeof(v) * 4 + 1;
56 int const mod = std::abs(static_cast<int>(v % 10));
61 if (flags & with_width) {
62 if (lead && width > 0) {
72 if (static_cast<size_t>(end - p) < width) {
73 ret.append(width - (end - p),
'0');
78 if (static_cast<size_t>(end - p) < width && !(flags & left_align)) {
79 ret.append(width - (end - p),
' ');
85 if (static_cast<size_t>(end - p) < width && flags & left_align) {
86 ret.append(width - (end - p),
' ');
96 return String(p, end);
101 template<
typename String,
bool Un
signed,
typename Arg>
102 typename std::enable_if_t<std::is_enum<std::decay_t<Arg>>::value, String> integral_to_string(
char flags,
size_t width, Arg && arg)
104 return integral_to_string<String, Unsigned>(flags, width,
static_cast<std::underlying_type_t<std::decay_t<Arg>
>>(arg));
108 template<
typename String,
bool Un
signed,
typename Arg>
109 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(
char,
size_t, Arg &&)
118 template<
typename String,
typename Arg>
119 auto arg_to_string(Arg&& arg) -> decltype(toString<String>(std::forward<Arg>(arg)))
121 return toString<String>(std::forward<Arg>(arg));
125 template<
typename String>
126 String arg_to_string(...)
135 template<
typename String,
bool Lowercase,
typename Arg>
136 typename std::enable_if_t<std::is_integral<std::decay_t<Arg>>::value && !std::is_enum<std::decay_t<Arg>>::value, String> integral_to_hex_string(Arg && arg)
138 std::decay_t<Arg> v = arg;
139 typename String::value_type buf[
sizeof(v) * 2];
140 auto *
const end = buf +
sizeof(v) * 2;
144 *(--p) = fz::int_to_hex_char<typename String::value_type, Lowercase>(v & 0xf);
148 return String(p, end);
152 template<
typename String,
bool Lowercase,
typename Arg>
153 typename std::enable_if_t<std::is_enum<std::decay_t<Arg>>::value, String> integral_to_hex_string(Arg && arg)
155 return integral_to_hex_string<String, Lowercase>(
static_cast<std::underlying_type_t<std::decay_t<Arg>
>>(arg));
159 template<
typename String,
bool Lowercase,
typename Arg>
160 typename std::enable_if_t<!std::is_integral<std::decay_t<Arg>>::value && !std::is_enum<std::decay_t<Arg>>::value, String> integral_to_hex_string(Arg &&)
168 template<
typename String,
typename Arg>
169 typename std::enable_if_t<std::is_pointer<std::decay_t<Arg>>::value, String> pointer_to_string(Arg&& arg)
171 return String({
'0',
'x'}) + integral_to_hex_string<String, true>(reinterpret_cast<uintptr_t>(arg));
175 template<
typename String,
typename Arg>
176 typename std::enable_if_t<!std::is_pointer<std::decay_t<Arg>>::value, String> pointer_to_string(Arg&&)
182 template<
typename String,
typename Arg>
183 typename std::enable_if_t<std::is_integral<std::decay_t<Arg>>::value, String> char_to_string(Arg&& arg)
185 return String({
static_cast<typename String::value_type
>(
static_cast<unsigned char>(arg))});
189 template<
typename String,
typename Arg>
190 typename std::enable_if_t<!std::is_integral<std::decay_t<Arg>>::value, String> char_to_string(Arg&&)
197 template<
typename String,
typename... Args>
198 String extract_arg(
char,
size_t,
typename String::value_type,
size_t)
203 template<
typename String>
204 void pad_arg(String& s,
char flags,
size_t width)
206 if (flags & with_width && s.size() < width) {
207 if (flags & left_align) {
208 s += String(width - s.size(),
' ');
211 s = String(width - s.size(), (flags & pad_0) ?
'0' :
' ') + s;
216 template<
typename String,
typename Arg,
typename... Args>
217 String extract_arg(
char flags,
size_t width,
typename String::value_type type,
size_t arg_n, Arg&& arg, Args&&...args)
223 ret = arg_to_string<String>(std::forward<Arg>(arg));
224 pad_arg(ret, flags, width);
226 else if (type ==
'd' || type ==
'i') {
227 ret = integral_to_string<String, false>(flags, width, std::forward<Arg>(arg));
229 else if (type ==
'u') {
230 ret = integral_to_string<String, true>(flags, width, std::forward<Arg>(arg));
232 else if (type ==
'x') {
233 ret = integral_to_hex_string<String, true>(std::forward<Arg>(arg));
234 pad_arg(ret, flags, width);
236 else if (type ==
'X') {
237 ret = integral_to_hex_string<String, false>(std::forward<Arg>(arg));
238 pad_arg(ret, flags, width);
240 else if (type ==
'p') {
241 ret = pointer_to_string<String>(std::forward<Arg>(arg));
242 pad_arg(ret, flags, width);
244 else if (type ==
'c') {
245 ret = char_to_string<String>(std::forward<Arg>(arg));
252 ret = extract_arg<String>(flags, width, type, arg_n - 1, std::forward<Args>(args)...);
258 template<
typename String,
typename... Args>
259 void process_arg(String
const& fmt,
typename String::size_type & pos, String& ret,
size_t& arg_n, Args&&... args)
264 if (fmt[pos] ==
'%') {
273 if (fmt[pos] ==
'0') {
276 else if (fmt[pos] ==
' ') {
279 else if (fmt[pos] ==
'-') {
283 else if (fmt[pos] ==
'+') {
285 flags |= always_sign;
295 while (fmt[pos] >=
'0' && fmt[pos] <=
'9') {
298 width += fmt[pos] -
'0';
306 if (fmt[pos] ==
'$') {
316 if (c ==
'h' || c ==
'l' || c ==
'L' || c ==
'j' || c ==
'z' || c ==
't') {
324 assert(arg_n <
sizeof...(args));
325 if (arg_n >=
sizeof...(args)) {
330 auto const type = fmt[pos++];
332 ret += extract_arg<String>(flags, width, type, arg_n++, std::forward<Args>(args)...);
361 template<
typename String,
typename... Args>
362 String
sprintf(String
const& fmt, Args&&... args)
367 typename String::size_type start = 0, pos;
369 while ((pos = fmt.find(
'%', start)) != String::npos) {
372 ret += fmt.substr(start, pos - start);
374 detail::process_arg(fmt, pos, ret, arg_n, std::forward<Args>(args)...);
380 ret += fmt.substr(start);
385 template<
typename... Args>
386 std::string
sprintf(
char const* fmt, Args&&... args)
388 return sprintf(std::string(fmt), std::forward<Args>(args)...);
391 template<
typename... Args>
392 std::wstring
sprintf(
wchar_t const* fmt, Args&&... args)
394 return sprintf(std::wstring(fmt), std::forward<Args>(args)...);
Functions to encode/decode strings.
String types and assorted functions.
String sprintf(String const &fmt, Args &&...args)
A simple type-safe sprintf replacement.
Definition: format.hpp:362