13 #ifndef vtkPVStringFormatter_h 14 #define vtkPVStringFormatter_h 16 #include "vtkLogger.h" 19 #include "vtkStringFormatter.h" 40 template <
typename... Args>
46 template <
typename... Args>
59 template <
typename... Args>
62 std::shared_ptr<vtkArgumentScope> newScope;
64 if (vtkPVStringFormatter::ScopeStack.empty())
66 newScope = std::make_shared<vtkArgumentScope>();
70 newScope = std::make_shared<vtkArgumentScope>(*vtkPVStringFormatter::ScopeStack.top());
72 vtkPVStringFormatter::Push(*newScope, args...);
73 vtkPVStringFormatter::ScopeStack.push(newScope);
86 template <
typename... Args>
87 static void PushScope(
const char* scopeName, Args&&... args)
89 std::shared_ptr<vtkArgumentScope> newScope;
91 if (vtkPVStringFormatter::ScopeStack.empty())
93 newScope = std::make_shared<vtkArgumentScope>();
97 newScope = std::make_shared<vtkArgumentScope>(*vtkPVStringFormatter::ScopeStack.top());
99 vtkPVStringFormatter::Push(*newScope, scopeName, args...);
100 vtkPVStringFormatter::ScopeStack.push(newScope);
106 static void PopScope();
112 static std::string Format(
const std::string& formattableString);
122 using char_type = fmt::format_context::char_type;
127 struct vtkNamedArgument
163 std::chrono::time_point<std::chrono::system_clock>
TimePoint;
170 : Type(ValueType::
NONE)
175 : Type(ValueType::INT)
181 : Type(ValueType::UNSIGNED)
187 : Type(ValueType::LONG_LONG)
193 : Type(ValueType::UNSIGNED_LONG_LONG)
194 , UnsignedLongLong(value)
199 : Type(ValueType::BOOL)
205 : Type(ValueType::CHAR)
211 : Type(ValueType::
FLOAT)
217 : Type(ValueType::DOUBLE)
223 : Type(ValueType::LONG_DOUBLE)
229 : Type(ValueType::STRING)
234 Value(
const std::basic_string<char_type>& value)
235 : Type(ValueType::STRING)
240 Value(
const std::chrono::time_point<std::chrono::system_clock>& value)
241 : Type(ValueType::TIME_POINT)
246 Value(
const std::vector<double>& values)
247 : Type(ValueType::DOUBLE_VECTOR)
248 , DoubleVector(values)
254 this->Type = value.
Type;
258 this->Int = value.
Int;
260 case ValueType::UNSIGNED:
263 case ValueType::LONG_LONG:
266 case ValueType::UNSIGNED_LONG_LONG:
269 case ValueType::BOOL:
270 this->Bool = value.
Bool;
272 case ValueType::CHAR:
273 this->Char = value.
Char;
276 this->Float = value.
Float;
278 case ValueType::DOUBLE:
279 this->Double = value.
Double;
281 case ValueType::LONG_DOUBLE:
284 case ValueType::STRING:
285 new (&this->String) std::basic_string<char_type>(value.
String);
287 case ValueType::TIME_POINT:
290 case ValueType::DOUBLE_VECTOR:
291 new (&this->DoubleVector) std::vector<double>(value.
DoubleVector);
302 case ValueType::STRING:
303 this->String.~basic_string();
305 case ValueType::DOUBLE_VECTOR:
306 this->DoubleVector.~vector();
314 std::basic_string<char_type> Name;
317 vtkNamedArgument() =
default;
319 template <
typename DataType>
320 vtkNamedArgument(
const std::basic_string<char_type>&
name,
const DataType&
value)
326 ~vtkNamedArgument() =
default;
332 class vtkArgumentScope
335 std::vector<vtkNamedArgument> Arguments;
338 vtkArgumentScope() =
default;
340 vtkArgumentScope(
const vtkArgumentScope& other)
342 this->Arguments.reserve(other.Arguments.size());
343 for (
const auto& arg : other.Arguments)
345 this->Arguments.emplace_back(arg);
353 template <
typename T>
354 #if FMT_VERSION >= 120200 355 void AddArg(
const fmt::named_arg<T, char_type>& fmtArg)
357 void AddArg(
const fmt::detail::named_arg<char_type, T>& fmtArg)
360 bool argNotFound = std::find_if(this->Arguments.begin(), this->Arguments.end(),
361 [&fmtArg](
const vtkNamedArgument& arg)
362 {
return arg.Name == fmtArg.name; }) == this->Arguments.end();
366 vtkNamedArgument newArg(fmtArg.name, fmtArg.value);
367 this->Arguments.push_back(newArg);
371 vtkLogF(TRACE,
"Argument %s already exists. Try to add another one.", fmtArg.name);
378 std::basic_string<char_type> GetArgInfo()
const 380 std::basic_stringstream<char_type> argInfo;
381 for (
const auto& arg : this->Arguments)
383 argInfo <<
"\tName: " << arg.Name;
384 argInfo <<
"\tType: ";
385 switch (arg.Value.Type)
387 case vtkNamedArgument::ValueType::INT:
390 case vtkNamedArgument::ValueType::UNSIGNED:
391 argInfo <<
"unsigned";
393 case vtkNamedArgument::ValueType::LONG_LONG:
394 argInfo <<
"long long";
396 case vtkNamedArgument::ValueType::UNSIGNED_LONG_LONG:
397 argInfo <<
"unsigned long long";
399 case vtkNamedArgument::ValueType::BOOL:
402 case vtkNamedArgument::ValueType::CHAR:
408 case vtkNamedArgument::ValueType::DOUBLE:
411 case vtkNamedArgument::ValueType::LONG_DOUBLE:
412 argInfo <<
"long double";
414 case vtkNamedArgument::ValueType::STRING:
415 argInfo <<
"std::string";
417 case vtkNamedArgument::ValueType::TIME_POINT:
418 argInfo <<
"std::chrono::time_point<std::chrono::system_clock>";
420 case vtkNamedArgument::ValueType::DOUBLE_VECTOR:
421 argInfo <<
"std::vector<double>";
424 argInfo <<
"unknown";
429 return argInfo.str();
435 fmt::dynamic_format_arg_store<fmt::format_context> GetArgs()
const 437 fmt::dynamic_format_arg_store<fmt::format_context> args;
438 for (
const auto& arg : this->Arguments)
440 switch (arg.Value.Type)
442 case vtkNamedArgument::ValueType::INT:
443 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Int));
445 case vtkNamedArgument::ValueType::UNSIGNED:
446 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Unsigned));
448 case vtkNamedArgument::ValueType::LONG_LONG:
449 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.LongLong));
451 case vtkNamedArgument::ValueType::UNSIGNED_LONG_LONG:
452 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.UnsignedLongLong));
454 case vtkNamedArgument::ValueType::BOOL:
455 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Bool));
457 case vtkNamedArgument::ValueType::CHAR:
458 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Char));
461 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Float));
463 case vtkNamedArgument::ValueType::DOUBLE:
464 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.Double));
466 case vtkNamedArgument::ValueType::LONG_DOUBLE:
467 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.LongDouble));
469 case vtkNamedArgument::ValueType::STRING:
470 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.String));
472 case vtkNamedArgument::ValueType::TIME_POINT:
473 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.TimePoint));
475 case vtkNamedArgument::ValueType::DOUBLE_VECTOR:
476 args.push_back(fmt::arg(arg.Name.c_str(), arg.Value.DoubleVector));
488 void clear() { this->Arguments.clear(); }
494 static std::string GetArgInfo();
499 static void Push(vtkArgumentScope& vtkNotUsed(scope)) {}
504 template <
typename T0,
typename... TArgs>
505 static void Push(vtkArgumentScope& scope, T0& arg0, TArgs&... args)
508 vtkPVStringFormatter::Push(scope, args...);
514 static void Push(vtkArgumentScope& vtkNotUsed(scope),
const char* vtkNotUsed(scopeName)) {}
519 template <
typename T0,
typename... TArgs>
520 static void Push(vtkArgumentScope& scope,
const char* scopeName, T0& arg0, TArgs&... args)
522 auto scopeBasedArgName = std::string(scopeName) +
"_" + arg0.name;
523 scope.AddArg(fmt::arg(scopeBasedArgName.c_str(), arg0.value));
525 vtkPVStringFormatter::Push(scope, scopeName, args...);
528 static std::stack<std::shared_ptr<vtkArgumentScope>> ScopeStack;
531 #define PV_STRING_FORMATTER_SCOPE_0(x, y) x##y 532 #define PV_STRING_FORMATTER_SCOPE_1(x, y) PV_STRING_FORMATTER_SCOPE_0(x, y) 533 #define PV_STRING_FORMATTER_SCOPE(...) \ 534 vtkPVStringFormatter::TraceScope PV_STRING_FORMATTER_SCOPE_1(_trace_item, __LINE__)(__VA_ARGS__) 535 #define PV_STRING_FORMATTER_NAMED_SCOPE(NAME, ...) \ 536 vtkPVStringFormatter::TraceScope PV_STRING_FORMATTER_SCOPE_1(_trace_item, __LINE__)( \
#define VTKPVVTKEXTENSIONSCORE_EXPORT
void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE