#include "cmInstrumentationQuery.h" #include #include #include #include #include #include #include #include #include #include "cmJSONHelpers.h" #include "cmStringAlgorithms.h" std::vector const cmInstrumentationQuery::QueryString{ "staticSystemInformation", "dynamicSystemInformation" }; std::vector const cmInstrumentationQuery::HookString{ "postGenerate", "preBuild", "postBuild", "preCMakeBuild", "postCMakeBuild", "postTest", "postInstall", "prepareForCDash", "manual" }; namespace ErrorMessages { using ErrorGenerator = std::function; 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 static std::function EnumHelper( std::vector 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::QueryString, "query"); static auto const QueryListHelper = JSONHelperBuilder::Vector( ErrorMessages::InvalidArray, QueryHelper); static auto const HookHelper = EnumHelper( cmInstrumentationQuery::HookString, "hook"); static auto const HookListHelper = JSONHelperBuilder::Vector( ErrorMessages::InvalidArray, HookHelper); static auto const CallbackHelper = JSONHelperBuilder::String(); static auto const CallbackListHelper = JSONHelperBuilder::Vector( ErrorMessages::InvalidArray, CallbackHelper); static auto const VersionHelper = JSONHelperBuilder::Int(); using QueryRoot = cmInstrumentationQuery::QueryJSONRoot; static auto const QueryRootHelper = JSONHelperBuilder::Object(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& queries, std::set& hooks, std::vector& 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; }