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

View File

@ -238,6 +238,12 @@ Convenience functions
.. doxygenfunction:: logmesg(LAMMPS *lmp, const std::string &mesg) .. doxygenfunction:: logmesg(LAMMPS *lmp, const std::string &mesg)
:project: progguide :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 .. doxygenfunction:: errorurl
:project: progguide :project: progguide

View File

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

View File

@ -1236,6 +1236,7 @@ fp
fphi fphi
fPIC fPIC
fplo fplo
fprintf
Fqq Fqq
Fraige Fraige
framerate 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) std::string utils::errorurl(int errorcode)
{ {
return fmt::format("\nFor more information see https://docs.lammps.org/err{:04d}", 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 * This function simplifies the repetitive task of outputting some
* message to both the screen and/or the log file. The template * message to both the screen and/or the log file. The template
* wrapper with fmtlib format and argument processing allows * wrapper with {fmt} formatting and argument processing allows
* this function to work similar to ``fmt::print()``. * this function to work similar to :cpp:func:`utils::print() <LAMMPS_NS::utils::print>`.
* *
* \param lmp pointer to LAMMPS class instance * \param lmp pointer to LAMMPS class instance
* \param format format string of message to be printed * \param format format string of message to be printed
@ -111,6 +111,40 @@ namespace utils {
void logmesg(LAMMPS *lmp, const std::string &mesg); 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 /*! Return text redirecting the user to a specific paragraph in the manual
* *
* The LAMMPS manual contains detailed explanations for errors and * The LAMMPS manual contains detailed explanations for errors and