blob: a4cdce525e2cb8904c983c811a588575aae0f12d [file] [log] [blame]
Greg Clayton880afc52013-03-22 02:31:35 +00001//===-- Results.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Results.h"
11#include <assert.h>
12
13#ifdef __APPLE__
14#include "CFCMutableArray.h"
15#include "CFCMutableDictionary.h"
16#include "CFCReleaser.h"
17#include "CFCString.h"
18#endif
19
20using namespace lldb_perf;
21
Kate Stoneb9c1b512016-09-06 20:57:50 +000022static void AddResultToArray(CFCMutableArray &array, Results::Result *result);
Greg Clayton880afc52013-03-22 02:31:35 +000023
Kate Stoneb9c1b512016-09-06 20:57:50 +000024static void AddResultToDictionary(CFCMutableDictionary &parent_dict,
25 const char *key, Results::Result *result);
Greg Clayton880afc52013-03-22 02:31:35 +000026
Kate Stoneb9c1b512016-09-06 20:57:50 +000027static void AddResultToArray(CFCMutableArray &parent_array,
28 Results::Result *result) {
29 switch (result->GetType()) {
30 case Results::Result::Type::Invalid:
31 break;
Greg Clayton880afc52013-03-22 02:31:35 +000032
Kate Stoneb9c1b512016-09-06 20:57:50 +000033 case Results::Result::Type::Array: {
34 Results::Array *value = result->GetAsArray();
35 CFCMutableArray array;
36 value->ForEach([&array](const Results::ResultSP &value_sp) -> bool {
37 AddResultToArray(array, value_sp.get());
38 return true;
39 });
40 parent_array.AppendValue(array.get(), true);
41 } break;
Greg Clayton880afc52013-03-22 02:31:35 +000042
Kate Stoneb9c1b512016-09-06 20:57:50 +000043 case Results::Result::Type::Dictionary: {
44 Results::Dictionary *value = result->GetAsDictionary();
Greg Clayton880afc52013-03-22 02:31:35 +000045 CFCMutableDictionary dict;
Kate Stoneb9c1b512016-09-06 20:57:50 +000046 value->ForEach([&dict](const std::string &key,
47 const Results::ResultSP &value_sp) -> bool {
48 AddResultToDictionary(dict, key.c_str(), value_sp.get());
49 return true;
50 });
51 if (result->GetDescription()) {
52 dict.AddValueCString(CFSTR("description"), result->GetDescription());
53 }
54 parent_array.AppendValue(dict.get(), true);
55 } break;
Greg Clayton5c78d992013-03-23 00:49:30 +000056
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 case Results::Result::Type::Double: {
58 double d = result->GetAsDouble()->GetValue();
59 CFCReleaser<CFNumberRef> cf_number(
60 ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &d));
61 if (cf_number.get())
62 parent_array.AppendValue(cf_number.get(), true);
63 } break;
64 case Results::Result::Type::String: {
65 CFCString cfstr(result->GetAsString()->GetValue());
66 if (cfstr.get())
67 parent_array.AppendValue(cfstr.get(), true);
68 } break;
69
70 case Results::Result::Type::Unsigned: {
71 uint64_t uval64 = result->GetAsUnsigned()->GetValue();
72 CFCReleaser<CFNumberRef> cf_number(
73 ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &uval64));
74 if (cf_number.get())
75 parent_array.AppendValue(cf_number.get(), true);
76 } break;
77
78 default:
David Blaikiea322f362017-01-06 00:38:06 +000079 llvm_unreachable("unhandled result");
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 }
81}
82
83static void AddResultToDictionary(CFCMutableDictionary &parent_dict,
84 const char *key, Results::Result *result) {
85 assert(key && key[0]);
86 CFCString cf_key(key);
87 switch (result->GetType()) {
88 case Results::Result::Type::Invalid:
89 break;
90
91 case Results::Result::Type::Array: {
92 Results::Array *value = result->GetAsArray();
93 CFCMutableArray array;
94 value->ForEach([&array](const Results::ResultSP &value_sp) -> bool {
95 AddResultToArray(array, value_sp.get());
96 return true;
97 });
98 parent_dict.AddValue(cf_key.get(), array.get(), true);
99 } break;
100 case Results::Result::Type::Dictionary: {
101 Results::Dictionary *value = result->GetAsDictionary();
102 CFCMutableDictionary dict;
103 value->ForEach([&dict](const std::string &key,
104 const Results::ResultSP &value_sp) -> bool {
105 AddResultToDictionary(dict, key.c_str(), value_sp.get());
106 return true;
107 });
108 if (result->GetDescription()) {
109 dict.AddValueCString(CFSTR("description"), result->GetDescription());
110 }
111 parent_dict.AddValue(cf_key.get(), dict.get(), true);
112 } break;
113 case Results::Result::Type::Double: {
114 parent_dict.SetValueDouble(cf_key.get(), result->GetAsDouble()->GetValue(),
115 true);
116 } break;
117 case Results::Result::Type::String: {
118 parent_dict.SetValueCString(cf_key.get(), result->GetAsString()->GetValue(),
119 true);
120 } break;
121
122 case Results::Result::Type::Unsigned: {
123 parent_dict.SetValueUInt64(cf_key.get(),
124 result->GetAsUnsigned()->GetValue(), true);
125 } break;
126 default:
David Blaikiea322f362017-01-06 00:38:06 +0000127 llvm_unreachable("unhandled result");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 }
129}
130void Results::Write(const char *out_path) {
131#ifdef __APPLE__
132 CFCMutableDictionary dict;
133
134 m_results.ForEach(
135 [&dict](const std::string &key, const ResultSP &value_sp) -> bool {
136 AddResultToDictionary(dict, key.c_str(), value_sp.get());
137 return true;
138 });
139 CFDataRef xmlData = CFPropertyListCreateData(
140 kCFAllocatorDefault, dict.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL);
141
142 if (out_path == NULL)
143 out_path = "/dev/stdout";
144
145 CFURLRef file = CFURLCreateFromFileSystemRepresentation(
146 NULL, (const UInt8 *)out_path, strlen(out_path), FALSE);
147
148 CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL);
Greg Clayton880afc52013-03-22 02:31:35 +0000149#endif
150}
151
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152Results::ResultSP Results::Dictionary::AddUnsigned(const char *name,
153 const char *description,
154 uint64_t value) {
155 assert(name && name[0]);
156 if (description && description[0]) {
157 std::unique_ptr<Results::Dictionary> value_dict_ap(
158 new Results::Dictionary());
159 value_dict_ap->AddString("description", NULL, description);
160 value_dict_ap->AddUnsigned("value", NULL, value);
161 m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release());
162 } else
163 m_dictionary[std::string(name)] =
164 ResultSP(new Unsigned(name, description, value));
165 return m_dictionary[std::string(name)];
Greg Clayton880afc52013-03-22 02:31:35 +0000166}
167
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168Results::ResultSP Results::Dictionary::AddDouble(const char *name,
169 const char *description,
170 double value) {
171 assert(name && name[0]);
172
173 if (description && description[0]) {
174 std::unique_ptr<Results::Dictionary> value_dict_ap(
175 new Results::Dictionary());
176 value_dict_ap->AddString("description", NULL, description);
177 value_dict_ap->AddDouble("value", NULL, value);
178 m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release());
179 } else
180 m_dictionary[std::string(name)] =
181 ResultSP(new Double(name, description, value));
182 return m_dictionary[std::string(name)];
Greg Clayton880afc52013-03-22 02:31:35 +0000183}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184Results::ResultSP Results::Dictionary::AddString(const char *name,
185 const char *description,
186 const char *value) {
187 assert(name && name[0]);
188 if (description && description[0]) {
189 std::unique_ptr<Results::Dictionary> value_dict_ap(
190 new Results::Dictionary());
191 value_dict_ap->AddString("description", NULL, description);
192 value_dict_ap->AddString("value", NULL, value);
193 m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release());
194 } else
195 m_dictionary[std::string(name)] =
196 ResultSP(new String(name, description, value));
197 return m_dictionary[std::string(name)];
Greg Clayton880afc52013-03-22 02:31:35 +0000198}
199
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200Results::ResultSP Results::Dictionary::Add(const char *name,
201 const char *description,
202 const ResultSP &result_sp) {
203 assert(name && name[0]);
204 if (description && description[0]) {
205 std::unique_ptr<Results::Dictionary> value_dict_ap(
206 new Results::Dictionary());
207 value_dict_ap->AddString("description", NULL, description);
208 value_dict_ap->Add("value", NULL, result_sp);
209 m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release());
210 } else
211 m_dictionary[std::string(name)] = result_sp;
212 return m_dictionary[std::string(name)];
Greg Clayton880afc52013-03-22 02:31:35 +0000213}
214
Kate Stoneb9c1b512016-09-06 20:57:50 +0000215void Results::Dictionary::ForEach(
216 const std::function<bool(const std::string &, const ResultSP &)>
217 &callback) {
218 collection::const_iterator pos, end = m_dictionary.end();
219 for (pos = m_dictionary.begin(); pos != end; ++pos) {
220 if (callback(pos->first.c_str(), pos->second) == false)
221 return;
222 }
Greg Clayton880afc52013-03-22 02:31:35 +0000223}
224
Kate Stoneb9c1b512016-09-06 20:57:50 +0000225Results::ResultSP Results::Array::Append(const ResultSP &result_sp) {
226 m_array.push_back(result_sp);
227 return result_sp;
Greg Clayton880afc52013-03-22 02:31:35 +0000228}
229
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230void Results::Array::ForEach(
231 const std::function<bool(const ResultSP &)> &callback) {
232 collection::const_iterator pos, end = m_array.end();
233 for (pos = m_array.begin(); pos != end; ++pos) {
234 if (callback(*pos) == false)
235 return;
236 }
Greg Clayton880afc52013-03-22 02:31:35 +0000237}