diff --git a/lldb/include/lldb/Utility/StructuredData.h b/lldb/include/lldb/Utility/StructuredData.h --- a/lldb/include/lldb/Utility/StructuredData.h +++ b/lldb/include/lldb/Utility/StructuredData.h @@ -9,10 +9,10 @@ #ifndef LLDB_UTILITY_STRUCTUREDDATA_H #define LLDB_UTILITY_STRUCTUREDDATA_H +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/JSON.h" -#include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Stream.h" #include "lldb/lldb-enumerations.h" @@ -423,34 +423,26 @@ size_t GetSize() const { return m_dict.size(); } - void ForEach(std::function const + void ForEach(std::function const &callback) const { for (const auto &pair : m_dict) { - if (!callback(pair.first, pair.second.get())) + if (!callback(pair.first(), pair.second.get())) break; } } ArraySP GetKeys() const { auto array_sp = std::make_shared(); - collection::const_iterator iter; - for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) { + for (auto iter = m_dict.begin(); iter != m_dict.end(); ++iter) { auto key_object_sp = std::make_shared(); - key_object_sp->SetValue(iter->first.AsCString()); + key_object_sp->SetValue(iter->first()); array_sp->Push(key_object_sp); } return array_sp; } ObjectSP GetValueForKey(llvm::StringRef key) const { - ObjectSP value_sp; - if (!key.empty()) { - ConstString key_cs(key); - collection::const_iterator iter = m_dict.find(key_cs); - if (iter != m_dict.end()) - value_sp = iter->second; - } - return value_sp; + return m_dict.lookup(key); } bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const { @@ -539,15 +531,10 @@ return false; } - bool HasKey(llvm::StringRef key) const { - ConstString key_cs(key); - collection::const_iterator search = m_dict.find(key_cs); - return search != m_dict.end(); - } + bool HasKey(llvm::StringRef key) const { return m_dict.contains(key); } void AddItem(llvm::StringRef key, ObjectSP value_sp) { - ConstString key_cs(key); - m_dict[key_cs] = std::move(value_sp); + m_dict.insert({key, std::move(value_sp)}); } template void AddIntegerItem(llvm::StringRef key, T value) { @@ -577,8 +564,7 @@ void GetDescription(lldb_private::Stream &s) const override; protected: - typedef std::map collection; - collection m_dict; + llvm::StringMap m_dict; }; class Null : public Object { diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -989,7 +989,7 @@ StructuredData::DictionarySP dict_sp = std::make_shared(); - auto flatten_asi_dict = [&dict_sp](ConstString key, + auto flatten_asi_dict = [&dict_sp](llvm::StringRef key, StructuredData::Object *val) -> bool { if (!val) return false; @@ -998,7 +998,7 @@ if (!arr || !arr->GetSize()) return false; - dict_sp->AddItem(key.AsCString(), arr->GetItemAtIndex(0)); + dict_sp->AddItem(key, arr->GetItemAtIndex(0)); return true; }; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1926,24 +1926,23 @@ lldb::ThreadSP ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { - static ConstString g_key_tid("tid"); - static ConstString g_key_name("name"); - static ConstString g_key_reason("reason"); - static ConstString g_key_metype("metype"); - static ConstString g_key_medata("medata"); - static ConstString g_key_qaddr("qaddr"); - static ConstString g_key_dispatch_queue_t("dispatch_queue_t"); - static ConstString g_key_associated_with_dispatch_queue( + static constexpr llvm::StringLiteral g_key_tid("tid"); + static constexpr llvm::StringLiteral g_key_name("name"); + static constexpr llvm::StringLiteral g_key_reason("reason"); + static constexpr llvm::StringLiteral g_key_metype("metype"); + static constexpr llvm::StringLiteral g_key_medata("medata"); + static constexpr llvm::StringLiteral g_key_qaddr("qaddr"); + static constexpr llvm::StringLiteral g_key_dispatch_queue_t( + "dispatch_queue_t"); + static constexpr llvm::StringLiteral g_key_associated_with_dispatch_queue( "associated_with_dispatch_queue"); - static ConstString g_key_queue_name("qname"); - static ConstString g_key_queue_kind("qkind"); - static ConstString g_key_queue_serial_number("qserialnum"); - static ConstString g_key_registers("registers"); - static ConstString g_key_memory("memory"); - static ConstString g_key_address("address"); - static ConstString g_key_bytes("bytes"); - static ConstString g_key_description("description"); - static ConstString g_key_signal("signal"); + static constexpr llvm::StringLiteral g_key_queue_name("qname"); + static constexpr llvm::StringLiteral g_key_queue_kind("qkind"); + static constexpr llvm::StringLiteral g_key_queue_serial_number("qserialnum"); + static constexpr llvm::StringLiteral g_key_registers("registers"); + static constexpr llvm::StringLiteral g_key_memory("memory"); + static constexpr llvm::StringLiteral g_key_description("description"); + static constexpr llvm::StringLiteral g_key_signal("signal"); // Stop with signal and thread info lldb::tid_t tid = LLDB_INVALID_THREAD_ID; @@ -1971,7 +1970,7 @@ &thread_dispatch_qaddr, &queue_vars_valid, &associated_with_dispatch_queue, &dispatch_queue_t, &queue_name, &queue_kind, &queue_serial_number]( - ConstString key, + llvm::StringRef key, StructuredData::Object *object) -> bool { if (key == g_key_tid) { // thread in big endian hex @@ -2029,10 +2028,10 @@ if (registers_dict) { registers_dict->ForEach( - [&expedited_register_map](ConstString key, + [&expedited_register_map](llvm::StringRef key, StructuredData::Object *object) -> bool { uint32_t reg; - if (llvm::to_integer(key.AsCString(), reg)) + if (llvm::to_integer(key, reg)) expedited_register_map[reg] = std::string(object->GetStringValue()); return true; // Keep iterating through all array items diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp --- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp +++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp @@ -224,7 +224,7 @@ [&module_sp, new_style_source_remapping_dictionary, original_DBGSourcePath_value, do_truncate_remapping_names]( - ConstString key, + llvm::StringRef key, StructuredData::Object *object) -> bool { if (object && object->GetAsString()) { @@ -237,7 +237,7 @@ DBGSourcePath = original_DBGSourcePath_value; } module_sp->GetSourceMappingList().Append( - key.GetStringRef(), DBGSourcePath, true); + key, DBGSourcePath, true); // With version 2 of DBGSourcePathRemapping, we // can chop off the last two filename parts // from the source remapping and get a more @@ -245,7 +245,7 @@ // Add this as another option in addition to // the full source path remap. if (do_truncate_remapping_names) { - FileSpec build_path(key.AsCString()); + FileSpec build_path(key); FileSpec source_path(DBGSourcePath.c_str()); build_path.RemoveLastPathComponent(); build_path.RemoveLastPathComponent(); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -3859,11 +3859,10 @@ s.Indent("Args:\n"); s.SetIndentLevel(s.GetIndentLevel() + 4); - auto print_one_element = [&s](ConstString key, + auto print_one_element = [&s](llvm::StringRef key, StructuredData::Object *object) { s.Indent(); - s.Printf("%s : %s\n", key.GetCString(), - object->GetStringValue().str().c_str()); + s.Format("{0} : {1}\n", key, object->GetStringValue()); return true; }; diff --git a/lldb/source/Utility/StructuredData.cpp b/lldb/source/Utility/StructuredData.cpp --- a/lldb/source/Utility/StructuredData.cpp +++ b/lldb/source/Utility/StructuredData.cpp @@ -162,8 +162,20 @@ void StructuredData::Dictionary::Serialize(json::OStream &s) const { s.objectBegin(); - for (const auto &pair : m_dict) { - s.attributeBegin(pair.first.GetStringRef()); + + // To ensure the output format is always stable, we sort the dictionary by key + // first. + using Entry = std::pair; + std::vector sorted_entries; + for (const auto &pair : m_dict) + sorted_entries.push_back({pair.first(), pair.second}); + + llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool { + return lhs.first < rhs.first; + }); + + for (const auto &pair : sorted_entries) { + s.attributeBegin(pair.first); pair.second->Serialize(s); s.attributeEnd(); } @@ -228,9 +240,22 @@ void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const { size_t indentation_level = s.GetIndentLevel(); - for (auto iter = m_dict.begin(); iter != m_dict.end(); iter++) { + + // To ensure the output format is always stable, we sort the dictionary by key + // first. + using Entry = std::pair; + std::vector sorted_entries; + for (const auto &pair : m_dict) + sorted_entries.push_back({pair.first(), pair.second}); + + llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool { + return lhs.first < rhs.first; + }); + + for (auto iter = sorted_entries.begin(); iter != sorted_entries.end(); + iter++) { // Sanitize. - if (iter->first.IsNull() || iter->first.IsEmpty() || !iter->second) + if (iter->first.empty() || !iter->second) continue; // Reset original indentation level. @@ -238,7 +263,7 @@ s.Indent(); // Print key. - s.Printf("%s:", iter->first.AsCString()); + s.Format("{0}:", iter->first); // Return to new line and increase indentation if value is record type. // Otherwise add spacing. @@ -252,7 +277,7 @@ // Print value and new line if now last pair. iter->second->GetDescription(s); - if (std::next(iter) != m_dict.end()) + if (std::next(iter) != sorted_entries.end()) s.EOL(); // Reset indentation level if it was incremented previously.