1 //===-- 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
20 using namespace lldb_perf;
21
22 static void
23 AddResultToArray (CFCMutableArray &array, Results::Result *result);
24
25 static void
26 AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result);
27
28 static void
AddResultToArray(CFCMutableArray & parent_array,Results::Result * result)29 AddResultToArray (CFCMutableArray &parent_array, Results::Result *result)
30 {
31 switch (result->GetType())
32 {
33 case Results::Result::Type::Invalid:
34 break;
35
36 case Results::Result::Type::Array:
37 {
38 Results::Array *value = result->GetAsArray();
39 CFCMutableArray array;
40 value->ForEach([&array](const Results::ResultSP &value_sp) -> bool
41 {
42 AddResultToArray (array, value_sp.get());
43 return true;
44 });
45 parent_array.AppendValue(array.get(), true);
46 }
47 break;
48
49 case Results::Result::Type::Dictionary:
50 {
51 Results::Dictionary *value = result->GetAsDictionary();
52 CFCMutableDictionary dict;
53 value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool
54 {
55 AddResultToDictionary (dict, key.c_str(), value_sp.get());
56 return true;
57 });
58 if (result->GetDescription())
59 {
60 dict.AddValueCString(CFSTR("description"), result->GetDescription());
61 }
62 parent_array.AppendValue(dict.get(), true);
63 }
64 break;
65
66 case Results::Result::Type::Double:
67 {
68 double d = result->GetAsDouble()->GetValue();
69 CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &d));
70 if (cf_number.get())
71 parent_array.AppendValue(cf_number.get(), true);
72 }
73 break;
74 case Results::Result::Type::String:
75 {
76 CFCString cfstr (result->GetAsString()->GetValue());
77 if (cfstr.get())
78 parent_array.AppendValue(cfstr.get(), true);
79 }
80 break;
81
82 case Results::Result::Type::Unsigned:
83 {
84 uint64_t uval64 = result->GetAsUnsigned()->GetValue();
85 CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &uval64));
86 if (cf_number.get())
87 parent_array.AppendValue(cf_number.get(), true);
88 }
89 break;
90
91 default:
92 assert (!"unhandled result");
93 break;
94 }
95 }
96
97
98 static void
AddResultToDictionary(CFCMutableDictionary & parent_dict,const char * key,Results::Result * result)99 AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result)
100 {
101 assert (key && key[0]);
102 CFCString cf_key(key);
103 switch (result->GetType())
104 {
105 case Results::Result::Type::Invalid:
106 break;
107
108 case Results::Result::Type::Array:
109 {
110 Results::Array *value = result->GetAsArray();
111 CFCMutableArray array;
112 value->ForEach([&array](const Results::ResultSP &value_sp) -> bool
113 {
114 AddResultToArray (array, value_sp.get());
115 return true;
116 });
117 parent_dict.AddValue(cf_key.get(), array.get(), true);
118 }
119 break;
120 case Results::Result::Type::Dictionary:
121 {
122 Results::Dictionary *value = result->GetAsDictionary();
123 CFCMutableDictionary dict;
124 value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool
125 {
126 AddResultToDictionary (dict, key.c_str(), value_sp.get());
127 return true;
128 });
129 if (result->GetDescription())
130 {
131 dict.AddValueCString(CFSTR("description"), result->GetDescription());
132 }
133 parent_dict.AddValue(cf_key.get(), dict.get(), true);
134 }
135 break;
136 case Results::Result::Type::Double:
137 {
138 parent_dict.SetValueDouble(cf_key.get(), result->GetAsDouble()->GetValue(), true);
139 }
140 break;
141 case Results::Result::Type::String:
142 {
143 parent_dict.SetValueCString(cf_key.get(), result->GetAsString()->GetValue(), true);
144 }
145 break;
146
147 case Results::Result::Type::Unsigned:
148 {
149 parent_dict.SetValueUInt64 (cf_key.get(), result->GetAsUnsigned()->GetValue(), true);
150 }
151 break;
152 default:
153 assert (!"unhandled result");
154 break;
155 }
156 }
157 void
Write(const char * out_path)158 Results::Write (const char *out_path)
159 {
160 #ifdef __APPLE__
161 CFCMutableDictionary dict;
162
163 m_results.ForEach([&dict](const std::string &key, const ResultSP &value_sp) -> bool
164 {
165 AddResultToDictionary (dict, key.c_str(), value_sp.get());
166 return true;
167 });
168 CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, dict.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL);
169
170 if (out_path == NULL)
171 out_path = "/dev/stdout";
172
173 CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)out_path, strlen(out_path), FALSE);
174
175 CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL);
176 #endif
177 }
178
179 Results::ResultSP
AddUnsigned(const char * name,const char * description,uint64_t value)180 Results::Dictionary::AddUnsigned (const char *name, const char *description, uint64_t value)
181 {
182 assert (name && name[0]);
183 if (description && description[0])
184 {
185 std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
186 value_dict_ap->AddString("description", NULL, description);
187 value_dict_ap->AddUnsigned("value", NULL, value);
188 m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
189 }
190 else
191 m_dictionary[std::string(name)] = ResultSP (new Unsigned (name, description, value));
192 return m_dictionary[std::string(name)];
193 }
194
195 Results::ResultSP
AddDouble(const char * name,const char * description,double value)196 Results::Dictionary::AddDouble (const char *name, const char *description, double value)
197 {
198 assert (name && name[0]);
199
200 if (description && description[0])
201 {
202 std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
203 value_dict_ap->AddString("description", NULL, description);
204 value_dict_ap->AddDouble("value", NULL, value);
205 m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
206 }
207 else
208 m_dictionary[std::string(name)] = ResultSP (new Double (name, description, value));
209 return m_dictionary[std::string(name)];
210 }
211 Results::ResultSP
AddString(const char * name,const char * description,const char * value)212 Results::Dictionary::AddString (const char *name, const char *description, const char *value)
213 {
214 assert (name && name[0]);
215 if (description && description[0])
216 {
217 std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
218 value_dict_ap->AddString("description", NULL, description);
219 value_dict_ap->AddString("value", NULL, value);
220 m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
221 }
222 else
223 m_dictionary[std::string(name)] = ResultSP (new String (name, description, value));
224 return m_dictionary[std::string(name)];
225 }
226
227 Results::ResultSP
Add(const char * name,const char * description,const ResultSP & result_sp)228 Results::Dictionary::Add (const char *name, const char *description, const ResultSP &result_sp)
229 {
230 assert (name && name[0]);
231 if (description && description[0])
232 {
233 std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
234 value_dict_ap->AddString("description", NULL, description);
235 value_dict_ap->Add("value", NULL, result_sp);
236 m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
237 }
238 else
239 m_dictionary[std::string(name)] = result_sp;
240 return m_dictionary[std::string(name)];
241 }
242
243 void
ForEach(const std::function<bool (const std::string &,const ResultSP &)> & callback)244 Results::Dictionary::ForEach (const std::function <bool (const std::string &, const ResultSP &)> &callback)
245 {
246 collection::const_iterator pos, end = m_dictionary.end();
247 for (pos = m_dictionary.begin(); pos != end; ++pos)
248 {
249 if (callback (pos->first.c_str(), pos->second) == false)
250 return;
251 }
252 }
253
254
255
256 Results::ResultSP
Append(const ResultSP & result_sp)257 Results::Array::Append (const ResultSP &result_sp)
258 {
259 m_array.push_back (result_sp);
260 return result_sp;
261 }
262
263 void
ForEach(const std::function<bool (const ResultSP &)> & callback)264 Results::Array::ForEach (const std::function <bool (const ResultSP &)> &callback)
265 {
266 collection::const_iterator pos, end = m_array.end();
267 for (pos = m_array.begin(); pos != end; ++pos)
268 {
269 if (callback (*pos) == false)
270 return;
271 }
272 }
273
274
275
276