cmInstrumentationQuery.cxx 4.2 KB

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