1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-05-10 07:10:32 +08:00
CMake/Source/cmInstrumentationQuery.cxx

116 lines
4.2 KiB
C++

#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;
}