implement an utils::print() function similar to fmt::print()

this doesn't have the constexpr requirement for the format string.
also it will help porting to std::format in C++20, which doesn't
have a similar functionality either.
This commit is contained in:
Axel Kohlmeyer
2025-01-23 00:03:30 -05:00
parent b4f012057c
commit 8baec60155
6 changed files with 80 additions and 20 deletions

View File

@ -300,18 +300,19 @@ Formatting with the {fmt} library
The LAMMPS source code includes a copy of the `{fmt} library
<https://fmt.dev>`_, which is preferred over formatting with the
"printf()" family of functions. The primary reason is that it allows
a typesafe default format for any type of supported data. This is
"printf()" family of functions. The primary reason is that it allows a
typesafe default format for any type of supported data. This is
particularly useful for formatting integers of a given size (32-bit or
64-bit) which may require different format strings depending on
compile time settings or compilers/operating systems. Furthermore,
{fmt} gives better performance, has more functionality, a familiar
formatting syntax that has similarities to ``format()`` in Python, and
provides a facility that can be used to integrate format strings and a
variable number of arguments into custom functions in a much simpler
way than the varargs mechanism of the C library. Finally, {fmt} has
been included into the C++20 language standard, so changes to adopt it
are future-proof.
64-bit) which may require different format strings depending on compile
time settings or compilers/operating systems. Furthermore, {fmt} gives
better performance, has more functionality, a familiar formatting syntax
that has similarities to ``format()`` in Python, and provides a facility
that can be used to integrate format strings and a variable number of
arguments into custom functions in a much simpler way than the varargs
mechanism of the C library. Finally, {fmt} has been included into the
C++20 language standard as ``std::format()``, so changes to adopt it are
future-proof, for as long as they are not using any extensions that are
not (yet) included into C++.
Formatted strings are frequently created by calling the
``fmt::format()`` function, which will return a string as a
@ -319,11 +320,13 @@ Formatted strings are frequently created by calling the
``printf()``, the {fmt} library uses ``{}`` to embed format descriptors.
In the simplest case, no additional characters are needed, as {fmt} will
choose the default format based on the data type of the argument.
Otherwise, the ``fmt::print()`` function may be used instead of
``printf()`` or ``fprintf()``. In addition, several LAMMPS output
functions, that originally accepted a single string as argument have
been overloaded to accept a format string with optional arguments as
well (e.g., ``Error::all()``, ``Error::one()``, ``utils::logmesg()``).
Otherwise, the :cpp:func:`utils::print() <LAMMPS_NS::utils::print>`
function may be used instead of ``printf()`` or ``fprintf()``. In
addition, several LAMMPS output functions, that originally accepted a
single string as argument have been overloaded to accept a format string
with optional arguments as well (e.g., ``Error::all()``,
``Error::one()``, :cpp:func:`utils::logmesg()
<LAMMPS_NS::utils::logmesg>`).
Summary of the {fmt} format syntax
==================================

View File

@ -238,6 +238,12 @@ Convenience functions
.. doxygenfunction:: logmesg(LAMMPS *lmp, const std::string &mesg)
:project: progguide
.. doxygenfunction:: print(FILE *fp, const std::string &format, Args&&... args)
:project: progguide
.. doxygenfunction:: print(FILE *fp, const std::string &mesg)
:project: progguide
.. doxygenfunction:: errorurl
:project: progguide

View File

@ -96,8 +96,8 @@ Here the we specify which methods of the fix should be called during
MPI_Allreduce(localAvgVel, globalAvgVel, 4, MPI_DOUBLE, MPI_SUM, world);
scale3(1.0 / globalAvgVel[3], globalAvgVel);
if ((comm->me == 0) && screen) {
fmt::print(screen,"{}, {}, {}\n",
globalAvgVel[0], globalAvgVel[1], globalAvgVel[2]);
utils::print(screen, "{}, {}, {}\n",
globalAvgVel[0], globalAvgVel[1], globalAvgVel[2]);
}
}

View File

@ -1236,6 +1236,7 @@ fp
fphi
fPIC
fplo
fprintf
Fqq
Fraige
framerate

View File

@ -262,6 +262,22 @@ void utils::fmtargs_logmesg(LAMMPS *lmp, fmt::string_view format, fmt::format_ar
}
}
/* specialization for the case of just a single string argument */
void utils::print(FILE *fp, const std::string &mesg)
{
fputs(mesg.c_str(), fp);
}
void utils::fmtargs_print(FILE *fp, fmt::string_view format, fmt::format_args args)
{
try {
print(fp, fmt::vformat(format, args));
} catch (fmt::format_error &) {
; // do nothing
}
}
std::string utils::errorurl(int errorcode)
{
return fmt::format("\nFor more information see https://docs.lammps.org/err{:04d}", errorcode);

View File

@ -92,8 +92,8 @@ namespace utils {
*
* This function simplifies the repetitive task of outputting some
* message to both the screen and/or the log file. The template
* wrapper with fmtlib format and argument processing allows
* this function to work similar to ``fmt::print()``.
* wrapper with {fmt} formatting and argument processing allows
* this function to work similar to :cpp:func:`utils::print() <LAMMPS_NS::utils::print>`.
*
* \param lmp pointer to LAMMPS class instance
* \param format format string of message to be printed
@ -111,6 +111,40 @@ namespace utils {
void logmesg(LAMMPS *lmp, const std::string &mesg);
/*! Return text redirecting the user to a specific paragraph in the manual
*
* The LAMMPS manual contains detailed explanations for errors and
* warnings where a simple error message may not be sufficient. These can
* be reached through URLs with a numeric code. This function creates the
* corresponding text to be included into the error message that redirects
* the user to that URL.
*
* \param errorcode number pointing to a paragraph in the manual */
/*! Internal function handling the argument list for print(). */
void fmtargs_print(FILE *fp, fmt::string_view format, fmt::format_args args);
/*! Write formatted message to file
*
* This function implements a version of fprintf() that uses {fmt} formatting
*
* \param fp stdio FILE pointer
* \param format format string of message to be printed
* \param args arguments to format string */
template <typename... Args> void print(FILE *fp, const std::string &format, Args &&...args)
{
fmtargs_print(fp, format, fmt::make_format_args(args...));
}
/*! \overload
*
* \param fp stdio FILE pointer
* \param mesg string with message to be printed */
void print(FILE *fp, const std::string &mesg);
/*! Return text redirecting the user to a specific paragraph in the manual
*
* The LAMMPS manual contains detailed explanations for errors and