chigraph  master
Systems programming language written for beginners in LLVM
Result.cpp
Go to the documentation of this file.
1 
3 #include "chi/Support/Result.hpp"
4 
5 #include <boost/range/adaptor/reversed.hpp>
6 
7 namespace {
8 
10 void mergeJsonIntoConservative(nlohmann::json& into, const nlohmann::json& from) {
11  for (const auto& j : nlohmann::json::iterator_wrapper(from)) {
12  if (into.find(j.key()) == into.end()) { into[j.key()] = j.value(); }
13  }
14 }
15 
16 std::string prettyPrintJson(const nlohmann::json& j, int indentLevel) {
17  std::string indentString(indentLevel * 2, ' ');
18 
19  std::string ret;
20  if (j.is_array()) {
21  ret += indentString + "[\n";
22 
23  for (const auto& elem : j) {
24  ret += prettyPrintJson(elem, indentLevel + 1);
25  ret += ",\n";
26  }
27  ret += indentString + "]";
28 
29  } else if (j.is_string()) {
30  std::string str = j;
31 
32  // replace find and indent them
33  for (auto idx = str.find('\n'); idx < str.length(); idx = str.find('\n', idx + 1)) {
34  str.insert(idx + 1, indentString); // + 1 because it inserts before
35  }
36  ret += indentString + str;
37  } else if (j.is_number()) {
38  ret += indentString + j.dump();
39  } else if (j.is_object()) {
40  for (auto iter = j.begin(); iter != j.end(); ++iter) {
41  ret += indentString + iter.key() + "\n";
42  ret += prettyPrintJson(iter.value(), indentLevel + 1) + "\n";
43  }
44  }
45  return ret;
46 }
47 
48 } // anonymous namespace
49 
50 namespace chi {
51 
52 void Result::addEntry(const char* ec, const char* overview, nlohmann::json data) {
53  assert((ec[0] == 'E' || ec[0] == 'I' || ec[0] == 'W') &&
54  "error code passed to addEntry must start with E, I , or W");
55  assert((data.is_object() || data.is_null()) &&
56  "data passed to addEntry must be a json object or {}");
57 
58  mergeJsonIntoConservative(data, contextJson());
59 
60  result_json.push_back(
61  nlohmann::json({{"errorcode", ec}, {"overview", overview}, {"data", data}}));
62  if (ec[0] == 'E') mSuccess = false;
63 }
64 
65 std::string Result::dump() const {
66  std::string ret;
67  if (result_json.size() != 0) {
68  for (auto error : result_json) {
69  if (error.find("errorcode") == error.end() || !error["errorcode"].is_string() ||
70  error.find("overview") == error.end() || !error["overview"].is_string()) {
71  return "";
72  }
73  std::string ec = error["errorcode"];
74  std::string desc = error["overview"];
75  ret += ec + ": " + desc + "\n";
76  // recursively display children
77  auto& data = error["data"];
78  ret += prettyPrintJson(data, 1);
79  }
80  }
81  return ret;
82 }
83 
84 int Result::addContext(const nlohmann::json& data) {
85  assert(data.is_object() && "Json added to context must be an object");
86 
87  static int ctxId = 0;
88 
89  mContexts.emplace(ctxId, data);
90  return ctxId++;
91 }
92 
93 void chi::Result::removeContext(int id) { mContexts.erase(id); }
94 
95 nlohmann::json Result::contextJson() const {
96  // merge all the contexts
97  auto merged = nlohmann::json::object();
98 
99  for (const auto& ctx : mContexts | boost::adaptors::reversed) {
100  mergeJsonIntoConservative(merged, ctx.second);
101  }
102 
103  return merged;
104 }
105 
106 Result operator+(const Result& lhs, const Result& rhs) {
107  Result ret;
108  ret.mSuccess = lhs.success() && rhs.success(); // if either of them are false, then result is
109 
110  // copy each of the results in
111  std::transform(lhs.result_json.begin(), lhs.result_json.end(),
112  std::back_inserter(ret.result_json), [&](nlohmann::json j) {
113  // apply the context
114  mergeJsonIntoConservative(j["data"], rhs.contextJson());
115  return j;
116  });
117  std::transform(rhs.result_json.begin(), rhs.result_json.end(),
118  std::back_inserter(ret.result_json), [&](nlohmann::json j) {
119  // apply context
120  mergeJsonIntoConservative(j["data"], lhs.contextJson());
121  return j;
122  });
123 
124  return ret;
125 }
126 
127 Result& operator+=(Result& lhs, const Result& rhs) {
128  lhs.mSuccess = lhs.success() && rhs.success(); // if either of them are false, then result is
129 
130  // change the existing entires in lhs to have rhs's context
131  for (auto& entry : lhs.result_json) {
132  mergeJsonIntoConservative(entry["data"], rhs.contextJson());
133  }
134 
135  // copy each of the results in and fix context
136  std::transform(rhs.result_json.begin(), rhs.result_json.end(),
137  std::back_inserter(lhs.result_json), [&](nlohmann::json j) {
138  mergeJsonIntoConservative(j["data"], lhs.contextJson());
139  return j;
140  });
141 
142  return lhs;
143 }
144 
145 } // namespace chi
std::string dump() const
Dump to a pretty-printed error message.
Definition: Result.cpp:65
void addEntry(const char *ec, const char *overview, nlohmann::json data)
Add a entry to the result, either a warning or an error.
Definition: Result.cpp:52
nlohmann::json contextJson() const
Get the JSON associated with the context that&#39;s been added.
Definition: Result.cpp:95
bool mSuccess
If it&#39;s successful.
Definition: Result.hpp:155
nlohmann::json result_json
The result JSON.
Definition: Result.hpp:152
Defines the Result class and related functions.
Result operator+(const Result &lhs, const Result &rhs)
Append two Result objects.
Definition: Result.cpp:106
int addContext(const nlohmann::json &data)
Add some json that will ALWAYS be merged with entries that are added and when results are added to th...
Definition: Result.cpp:84
bool success() const
Success test.
Definition: Result.hpp:141
Result & operator+=(Result &lhs, const Result &rhs)
Append one result to an existing one.
Definition: Result.cpp:127
The namespace where chigraph lives.
The result object, used for identifiying errors with good diagnostics.
Definition: Result.hpp:72
void removeContext(int id)
Removes a previously added context.
Definition: Result.cpp:93