cmInstrumentationQuery.cxx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "cmInstrumentationQuery.h"
  2. #include <algorithm>
  3. #include <ctime>
  4. #include <functional>
  5. #include <iostream>
  6. #include <iterator>
  7. #include <set>
  8. #include <vector>
  9. #include <cmext/string_view>
  10. #include <cm3p/json/value.h>
  11. #include "cmJSONHelpers.h"
  12. #include "cmStringAlgorithms.h"
  13. std::vector<std::string> const cmInstrumentationQuery::OptionString{
  14. "staticSystemInformation", "dynamicSystemInformation", "cdashSubmit",
  15. "cdashVerbose", "trace"
  16. };
  17. std::vector<std::string> const cmInstrumentationQuery::HookString{
  18. "postGenerate", "preBuild", "postBuild",
  19. "preCMakeBuild", "postCMakeBuild", "postCTest",
  20. "postCMakeInstall", "prepareForCDash", "manual"
  21. };
  22. namespace ErrorMessages {
  23. using ErrorGenerator =
  24. std::function<void(Json::Value const*, cmJSONState* state)>;
  25. ErrorGenerator ErrorGeneratorBuilder(std::string const& errorMessage)
  26. {
  27. return [errorMessage](Json::Value const* value, cmJSONState* state) -> void {
  28. state->AddErrorAtValue(errorMessage, value);
  29. };
  30. };
  31. static ErrorGenerator InvalidArray = ErrorGeneratorBuilder("Invalid Array");
  32. JsonErrors::ErrorGenerator InvalidRootQueryObject(
  33. JsonErrors::ObjectError errorType, Json::Value::Members const& extraFields)
  34. {
  35. return JsonErrors::INVALID_NAMED_OBJECT(
  36. [](Json::Value const*, cmJSONState*) -> std::string {
  37. return "root object";
  38. })(errorType, extraFields);
  39. }
  40. };
  41. using JSONHelperBuilder = cmJSONHelperBuilder;
  42. template <typename E>
  43. static std::function<bool(E&, Json::Value const*, cmJSONState*)> EnumHelper(
  44. std::vector<std::string> const toString, std::string const& type)
  45. {
  46. return [toString, type](E& out, Json::Value const* value,
  47. cmJSONState* state) -> bool {
  48. for (size_t i = 0; i < toString.size(); ++i) {
  49. if (value->asString() == toString[i]) {
  50. out = (E)i;
  51. return true;
  52. }
  53. }
  54. state->AddErrorAtValue(
  55. cmStrCat("Not a valid ", type, ": \"", value->asString(), '"'), value);
  56. return false;
  57. };
  58. }
  59. static auto const OptionHelper = EnumHelper<cmInstrumentationQuery::Option>(
  60. cmInstrumentationQuery::OptionString, "option");
  61. static auto const QueryListHelper =
  62. JSONHelperBuilder::Vector<cmInstrumentationQuery::Option>(
  63. ErrorMessages::InvalidArray, OptionHelper);
  64. static auto const HookHelper = EnumHelper<cmInstrumentationQuery::Hook>(
  65. cmInstrumentationQuery::HookString, "hook");
  66. static auto const HookListHelper =
  67. JSONHelperBuilder::Vector<cmInstrumentationQuery::Hook>(
  68. ErrorMessages::InvalidArray, HookHelper);
  69. static auto const CallbackHelper = JSONHelperBuilder::String();
  70. static auto const CallbackListHelper = JSONHelperBuilder::Vector<std::string>(
  71. ErrorMessages::InvalidArray, CallbackHelper);
  72. static auto const VersionHelper = JSONHelperBuilder::Int();
  73. using QueryRoot = cmInstrumentationQuery::QueryJSONRoot;
  74. static auto const QueryRootHelper =
  75. JSONHelperBuilder::Object<QueryRoot>(ErrorMessages::InvalidRootQueryObject,
  76. false)
  77. .Bind("version"_s, &QueryRoot::version, VersionHelper, true)
  78. .Bind("options"_s, &QueryRoot::options, QueryListHelper, false)
  79. .Bind("hooks"_s, &QueryRoot::hooks, HookListHelper, false)
  80. .Bind("callbacks"_s, &QueryRoot::callbacks, CallbackListHelper, false);
  81. bool cmInstrumentationQuery::ReadJSON(std::string const& filename,
  82. std::string& errorMessage,
  83. std::set<Option>& options,
  84. std::set<Hook>& hooks,
  85. std::vector<std::string>& callbacks)
  86. {
  87. Json::Value root;
  88. this->parseState = cmJSONState(filename, &root);
  89. if (!this->parseState.errors.empty()) {
  90. std::cerr << this->parseState.GetErrorMessage(true) << std::endl;
  91. return false;
  92. }
  93. if (!QueryRootHelper(this->queryRoot, &root, &this->parseState)) {
  94. errorMessage = this->parseState.GetErrorMessage(true);
  95. return false;
  96. }
  97. std::move(this->queryRoot.options.begin(), this->queryRoot.options.end(),
  98. std::inserter(options, options.end()));
  99. std::move(this->queryRoot.hooks.begin(), this->queryRoot.hooks.end(),
  100. std::inserter(hooks, hooks.end()));
  101. std::move(this->queryRoot.callbacks.begin(), this->queryRoot.callbacks.end(),
  102. std::back_inserter(callbacks));
  103. return true;
  104. }