//===-- Results.cpp ---------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Results.h" #include #ifdef __APPLE__ #include "CFCMutableArray.h" #include "CFCMutableDictionary.h" #include "CFCReleaser.h" #include "CFCString.h" #endif using namespace lldb_perf; static void AddResultToArray (CFCMutableArray &array, Results::Result *result); static void AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result); static void AddResultToArray (CFCMutableArray &parent_array, Results::Result *result) { switch (result->GetType()) { case Results::Result::Type::Invalid: break; case Results::Result::Type::Array: { Results::Array *value = result->GetAsArray(); CFCMutableArray array; value->ForEach([&array](const Results::ResultSP &value_sp) -> bool { AddResultToArray (array, value_sp.get()); return true; }); parent_array.AppendValue(array.get(), true); } break; case Results::Result::Type::Dictionary: { Results::Dictionary *value = result->GetAsDictionary(); CFCMutableDictionary dict; value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool { AddResultToDictionary (dict, key.c_str(), value_sp.get()); return true; }); if (result->GetDescription()) { dict.AddValueCString(CFSTR("description"), result->GetDescription()); } parent_array.AppendValue(dict.get(), true); } break; case Results::Result::Type::Double: { double d = result->GetAsDouble()->GetValue(); CFCReleaser cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &d)); if (cf_number.get()) parent_array.AppendValue(cf_number.get(), true); } break; case Results::Result::Type::String: { CFCString cfstr (result->GetAsString()->GetValue()); if (cfstr.get()) parent_array.AppendValue(cfstr.get(), true); } break; case Results::Result::Type::Unsigned: { uint64_t uval64 = result->GetAsUnsigned()->GetValue(); CFCReleaser cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &uval64)); if (cf_number.get()) parent_array.AppendValue(cf_number.get(), true); } break; default: assert (!"unhandled result"); break; } } static void AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result) { assert (key && key[0]); CFCString cf_key(key); switch (result->GetType()) { case Results::Result::Type::Invalid: break; case Results::Result::Type::Array: { Results::Array *value = result->GetAsArray(); CFCMutableArray array; value->ForEach([&array](const Results::ResultSP &value_sp) -> bool { AddResultToArray (array, value_sp.get()); return true; }); parent_dict.AddValue(cf_key.get(), array.get(), true); } break; case Results::Result::Type::Dictionary: { Results::Dictionary *value = result->GetAsDictionary(); CFCMutableDictionary dict; value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool { AddResultToDictionary (dict, key.c_str(), value_sp.get()); return true; }); if (result->GetDescription()) { dict.AddValueCString(CFSTR("description"), result->GetDescription()); } parent_dict.AddValue(cf_key.get(), dict.get(), true); } break; case Results::Result::Type::Double: { parent_dict.SetValueDouble(cf_key.get(), result->GetAsDouble()->GetValue(), true); } break; case Results::Result::Type::String: { parent_dict.SetValueCString(cf_key.get(), result->GetAsString()->GetValue(), true); } break; case Results::Result::Type::Unsigned: { parent_dict.SetValueUInt64 (cf_key.get(), result->GetAsUnsigned()->GetValue(), true); } break; default: assert (!"unhandled result"); break; } } void Results::Write (const char *out_path) { #ifdef __APPLE__ CFCMutableDictionary dict; m_results.ForEach([&dict](const std::string &key, const ResultSP &value_sp) -> bool { AddResultToDictionary (dict, key.c_str(), value_sp.get()); return true; }); CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, dict.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL); if (out_path == NULL) out_path = "/dev/stdout"; CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)out_path, strlen(out_path), FALSE); CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL); #endif } Results::ResultSP Results::Dictionary::AddUnsigned (const char *name, const char *description, uint64_t value) { assert (name && name[0]); if (description && description[0]) { std::unique_ptr value_dict_ap (new Results::Dictionary ()); value_dict_ap->AddString("description", NULL, description); value_dict_ap->AddUnsigned("value", NULL, value); m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); } else m_dictionary[std::string(name)] = ResultSP (new Unsigned (name, description, value)); return m_dictionary[std::string(name)]; } Results::ResultSP Results::Dictionary::AddDouble (const char *name, const char *description, double value) { assert (name && name[0]); if (description && description[0]) { std::unique_ptr value_dict_ap (new Results::Dictionary ()); value_dict_ap->AddString("description", NULL, description); value_dict_ap->AddDouble("value", NULL, value); m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); } else m_dictionary[std::string(name)] = ResultSP (new Double (name, description, value)); return m_dictionary[std::string(name)]; } Results::ResultSP Results::Dictionary::AddString (const char *name, const char *description, const char *value) { assert (name && name[0]); if (description && description[0]) { std::unique_ptr value_dict_ap (new Results::Dictionary ()); value_dict_ap->AddString("description", NULL, description); value_dict_ap->AddString("value", NULL, value); m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); } else m_dictionary[std::string(name)] = ResultSP (new String (name, description, value)); return m_dictionary[std::string(name)]; } Results::ResultSP Results::Dictionary::Add (const char *name, const char *description, const ResultSP &result_sp) { assert (name && name[0]); if (description && description[0]) { std::unique_ptr value_dict_ap (new Results::Dictionary ()); value_dict_ap->AddString("description", NULL, description); value_dict_ap->Add("value", NULL, result_sp); m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); } else m_dictionary[std::string(name)] = result_sp; return m_dictionary[std::string(name)]; } void Results::Dictionary::ForEach (const std::function &callback) { collection::const_iterator pos, end = m_dictionary.end(); for (pos = m_dictionary.begin(); pos != end; ++pos) { if (callback (pos->first.c_str(), pos->second) == false) return; } } Results::ResultSP Results::Array::Append (const ResultSP &result_sp) { m_array.push_back (result_sp); return result_sp; } void Results::Array::ForEach (const std::function &callback) { collection::const_iterator pos, end = m_array.end(); for (pos = m_array.begin(); pos != end; ++pos) { if (callback (*pos) == false) return; } }