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 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 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 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 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 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 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 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 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 257 Results::Array::Append (const ResultSP &result_sp) 258 { 259 m_array.push_back (result_sp); 260 return result_sp; 261 } 262 263 void 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