mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-24 12:14:26 +00:00
parent
fa0f870ac9
commit
d4ddaaf2b1
12
doc/api.rst
12
doc/api.rst
@ -125,12 +125,15 @@ custom argument formatter class::
|
|||||||
.. doxygenclass:: fmt::ArgFormatter
|
.. doxygenclass:: fmt::ArgFormatter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
Printf formatting functions
|
Printf formatting
|
||||||
---------------------------
|
-----------------
|
||||||
|
|
||||||
|
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
|
||||||
The following functions use `printf format string syntax
|
The following functions use `printf format string syntax
|
||||||
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
|
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
|
||||||
a POSIX extension for positional arguments.
|
the POSIX extension for positional arguments. Unlike their standard
|
||||||
|
counterparts, the ``fmt`` functions are type-safe and throw an exception if an
|
||||||
|
argument type doesn't match its format specification.
|
||||||
|
|
||||||
.. doxygenfunction:: printf(CStringRef, ArgList)
|
.. doxygenfunction:: printf(CStringRef, ArgList)
|
||||||
|
|
||||||
@ -138,6 +141,9 @@ a POSIX extension for positional arguments.
|
|||||||
|
|
||||||
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::PrintfFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
Write API
|
Write API
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -521,7 +521,7 @@ template void internal::FixedBuffer<char>::grow(std::size_t);
|
|||||||
|
|
||||||
template void internal::ArgMap<char>::init(const ArgList &args);
|
template void internal::ArgMap<char>::init(const ArgList &args);
|
||||||
|
|
||||||
template void internal::PrintfFormatter<char>::format(
|
template void PrintfFormatter<char>::format(
|
||||||
BasicWriter<char> &writer, CStringRef format);
|
BasicWriter<char> &writer, CStringRef format);
|
||||||
|
|
||||||
template int internal::CharTraits<char>::format_float(
|
template int internal::CharTraits<char>::format_float(
|
||||||
@ -538,7 +538,7 @@ template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
|||||||
|
|
||||||
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
|
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
|
||||||
|
|
||||||
template void internal::PrintfFormatter<wchar_t>::format(
|
template void PrintfFormatter<wchar_t>::format(
|
||||||
BasicWriter<wchar_t> &writer, WCStringRef format);
|
BasicWriter<wchar_t> &writer, WCStringRef format);
|
||||||
|
|
||||||
template int internal::CharTraits<wchar_t>::format_float(
|
template int internal::CharTraits<wchar_t>::format_float(
|
||||||
|
45
fmt/printf.h
45
fmt/printf.h
@ -248,23 +248,34 @@ class PrintfArgFormatter
|
|||||||
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
|
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
|
||||||
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
|
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
|
||||||
};
|
};
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
// A printf formatter.
|
/** This template formats data and writes the output to a writer. */
|
||||||
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
|
template <typename Char,
|
||||||
class PrintfFormatter : private FormatterBase {
|
typename ArgFormatter = internal::PrintfArgFormatter<Char> >
|
||||||
|
class PrintfFormatter : private internal::FormatterBase {
|
||||||
private:
|
private:
|
||||||
void parse_flags(FormatSpec &spec, const Char *&s);
|
void parse_flags(FormatSpec &spec, const Char *&s);
|
||||||
|
|
||||||
// Returns the argument with specified index or, if arg_index is equal
|
// Returns the argument with specified index or, if arg_index is equal
|
||||||
// to the maximum unsigned value, the next argument.
|
// to the maximum unsigned value, the next argument.
|
||||||
Arg get_arg(const Char *s,
|
internal::Arg get_arg(
|
||||||
|
const Char *s,
|
||||||
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
|
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
|
||||||
|
|
||||||
// Parses argument index, flags and width and returns the argument index.
|
// Parses argument index, flags and width and returns the argument index.
|
||||||
unsigned parse_header(const Char *&s, FormatSpec &spec);
|
unsigned parse_header(const Char *&s, FormatSpec &spec);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Constructs a ``PrintfFormatter`` object. References to the arguments
|
||||||
|
are stored in the formatter object so make sure they have appropriate
|
||||||
|
lifetimes.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
|
explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
|
||||||
|
|
||||||
FMT_API void format(BasicWriter<Char> &writer,
|
FMT_API void format(BasicWriter<Char> &writer,
|
||||||
BasicCStringRef<Char> format_str);
|
BasicCStringRef<Char> format_str);
|
||||||
};
|
};
|
||||||
@ -296,10 +307,11 @@ void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename AF>
|
template <typename Char, typename AF>
|
||||||
Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, unsigned arg_index) {
|
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
|
||||||
|
unsigned arg_index) {
|
||||||
(void)s;
|
(void)s;
|
||||||
const char *error = 0;
|
const char *error = 0;
|
||||||
Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
|
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
|
||||||
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
|
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
|
||||||
if (error)
|
if (error)
|
||||||
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
|
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
|
||||||
@ -314,7 +326,7 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
|
|||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
// Parse an argument index (if followed by '$') or a width possibly
|
// Parse an argument index (if followed by '$') or a width possibly
|
||||||
// preceded with '0' flag(s).
|
// preceded with '0' flag(s).
|
||||||
unsigned value = parse_nonnegative_int(s);
|
unsigned value = internal::parse_nonnegative_int(s);
|
||||||
if (*s == '$') { // value is an argument index
|
if (*s == '$') { // value is an argument index
|
||||||
++s;
|
++s;
|
||||||
arg_index = value;
|
arg_index = value;
|
||||||
@ -332,10 +344,10 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
|
|||||||
parse_flags(spec, s);
|
parse_flags(spec, s);
|
||||||
// Parse width.
|
// Parse width.
|
||||||
if (*s >= '0' && *s <= '9') {
|
if (*s >= '0' && *s <= '9') {
|
||||||
spec.width_ = parse_nonnegative_int(s);
|
spec.width_ = internal::parse_nonnegative_int(s);
|
||||||
} else if (*s == '*') {
|
} else if (*s == '*') {
|
||||||
++s;
|
++s;
|
||||||
spec.width_ = WidthHandler(spec).visit(get_arg(s));
|
spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
|
||||||
}
|
}
|
||||||
return arg_index;
|
return arg_index;
|
||||||
}
|
}
|
||||||
@ -365,16 +377,17 @@ void PrintfFormatter<Char, AF>::format(
|
|||||||
if (*s == '.') {
|
if (*s == '.') {
|
||||||
++s;
|
++s;
|
||||||
if ('0' <= *s && *s <= '9') {
|
if ('0' <= *s && *s <= '9') {
|
||||||
spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
|
spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
|
||||||
} else if (*s == '*') {
|
} else if (*s == '*') {
|
||||||
++s;
|
++s;
|
||||||
spec.precision_ = PrecisionHandler().visit(get_arg(s));
|
spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using internal::Arg;
|
||||||
Arg arg = get_arg(s, arg_index);
|
Arg arg = get_arg(s, arg_index);
|
||||||
if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
|
if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
|
||||||
spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
|
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
|
||||||
if (spec.fill_ == '0') {
|
if (spec.fill_ == '0') {
|
||||||
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
|
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
|
||||||
spec.align_ = ALIGN_NUMERIC;
|
spec.align_ = ALIGN_NUMERIC;
|
||||||
@ -383,6 +396,7 @@ void PrintfFormatter<Char, AF>::format(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse length and convert the argument to the required type.
|
// Parse length and convert the argument to the required type.
|
||||||
|
using internal::ArgConverter;
|
||||||
switch (*s++) {
|
switch (*s++) {
|
||||||
case 'h':
|
case 'h':
|
||||||
if (*s == 'h')
|
if (*s == 'h')
|
||||||
@ -426,7 +440,7 @@ void PrintfFormatter<Char, AF>::format(
|
|||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
// TODO: handle wchar_t
|
// TODO: handle wchar_t
|
||||||
CharConverter(arg).visit(arg);
|
internal::CharConverter(arg).visit(arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,11 +452,10 @@ void PrintfFormatter<Char, AF>::format(
|
|||||||
}
|
}
|
||||||
write(writer, start, s);
|
write(writer, start, s);
|
||||||
}
|
}
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
|
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
|
||||||
internal::PrintfFormatter<Char>(args).format(w, format);
|
PrintfFormatter<Char>(args).format(w, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +53,7 @@ FMT_VARIADIC(std::string, custom_format, const char *)
|
|||||||
|
|
||||||
std::string custom_sprintf(const char* fstr, fmt::ArgList args){
|
std::string custom_sprintf(const char* fstr, fmt::ArgList args){
|
||||||
fmt::MemoryWriter writer;
|
fmt::MemoryWriter writer;
|
||||||
fmt::internal::PrintfFormatter< char, CustomPAF > pfer( args);
|
fmt::PrintfFormatter<char, CustomPAF> pfer( args);
|
||||||
pfer.format(writer, fstr);
|
pfer.format(writer, fstr);
|
||||||
return writer.str();
|
return writer.str();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user