blob: 7de4a63aff5f09269696f2dd94155fbd88c39f3a [file]
//===- EntityPointerLevelFormat.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
#include "SSAFAnalysesCommon.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
using namespace clang;
using namespace ssaf;
// Writes an EntityPointerLevel as
// Array [
// Object { "@" : [entity-id]},
// [pointer-level-integer]
// ]
llvm::json::Value clang::ssaf::entityPointerLevelToJSON(
const EntityPointerLevel &EPL, JSONFormat::EntityIdToJSONFn EntityId2JSON) {
return llvm::json::Array{EntityId2JSON(EPL.getEntity()),
llvm::json::Value(EPL.getPointerLevel())};
}
llvm::Expected<EntityPointerLevel> clang::ssaf::entityPointerLevelFromJSON(
const llvm::json::Value &EPLData,
JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
auto *AsArr = EPLData.getAsArray();
if (!AsArr || AsArr->size() != 2)
return makeSawButExpectedError(
EPLData, "an array with exactly two elements representing "
"EntityId and PointerLevel, respectively");
auto *EntityIdObj = (*AsArr)[0].getAsObject();
if (!EntityIdObj)
return makeSawButExpectedError((*AsArr)[0],
"an object representing EntityId");
llvm::Expected<EntityId> Id = EntityIdFromJSON(*EntityIdObj);
if (!Id)
return Id.takeError();
std::optional<uint64_t> PtrLv = (*AsArr)[1].getAsInteger();
if (!PtrLv)
return makeSawButExpectedError((*AsArr)[1],
"an integer representing PointerLevel");
return buildEntityPointerLevel(*Id, *PtrLv);
}
llvm::json::Array clang::ssaf::entityPointerLevelSetToJSON(
llvm::iterator_range<EntityPointerLevelSet::const_iterator> EPLs,
JSONFormat::EntityIdToJSONFn EntityId2JSON) {
llvm::json::Array Result;
for (const auto &EPL : EPLs)
Result.push_back(entityPointerLevelToJSON(EPL, EntityId2JSON));
return Result;
}
Expected<EntityPointerLevelSet> clang::ssaf::entityPointerLevelSetFromJSON(
const llvm::json::Array &EPLsData,
JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
EntityPointerLevelSet EPLs;
for (const auto &EltData : EPLsData) {
llvm::Expected<EntityPointerLevel> EPL =
entityPointerLevelFromJSON(EltData, EntityIdFromJSON);
if (!EPL)
return EPL.takeError();
EPLs.insert(*EPL);
}
return EPLs;
}
llvm::json::Array clang::ssaf::entityPointerLevelMapToJSON(
const std::map<EntityId, EntityPointerLevelSet> &Map,
JSONFormat::EntityIdToJSONFn IdToJSON) {
llvm::json::Array Content;
for (const auto &[Id, EPLs] : Map) {
Content.push_back(IdToJSON(Id));
Content.push_back(entityPointerLevelSetToJSON(EPLs, IdToJSON));
}
return Content;
}
Expected<std::map<EntityId, EntityPointerLevelSet>>
clang::ssaf::entityPointerLevelMapFromJSON(
const llvm::json::Array &Content,
JSONFormat::EntityIdFromJSONFn IdFromJSON) {
if (Content.size() % 2 != 0)
return makeSawButExpectedError(Content,
"an even number of elements, got %lu",
static_cast<size_t>(Content.size()));
std::map<EntityId, EntityPointerLevelSet> Result;
for (size_t I = 0; I < Content.size(); I += 2) {
const llvm::json::Object *IdData = Content[I].getAsObject();
if (!IdData)
return makeSawButExpectedError(Content[I],
"an object representing EntityId");
auto Id = IdFromJSON(*IdData);
if (!Id)
return Id.takeError();
const llvm::json::Array *EPLsData = Content[I + 1].getAsArray();
if (!EPLsData)
return makeSawButExpectedError(
Content[I + 1], "an array representing EntityPointerLevelSet");
auto EPLs = entityPointerLevelSetFromJSON(*EPLsData, IdFromJSON);
if (!EPLs)
return EPLs.takeError();
Result[*Id] = std::move(*EPLs);
}
return Result;
}