String Formatting Helpers¶
fmt¶
For C++ users, conduit includes a built-in version of the fmt
library (https://fmt.dev/).
Since other projects also bundle fmt
, the conduit version is modified to
place everything in the conduit_fmt
namespace instead of the default fmt
namespace.
This is a safe approach to avoid potential confusion and static linking consequences.
When using conduit in C++, you can use its built-in fmt
as follows:
// conduit_fmt is installed along with conduit
#include "conduit_fmt/conduit_fmt.h"
// fmt features are in the conduit_fmt namespace
std::string res = conduit_fmt::format("The answer is {}.", 42);
std::cout << res << std::endl;
res = conduit_fmt::format("The answer is {answer:0.4f}.",
conduit_fmt::arg("answer",3.1415));
std::cout << res << std::endl;
The answer is 42.
The answer is 3.1415.
conduit::utils::format¶
In addition to direct fmt
support, conduit utils provides conduit::utils::format
methods that enable fmt
style string formatting with the arguments are passed as a conduit::Node
tree.
These simplify use cases such as generating path string, allowing the pattern string and
arguments to be stored as part of a conduit hierarchy (and in HDF5, YAML, etc files).
This feature is also available in Conduit’s Python API (conduit.utils.format
).
conduit::utils::format(string, args)¶
The args
case allows named arguments (args passed as object) or ordered args (args passed as list).
conduit::utils::format(string, args) – object case:
// conduit::utils::format w/ args + object
// processes named args passed via a conduit Node
Node args;
args["answer"] = 42;
std::string res = conduit::utils::format("The answer is {answer:04}.",
args);
std::cout << res << std::endl;
args.reset();
args["adjective"] = "other";
args["answer"] = 3.1415;
res = conduit::utils::format("The {adjective} answer is {answer:0.4f}.",
args);
std::cout << res << std::endl;
The answer is 0042.
The other answer is 3.1415.
conduit::utils::format(string, args) – list case:
// conduit::utils::format w/ args + list
// processes ordered args passed via a conduit Node
Node args;
args.append() = 42;
std::string res = conduit::utils::format("The answer is {}.", args);
std::cout << res << std::endl;
args.reset();
args.append() = "other";
args.append() = 3.1415;
res = conduit::utils::format("The {} answer is {:0.4f}.", args);
std::cout << res << std::endl;
The answer is 42.
The other answer is 3.1415.
conduit::utils::format(string, maps, map_index)¶
The maps
case also supports named or ordered args and works in conjunction with a map_index
. The map_index
is used to fetch a value from an array, or list of strings, which is then passed to fmt. The maps
style of indexed indirection supports generating path strings for non-trivial domain partition mappings in Blueprint.
conduit::utils::format(string, maps, map_index) – object case:
// conduit::utils::format w/ maps + object
// processing named args passed via a conduit Node, indexed by map_index
Node maps;
maps["answer"].set({ 42.0, 3.1415});
std::string res = conduit::utils::format("The answer is {answer:04}.",
maps, 0);
std::cout << res << std::endl;
res = conduit::utils::format("The answer is {answer:04}.", maps, 1);
std::cout << res << std::endl << std::endl;
maps.reset();
maps["answer"].set({ 42.0, 3.1415});
Node &slist = maps["position"];
slist.append() = "first";
slist.append() = "second";
res = conduit::utils::format("The {position} answer is {answer:0.4f}.",
maps, 0);
std::cout << res << std::endl;
res = conduit::utils::format("The {position} answer is {answer:0.4f}.",
maps, 1);
std::cout << res << std::endl;
The answer is 0042.
The answer is 3.1415.
The first answer is 42.0000.
The second answer is 3.1415.
conduit::utils::format(string, maps, map_index ) – list case:
// conduit::utils::format w/ maps + list
// processing ordered args passed via a conduit Node, indexed by map_index
Node maps;
maps.append() = { 42.0, 3.1415};
std::string res = conduit::utils::format("The answer is {}.",
maps, 0);
std::cout << res << std::endl;
res = conduit::utils::format("The answer is {}.", maps, 1);
std::cout << res << std::endl << std::endl;
maps.reset();
// first arg
Node &slist = maps.append();
slist.append() = "first";
slist.append() = "second";
// second arg
maps.append() = { 42.0, 3.1415};
res = conduit::utils::format("The {} answer is {:0.4f}.", maps, 0);
std::cout << res << std::endl;
res = conduit::utils::format("The {} answer is {:0.4f}.", maps, 1);
std::cout << res << std::endl;
The answer is 42.
The answer is 3.1415.
The first answer is 42.0000.
The second answer is 3.1415.