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,
int 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 (end - p < width) {
73 ret.append(width - (end - p),
'0');
78 if (end - p < width && !(flags & left_align)) {
79 ret.append(width - (end - p),
' ');
85 if (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,
int 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,
int, 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&&)
183 template<
typename String,
typename... Args>
184 String extract_arg(
char,
size_t,
typename String::value_type,
size_t)
189 template<
typename String>
190 void pad_arg(String& s,
char flags,
size_t width)
192 if (flags & with_width && s.size() < width) {
193 if (flags & left_align) {
194 s += String(width - s.size(),
' ');
197 s = String(width - s.size(), (flags & pad_0) ?
'0' :
' ') + s;
202 template<
typename String,
typename Arg,
typename... Args>
203 String extract_arg(
char flags,
size_t width,
typename String::value_type type,
size_t arg_n, Arg&& arg, Args&&...args)
209 ret = arg_to_string<String>(std::forward<Arg>(arg));
210 pad_arg(ret, flags, width);
212 else if (type ==
'd' || type ==
'i') {
213 ret = integral_to_string<String, false>(flags, width, std::forward<Arg>(arg));
215 else if (type ==
'u') {
216 ret = integral_to_string<String, true>(flags, width, std::forward<Arg>(arg));
218 else if (type ==
'x') {
219 ret = integral_to_hex_string<String, true>(std::forward<Arg>(arg));
220 pad_arg(ret, flags, width);
222 else if (type ==
'X') {
223 ret = integral_to_hex_string<String, false>(std::forward<Arg>(arg));
224 pad_arg(ret, flags, width);
226 else if (type ==
'p') {
227 ret = pointer_to_string<String>(std::forward<Arg>(arg));
228 pad_arg(ret, flags, width);
235 ret = extract_arg<String>(flags, width, type, arg_n - 1, std::forward<Args>(args)...);
241 template<
typename String,
typename... Args>
242 void process_arg(String
const& fmt,
typename String::size_type & pos, String& ret,
size_t& arg_n, Args&&... args)
247 if (fmt[pos] ==
'%') {
256 if (fmt[pos] ==
'0') {
259 else if (fmt[pos] ==
' ') {
262 else if (fmt[pos] ==
'-') {
266 else if (fmt[pos] ==
'+') {
268 flags |= always_sign;
278 while (fmt[pos] >=
'0' && fmt[pos] <=
'9') {
281 width += fmt[pos] -
'0';
289 if (fmt[pos] ==
'$') {
299 if (c ==
'h' || c ==
'l' || c ==
'L' || c ==
'j' || c ==
'z' || c ==
't') {
307 assert(arg_n <
sizeof...(args));
308 if (arg_n >=
sizeof...(args)) {
313 auto const type = fmt[pos++];
315 ret += extract_arg<String>(flags, width, type, arg_n++, std::forward<Args>(args)...);
344 template<
typename String,
typename... Args>
345 String
sprintf(String
const& fmt, Args&&... args)
350 typename String::size_type start = 0, pos;
352 while ((pos = fmt.find(
'%', start)) != String::npos) {
355 ret += fmt.substr(start, pos - start);
357 detail::process_arg(fmt, pos, ret, arg_n, std::forward<Args>(args)...);
363 ret += fmt.substr(start);
368 template<
typename... Args>
369 std::string
sprintf(
char const* fmt, Args&&... args)
371 return sprintf(std::string(fmt), std::forward<Args>(args)...);
374 template<
typename... Args>
375 std::wstring
sprintf(
wchar_t const* fmt, Args&&... args)
377 return sprintf(std::wstring(fmt), std::forward<Args>(args)...);
String sprintf(String const &fmt, Args &&... args)
A simple type-safe sprintf replacement.
Definition: format.hpp:345
Functions to encode/decode strings.
String types and assorted functions.
The namespace used by libfilezilla.
Definition: apply.hpp:16