| #include "cmInstrumentationQuery.h" |
| |
| #include <algorithm> |
| #include <ctime> |
| #include <functional> |
| #include <iostream> |
| #include <iterator> |
| #include <set> |
| #include <vector> |
| |
| #include <cmext/string_view> |
| |
| #include <cm3p/json/value.h> |
| |
| #include "cmJSONHelpers.h" |
| #include "cmStringAlgorithms.h" |
| |
| std::vector<std::string> const cmInstrumentationQuery::QueryString{ |
| "staticSystemInformation", "dynamicSystemInformation" |
| }; |
| std::vector<std::string> const cmInstrumentationQuery::HookString{ |
| "postGenerate", "preBuild", "postBuild", |
| "preCMakeBuild", "postCMakeBuild", "postTest", |
| "postInstall", "prepareForCDash", "manual" |
| }; |
| |
| namespace ErrorMessages { |
| using ErrorGenerator = |
| std::function<void(Json::Value const*, cmJSONState* state)>; |
| ErrorGenerator ErrorGeneratorBuilder(std::string const& errorMessage) |
| { |
| return [errorMessage](Json::Value const* value, cmJSONState* state) -> void { |
| state->AddErrorAtValue(errorMessage, value); |
| }; |
| }; |
| |
| static ErrorGenerator InvalidArray = ErrorGeneratorBuilder("Invalid Array"); |
| JsonErrors::ErrorGenerator InvalidRootQueryObject( |
| JsonErrors::ObjectError errorType, Json::Value::Members const& extraFields) |
| { |
| return JsonErrors::INVALID_NAMED_OBJECT( |
| [](Json::Value const*, cmJSONState*) -> std::string { |
| return "root object"; |
| })(errorType, extraFields); |
| } |
| }; |
| |
| using JSONHelperBuilder = cmJSONHelperBuilder; |
| |
| template <typename E> |
| static std::function<bool(E&, Json::Value const*, cmJSONState*)> EnumHelper( |
| std::vector<std::string> const toString, std::string const& type) |
| { |
| return [toString, type](E& out, Json::Value const* value, |
| cmJSONState* state) -> bool { |
| for (size_t i = 0; i < toString.size(); ++i) { |
| if (value->asString() == toString[i]) { |
| out = (E)i; |
| return true; |
| } |
| } |
| state->AddErrorAtValue( |
| cmStrCat("Not a valid ", type, ": \"", value->asString(), '"'), value); |
| return false; |
| }; |
| } |
| static auto const QueryHelper = EnumHelper<cmInstrumentationQuery::Query>( |
| cmInstrumentationQuery::QueryString, "query"); |
| static auto const QueryListHelper = |
| JSONHelperBuilder::Vector<cmInstrumentationQuery::Query>( |
| ErrorMessages::InvalidArray, QueryHelper); |
| static auto const HookHelper = EnumHelper<cmInstrumentationQuery::Hook>( |
| cmInstrumentationQuery::HookString, "hook"); |
| static auto const HookListHelper = |
| JSONHelperBuilder::Vector<cmInstrumentationQuery::Hook>( |
| ErrorMessages::InvalidArray, HookHelper); |
| static auto const CallbackHelper = JSONHelperBuilder::String(); |
| static auto const CallbackListHelper = JSONHelperBuilder::Vector<std::string>( |
| ErrorMessages::InvalidArray, CallbackHelper); |
| static auto const VersionHelper = JSONHelperBuilder::Int(); |
| |
| using QueryRoot = cmInstrumentationQuery::QueryJSONRoot; |
| |
| static auto const QueryRootHelper = |
| JSONHelperBuilder::Object<QueryRoot>(ErrorMessages::InvalidRootQueryObject, |
| false) |
| .Bind("version"_s, &QueryRoot::version, VersionHelper, true) |
| .Bind("queries"_s, &QueryRoot::queries, QueryListHelper, false) |
| .Bind("hooks"_s, &QueryRoot::hooks, HookListHelper, false) |
| .Bind("callbacks"_s, &QueryRoot::callbacks, CallbackListHelper, false); |
| |
| bool cmInstrumentationQuery::ReadJSON(std::string const& filename, |
| std::string& errorMessage, |
| std::set<Query>& queries, |
| std::set<Hook>& hooks, |
| std::vector<std::string>& callbacks) |
| { |
| Json::Value root; |
| this->parseState = cmJSONState(filename, &root); |
| if (!this->parseState.errors.empty()) { |
| std::cerr << this->parseState.GetErrorMessage(true) << std::endl; |
| return false; |
| } |
| if (!QueryRootHelper(this->queryRoot, &root, &this->parseState)) { |
| errorMessage = this->parseState.GetErrorMessage(true); |
| return false; |
| } |
| std::move(this->queryRoot.queries.begin(), this->queryRoot.queries.end(), |
| std::inserter(queries, queries.end())); |
| std::move(this->queryRoot.hooks.begin(), this->queryRoot.hooks.end(), |
| std::inserter(hooks, hooks.end())); |
| std::move(this->queryRoot.callbacks.begin(), this->queryRoot.callbacks.end(), |
| std::back_inserter(callbacks)); |
| return true; |
| } |