1 #ifndef LIBFILEZILLA_FORMAT_HEADER 2 #define LIBFILEZILLA_FORMAT_HEADER 30 template<
typename String,
bool Un
signed,
typename Arg>
31 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)
33 std::decay_t<Arg> v = arg;
37 assert(!Unsigned || !std::is_signed<std::decay_t<Arg>>::value || arg >= 0);
39 if (std::is_signed<std::decay_t<Arg>>::value && !(arg >= 0)) {
42 else if (std::is_signed<std::decay_t<Arg>>::value && flags & always_sign) {
45 else if (flags & pad_blank && arg >= 0) {
50 typename String::value_type buf[
sizeof(v) * 4 + 1];
51 auto *
const end = buf +
sizeof(v) * 4 + 1;
55 int const mod = std::abs(static_cast<int>(v % 10));
60 if (flags & with_width) {
61 if (lead && width > 0) {
71 if (end - p < width) {
72 ret.append(width - (end - p),
'0');
77 if (end - p < width && !(flags & left_align)) {
78 ret.append(width - (end - p),
' ');
84 if (end - p < width && flags & left_align) {
85 ret.append(width - (end - p),
' ');
95 return String(p, end);
100 template<
typename String,
bool Un
signed,
typename Arg>
101 typename std::enable_if_t<std::is_enum<std::decay_t<Arg>>::value, String> integral_to_string(
char flags,
int width, Arg && arg)
103 return integral_to_string<String, Unsigned>(flags, width,
static_cast<std::underlying_type_t<std::decay_t<Arg>
>>(arg));
107 template<
typename String,
bool Un
signed,
typename Arg>
108 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 &&)
117 template<
typename String,
typename Arg>
118 auto arg_to_string(Arg&& arg) -> decltype(toString<String>(std::forward<Arg>(arg)))
120 return toString<String>(std::forward<Arg>(arg));
124 template<
typename String>
125 String arg_to_string(...)
134 template<
typename String,
bool Lowercase,
typename Arg>
135 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)
137 std::decay_t<Arg> v = arg;
138 typename String::value_type buf[
sizeof(v) * 2];
139 auto *
const end = buf +
sizeof(v) * 2;
143 *(--p) = fz::int_to_hex_char<typename String::value_type, Lowercase>(v & 0xf);
147 return String(p, end);
151 template<
typename String,
bool Lowercase,
typename Arg>
152 typename std::enable_if_t<std::is_enum<std::decay_t<Arg>>::value, String> integral_to_hex_string(Arg && arg)
154 return integral_to_hex_string<String, Lowercase>(
static_cast<std::underlying_type_t<std::decay_t<Arg>
>>(arg));
158 template<
typename String,
bool Lowercase,
typename Arg>
159 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 &&)
167 template<
typename String,
typename Arg>
168 typename std::enable_if_t<std::is_pointer<std::decay_t<Arg>>::value, String> pointer_to_string(Arg&& arg)
170 return String({
'0',
'x'}) + integral_to_hex_string<String, true>(reinterpret_cast<uintptr_t>(arg));
174 template<
typename String,
typename Arg>
175 typename std::enable_if_t<!std::is_pointer<std::decay_t<Arg>>::value, String> pointer_to_string(Arg&&)
182 template<
typename String,
typename... Args>
183 String extract_arg(
char,
size_t,
typename String::value_type,
size_t)
188 template<
typename String>
189 void pad_arg(String& s,
char flags,
size_t width)
191 if (flags & with_width && s.size() < width) {
192 if (flags & left_align) {
193 s += String(width - s.size(),
' ');
196 s = String(width - s.size(), (flags & pad_0) ?
'0' :
' ') + s;
201 template<
typename String,
typename Arg,
typename... Args>
202 String extract_arg(
char flags,
size_t width,
typename String::value_type type,
size_t arg_n, Arg&& arg, Args&&...args)
208 ret = arg_to_string<String>(std::forward<Arg>(arg));
209 pad_arg(ret, flags, width);
211 else if (type ==
'd' || type ==
'i') {
212 ret = integral_to_string<String, false>(flags, width, std::forward<Arg>(arg));
214 else if (type ==
'u') {
215 ret = integral_to_string<String, true>(flags, width, std::forward<Arg>(arg));
217 else if (type ==
'x') {
218 ret = integral_to_hex_string<String, true>(std::forward<Arg>(arg));
219 pad_arg(ret, flags, width);
221 else if (type ==
'X') {
222 ret = integral_to_hex_string<String, false>(std::forward<Arg>(arg));
223 pad_arg(ret, flags, width);
225 else if (type ==
'p') {
226 ret = pointer_to_string<String>(std::forward<Arg>(arg));
227 pad_arg(ret, flags, width);
234 ret = extract_arg<String>(flags, width, type, arg_n - 1, std::forward<Args>(args)...);
240 template<
typename String,
typename... Args>
241 void process_arg(String
const& fmt,
typename String::size_type & pos, String& ret,
size_t& arg_n, Args&&... args)
246 if (fmt[pos] ==
'%') {
255 if (fmt[pos] ==
'0') {
258 else if (fmt[pos] ==
' ') {
261 else if (fmt[pos] ==
'-') {
265 else if (fmt[pos] ==
'+') {
267 flags |= always_sign;
277 while (fmt[pos] >=
'0' && fmt[pos] <=
'9') {
280 width += fmt[pos] -
'0';
288 if (fmt[pos] ==
'$') {
298 if (c ==
'h' || c ==
'l' || c ==
'L' || c ==
'j' || c ==
'z' || c ==
't') {
306 assert(arg_n <
sizeof...(args));
307 if (arg_n >=
sizeof...(args)) {
312 auto const type = fmt[pos++];
314 ret += extract_arg<String>(flags, width, type, arg_n++, std::forward<Args>(args)...);
343 template<
typename String,
typename... Args>
344 String
sprintf(String
const& fmt, Args&&... args)
349 typename String::size_type start = 0, pos;
351 while ((pos = fmt.find(
'%', start)) != String::npos) {
354 ret += fmt.substr(start, pos - start);
356 detail::process_arg(fmt, pos, ret, arg_n, std::forward<Args>(args)...);
362 ret += fmt.substr(start);
367 template<
typename... Args>
368 std::string
sprintf(
char const* fmt, Args&&... args)
370 return sprintf(std::string(fmt), std::forward<Args>(args)...);
373 template<
typename... Args>
374 std::wstring
sprintf(
wchar_t const* fmt, Args&&... args)
376 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:344
String types and assorted functions.
The namespace used by libfilezilla.
Definition: apply.hpp:16