| //===-- 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 <assert.h> |
| |
| #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<CFNumberRef> 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<CFNumberRef> 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<Results::Dictionary> 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<Results::Dictionary> 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<Results::Dictionary> 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<Results::Dictionary> 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 <bool (const std::string &, const ResultSP &)> &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 <bool (const ResultSP &)> &callback) |
| { |
| collection::const_iterator pos, end = m_array.end(); |
| for (pos = m_array.begin(); pos != end; ++pos) |
| { |
| if (callback (*pos) == false) |
| return; |
| } |
| } |
| |
| |
| |