Results.cpp revision 9de4dec874148d30cc1d4c498d38cd048a8164ca
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
20using namespace lldb_perf;
21
22static void
23AddResultToArray (CFCMutableArray &array, Results::Result *result);
24
25static void
26AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result);
27
28static void
29AddResultToArray (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
98static void
99AddResultToDictionary (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}
157void
158Results::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    CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)out_path, strlen(out_path), FALSE);
171
172    CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL);
173#endif
174}
175
176void
177Results::Dictionary::AddUnsigned (const char *name, const char *description, uint64_t value)
178{
179    assert (name && name[0]);
180    if (description && description[0])
181    {
182        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
183        value_dict_ap->AddString("description", NULL, description);
184        value_dict_ap->AddUnsigned("value", NULL, value);
185        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
186    }
187    else
188        m_dictionary[std::string(name)] = ResultSP (new Unsigned (name, description, value));
189}
190
191void
192Results::Dictionary::AddDouble (const char *name, const char *description, double value)
193{
194    assert (name && name[0]);
195
196    if (description && description[0])
197    {
198        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
199        value_dict_ap->AddString("description", NULL, description);
200        value_dict_ap->AddDouble("value", NULL, value);
201        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
202    }
203    else
204        m_dictionary[std::string(name)] = ResultSP (new Double (name, description, value));
205}
206void
207Results::Dictionary::AddString (const char *name, const char *description, const char *value)
208{
209    assert (name && name[0]);
210    if (description && description[0])
211    {
212        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
213        value_dict_ap->AddString("description", NULL, description);
214        value_dict_ap->AddString("value", NULL, value);
215        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
216    }
217    else
218        m_dictionary[std::string(name)] = ResultSP (new String (name, description, value));
219}
220
221void
222Results::Dictionary::Add (const char *name, const char *description, const ResultSP &result_sp)
223{
224    assert (name && name[0]);
225    if (description && description[0])
226    {
227        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
228        value_dict_ap->AddString("description", NULL, description);
229        value_dict_ap->Add("value", NULL, result_sp);
230        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
231    }
232    else
233        m_dictionary[std::string(name)] = result_sp;
234}
235
236void
237Results::Dictionary::ForEach (const std::function <bool (const std::string &, const ResultSP &)> &callback)
238{
239    collection::const_iterator pos, end = m_dictionary.end();
240    for (pos = m_dictionary.begin(); pos != end; ++pos)
241    {
242        if (callback (pos->first.c_str(), pos->second) == false)
243            return;
244    }
245}
246
247
248
249void
250Results::Array::Append (const ResultSP &result_sp)
251{
252    m_array.push_back (result_sp);
253}
254
255void
256Results::Array::ForEach (const std::function <bool (const ResultSP &)> &callback)
257{
258    collection::const_iterator pos, end = m_array.end();
259    for (pos = m_array.begin(); pos != end; ++pos)
260    {
261        if (callback (*pos) == false)
262            return;
263    }
264}
265
266
267
268