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    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
179Results::ResultSP
180Results::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
195Results::ResultSP
196Results::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}
211Results::ResultSP
212Results::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
227Results::ResultSP
228Results::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
243void
244Results::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
256Results::ResultSP
257Results::Array::Append (const ResultSP &result_sp)
258{
259    m_array.push_back (result_sp);
260    return result_sp;
261}
262
263void
264Results::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