13 #ifndef vtkPVStringFormatter_h 14 #define vtkPVStringFormatter_h 16 #include "vtkLogger.h" 27 #include VTK_FMT(fmt/args.h) 28 #include VTK_FMT(fmt/chrono.h) 29 #include VTK_FMT(fmt/core.h) 30 #include VTK_FMT(fmt/ranges.h) 47 template <
typename... Args>
53 template <
typename... Args>
66 template <
typename... Args>
69 std::shared_ptr<vtkArgumentScope> newScope;
71 if (vtkPVStringFormatter::ScopeStack.empty())
73 newScope = std::make_shared<vtkArgumentScope>();
77 newScope = std::make_shared<vtkArgumentScope>(*vtkPVStringFormatter::ScopeStack.top());
79 vtkPVStringFormatter::Push(*newScope, args...);
80 vtkPVStringFormatter::ScopeStack.push(newScope);
93 template <
typename... Args>
94 static void PushScope(
const char* scopeName, Args&&... args)
96 std::shared_ptr<vtkArgumentScope> newScope;
98 if (vtkPVStringFormatter::ScopeStack.empty())
100 newScope = std::make_shared<vtkArgumentScope>();
104 newScope = std::make_shared<vtkArgumentScope>(*vtkPVStringFormatter::ScopeStack.top());
106 vtkPVStringFormatter::Push(*newScope, scopeName, args...);
107 vtkPVStringFormatter::ScopeStack.push(newScope);
113 static void PopScope();
119 static std::string Format(
const std::string& formattableString);
129 using char_type = fmt::format_context::char_type;
134 struct vtkNamedArgument
170 std::chrono::time_point<std::chrono::system_clock>
TimePoint;
177 : Type(ValueType::
NONE)
182 : Type(ValueType::INT)
188 : Type(ValueType::UNSIGNED)
194 : Type(ValueType::LONG_LONG)
200 : Type(ValueType::UNSIGNED_LONG_LONG)
201 , UnsignedLongLong(value)
206 : Type(ValueType::BOOL)
212 : Type(ValueType::CHAR)
218 : Type(ValueType::
FLOAT)
224 : Type(ValueType::DOUBLE)
230 : Type(ValueType::LONG_DOUBLE)
236 : Type(ValueType::STRING)
241 Value(
const std::basic_string<char_type>& value)
242 : Type(ValueType::STRING)
247 Value(
const std::chrono::time_point<std::chrono::system_clock>& value)
248 : Type(ValueType::TIME_POINT)
253 Value(
const std::vector<double>& values)
254 : Type(ValueType::DOUBLE_VECTOR)
255 , DoubleVector(values)
261 this->Type = value.
Type;
265 this->Int = value.
Int;
267 case ValueType::UNSIGNED:
270 case ValueType::LONG_LONG:
273 case ValueType::UNSIGNED_LONG_LONG:
276 case ValueType::BOOL:
277 this->Bool = value.
Bool;
279 case ValueType::CHAR:
280 this->Char = value.
Char;
283 this->Float = value.
Float;
285 case ValueType::DOUBLE:
286 this->Double = value.
Double;
288 case ValueType::LONG_DOUBLE:
291 case ValueType::STRING:
292 new (&this->String) std::basic_string<char_type>(value.
String);
294 case ValueType::TIME_POINT:
297 case ValueType::DOUBLE_VECTOR:
298 new (&this->DoubleVector) std::vector<double>(value.
DoubleVector);
309 case ValueType::STRING:
310 this->String.~basic_string();
312 case ValueType::DOUBLE_VECTOR:
313 this->DoubleVector.~vector();
321 std::basic_string<char_type> Name;
324 vtkNamedArgument() =
default;
326 template <
typename DataType>
327 vtkNamedArgument(
const std::basic_string<char_type>&
name,
const DataType&
value)
333 ~vtkNamedArgument() =
default;
339 class vtkArgumentScope
342 std::vector<vtkNamedArgument> Arguments;
345 vtkArgumentScope() =
default;
347 vtkArgumentScope(
const vtkArgumentScope& other)
349 this->Arguments.reserve(other.Arguments.size());
350 for (
const auto& arg : other.Arguments)
352 this->Arguments.emplace_back(arg);
360 template <
typename T>
361 void AddArg(
const fmt::detail::named_arg<char_type, T>& fmtArg)
363 bool argNotFound = std::find_if(this->Arguments.begin(), this->Arguments.end(),
364 [&fmtArg](
const vtkNamedArgument& arg)
365 {
return arg.Name == fmtArg.name; }) == this->Arguments.end();
369 vtkNamedArgument newArg(fmtArg.name, fmtArg.value);
370 this->Arguments.push_back(newArg);
374 vtkLogF(TRACE,
"Argument %s already exists. Try to add another one.", fmtArg.name);
381 std::basic_string<char_type> GetArgInfo()
const 383 std::basic_stringstream<char_type> argInfo;
384 for (
const auto& arg : this->Arguments)
386 argInfo <<
"\tName: " << arg.Name;
387 argInfo <<
"\tType: ";
388 switch (arg.Value.Type)
390 case vtkNamedArgument::ValueType::INT:
393 case vtkNamedArgument::ValueType::UNSIGNED:
394 argInfo <<
"unsigned";
396 case vtkNamedArgument::ValueType::LONG_LONG:
397 argInfo <<
"long long";
399 case vtkNamedArgument::ValueType::UNSIGNED_LONG_LONG:
400 argInfo <<
"unsigned long long";
402 case vtkNamedArgument::ValueType::BOOL:
405 case vtkNamedArgument::ValueType::CHAR:
411 case vtkNamedArgument::ValueType::DOUBLE:
414 case vtkNamedArgument::ValueType::LONG_DOUBLE:
415 argInfo <<
"long double";
417 case vtkNamedArgument::ValueType::STRING:
418 argInfo <<
"std::string";
420 case vtkNamedArgument::ValueType::TIME_POINT:
421 argInfo <<
"std::chrono::time_point<std::chrono::system_clock>";
423 case vtkNamedArgument::ValueType::DOUBLE_VECTOR:
424 argInfo <<
"std::vector<double>";
427 argInfo <<
"unknown";
432 return argInfo.str();
438 fmt::dynamic_format_arg_store<fmt::format_context> GetArgs()
const 440 fmt::dynamic_format_arg_store<fmt::format_context> args;
441 for (
const auto& arg : this->Arguments)
443 switch (arg.Value.Type)
445 case vtkNamedArgument::ValueType::INT:
446 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Int));
448 case vtkNamedArgument::ValueType::UNSIGNED:
449 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Unsigned));
451 case vtkNamedArgument::ValueType::LONG_LONG:
452 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.LongLong));
454 case vtkNamedArgument::ValueType::UNSIGNED_LONG_LONG:
455 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.UnsignedLongLong));
457 case vtkNamedArgument::ValueType::BOOL:
458 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Bool));
460 case vtkNamedArgument::ValueType::CHAR:
461 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Char));
464 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Float));
466 case vtkNamedArgument::ValueType::DOUBLE:
467 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Double));
469 case vtkNamedArgument::ValueType::LONG_DOUBLE:
470 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.LongDouble));
472 case vtkNamedArgument::ValueType::STRING:
473 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.String));
475 case vtkNamedArgument::ValueType::TIME_POINT:
476 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.TimePoint));
478 case vtkNamedArgument::ValueType::DOUBLE_VECTOR:
479 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.DoubleVector));
491 void clear() { this->Arguments.clear(); }
497 static std::string GetArgInfo();
502 static void Push(vtkArgumentScope& vtkNotUsed(scope)) {}
507 template <
typename T0,
typename... TArgs>
508 static void Push(vtkArgumentScope& scope, T0& arg0, TArgs&... args)
511 vtkPVStringFormatter::Push(scope, args...);
517 static void Push(vtkArgumentScope& vtkNotUsed(scope),
const char* vtkNotUsed(scopeName)) {}
522 template <
typename T0,
typename... TArgs>
523 static void Push(vtkArgumentScope& scope,
const char* scopeName, T0& arg0, TArgs&... args)
525 auto scopeBasedArgName = std::string(scopeName) +
"_" + arg0.name;
526 scope.AddArg(fmt::arg(scopeBasedArgName.c_str(), arg0.value));
528 vtkPVStringFormatter::Push(scope, scopeName, args...);
531 static std::stack<std::shared_ptr<vtkArgumentScope>> ScopeStack;
534 #define PV_STRING_FORMATTER_SCOPE_0(x, y) x##y 535 #define PV_STRING_FORMATTER_SCOPE_1(x, y) PV_STRING_FORMATTER_SCOPE_0(x, y) 536 #define PV_STRING_FORMATTER_SCOPE(...) \ 537 vtkPVStringFormatter::TraceScope PV_STRING_FORMATTER_SCOPE_1(_trace_item, __LINE__)(__VA_ARGS__) 538 #define PV_STRING_FORMATTER_NAMED_SCOPE(NAME, ...) \ 539 vtkPVStringFormatter::TraceScope PV_STRING_FORMATTER_SCOPE_1(_trace_item, __LINE__)( \
#define VTKPVVTKEXTENSIONSCORE_EXPORT
void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE