| #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::OptionString{ | |
| "staticSystemInformation", "dynamicSystemInformation", "cdashSubmit", | |
| "cdashVerbose", "trace" | |
| }; | |
| std::vector<std::string> const cmInstrumentationQuery::HookString{ | |
| "postGenerate", "preBuild", "postBuild", "preCMakeBuild", | |
| "postCMakeBuild", "postCTest", "postCMakeInstall", "postCMakeWorkflow", | |
| "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 OptionHelper = EnumHelper<cmInstrumentationQuery::Option>( | |
| cmInstrumentationQuery::OptionString, "option"); | |
| static auto const QueryListHelper = | |
| JSONHelperBuilder::Vector<cmInstrumentationQuery::Option>( | |
| ErrorMessages::InvalidArray, OptionHelper); | |
| 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("options"_s, &QueryRoot::options, 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<Option>& options, | |
| 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.options.begin(), this->queryRoot.options.end(), | |
| std::inserter(options, options.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; | |
| } |