1//===- EntityPointerLevelFormat.cpp ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
10#include "SSAFAnalysesCommon.h"
11#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
12#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
13#include "llvm/Support/Error.h"
14#include "llvm/Support/JSON.h"
15
16using namespace clang;
17using namespace ssaf;
18
19// Writes an EntityPointerLevel as
20// Array [
21// Object { "@" : [entity-id]},
22// [pointer-level-integer]
23// ]
24llvm::json::Value clang::ssaf::entityPointerLevelToJSON(
25 const EntityPointerLevel &EPL, JSONFormat::EntityIdToJSONFn EntityId2JSON) {
26 return llvm::json::Array{EntityId2JSON(EPL.getEntity()),
27 llvm::json::Value(EPL.getPointerLevel())};
28}
29
30llvm::Expected<EntityPointerLevel> clang::ssaf::entityPointerLevelFromJSON(
31 const llvm::json::Value &EPLData,
32 JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
33 auto *AsArr = EPLData.getAsArray();
34
35 if (!AsArr || AsArr->size() != 2)
36 return makeSawButExpectedError(
37 Saw: EPLData, Expected: "an array with exactly two elements representing "
38 "EntityId and PointerLevel, respectively");
39
40 auto *EntityIdObj = (*AsArr)[0].getAsObject();
41
42 if (!EntityIdObj)
43 return makeSawButExpectedError(Saw: (*AsArr)[0],
44 Expected: "an object representing EntityId");
45
46 llvm::Expected<EntityId> Id = EntityIdFromJSON(*EntityIdObj);
47
48 if (!Id)
49 return Id.takeError();
50
51 std::optional<uint64_t> PtrLv = (*AsArr)[1].getAsInteger();
52
53 if (!PtrLv)
54 return makeSawButExpectedError(Saw: (*AsArr)[1],
55 Expected: "an integer representing PointerLevel");
56
57 return buildEntityPointerLevel(*Id, *PtrLv);
58}
59
60llvm::json::Array clang::ssaf::entityPointerLevelSetToJSON(
61 llvm::iterator_range<EntityPointerLevelSet::const_iterator> EPLs,
62 JSONFormat::EntityIdToJSONFn EntityId2JSON) {
63 llvm::json::Array Result;
64
65 for (const auto &EPL : EPLs)
66 Result.push_back(E: entityPointerLevelToJSON(EPL, EntityId2JSON));
67 return Result;
68}
69
70Expected<EntityPointerLevelSet> clang::ssaf::entityPointerLevelSetFromJSON(
71 const llvm::json::Array &EPLsData,
72 JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
73 EntityPointerLevelSet EPLs;
74
75 for (const auto &EltData : EPLsData) {
76 llvm::Expected<EntityPointerLevel> EPL =
77 entityPointerLevelFromJSON(EPLData: EltData, EntityIdFromJSON);
78
79 if (!EPL)
80 return EPL.takeError();
81 EPLs.insert(x: *EPL);
82 }
83 return EPLs;
84}
85
86llvm::json::Array clang::ssaf::entityPointerLevelMapToJSON(
87 const std::map<EntityId, EntityPointerLevelSet> &Map,
88 JSONFormat::EntityIdToJSONFn IdToJSON) {
89 llvm::json::Array Content;
90
91 for (const auto &[Id, EPLs] : Map) {
92 Content.push_back(E: IdToJSON(Id));
93 Content.push_back(E: entityPointerLevelSetToJSON(EPLs, EntityId2JSON: IdToJSON));
94 }
95 return Content;
96}
97
98Expected<std::map<EntityId, EntityPointerLevelSet>>
99clang::ssaf::entityPointerLevelMapFromJSON(
100 const llvm::json::Array &Content,
101 JSONFormat::EntityIdFromJSONFn IdFromJSON) {
102 if (Content.size() % 2 != 0)
103 return makeSawButExpectedError(Saw: Content,
104 Expected: "an even number of elements, got %lu",
105 ExpectedArgs: static_cast<size_t>(Content.size()));
106
107 std::map<EntityId, EntityPointerLevelSet> Result;
108
109 for (size_t I = 0; I < Content.size(); I += 2) {
110 const llvm::json::Object *IdData = Content[I].getAsObject();
111
112 if (!IdData)
113 return makeSawButExpectedError(Saw: Content[I],
114 Expected: "an object representing EntityId");
115
116 auto Id = IdFromJSON(*IdData);
117
118 if (!Id)
119 return Id.takeError();
120
121 const llvm::json::Array *EPLsData = Content[I + 1].getAsArray();
122
123 if (!EPLsData)
124 return makeSawButExpectedError(
125 Saw: Content[I + 1], Expected: "an array representing EntityPointerLevelSet");
126
127 auto EPLs = entityPointerLevelSetFromJSON(EPLsData: *EPLsData, EntityIdFromJSON: IdFromJSON);
128
129 if (!EPLs)
130 return EPLs.takeError();
131 Result[*Id] = std::move(*EPLs);
132 }
133 return Result;
134}
135