diff --git a/apriltag/src/main/native/cpp/AprilTagDetector.cpp b/apriltag/src/main/native/cpp/AprilTagDetector.cpp index 08046d16dc..458aa39798 100644 --- a/apriltag/src/main/native/cpp/AprilTagDetector.cpp +++ b/apriltag/src/main/native/cpp/AprilTagDetector.cpp @@ -130,7 +130,7 @@ void AprilTagDetector::RemoveFamily(std::string_view fam) { apriltag_detector_remove_family( static_cast(m_impl), static_cast(it->second)); - DestroyFamily(it->getKey(), it->second); + DestroyFamily(it->first, it->second); m_families.erase(it); } } @@ -158,7 +158,7 @@ void AprilTagDetector::Destroy() { void AprilTagDetector::DestroyFamilies() { for (auto&& entry : m_families) { - DestroyFamily(entry.getKey(), entry.second); + DestroyFamily(entry.first, entry.second); } } diff --git a/glass/src/lib/native/cpp/Context.cpp b/glass/src/lib/native/cpp/Context.cpp index be837e64b5..78fdc56af0 100644 --- a/glass/src/lib/native/cpp/Context.cpp +++ b/glass/src/lib/native/cpp/Context.cpp @@ -53,7 +53,7 @@ static void WorkspaceInit() { } for (auto&& root : gContext->storageRoots) { - root.getValue()->Apply(); + root.second->Apply(); } } @@ -176,7 +176,7 @@ static bool LoadStorageImpl(Context* ctx, std::string_view dir, bool rv = true; for (auto&& root : ctx->storageRoots) { std::string filename; - auto rootName = root.getKey(); + auto& rootName = root.first; if (rootName.empty()) { filename = (fs::path{dir} / fmt::format("{}.json", name)).string(); } else { @@ -291,7 +291,7 @@ static bool SaveStorageImpl(Context* ctx, std::string_view dir, if (exiting && wpi::gui::gContext->resetOnExit) { fs::remove(dirPath / fmt::format("{}-window.json", name), ec); for (auto&& root : ctx->storageRoots) { - auto rootName = root.getKey(); + auto& rootName = root.first; if (rootName.empty()) { fs::remove(dirPath / fmt::format("{}.json", name), ec); } else { @@ -304,14 +304,14 @@ static bool SaveStorageImpl(Context* ctx, std::string_view dir, (dirPath / fmt::format("{}-window.json", name)).string()); for (auto&& root : ctx->storageRoots) { - auto rootName = root.getKey(); + auto& rootName = root.first; std::string filename; if (rootName.empty()) { filename = (dirPath / fmt::format("{}.json", name)).string(); } else { filename = (dirPath / fmt::format("{}-{}.json", name, rootName)).string(); } - if (!SaveStorageRootImpl(ctx, filename, *root.getValue())) { + if (!SaveStorageRootImpl(ctx, filename, *root.second)) { rv = false; } } @@ -320,8 +320,7 @@ static bool SaveStorageImpl(Context* ctx, std::string_view dir, Context::Context() : sourceNameStorage{storageRoots.insert({"", std::make_unique()}) - .first->getValue() - ->GetChild("sourceNames")} { + .first->second->GetChild("sourceNames")} { storageStack.emplace_back(storageRoots[""].get()); // override ImGui ini saving diff --git a/glass/src/lib/native/cpp/DataSource.cpp b/glass/src/lib/native/cpp/DataSource.cpp index d9bee62e20..372d5f2ee5 100644 --- a/glass/src/lib/native/cpp/DataSource.cpp +++ b/glass/src/lib/native/cpp/DataSource.cpp @@ -112,5 +112,5 @@ DataSource* DataSource::Find(std::string_view id) { if (it == gContext->sources.end()) { return nullptr; } - return it->getValue(); + return it->second; } diff --git a/glass/src/lib/native/cpp/Storage.cpp b/glass/src/lib/native/cpp/Storage.cpp index f455212f61..d0009937c4 100644 --- a/glass/src/lib/native/cpp/Storage.cpp +++ b/glass/src/lib/native/cpp/Storage.cpp @@ -331,7 +331,7 @@ std::vector>& Storage::GetChildArray( std::unique_ptr Storage::Erase(std::string_view key) { auto it = m_values.find(key); if (it != m_values.end()) { - auto rv = std::move(it->getValue()); + auto rv = std::move(it->second); m_values.erase(it); return rv; } @@ -339,11 +339,9 @@ std::unique_ptr Storage::Erase(std::string_view key) { } void Storage::EraseChildren() { - for (auto&& kv : m_values) { - if (kv.getValue()->type == Value::kChild) { - m_values.remove(&kv); - } - } + std::erase_if(m_values, [](const auto& kv) { + return kv.second->type == Value::kChild; + }); } static bool JsonArrayToStorage(Storage::Value* valuePtr, const wpi::json& jarr, @@ -559,7 +557,7 @@ wpi::json Storage::ToJson() const { wpi::json j = wpi::json::object(); for (auto&& kv : m_values) { wpi::json jelem; - auto& value = *kv.getValue(); + auto& value = *kv.second; switch (value.type) { #define CASE(CapsName, LowerName) \ case Value::k##CapsName: \ @@ -602,7 +600,7 @@ wpi::json Storage::ToJson() const { default: continue; } - j.emplace(kv.getKey(), std::move(jelem)); + j.emplace(kv.first, std::move(jelem)); } return j; } @@ -617,7 +615,7 @@ void Storage::Clear() { void Storage::ClearValues() { for (auto&& kv : m_values) { - auto& value = *kv.getValue(); + auto& value = *kv.second; switch (value.type) { case Value::kInt: value.intVal = value.intDefault; @@ -703,7 +701,7 @@ void Storage::Apply() { void Storage::ApplyChildren() { for (auto&& kv : m_values) { - auto& value = *kv.getValue(); + auto& value = *kv.second; switch (value.type) { case Value::kChild: value.child->Apply(); diff --git a/glass/src/lib/native/include/glass/Storage.h b/glass/src/lib/native/include/glass/Storage.h index bdb2b3d083..765bbfe8a4 100644 --- a/glass/src/lib/native/include/glass/Storage.h +++ b/glass/src/lib/native/include/glass/Storage.h @@ -249,8 +249,7 @@ class ChildIterator { public: ChildIterator(IteratorType it, IteratorType end) noexcept : anchor(it), end(end) { - while (anchor != end && - anchor->getValue()->type != Storage::Value::kChild) { + while (anchor != end && anchor->second->type != Storage::Value::kChild) { ++anchor; } } @@ -261,8 +260,7 @@ class ChildIterator { /// increment operator (needed for range-based for) ChildIterator& operator++() { ++anchor; - while (anchor != end && - anchor->getValue()->type != Storage::Value::kChild) { + while (anchor != end && anchor->second->type != Storage::Value::kChild) { ++anchor; } return *this; @@ -274,10 +272,10 @@ class ChildIterator { } /// return key of the iterator - std::string_view key() const { return anchor->getKey(); } + std::string_view key() const { return anchor->first; } /// return value of the iterator - Storage& value() const { return *anchor->getValue()->child; } + Storage& value() const { return *anchor->second->child; } }; } // namespace detail diff --git a/hal/src/main/native/sim/mockdata/SimDeviceData.cpp b/hal/src/main/native/sim/mockdata/SimDeviceData.cpp index b849957f68..b03fde6b1f 100644 --- a/hal/src/main/native/sim/mockdata/SimDeviceData.cpp +++ b/hal/src/main/native/sim/mockdata/SimDeviceData.cpp @@ -317,7 +317,7 @@ HAL_SimDeviceHandle SimDeviceData::GetDeviceHandle(const char* name) { if (it == m_deviceMap.end()) { return 0; } - if (auto deviceImpl = it->getValue().lock()) { + if (auto deviceImpl = it->second.lock()) { return deviceImpl->handle; } else { return 0; @@ -459,10 +459,10 @@ HAL_SimValueHandle SimDeviceData::GetValueHandle(HAL_SimDeviceHandle device, if (it == deviceImpl->valueMap.end()) { return 0; } - if (!it->getValue()) { + if (!it->second) { return 0; } - return it->getValue()->handle; + return it->second->handle; } void SimDeviceData::EnumerateValues(HAL_SimDeviceHandle device, void* param, diff --git a/simulation/halsim_ws_client/src/main/native/cpp/HALSimWS.cpp b/simulation/halsim_ws_client/src/main/native/cpp/HALSimWS.cpp index 3e27d3ec94..fa1aab2e97 100644 --- a/simulation/halsim_ws_client/src/main/native/cpp/HALSimWS.cpp +++ b/simulation/halsim_ws_client/src/main/native/cpp/HALSimWS.cpp @@ -112,8 +112,8 @@ void HALSimWS::Start() { // Print any filters we are using if (m_useMsgFiltering) { wpi::print("WS Message Filters:"); - for (auto filter : m_msgFilters.keys()) { - wpi::print("* \"{}\"\n", filter); + for (auto&& filter : m_msgFilters) { + wpi::print("* \"{}\"\n", filter.first); } } else { wpi::print("No WS Message Filters specified"); diff --git a/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_SimDevice.cpp b/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_SimDevice.cpp index cad7e22b9b..e48de73655 100644 --- a/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_SimDevice.cpp +++ b/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_SimDevice.cpp @@ -54,7 +54,7 @@ void HALSimWSProviderSimDevice::CancelCallbacks() { m_simValueCreatedCbKey = 0; for (auto& kv : m_simValueChangedCbKeys) { - HALSIM_CancelSimValueChangedCallback(kv.getValue()); + HALSIM_CancelSimValueChangedCallback(kv.second); } m_simValueChangedCbKeys.clear(); diff --git a/simulation/halsim_ws_core/src/main/native/include/WSProviderContainer.h b/simulation/halsim_ws_core/src/main/native/include/WSProviderContainer.h index 7c8f8617b5..b83235b524 100644 --- a/simulation/halsim_ws_core/src/main/native/include/WSProviderContainer.h +++ b/simulation/halsim_ws_core/src/main/native/include/WSProviderContainer.h @@ -40,7 +40,7 @@ class ProviderContainer { void ForEach(IterFn fn) { std::shared_lock lock(m_mutex); for (auto& kv : m_providers) { - fn(kv.getValue()); + fn(kv.second); } } diff --git a/simulation/halsim_ws_server/src/main/native/cpp/HALSimWeb.cpp b/simulation/halsim_ws_server/src/main/native/cpp/HALSimWeb.cpp index f231cf4487..c482cf2ee9 100644 --- a/simulation/halsim_ws_server/src/main/native/cpp/HALSimWeb.cpp +++ b/simulation/halsim_ws_server/src/main/native/cpp/HALSimWeb.cpp @@ -123,8 +123,8 @@ void HALSimWeb::Start() { // Print any filters we are using if (m_useMsgFiltering) { wpi::print("WS Message Filters:"); - for (auto filter : m_msgFilters.keys()) { - wpi::print("* \"{}\"\n", filter); + for (auto&& filter : m_msgFilters) { + wpi::print("* \"{}\"\n", filter.first); } } else { wpi::print("No WS Message Filters specified"); diff --git a/sysid/src/main/native/cpp/analysis/AnalysisManager.cpp b/sysid/src/main/native/cpp/analysis/AnalysisManager.cpp index c97485330d..ba24cb0d38 100644 --- a/sysid/src/main/native/cpp/analysis/AnalysisManager.cpp +++ b/sysid/src/main/native/cpp/analysis/AnalysisManager.cpp @@ -90,8 +90,8 @@ static void CopyRawData(wpi::StringMap* dataset) { auto& data = *dataset; // Loads the Raw Data for (auto& it : data) { - auto key = it.first(); - auto& motorData = it.getValue(); + auto& key = it.first; + auto& motorData = it.second; if (!wpi::contains(key, "raw")) { data[fmt::format("raw-{}", key)] = motorData; @@ -126,7 +126,7 @@ void AnalysisManager::PrepareGeneralData() { WPI_INFO(m_logger, "{}", "Converting raw data to PreparedData struct."); // Convert data to PreparedData structs for (auto& it : m_data.motorData) { - auto key = it.first(); + auto key = it.first; preparedData[key] = ConvertToPrepared(m_data.motorData[key]); WPI_INFO(m_logger, "SAMPLES {}", preparedData[key].size()); } diff --git a/sysid/src/main/native/cpp/analysis/FilteringUtils.cpp b/sysid/src/main/native/cpp/analysis/FilteringUtils.cpp index b20c88e15f..94726ad601 100644 --- a/sysid/src/main/native/cpp/analysis/FilteringUtils.cpp +++ b/sysid/src/main/native/cpp/analysis/FilteringUtils.cpp @@ -322,8 +322,8 @@ static units::second_t GetMaxStepTime( wpi::StringMap>& data) { auto maxStepTime = 0_s; for (auto& it : data) { - auto key = it.first(); - auto& dataset = it.getValue(); + auto& key = it.first; + auto& dataset = it.second; if (IsRaw(key) && wpi::contains(key, "dynamic")) { if (!dataset.empty()) { @@ -351,8 +351,8 @@ void sysid::InitialTrimAndFilter( // Calculate Velocity Threshold if it hasn't been set yet if (settings->velocityThreshold == std::numeric_limits::infinity()) { for (auto& it : preparedData) { - auto key = it.first(); - auto& dataset = it.getValue(); + auto& key = it.first; + auto& dataset = it.second; if (wpi::contains(key, "quasistatic")) { settings->velocityThreshold = std::min(settings->velocityThreshold, @@ -363,8 +363,8 @@ void sysid::InitialTrimAndFilter( } for (auto& it : preparedData) { - auto key = it.first(); - auto& dataset = it.getValue(); + auto& key = it.first; + auto& dataset = it.second; // Trim quasistatic test data to remove all points where voltage is zero or // velocity < velocity threshold. @@ -424,7 +424,7 @@ void sysid::AccelFilter(wpi::StringMap>* data) { // Remove points with acceleration = 0 for (auto& it : preparedData) { - auto& dataset = it.getValue(); + auto& dataset = it.second; for (size_t i = 0; i < dataset.size(); i++) { if (dataset.at(i).acceleration == 0.0) { @@ -436,7 +436,7 @@ void sysid::AccelFilter(wpi::StringMap>* data) { // Confirm there's still data if (std::any_of(preparedData.begin(), preparedData.end(), - [](const auto& it) { return it.getValue().empty(); })) { + [](const auto& it) { return it.second.empty(); })) { throw sysid::InvalidDataError( "Acceleration filtering has removed all data."); } diff --git a/sysid/src/main/native/cpp/view/DataSelector.cpp b/sysid/src/main/native/cpp/view/DataSelector.cpp index ecb1c01217..3409bf6ee3 100644 --- a/sysid/src/main/native/cpp/view/DataSelector.cpp +++ b/sysid/src/main/native/cpp/view/DataSelector.cpp @@ -56,7 +56,7 @@ void DataSelector::Display() { TestData data = m_testdataFuture.get(); for (auto&& motordata : data.motorData) { m_testdataStats.emplace_back( - fmt::format("Test State: {}", motordata.first())); + fmt::format("Test State: {}", motordata.first)); int i = 0; for (auto&& run : motordata.second.runs) { m_testdataStats.emplace_back(fmt::format( diff --git a/sysid/src/main/native/cpp/view/LogLoader.cpp b/sysid/src/main/native/cpp/view/LogLoader.cpp index 6884519a6d..d43f6ec4da 100644 --- a/sysid/src/main/native/cpp/view/LogLoader.cpp +++ b/sysid/src/main/native/cpp/view/LogLoader.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/upstream_utils/llvm_patches/0001-Remove-StringRef-ArrayRef-and-Optional.patch b/upstream_utils/llvm_patches/0001-Remove-StringRef-ArrayRef-and-Optional.patch index b4c1512195..d14c5fadca 100644 --- a/upstream_utils/llvm_patches/0001-Remove-StringRef-ArrayRef-and-Optional.patch +++ b/upstream_utils/llvm_patches/0001-Remove-StringRef-ArrayRef-and-Optional.patch @@ -8,8 +8,6 @@ Subject: [PATCH 01/38] Remove StringRef, ArrayRef, and Optional llvm/include/llvm/ADT/SmallSet.h | 2 +- llvm/include/llvm/ADT/SmallString.h | 103 ++++++++++-------- llvm/include/llvm/ADT/SmallVector.h | 7 +- - llvm/include/llvm/ADT/StringMap.h | 38 +++---- - llvm/include/llvm/ADT/StringMapEntry.h | 20 ++-- llvm/include/llvm/Support/Chrono.h | 10 +- llvm/include/llvm/Support/Compiler.h | 2 +- llvm/include/llvm/Support/ConvertUTF.h | 31 +++--- @@ -22,7 +20,6 @@ Subject: [PATCH 01/38] Remove StringRef, ArrayRef, and Optional llvm/lib/Support/ConvertUTFWrapper.cpp | 38 +++---- llvm/lib/Support/ErrorHandling.cpp | 13 +-- llvm/lib/Support/SmallVector.cpp | 5 +- - llvm/lib/Support/StringMap.cpp | 12 +- llvm/lib/Support/raw_ostream.cpp | 25 ++--- llvm/lib/Support/xxhash.cpp | 10 +- llvm/unittests/ADT/DenseMapTest.cpp | 29 +---- @@ -31,7 +28,6 @@ Subject: [PATCH 01/38] Remove StringRef, ArrayRef, and Optional llvm/unittests/ADT/SmallPtrSetTest.cpp | 1 - llvm/unittests/ADT/SmallStringTest.cpp | 50 ++++----- llvm/unittests/ADT/SmallVectorTest.cpp | 30 +---- - llvm/unittests/ADT/StringMapTest.cpp | 32 +++--- llvm/unittests/Support/ConvertUTFTest.cpp | 41 ++++--- llvm/unittests/Support/xxhashTest.cpp | 4 +- 30 files changed, 282 insertions(+), 323 deletions(-) @@ -372,230 +368,6 @@ index 09676d792dfebd88e5c8eace666b3ab0044a962e..c96fd0e4956ee6d586f85dc79623de13 this->append(A.begin(), A.end()); } -diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h -index 466f95254d102e98343290b211f317f749d7692b..34dfbf83c681f4e81a9dadd9382ddca6ef8d6c1d 100644 ---- a/llvm/include/llvm/ADT/StringMap.h -+++ b/llvm/include/llvm/ADT/StringMap.h -@@ -60,12 +60,12 @@ protected: - /// specified bucket will be non-null. Otherwise, it will be null. In either - /// case, the FullHashValue field of the bucket will be set to the hash value - /// of the string. -- unsigned LookupBucketFor(StringRef Key); -+ unsigned LookupBucketFor(std::string_view Key); - - /// FindKey - Look up the bucket that contains the specified key. If it exists - /// in the map, return the bucket number of the key. Otherwise return -1. - /// This does not modify the map. -- int FindKey(StringRef Key) const; -+ int FindKey(std::string_view Key) const; - - /// RemoveKey - Remove the specified StringMapEntry from the table, but do not - /// delete it. This aborts if the value isn't in the table. -@@ -73,7 +73,7 @@ protected: - - /// RemoveKey - Remove the StringMapEntry for the specified key from the - /// table, returning it. If the key is not in the table, this returns null. -- StringMapEntryBase *RemoveKey(StringRef Key); -+ StringMapEntryBase *RemoveKey(std::string_view Key); - - /// Allocate the table with the specified number of buckets and otherwise - /// setup the map as empty. -@@ -127,7 +127,7 @@ public: - : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), - AllocTy(A) {} - -- StringMap(std::initializer_list> List) -+ StringMap(std::initializer_list> List) - : StringMapImpl(List.size(), static_cast(sizeof(MapEntryTy))) { - insert(List); - } -@@ -215,14 +215,14 @@ public: - StringMapKeyIterator(end())); - } - -- iterator find(StringRef Key) { -+ iterator find(std::string_view Key) { - int Bucket = FindKey(Key); - if (Bucket == -1) - return end(); - return iterator(TheTable + Bucket, true); - } - -- const_iterator find(StringRef Key) const { -+ const_iterator find(std::string_view Key) const { - int Bucket = FindKey(Key); - if (Bucket == -1) - return end(); -@@ -231,7 +231,7 @@ public: - - /// lookup - Return the entry for the specified key, or a default - /// constructed value if no such entry exists. -- ValueTy lookup(StringRef Key) const { -+ ValueTy lookup(std::string_view Key) const { - const_iterator Iter = find(Key); - if (Iter != end()) - return Iter->second; -@@ -240,7 +240,7 @@ public: - - /// at - Return the entry for the specified key, or abort if no such - /// entry exists. -- const ValueTy &at(StringRef Val) const { -+ const ValueTy &at(std::string_view Val) const { - auto Iter = this->find(std::move(Val)); - assert(Iter != this->end() && "StringMap::at failed due to a missing key"); - return Iter->second; -@@ -248,13 +248,13 @@ public: - - /// Lookup the ValueTy for the \p Key, or create a default constructed value - /// if the key is not in the map. -- ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; } -+ ValueTy &operator[](std::string_view Key) { return try_emplace(Key).first->second; } - - /// contains - Return true if the element is in the map, false otherwise. -- bool contains(StringRef Key) const { return find(Key) != end(); } -+ bool contains(std::string_view Key) const { return find(Key) != end(); } - - /// count - Return 1 if the element is in the map, 0 otherwise. -- size_type count(StringRef Key) const { return contains(Key) ? 1 : 0; } -+ size_type count(std::string_view Key) const { return contains(Key) ? 1 : 0; } - - template - size_type count(const StringMapEntry &MapEntry) const { -@@ -304,7 +304,7 @@ public: - /// isn't already in the map. The bool component of the returned pair is true - /// if and only if the insertion takes place, and the iterator component of - /// the pair points to the element with key equivalent to the key of the pair. -- std::pair insert(std::pair KV) { -+ std::pair insert(std::pair KV) { - return try_emplace(KV.first, std::move(KV.second)); - } - -@@ -319,14 +319,14 @@ public: - /// Inserts elements from initializer list ilist. If multiple elements in - /// the range have keys that compare equivalent, it is unspecified which - /// element is inserted -- void insert(std::initializer_list> List) { -+ void insert(std::initializer_list> List) { - insert(List.begin(), List.end()); - } - - /// Inserts an element or assigns to the current element if the key already - /// exists. The return type is the same as try_emplace. - template -- std::pair insert_or_assign(StringRef Key, V &&Val) { -+ std::pair insert_or_assign(std::string_view Key, V &&Val) { - auto Ret = try_emplace(Key, std::forward(Val)); - if (!Ret.second) - Ret.first->second = std::forward(Val); -@@ -338,7 +338,7 @@ public: - /// if and only if the insertion takes place, and the iterator component of - /// the pair points to the element with key equivalent to the key of the pair. - template -- std::pair try_emplace(StringRef Key, ArgsTy &&...Args) { -+ std::pair try_emplace(std::string_view Key, ArgsTy &&...Args) { - unsigned BucketNo = LookupBucketFor(Key); - StringMapEntryBase *&Bucket = TheTable[BucketNo]; - if (Bucket && Bucket != getTombstoneVal()) -@@ -385,7 +385,7 @@ public: - V.Destroy(getAllocator()); - } - -- bool erase(StringRef Key) { -+ bool erase(std::string_view Key) { - iterator I = find(Key); - if (I == end()) - return false; -@@ -482,17 +482,17 @@ template - class StringMapKeyIterator - : public iterator_adaptor_base, - StringMapConstIterator, -- std::forward_iterator_tag, StringRef> { -+ std::forward_iterator_tag, std::string_view> { - using base = iterator_adaptor_base, - StringMapConstIterator, -- std::forward_iterator_tag, StringRef>; -+ std::forward_iterator_tag, std::string_view>; - - public: - StringMapKeyIterator() = default; - explicit StringMapKeyIterator(StringMapConstIterator Iter) - : base(std::move(Iter)) {} - -- StringRef operator*() const { return this->wrapped()->getKey(); } -+ std::string_view operator*() const { return this->wrapped()->getKey(); } - }; - - } // end namespace llvm -diff --git a/llvm/include/llvm/ADT/StringMapEntry.h b/llvm/include/llvm/ADT/StringMapEntry.h -index 98b51cc1aebd59eba20076e6d8a4eebc0eebb982..388e81c361642113937f7d5680de73a50635b07d 100644 ---- a/llvm/include/llvm/ADT/StringMapEntry.h -+++ b/llvm/include/llvm/ADT/StringMapEntry.h -@@ -16,8 +16,8 @@ - #ifndef LLVM_ADT_STRINGMAPENTRY_H - #define LLVM_ADT_STRINGMAPENTRY_H - --#include "llvm/ADT/StringRef.h" - #include -+#include - - namespace llvm { - -@@ -36,13 +36,13 @@ protected: - /// type-erase the allocator and put it in a source file. - template - static void *allocateWithKey(size_t EntrySize, size_t EntryAlign, -- StringRef Key, AllocatorTy &Allocator); -+ std::string_view Key, AllocatorTy &Allocator); - }; - - // Define out-of-line to dissuade inlining. - template - void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign, -- StringRef Key, -+ std::string_view Key, - AllocatorTy &Allocator) { - size_t KeyLength = Key.size(); - -@@ -105,8 +105,8 @@ public: - - using ValueType = ValueTy; - -- StringRef getKey() const { -- return StringRef(getKeyData(), this->getKeyLength()); -+ std::string_view getKey() const { -+ return std::string_view(getKeyData(), this->getKeyLength()); - } - - /// getKeyData - Return the start of the string data that is the key for this -@@ -116,15 +116,15 @@ public: - return reinterpret_cast(this + 1); - } - -- StringRef first() const { -- return StringRef(getKeyData(), this->getKeyLength()); -+ std::string_view first() const { -+ return std::string_view(getKeyData(), this->getKeyLength()); - } - - /// Create a StringMapEntry for the specified key construct the value using - /// \p InitiVals. - template -- static StringMapEntry *create(StringRef key, AllocatorTy &allocator, -- InitTy &&...initVals) { -+ static StringMapEntry *create(std::string_view key, AllocatorTy &allocator, -+ InitTy &&... initVals) { - return new (StringMapEntryBase::allocateWithKey( - sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator)) - StringMapEntry(key.size(), std::forward(initVals)...); -@@ -167,7 +167,7 @@ struct tuple_size> - - template - struct tuple_element> -- : std::conditional {}; -+ : std::conditional {}; - } // namespace std - - #endif // LLVM_ADT_STRINGMAPENTRY_H diff --git a/llvm/include/llvm/Support/Chrono.h b/llvm/include/llvm/Support/Chrono.h index 71859af7c7e4a595140475daf356744f52d14d24..9c9ba7002310eba5113c14957f769702c61f4326 100644 --- a/llvm/include/llvm/Support/Chrono.h @@ -1228,63 +1000,6 @@ index b6ce37842040b36fc79770ca0296255f2bb42a1a..4f6fee18b659adcbfd79822832f91417 #endif } -diff --git a/llvm/lib/Support/StringMap.cpp b/llvm/lib/Support/StringMap.cpp -index 67c05a87959cf0c243d17646ae2f28f6c9f0d708..7be219323f6d76f32a9a841115f2f146141cdbab 100644 ---- a/llvm/lib/Support/StringMap.cpp -+++ b/llvm/lib/Support/StringMap.cpp -@@ -81,7 +81,7 @@ void StringMapImpl::init(unsigned InitSize) { - /// specified bucket will be non-null. Otherwise, it will be null. In either - /// case, the FullHashValue field of the bucket will be set to the hash value - /// of the string. --unsigned StringMapImpl::LookupBucketFor(StringRef Name) { -+unsigned StringMapImpl::LookupBucketFor(std::string_view Name) { - // Hash table unallocated so far? - if (NumBuckets == 0) - init(16); -@@ -121,7 +121,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) { - // Do the comparison like this because Name isn't necessarily - // null-terminated! - char *ItemStr = (char *)BucketItem + ItemSize; -- if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) { -+ if (Name == std::string_view(ItemStr, BucketItem->getKeyLength())) { - // We found a match! - return BucketNo; - } -@@ -139,7 +139,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) { - /// FindKey - Look up the bucket that contains the specified key. If it exists - /// in the map, return the bucket number of the key. Otherwise return -1. - /// This does not modify the map. --int StringMapImpl::FindKey(StringRef Key) const { -+int StringMapImpl::FindKey(std::string_view Key) const { - if (NumBuckets == 0) - return -1; // Really empty table? - unsigned FullHashValue = xxh3_64bits(Key); -@@ -166,7 +166,7 @@ int StringMapImpl::FindKey(StringRef Key) const { - // Do the comparison like this because NameStart isn't necessarily - // null-terminated! - char *ItemStr = (char *)BucketItem + ItemSize; -- if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) { -+ if (Key == std::string_view(ItemStr, BucketItem->getKeyLength())) { - // We found a match! - return BucketNo; - } -@@ -185,14 +185,14 @@ int StringMapImpl::FindKey(StringRef Key) const { - /// delete it. This aborts if the value isn't in the table. - void StringMapImpl::RemoveKey(StringMapEntryBase *V) { - const char *VStr = (char *)V + ItemSize; -- StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength())); -+ StringMapEntryBase *V2 = RemoveKey(std::string_view(VStr, V->getKeyLength())); - (void)V2; - assert(V == V2 && "Didn't find key?"); - } - - /// RemoveKey - Remove the StringMapEntry for the specified key from the - /// table, returning it. If the key is not in the table, this returns null. --StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { -+StringMapEntryBase *StringMapImpl::RemoveKey(std::string_view Key) { - int Bucket = FindKey(Key); - if (Bucket == -1) - return nullptr; diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 3d3a564af51d120786b358b96a3c90e2b7fbf9f3..220d850b9bc69f8fc2fba7cd23629eca487cde23 100644 --- a/llvm/lib/Support/raw_ostream.cpp @@ -1746,132 +1461,6 @@ index 137dd43b473068eae34b39edc4b9b8b9633bab95..7029038d18d433cef987bedbfa4fda26 { llvm::SmallVector Vector(Array); -diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp -index f9b138e9a472137139397d9cae76823711594211..7f10b3d7d3a8894b1ab0ac660268d94a8b89e082 100644 ---- a/llvm/unittests/ADT/StringMapTest.cpp -+++ b/llvm/unittests/ADT/StringMapTest.cpp -@@ -7,8 +7,6 @@ - //===----------------------------------------------------------------------===// - - #include "llvm/ADT/StringMap.h" --#include "llvm/ADT/STLExtras.h" --#include "llvm/ADT/Twine.h" - #include "llvm/Support/DataTypes.h" - #include "gtest/gtest.h" - #include -@@ -43,10 +41,10 @@ protected: - // Lookup tests - EXPECT_FALSE(testMap.contains(testKey)); - EXPECT_EQ(0u, testMap.count(testKey)); -- EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength))); -+ EXPECT_EQ(0u, testMap.count(std::string_view(testKeyFirst, testKeyLength))); - EXPECT_EQ(0u, testMap.count(testKeyStr)); - EXPECT_TRUE(testMap.find(testKey) == testMap.end()); -- EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) == -+ EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) == - testMap.end()); - EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end()); - } -@@ -67,10 +65,10 @@ protected: - // Lookup tests - EXPECT_TRUE(testMap.contains(testKey)); - EXPECT_EQ(1u, testMap.count(testKey)); -- EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength))); -+ EXPECT_EQ(1u, testMap.count(std::string_view(testKeyFirst, testKeyLength))); - EXPECT_EQ(1u, testMap.count(testKeyStr)); - EXPECT_TRUE(testMap.find(testKey) == testMap.begin()); -- EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) == -+ EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) == - testMap.begin()); - EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin()); - } -@@ -108,10 +106,10 @@ TEST_F(StringMapTest, ConstEmptyMapTest) { - - // Lookup tests - EXPECT_EQ(0u, constTestMap.count(testKey)); -- EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength))); -+ EXPECT_EQ(0u, constTestMap.count(std::string_view(testKeyFirst, testKeyLength))); - EXPECT_EQ(0u, constTestMap.count(testKeyStr)); - EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end()); -- EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) == -+ EXPECT_TRUE(constTestMap.find(std::string_view(testKeyFirst, testKeyLength)) == - constTestMap.end()); - EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end()); - } -@@ -251,7 +249,7 @@ TEST_F(StringMapTest, StringMapEntryTest) { - MallocAllocator Allocator; - StringMap::value_type *entry = - StringMap::value_type::create( -- StringRef(testKeyFirst, testKeyLength), Allocator, 1u); -+ std::string_view(testKeyFirst, testKeyLength), Allocator, 1u); - EXPECT_STREQ(testKey, entry->first().data()); - EXPECT_EQ(1u, entry->second); - entry->Destroy(Allocator); -@@ -261,7 +259,7 @@ TEST_F(StringMapTest, StringMapEntryTest) { - TEST_F(StringMapTest, InsertTest) { - SCOPED_TRACE("InsertTest"); - testMap.insert(StringMap::value_type::create( -- StringRef(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u)); -+ std::string_view(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u)); - assertSingleItemMap(); - } - -@@ -330,10 +328,10 @@ TEST_F(StringMapTest, IterMapKeysVector) { - Map["C"] = 3; - Map["D"] = 3; - -- std::vector Keys{Map.keys().begin(), Map.keys().end()}; -+ std::vector Keys{Map.keys().begin(), Map.keys().end()}; - llvm::sort(Keys); - -- std::vector Expected{{"A", "B", "C", "D"}}; -+ std::vector Expected{{"A", "B", "C", "D"}}; - EXPECT_EQ(Expected, Keys); - } - -@@ -347,7 +345,7 @@ TEST_F(StringMapTest, IterMapKeysSmallVector) { - auto Keys = to_vector<4>(Map.keys()); - llvm::sort(Keys); - -- SmallVector Expected = {"A", "B", "C", "D"}; -+ SmallVector Expected = {"A", "B", "C", "D"}; - EXPECT_EQ(Expected, Keys); - } - -@@ -389,13 +387,13 @@ private: - TEST_F(StringMapTest, MoveOnly) { - StringMap t; - t.insert(std::make_pair("Test", MoveOnly(42))); -- StringRef Key = "Test"; -+ std::string_view Key = "Test"; - StringMapEntry::create(Key, t.getAllocator(), MoveOnly(42)) - ->Destroy(t.getAllocator()); - } - - TEST_F(StringMapTest, CtorArg) { -- StringRef Key = "Test"; -+ std::string_view Key = "Test"; - MallocAllocator Allocator; - StringMapEntry::create(Key, Allocator, Immovable()) - ->Destroy(Allocator); -@@ -580,7 +578,7 @@ TEST(StringMapCustomTest, InitialSizeTest) { - CountCtorCopyAndMove::Copy = 0; - for (int i = 0; i < Size; ++i) - Map.insert(std::pair( -- std::piecewise_construct, std::forward_as_tuple(Twine(i).str()), -+ std::piecewise_construct, std::forward_as_tuple(std::to_string(i)), - std::forward_as_tuple(i))); - // After the initial move, the map will move the Elts in the Entry. - EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move); -@@ -649,7 +647,7 @@ TEST(StringMapCustomTest, StringMapEntrySize) { - else - LargeValue = std::numeric_limits::max() + 1ULL; - StringMapEntry LargeEntry(LargeValue); -- StringRef Key = LargeEntry.getKey(); -+ std::string_view Key = LargeEntry.getKey(); - EXPECT_EQ(LargeValue, Key.size()); - - // Test that the entry can hold at least max size_t. diff --git a/llvm/unittests/Support/ConvertUTFTest.cpp b/llvm/unittests/Support/ConvertUTFTest.cpp index 6e75fbae0969ba1bf0a76c4d79a123e405a8dae7..3b07d344f15a555f11ad5f8177a0a65b8a4fa472 100644 --- a/llvm/unittests/Support/ConvertUTFTest.cpp diff --git a/upstream_utils/llvm_patches/0006-Explicitly-use-std.patch b/upstream_utils/llvm_patches/0006-Explicitly-use-std.patch index 04e4c6a739..0f1e9a278b 100644 --- a/upstream_utils/llvm_patches/0006-Explicitly-use-std.patch +++ b/upstream_utils/llvm_patches/0006-Explicitly-use-std.patch @@ -8,7 +8,6 @@ Subject: [PATCH 06/38] Explicitly use std:: llvm/lib/Support/ErrorHandling.cpp | 2 +- llvm/unittests/ADT/SmallPtrSetTest.cpp | 2 +- llvm/unittests/ADT/SmallSetTest.cpp | 10 +++++----- - llvm/unittests/ADT/StringMapTest.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h @@ -100,16 +99,3 @@ index b50b368ae663614f050c220432c05b32c201db00..f9d84fa8a42a7feaaffa3aa080e84574 EXPECT_EQ(4u, s1.size()); EXPECT_EQ("str 0", V[0]); EXPECT_EQ("str 1", V[1]); -diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp -index 7f10b3d7d3a8894b1ab0ac660268d94a8b89e082..acd8b566f9c7a6efc2c9204624c01104dd34daf6 100644 ---- a/llvm/unittests/ADT/StringMapTest.cpp -+++ b/llvm/unittests/ADT/StringMapTest.cpp -@@ -343,7 +343,7 @@ TEST_F(StringMapTest, IterMapKeysSmallVector) { - Map["D"] = 3; - - auto Keys = to_vector<4>(Map.keys()); -- llvm::sort(Keys); -+ std::sort(Keys.begin(), Keys.end()); - - SmallVector Expected = {"A", "B", "C", "D"}; - EXPECT_EQ(Expected, Keys); diff --git a/upstream_utils/llvm_patches/0012-Extra-collections-features.patch b/upstream_utils/llvm_patches/0012-Extra-collections-features.patch index 1f32c604c2..d0c4a2838a 100644 --- a/upstream_utils/llvm_patches/0012-Extra-collections-features.patch +++ b/upstream_utils/llvm_patches/0012-Extra-collections-features.patch @@ -4,143 +4,9 @@ Date: Tue, 3 May 2022 22:16:10 -0400 Subject: [PATCH 12/38] Extra collections features --- - llvm/include/llvm/ADT/StringMap.h | 103 +++++++++++++++++++++++++++++- llvm/lib/Support/raw_ostream.cpp | 8 +++ 2 files changed, 110 insertions(+), 1 deletion(-) -diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h -index 34dfbf83c681f4e81a9dadd9382ddca6ef8d6c1d..c133e84f9b2e3a225cdac782c011fadbf07adab2 100644 ---- a/llvm/include/llvm/ADT/StringMap.h -+++ b/llvm/include/llvm/ADT/StringMap.h -@@ -42,7 +42,7 @@ protected: - - protected: - explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) {} -- StringMapImpl(StringMapImpl &&RHS) -+ StringMapImpl(StringMapImpl &&RHS) noexcept - : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), - NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), - ItemSize(RHS.ItemSize) { -@@ -432,11 +432,27 @@ public: - return Tmp; - } - -+ DerivedTy &operator--() { // Predecrement -+ --Ptr; -+ ReversePastEmptyBuckets(); -+ return static_cast(*this); -+ } -+ -+ DerivedTy operator--(int) { // Post-decrement -+ DerivedTy Tmp(Ptr); -+ --*this; -+ return Tmp; -+ } -+ - private: - void AdvancePastEmptyBuckets() { - while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) - ++Ptr; - } -+ void ReversePastEmptyBuckets() { -+ while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) -+ --Ptr; -+ } - }; - - template -@@ -495,6 +511,91 @@ public: - std::string_view operator*() const { return this->wrapped()->getKey(); } - }; - -+template -+bool operator==(const StringMap& lhs, const StringMap& rhs) { -+ // same instance? -+ if (&lhs == &rhs) return true; -+ -+ // first check that sizes are identical -+ if (lhs.size() != rhs.size()) return false; -+ -+ // copy into vectors and sort by key -+ SmallVector, 16> lhs_items; -+ lhs_items.reserve(lhs.size()); -+ for (auto i = lhs.begin(), end = lhs.end(); i != end; ++i) -+ lhs_items.push_back(i); -+ std::sort(lhs_items.begin(), lhs_items.end(), -+ [](const StringMapConstIterator& a, -+ const StringMapConstIterator& b) { -+ return a->getKey() < b->getKey(); -+ }); -+ -+ SmallVector, 16> rhs_items; -+ rhs_items.reserve(rhs.size()); -+ for (auto i = rhs.begin(), end = rhs.end(); i != end; ++i) -+ rhs_items.push_back(i); -+ std::sort(rhs_items.begin(), rhs_items.end(), -+ [](const StringMapConstIterator& a, -+ const StringMapConstIterator& b) { -+ return a->getKey() < b->getKey(); -+ }); -+ -+ // compare vector keys and values -+ for (auto a = lhs_items.begin(), b = rhs_items.begin(), -+ aend = lhs_items.end(), bend = rhs_items.end(); -+ a != aend && b != bend; ++a, ++b) { -+ if ((*a)->first() != (*b)->first() || (*a)->second != (*b)->second) -+ return false; -+ } -+ return true; -+} -+ -+template -+inline bool operator!=(const StringMap& lhs, -+ const StringMap& rhs) { -+ return !(lhs == rhs); -+} -+ -+template -+bool operator<(const StringMap& lhs, const StringMap& rhs) { -+ // same instance? -+ if (&lhs == &rhs) return false; -+ -+ // copy into vectors and sort by key -+ SmallVector lhs_keys; -+ lhs_keys.reserve(lhs.size()); -+ for (auto i = lhs.begin(), end = lhs.end(); i != end; ++i) -+ lhs_keys.push_back(i->getKey()); -+ std::sort(lhs_keys.begin(), lhs_keys.end()); -+ -+ SmallVector rhs_keys; -+ rhs_keys.reserve(rhs.size()); -+ for (auto i = rhs.begin(), end = rhs.end(); i != end; ++i) -+ rhs_keys.push_back(i->getKey()); -+ std::sort(rhs_keys.begin(), rhs_keys.end()); -+ -+ // use std::vector comparison -+ return lhs_keys < rhs_keys; -+} -+ -+template -+inline bool operator<=(const StringMap& lhs, -+ const StringMap& rhs) { -+ return !(rhs < lhs); -+} -+ -+template -+inline bool operator>(const StringMap& lhs, -+ const StringMap& rhs) { -+ return !(lhs <= rhs); -+} -+ -+template -+inline bool operator>=(const StringMap& lhs, -+ const StringMap& rhs) { -+ return !(lhs < rhs); -+} -+ - } // end namespace llvm - - #endif // LLVM_ADT_STRINGMAP_H diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 57d3091fd5cc5b416e814f9f33811f0fa7afe9cf..5bec803ccc76ce287b7ff3ea037d5e490a7af20c 100644 --- a/llvm/lib/Support/raw_ostream.cpp diff --git a/upstream_utils/llvm_patches/0016-Fixup-includes.patch b/upstream_utils/llvm_patches/0016-Fixup-includes.patch index 378b9b4598..17c463f8d9 100644 --- a/upstream_utils/llvm_patches/0016-Fixup-includes.patch +++ b/upstream_utils/llvm_patches/0016-Fixup-includes.patch @@ -4,48 +4,15 @@ Date: Sun, 8 May 2022 16:38:11 -0400 Subject: [PATCH 16/38] Fixup includes --- - llvm/include/llvm/ADT/StringMap.h | 4 ++++ - llvm/include/llvm/ADT/StringMapEntry.h | 4 ++++ llvm/include/llvm/Support/PointerLikeTypeTraits.h | 1 + llvm/lib/Support/ConvertUTFWrapper.cpp | 1 + llvm/lib/Support/ErrorHandling.cpp | 7 +++---- llvm/lib/Support/raw_ostream.cpp | 11 ++++++----- llvm/unittests/ADT/SmallPtrSetTest.cpp | 2 ++ llvm/unittests/ADT/SmallVectorTest.cpp | 1 + - llvm/unittests/ADT/StringMapTest.cpp | 1 + llvm/unittests/Support/ConvertUTFTest.cpp | 2 ++ 10 files changed, 25 insertions(+), 9 deletions(-) -diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h -index c133e84f9b2e3a225cdac782c011fadbf07adab2..2173a4159111e7fea70325de82dbfce628ae3ea8 100644 ---- a/llvm/include/llvm/ADT/StringMap.h -+++ b/llvm/include/llvm/ADT/StringMap.h -@@ -17,6 +17,10 @@ - #include "llvm/ADT/StringMapEntry.h" - #include "llvm/ADT/iterator.h" - #include "llvm/Support/AllocatorBase.h" -+#include "llvm/Support/MemAlloc.h" -+#include "llvm/Support/SmallVector.h" -+#include "llvm/Support/iterator.h" -+#include "llvm/Support/iterator_range.h" - #include "llvm/Support/PointerLikeTypeTraits.h" - #include - #include -diff --git a/llvm/include/llvm/ADT/StringMapEntry.h b/llvm/include/llvm/ADT/StringMapEntry.h -index 388e81c361642113937f7d5680de73a50635b07d..011806f5fd89ff738ed805a82b3ddbc6fc9b08ce 100644 ---- a/llvm/include/llvm/ADT/StringMapEntry.h -+++ b/llvm/include/llvm/ADT/StringMapEntry.h -@@ -16,6 +16,10 @@ - #ifndef LLVM_ADT_STRINGMAPENTRY_H - #define LLVM_ADT_STRINGMAPENTRY_H - -+#include "wpi/MemAlloc.h" -+ -+#include -+#include - #include - #include - diff --git a/llvm/include/llvm/Support/PointerLikeTypeTraits.h b/llvm/include/llvm/Support/PointerLikeTypeTraits.h index 1b15f930bd87d97d51824af5e62ea5f222a6b4c9..acadd5e89a1651cfbad67a5b1b0933d1f288d094 100644 --- a/llvm/include/llvm/Support/PointerLikeTypeTraits.h @@ -153,18 +120,6 @@ index f8c37820ef9fdfe0af067f5aa8d2297ed15e73bc..5e91f71bc9ac0e499a64dd1591e581d0 #include #include #include -diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp -index acd8b566f9c7a6efc2c9204624c01104dd34daf6..6b6cf564909f329c220eb225f3b7af6c35301029 100644 ---- a/llvm/unittests/ADT/StringMapTest.cpp -+++ b/llvm/unittests/ADT/StringMapTest.cpp -@@ -9,6 +9,7 @@ - #include "llvm/ADT/StringMap.h" - #include "llvm/Support/DataTypes.h" - #include "gtest/gtest.h" -+#include - #include - #include - using namespace llvm; diff --git a/llvm/unittests/Support/ConvertUTFTest.cpp b/llvm/unittests/Support/ConvertUTFTest.cpp index 3b07d344f15a555f11ad5f8177a0a65b8a4fa472..77e70a46d3621ecfaed923d87256184addfda721 100644 --- a/llvm/unittests/Support/ConvertUTFTest.cpp diff --git a/upstream_utils/llvm_patches/0027-Remove-StringMap-test-for-llvm-sort.patch b/upstream_utils/llvm_patches/0027-Remove-StringMap-test-for-llvm-sort.patch deleted file mode 100644 index 65960f6c30..0000000000 --- a/upstream_utils/llvm_patches/0027-Remove-StringMap-test-for-llvm-sort.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tyler Veness -Date: Wed, 10 Aug 2022 22:35:00 -0700 -Subject: [PATCH 27/38] Remove StringMap test for llvm::sort() - ---- - llvm/unittests/ADT/StringMapTest.cpp | 14 -------------- - 1 file changed, 14 deletions(-) - -diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp -index 6b6cf564909f329c220eb225f3b7af6c35301029..0d83669a580408e925ec6308410ebe7c01b48b12 100644 ---- a/llvm/unittests/ADT/StringMapTest.cpp -+++ b/llvm/unittests/ADT/StringMapTest.cpp -@@ -322,20 +322,6 @@ TEST_F(StringMapTest, InsertOrAssignTest) { - EXPECT_EQ(0, try1.first->second.copy); - } - --TEST_F(StringMapTest, IterMapKeysVector) { -- StringMap Map; -- Map["A"] = 1; -- Map["B"] = 2; -- Map["C"] = 3; -- Map["D"] = 3; -- -- std::vector Keys{Map.keys().begin(), Map.keys().end()}; -- llvm::sort(Keys); -- -- std::vector Expected{{"A", "B", "C", "D"}}; -- EXPECT_EQ(Expected, Keys); --} -- - TEST_F(StringMapTest, IterMapKeysSmallVector) { - StringMap Map; - Map["A"] = 1; diff --git a/upstream_utils/llvm_patches/0038-StringMap-fix-structured-bindings-with-move-only-typ.patch b/upstream_utils/llvm_patches/0038-StringMap-fix-structured-bindings-with-move-only-typ.patch deleted file mode 100644 index d7f4a78202..0000000000 --- a/upstream_utils/llvm_patches/0038-StringMap-fix-structured-bindings-with-move-only-typ.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ryan Blue -Date: Tue, 24 Sep 2024 23:36:16 -0400 -Subject: [PATCH 38/38] StringMap: fix structured bindings with move-only types - ---- - llvm/include/llvm/ADT/StringMapEntry.h | 12 +++++++++++- - llvm/unittests/ADT/StringMapTest.cpp | 10 ++++++++++ - 2 files changed, 21 insertions(+), 1 deletion(-) - -diff --git a/llvm/include/llvm/ADT/StringMapEntry.h b/llvm/include/llvm/ADT/StringMapEntry.h -index 011806f5fd89ff738ed805a82b3ddbc6fc9b08ce..5b8eeb167c53c7ab15d05b0c71b75cd7f5b496c5 100644 ---- a/llvm/include/llvm/ADT/StringMapEntry.h -+++ b/llvm/include/llvm/ADT/StringMapEntry.h -@@ -159,7 +159,17 @@ decltype(auto) get(const StringMapEntry &E) { - if constexpr (Index == 0) - return E.first(); - else -- return E.second; -+ return (E.second); -+} -+ -+// Allow structured bindings on StringMapEntry. -+template -+decltype(auto) get(StringMapEntry &E) { -+ static_assert(Index < 2); -+ if constexpr (Index == 0) -+ return E.first(); -+ else -+ return (E.second); - } - - } // end namespace llvm -diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp -index 0d83669a580408e925ec6308410ebe7c01b48b12..f1834bec65afec6be4365e52c4e21aa61cbb1d12 100644 ---- a/llvm/unittests/ADT/StringMapTest.cpp -+++ b/llvm/unittests/ADT/StringMapTest.cpp -@@ -526,6 +526,16 @@ TEST_F(StringMapTest, StructuredBindings) { - } - } - -+TEST_F(StringMapTest, StructuredBindingsMoveOnly) { -+ StringMap A; -+ A.insert(std::make_pair("a", MoveOnly(42))); -+ -+ for (auto &&[Key, Value] : A) { -+ EXPECT_EQ("a", Key); -+ EXPECT_EQ(42, Value.i); -+ } -+} -+ - namespace { - // Simple class that counts how many moves and copy happens when growing a map - struct CountCtorCopyAndMove { diff --git a/wpilibc/src/main/native/cpp/Tracer.cpp b/wpilibc/src/main/native/cpp/Tracer.cpp index 41b0863e47..018abde3eb 100644 --- a/wpilibc/src/main/native/cpp/Tracer.cpp +++ b/wpilibc/src/main/native/cpp/Tracer.cpp @@ -49,8 +49,8 @@ void Tracer::PrintEpochs(wpi::raw_ostream& os) { m_lastEpochsPrintTime = now; for (const auto& epoch : m_epochs) { os << fmt::format( - "\t{}: {:.6f}s\n", epoch.getKey(), - duration_cast(epoch.getValue()).count() / 1.0e6); + "\t{}: {:.6f}s\n", epoch.first, + duration_cast(epoch.second).count() / 1.0e6); } } } diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp index 4ef59fdd56..8dc962e819 100644 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp +++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp @@ -46,7 +46,7 @@ void ShuffleboardComponentBase::BuildMetadata( if (GetProperties().size() > 0) { auto propTable = metaTable->GetSubTable("Properties"); for (auto& entry : GetProperties()) { - propTable->GetEntry(entry.first()).SetValue(entry.second); + propTable->GetEntry(entry.first).SetValue(entry.second); } } m_metadataDirty = false; diff --git a/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp index e060e49bf6..5956071be5 100644 --- a/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp +++ b/wpilibc/src/main/native/cpp/smartdashboard/Mechanism2d.cpp @@ -51,7 +51,7 @@ void Mechanism2d::InitSendable(nt::NTSendableBuilder& builder) { m_colorPub = m_table->GetStringTopic(kBackgroundColor).Publish(); m_colorPub.Set(m_color); for (const auto& entry : m_roots) { - const auto& root = entry.getValue().get(); - root->Update(m_table->GetSubTable(entry.getKey())); + const auto& root = entry.second.get(); + root->Update(m_table->GetSubTable(entry.first)); } } diff --git a/wpilibc/src/main/native/cpp/smartdashboard/MechanismObject2d.cpp b/wpilibc/src/main/native/cpp/smartdashboard/MechanismObject2d.cpp index c6419d1403..136c619d0f 100644 --- a/wpilibc/src/main/native/cpp/smartdashboard/MechanismObject2d.cpp +++ b/wpilibc/src/main/native/cpp/smartdashboard/MechanismObject2d.cpp @@ -18,8 +18,7 @@ void MechanismObject2d::Update(std::shared_ptr table) { std::scoped_lock lock(m_mutex); m_table = table; UpdateEntries(m_table); - for (const wpi::StringMapEntry>& entry : - m_objects) { - entry.getValue()->Update(m_table->GetSubTable(entry.getKey())); + for (const auto& entry : m_objects) { + entry.second->Update(m_table->GetSubTable(entry.first)); } } diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp index 30b542b81b..8248a94dc8 100644 --- a/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp +++ b/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp @@ -126,7 +126,7 @@ wpi::Sendable* SmartDashboard::GetData(std::string_view key) { if (it == inst.tablesToData.end()) { throw FRC_MakeError(err::SmartDashboardMissingKey, "{}", key); } - return wpi::SendableRegistry::GetSendable(it->getValue()); + return wpi::SendableRegistry::GetSendable(it->second); } bool SmartDashboard::PutBoolean(std::string_view keyName, bool value) { @@ -254,6 +254,6 @@ void SmartDashboard::UpdateValues() { inst.listenerExecutor.RunListenerTasks(); std::scoped_lock lock(inst.tablesToDataMutex); for (auto& i : inst.tablesToData) { - wpi::SendableRegistry::Update(i.getValue()); + wpi::SendableRegistry::Update(i.second); } } diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h index 3cf022ba12..40588dd58a 100644 --- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h +++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h @@ -49,7 +49,7 @@ class SendableChooser : public SendableChooserBase { } public: - using CopyType = decltype(_unwrap_smart_ptr(m_choices.lookup(""))); + using CopyType = decltype(_unwrap_smart_ptr(m_choices.find("")->second)); SendableChooser() = default; ~SendableChooser() override = default; @@ -105,7 +105,11 @@ class SendableChooser : public SendableChooserBase { if (selected.empty()) { return CopyType{}; } else { - return _unwrap_smart_ptr(m_choices.lookup(selected)); + auto it = m_choices.find(selected); + if (it == m_choices.end()) { + return CopyType{}; + } + return _unwrap_smart_ptr(it->second); } } @@ -128,13 +132,8 @@ class SendableChooser : public SendableChooserBase { [=, this] { std::vector keys; for (const auto& choice : m_choices) { - keys.emplace_back(choice.first()); + keys.emplace_back(choice.first); } - - // Unlike std::map, wpi::StringMap elements - // are not sorted - std::sort(keys.begin(), keys.end()); - return keys; }, nullptr); diff --git a/wpinet/src/main/native/cpp/MimeTypes.cpp b/wpinet/src/main/native/cpp/MimeTypes.cpp index d5f6fb3d9e..4279633632 100644 --- a/wpinet/src/main/native/cpp/MimeTypes.cpp +++ b/wpinet/src/main/native/cpp/MimeTypes.cpp @@ -60,7 +60,7 @@ std::string_view MimeTypeFromPath(std::string_view path) { if (dot_pos > 0 && dot_pos != std::string_view::npos) { auto type = mimeTypes.find(wpi::substr(path, dot_pos + 1)); if (type != mimeTypes.end()) { - return type->getValue(); + return type->second; } } return defaultType; diff --git a/wpinet/src/main/native/include/wpinet/HttpUtil.h b/wpinet/src/main/native/include/wpinet/HttpUtil.h index ffc2dd1db3..32edda6fe1 100644 --- a/wpinet/src/main/native/include/wpinet/HttpUtil.h +++ b/wpinet/src/main/native/include/wpinet/HttpUtil.h @@ -375,8 +375,8 @@ class HttpRequest { return elem.first; } template - static std::string_view GetFirst(const StringMapEntry& elem) { - return elem.getKey(); + static std::string_view GetFirst(const std::pair& elem) { + return elem.first; } template static std::string_view GetSecond(const T& elem) { diff --git a/wpiutil/src/main/native/cpp/DataLog.cpp b/wpiutil/src/main/native/cpp/DataLog.cpp index 45c1844b11..86649beecf 100644 --- a/wpiutil/src/main/native/cpp/DataLog.cpp +++ b/wpiutil/src/main/native/cpp/DataLog.cpp @@ -83,7 +83,7 @@ void DataLog::StartFile() { // Existing start and schema data records for (auto&& entryInfo : m_entries) { - AppendStartRecord(entryInfo.second.id, entryInfo.first(), + AppendStartRecord(entryInfo.second.id, entryInfo.first, entryInfo.second.type, m_entryIds[entryInfo.second.id].metadata, 0); if (!entryInfo.second.schemaData.empty()) { diff --git a/wpiutil/src/main/native/include/wpi/StringMap.h b/wpiutil/src/main/native/include/wpi/StringMap.h new file mode 100644 index 0000000000..27b5001921 --- /dev/null +++ b/wpiutil/src/main/native/include/wpi/StringMap.h @@ -0,0 +1,777 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace wpi { + +/** + * StringMap is a sorted associative container that contains key-value pairs + * with unique string keys. Keys are sorted in the same order as std::string's + * are compared. Search, removal, and insertion operations have logarithmic + * complexity. The underlying implementation is std::map. + */ +template >> +class StringMap : public std::map, Allocator> { + public: + using map_type = typename std::map>; + using key_type = typename map_type::key_type; + using mapped_type = typename map_type::mapped_type; + using value_type = typename map_type::value_type; + using size_type = typename map_type::size_type; + using difference_type = typename map_type::difference_type; + using key_compare = typename map_type::key_compare; + using allocator_type = typename map_type::allocator_type; + using reference = typename map_type::reference; + using const_reference = typename map_type::const_reference; + using pointer = typename map_type::pointer; + using const_pointer = typename map_type::const_pointer; + using iterator = typename map_type::iterator; + using const_iterator = typename map_type::const_iterator; + using reverse_iterator = typename map_type::reverse_iterator; + using const_reverse_iterator = typename map_type::const_reverse_iterator; + using node_type = typename map_type::node_type; + using insert_return_type = typename map_type::insert_return_type; + + /** Constructs an empty container. */ + StringMap() = default; + + /** + * Constructs an empty container. + * + * @param alloc allocator to use for all memory allocations of this container + */ + explicit StringMap(const Allocator& alloc) : map_type{alloc} {} + + /** + * Constructs the container with the contents of the range [first, last). If + * multiple elements in the range have keys that compare equivalent, it is + * unspecified which element is inserted. If [first, last) is not a valid + * range, the behavior is undefined. + * + * @param first start of the range to copy the elements from + * @param last end of the range to copy the elements from + * @param alloc allocator to use for all memory allocations of this container + */ + template + StringMap(InputIt first, InputIt last, const Allocator& alloc = Allocator()) + : map_type{first, last, alloc} {} + + /** Copy constructor. */ + StringMap(const StringMap&) = default; + + /** + * Copy constructor. + * + * @param other another container to be used as source to initialize the + * elements of the container with + * @param alloc allocator to use for all memory allocations of this container + */ + StringMap(const StringMap& other, const Allocator& alloc) + : map_type{other, alloc} {} + + /** Move constructor. */ + StringMap(StringMap&&) = default; + + /** + * Move constructor. + * + * @param other another container to be used as source to initialize the + * elements of the container with + * @param alloc allocator to use for all memory allocations of this container + */ + StringMap(StringMap&& other, const Allocator& alloc) + : map_type{other, alloc} {} + + /** + * Initializer-list constructor. Construct the container with the contents of + * the initializer list init. If multiple elements in the range have keys + * that compare equal, it is unspecified which element is inserted. + * + * @param init initializer list to initialize the elements of the container + * with + * @param alloc allocator to use for all memory allocations of this container + */ + StringMap(std::initializer_list init, + const Allocator& alloc = Allocator()) + : map_type{init, alloc} {} + + /** Copy assignment operator. */ + StringMap& operator=(const StringMap&) = default; + + /** Move assignment operator. */ + StringMap& operator=(StringMap&&) noexcept( + std::allocator_traits::is_always_equal::value && + std::is_nothrow_move_assignable>::value) = default; + + /** + * Replaces the contents with those identified by initializer list ilist. + * + * @param ilist initializer list to use as data source + */ + StringMap& operator=(std::initializer_list ilist) { + map_type::operator=(ilist); + return *this; + } + + /** + * Returns a reference to the mapped value of the element with the specified + * key. If no such element exists, an exception of type std::out_of_range is + * thrown. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the requested element. + */ + T& at(const std::string& key) { return map_type::at(key); } + + /** + * Returns a reference to the mapped value of the element with the specified + * key. If no such element exists, an exception of type std::out_of_range is + * thrown. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the requested element. + */ + const T& at(const std::string& key) const { return map_type::at(key); } + + /** + * Returns a reference to the mapped value of the element with the specified + * key. If no such element exists, an exception of type std::out_of_range is + * thrown. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the requested element. + */ + T& at(const char* key) { return at(std::string_view{key}); } + + /** + * Returns a reference to the mapped value of the element with the specified + * key. If no such element exists, an exception of type std::out_of_range is + * thrown. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the requested element. + */ + const T& at(const char* key) const { return at(std::string_view{key}); } + + /** + * Returns a reference to the mapped value of the element with the specified + * key. If no such element exists, an exception of type std::out_of_range is + * thrown. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the requested element. + */ + T& at(std::string_view key) { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::at(key); +#else + auto it = find(key); + if (it == this->end()) { + throw std::out_of_range{std::string{key}}; + } + return it->second; +#endif + } + + /** + * Returns a reference to the mapped value of the element with the specified + * key. If no such element exists, an exception of type std::out_of_range is + * thrown. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the requested element. + */ + const T& at(std::string_view key) const { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::at(key); +#else + auto it = find(key); + if (it == this->end()) { + throw std::out_of_range{std::string{key}}; + } + return it->second; +#endif + } + + /** + * Returns a reference to the value that is mapped to a key, performing an + * insertion if such a key does not exist. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the new element if no element + * with key key existed. Otherwise, a reference to the mapped value + * of the existing element whose key is equal to key. + */ + T& operator[](const std::string& key) { return map_type::operator[](key); } + + /** + * Returns a reference to the value that is mapped to a key, performing an + * insertion if such a key does not exist. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the new element if no element + * with key key existed. Otherwise, a reference to the mapped value + * of the existing element whose key is equal to key. + */ + T& operator[](std::string&& key) { + return map_type::operator[](std::move(key)); + } + + /** + * Returns a reference to the value that is mapped to a key, performing an + * insertion if such a key does not exist. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the new element if no element + * with key key existed. Otherwise, a reference to the mapped value + * of the existing element whose key is equal to key. + */ + T& operator[](const char* key) { return operator[](std::string_view{key}); } + + /** + * Returns a reference to the value that is mapped to a key, performing an + * insertion if such a key does not exist. + * + * @param key the key of the element to find + * @return A reference to the mapped value of the new element if no element + * with key key existed. Otherwise, a reference to the mapped value + * of the existing element whose key is equal to key. + */ + T& operator[](std::string_view key) { return try_emplace(key).first->second; } + + /** + * If a key equal to key already exists in the container, assigns obj to the + * mapped type corresponding to that key. If the key does not exist, inserts + * the value as if by calling insert(). + * + * @param key the key used both to look up and to insert if not found + * @param obj the value to insert or assign + * @return The bool component is true if the insertion took place and false if + * the assignment took place. The iterator component is pointing at + * the element that was inserted or updated. + */ + template + std::pair insert_or_assign(std::string&& key, M&& obj) { + return map_type::insert_or_assign(std::move(key), std::forward(obj)); + } + + /** + * If a key equal to key already exists in the container, assigns obj to the + * mapped type corresponding to that key. If the key does not exist, inserts + * the value as if by calling insert(). + * + * @param key the key used both to look up and to insert if not found + * @param obj the value to insert or assign + * @return The bool component is true if the insertion took place and false if + * the assignment took place. The iterator component is pointing at + * the element that was inserted or updated. + */ + template + std::pair insert_or_assign(const char* key, M&& obj) { + return insert_or_assign(std::string_view{key}, std::forward(obj)); + } + + /** + * If a key equal to key already exists in the container, assigns obj to the + * mapped type corresponding to that key. If the key does not exist, inserts + * the value as if by calling insert(). + * + * @param key the key used both to look up and to insert if not found + * @param obj the value to insert or assign + * @return The bool component is true if the insertion took place and false if + * the assignment took place. The iterator component is pointing at + * the element that was inserted or updated. + */ + template + std::pair insert_or_assign(std::string_view key, M&& obj) { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::insert_or_assign(key, std::forward(obj)); +#else + auto it = lower_bound(key); + if (it != this->end() && it->first == key) { + it->second = std::forward(obj); + return {it, false}; + } else { + return {this->insert(it, {std::string{key}, std::forward(obj)}), true}; + } +#endif + } + + /** + * If a key equal to key already exists in the container, assigns obj to the + * mapped type corresponding to that key. If the key does not exist, inserts + * the value as if by calling insert(). + * + * @param hint iterator to the position before which the new element will be + * inserted + * @param key the key used both to look up and to insert if not found + * @param obj the value to insert or assign + * @return Iterator pointing at the element that was inserted or updated. + */ + template + iterator insert_or_assign(const_iterator hint, std::string&& key, M&& obj) { + return map_type::insert_or_assign(hint, std::move(key), + std::forward(obj)); + } + + /** + * If a key equal to key already exists in the container, assigns obj to the + * mapped type corresponding to that key. If the key does not exist, inserts + * the value as if by calling insert(). + * + * @param hint iterator to the position before which the new element will be + * inserted + * @param key the key used both to look up and to insert if not found + * @param obj the value to insert or assign + * @return Iterator pointing at the element that was inserted or updated. + */ + template + iterator insert_or_assign(const_iterator hint, const char* key, M&& obj) { + return insert_or_assign(hint, std::string_view{key}, std::forward(obj)); + } + + /** + * If a key equal to key already exists in the container, assigns obj to the + * mapped type corresponding to that key. If the key does not exist, inserts + * the value as if by calling insert(). + * + * @param hint iterator to the position before which the new element will be + * inserted + * @param key the key used both to look up and to insert if not found + * @param obj the value to insert or assign + * @return Iterator pointing at the element that was inserted or updated. + */ + template + iterator insert_or_assign(const_iterator hint, std::string_view key, + M&& obj) { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::insert_or_assign(hint, key, std::forward(obj)); +#else + return map_type::insert_or_assign(hint, std::string{key}, + std::forward(obj)); +#endif + } + + /** + * Inserts a new element into the container constructed in-place with the + * given args, if there is no element with the key in the container. + * + * No iterators or references are invalidated. + * + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return A pair consisting of an interator to the inserted element (or to + * the element that prevented the insertion) and a bool value set to + * true if and only if the insertion took place. + */ + template + std::pair emplace(std::string&& key, Args&&... args) { + return map_type::emplace(std::move(key), std::forward(args)...); + } + + /** + * Inserts a new element into the container constructed in-place with the + * given args, if there is no element with the key in the container. + * + * No iterators or references are invalidated. + * + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return A pair consisting of an interator to the inserted element (or to + * the element that prevented the insertion) and a bool value set to + * true if and only if the insertion took place. + */ + template + std::pair emplace(const char* key, Args&&... args) { + return emplace(std::string_view{key}, std::forward(args)...); + } + + /** + * Inserts a new element into the container constructed in-place with the + * given args, if there is no element with the key in the container. + * + * No iterators or references are invalidated. + * + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return A pair consisting of an interator to the inserted element (or to + * the element that prevented the insertion) and a bool value set to + * true if and only if the insertion took place. + */ + template + std::pair emplace(std::string_view key, Args&&... args) { + return try_emplace(key, std::forward(args)...); + } + + /** + * If a key equal to key already exists in the container, does nothing. + * Otherwise, inserts a new element into the container with key key and value + * constructed with args. + * + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return A pair consisting of an interator to the inserted element (or to + * the element that prevented the insertion) and a bool value set to + * true if and only if the insertion took place. + */ + template + std::pair try_emplace(std::string&& key, Args&&... args) { + return map_type::try_emplace(std::move(key), std::forward(args)...); + } + + /** + * If a key equal to key already exists in the container, does nothing. + * Otherwise, inserts a new element into the container with key key and value + * constructed with args. + * + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return A pair consisting of an interator to the inserted element (or to + * the element that prevented the insertion) and a bool value set to + * true if and only if the insertion took place. + */ + template + std::pair try_emplace(const char* key, Args&&... args) { + return try_emplace(std::string_view{key}, std::forward(args)...); + } + + /** + * If a key equal to key already exists in the container, does nothing. + * Otherwise, inserts a new element into the container with key key and value + * constructed with args. + * + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return A pair consisting of an interator to the inserted element (or to + * the element that prevented the insertion) and a bool value set to + * true if and only if the insertion took place. + */ + template + std::pair try_emplace(std::string_view key, Args&&... args) { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::try_emplace(key, std::forward(args)...); +#else + auto it = lower_bound(key); + if (it != this->end() && it->first == key) { + return {it, false}; + } else { + return {try_emplace(it, key, std::forward(args)...), true}; + } +#endif + } + + /** + * If a key equal to key already exists in the container, does nothing. + * Otherwise, inserts a new element into the container with key key and value + * constructed with args. + * + * @param hint iterator to the position before which the new element will be + * inserted + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return An interator to the inserted element, or to the element that + * prevented the insertion. + */ + template + iterator try_emplace(const_iterator hint, std::string&& key, Args&&... args) { + return map_type::try_emplace(hint, std::move(key), + std::forward(args)...); + } + + /** + * If a key equal to key already exists in the container, does nothing. + * Otherwise, inserts a new element into the container with key key and value + * constructed with args. + * + * @param hint iterator to the position before which the new element will be + * inserted + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return An interator to the inserted element, or to the element that + * prevented the insertion. + */ + template + iterator try_emplace(const_iterator hint, const char* key, Args&&... args) { + return try_emplace(hint, std::string_view{key}, + std::forward(args)...); + } + + /** + * If a key equal to key already exists in the container, does nothing. + * Otherwise, inserts a new element into the container with key key and value + * constructed with args. + * + * @param hint iterator to the position before which the new element will be + * inserted + * @param key the key used both to look up and to insert if not found + * @param args arguments to forward to the constructor of the element + * @return An interator to the inserted element, or to the element that + * prevented the insertion. + */ + template + iterator try_emplace(const_iterator hint, std::string_view key, + Args&&... args) { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::try_emplace(hint, key, std::forward(args)...); +#else + return map_type::try_emplace(hint, std::string{key}, + std::forward(args)...); +#endif + } + + /** + * Removes the element at pos. + * + * @param pos iterator to the element to remove + * @return Iterator following the removed element. + */ + iterator erase(iterator pos) { return map_type::erase(pos); } + + /** + * Removes the element at pos. + * + * @param pos iterator to the element to remove + * @return Iterator following the removed element. + */ + iterator erase(const_iterator pos) { return map_type::erase(pos); } + + /** + * Removes the elements in the range [first, last), which must be a valid + * range in this. + * + * @param first Start of the range of elements to remove + * @param last End of the range of elements to remove + * @return Iterator following the last removed element. + */ + iterator erase(iterator first, iterator last) { + return map_type::erase(first, last); + } + + /** + * Removes the elements in the range [first, last), which must be a valid + * range in this. + * + * @param first Start of the range of elements to remove + * @param last End of the range of elements to remove + * @return Iterator following the last removed element. + */ + iterator erase(const_iterator first, const_iterator last) { + return map_type::erase(first, last); + } + + /** + * Removes the element (if one exists) with the key equal to key. + * + * @param key key value of the elements to remove + * @return Number of elements removed (0 or 1). + */ + size_type erase(std::string_view key) { +#ifdef __cpp_lib_associative_heterogeneous_erasure + return map_type::erase(key); +#else + auto it = find(key); + if (it == this->end()) { + return 0; + } + this->erase(it); + return 1; +#endif + } + + /** + * Exchanges the contents of the container with those of other. Does not + * invoke any move, copy, or swap operations on individual elements. + * + * All iterators and references remain valid. The end() iterator is + * invalidated. + * + * @param other container to exchange the contents with + */ + void swap(StringMap& other) noexcept( + std::allocator_traits::is_always_equal::value && + std::is_nothrow_swappable>::value) { + map_type::swap(other); + } + + /** + * Unlinks the node that contains the element pointed to by position and + * returns a node handle that owns it. + * + * @param position a valid iterator into this container + * @return A node handle that owns the extracted element + */ + node_type extract(const_iterator position) { + return map_type::extract(position); + } + + /** + * If the container has an element with key equal to key, unlinks the node + * that contains that element from the container and returns a node handle + * that owns it. Otherwise, returns an empty node handle. + * + * @param key a key to identify the node to be extracted + * @return A node handle that owns the extracted element, or empty node handle + * in case the element is not found. + */ + node_type extract(std::string_view key) { +#ifdef __cpp_lib_associative_heterogeneous_insertion + return map_type::extract(key); +#else + auto it = find(key); + if (it == this->end()) { + return {}; + } + return extract(it); +#endif + } + + /** + * Returns the number of elements with key that equals the specified argument. + * + * @param key key value of the elements to count + * @return Number of elements with key that equals key (either 0 or 1). + */ + size_type count(std::string_view key) const { return map_type::count(key); } + + /** + * Finds an element with key equal to key. + * + * @param key key value of the element to search for + * @return An iterator to the requested element. If no such element is found, + * past-the-end (see end()) iterator is returned. + */ + iterator find(std::string_view key) { return map_type::find(key); } + + /** + * Finds an element with key equal to key. + * + * @param key key value of the element to search for + * @return An iterator to the requested element. If no such element is found, + * past-the-end (see end()) iterator is returned. + */ + const_iterator find(std::string_view key) const { + return map_type::find(key); + } + + /** + * Checks if there is an element with key equal to key in the container. + * + * @param key key value of the element to search for + * @return true if there is such an element, otherwise false + */ + bool contains(std::string_view key) const { return map_type::contains(key); } + + /** + * Returns a range containing all elements with the given key in the + * container. The range is defined by two iterators, one pointing to the + * first element that is not less than key and another pointing to the first + * element greater than key. Alternatively, the first iterator may be + * obtained with lower_bound(), and the second with upper_bound(). + * + * @param key key value to compare the elements to + * @return std::pair containing a pair of iterators defining the wanted range: + * the first pointing to the first element that is not less than key + * and the second pointing to the first element greater than key. If + * there are no elements not less than key, past-the-end (see end()) + * iterator is returned as the first element. Similarly if there are + * no elements greater than key, past-the-end iterator is returned as + * the second element. + */ + std::pair equal_range(std::string_view key) { + return map_type::equal_range(key); + } + + /** + * Returns a range containing all elements with the given key in the + * container. The range is defined by two iterators, one pointing to the + * first element that is not less than key and another pointing to the first + * element greater than key. Alternatively, the first iterator may be + * obtained with lower_bound(), and the second with upper_bound(). + * + * @param key key value to compare the elements to + * @return std::pair containing a pair of iterators defining the wanted range: + * the first pointing to the first element that is not less than key + * and the second pointing to the first element greater than key. If + * there are no elements not less than key, past-the-end (see end()) + * iterator is returned as the first element. Similarly if there are + * no elements greater than key, past-the-end iterator is returned as + * the second element. + */ + std::pair equal_range( + std::string_view key) const { + return map_type::equal_range(key); + } + + /** + * Returns an iterator pointing to the first element that is not less than + * (i.e. greater or equal to) key. + * + * @param key key value to compare the elements to + * @return Iterator pointing to the first element that is not less than key. + * If no such element is found, a past-the-end iterator (see end()) is + * returned. + */ + iterator lower_bound(std::string_view key) { + return map_type::lower_bound(key); + } + + /** + * Returns an iterator pointing to the first element that is not less than + * (i.e. greater or equal to) key. + * + * @param key key value to compare the elements to + * @return Iterator pointing to the first element that is not less than key. + * If no such element is found, a past-the-end iterator (see end()) is + * returned. + */ + const_iterator lower_bound(std::string_view key) const { + return map_type::lower_bound(key); + } + + /** + * Returns an interator pointing to the first element that is greater than + * key. + * + * @param key key value to compare the elements to + * @return Iterator pointing to the first element that is greater than key. + * If no such element is found, past-the-end (see end()) iterator is + * returned. + */ + iterator upper_bound(std::string_view key) { + return map_type::upper_bound(key); + } + + /** + * Returns an interator pointing to the first element that is greater than + * key. + * + * @param key key value to compare the elements to + * @return Iterator pointing to the first element that is greater than key. + * If no such element is found, past-the-end (see end()) iterator is + * returned. + */ + const_iterator upper_bound(std::string_view key) const { + return map_type::upper_bound(key); + } +}; + +} // namespace wpi + +namespace std { +template +inline void swap(wpi::StringMap& lhs, wpi::StringMap& rhs) { + lhs.swap(rhs); +} +} // namespace std diff --git a/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringMap.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringMap.cpp deleted file mode 100644 index de41aeac09..0000000000 --- a/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringMap.cpp +++ /dev/null @@ -1,259 +0,0 @@ -//===--- StringMap.cpp - String Hash table map implementation -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the StringMap class. -// -//===----------------------------------------------------------------------===// - -#include "wpi/StringMap.h" -#include "wpi/MathExtras.h" -#include "wpi/ReverseIteration.h" -#include "wpi/xxhash.h" - -using namespace wpi; - -/// Returns the number of buckets to allocate to ensure that the DenseMap can -/// accommodate \p NumEntries without need to grow(). -static inline unsigned getMinBucketToReserveForEntries(unsigned NumEntries) { - // Ensure that "NumEntries * 4 < NumBuckets * 3" - if (NumEntries == 0) - return 0; - // +1 is required because of the strict equality. - // For example if NumEntries is 48, we need to return 401. - return NextPowerOf2(NumEntries * 4 / 3 + 1); -} - -static inline StringMapEntryBase **createTable(unsigned NewNumBuckets) { - auto **Table = static_cast(safe_calloc( - NewNumBuckets + 1, sizeof(StringMapEntryBase **) + sizeof(unsigned))); - - // Allocate one extra bucket, set it to look filled so the iterators stop at - // end. - Table[NewNumBuckets] = (StringMapEntryBase *)2; - return Table; -} - -static inline unsigned *getHashTable(StringMapEntryBase **TheTable, - unsigned NumBuckets) { - return reinterpret_cast(TheTable + NumBuckets + 1); -} - -StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { - ItemSize = itemSize; - - // If a size is specified, initialize the table with that many buckets. - if (InitSize) { - // The table will grow when the number of entries reach 3/4 of the number of - // buckets. To guarantee that "InitSize" number of entries can be inserted - // in the table without growing, we allocate just what is needed here. - init(getMinBucketToReserveForEntries(InitSize)); - return; - } - - // Otherwise, initialize it with zero buckets to avoid the allocation. - TheTable = nullptr; - NumBuckets = 0; - NumItems = 0; - NumTombstones = 0; -} - -void StringMapImpl::init(unsigned InitSize) { - assert((InitSize & (InitSize - 1)) == 0 && - "Init Size must be a power of 2 or zero!"); - - unsigned NewNumBuckets = InitSize ? InitSize : 16; - NumItems = 0; - NumTombstones = 0; - - TheTable = createTable(NewNumBuckets); - - // Set the member only if TheTable was successfully allocated - NumBuckets = NewNumBuckets; -} - -/// LookupBucketFor - Look up the bucket that the specified string should end -/// up in. If it already exists as a key in the map, the Item pointer for the -/// specified bucket will be non-null. Otherwise, it will be null. In either -/// case, the FullHashValue field of the bucket will be set to the hash value -/// of the string. -unsigned StringMapImpl::LookupBucketFor(std::string_view Name) { - // Hash table unallocated so far? - if (NumBuckets == 0) - init(16); - unsigned FullHashValue = xxh3_64bits(Name); - if (shouldReverseIterate()) - FullHashValue = ~FullHashValue; - unsigned BucketNo = FullHashValue & (NumBuckets - 1); - unsigned *HashTable = getHashTable(TheTable, NumBuckets); - - unsigned ProbeAmt = 1; - int FirstTombstone = -1; - while (true) { - StringMapEntryBase *BucketItem = TheTable[BucketNo]; - // If we found an empty bucket, this key isn't in the table yet, return it. - if (LLVM_LIKELY(!BucketItem)) { - // If we found a tombstone, we want to reuse the tombstone instead of an - // empty bucket. This reduces probing. - if (FirstTombstone != -1) { - HashTable[FirstTombstone] = FullHashValue; - return FirstTombstone; - } - - HashTable[BucketNo] = FullHashValue; - return BucketNo; - } - - if (BucketItem == getTombstoneVal()) { - // Skip over tombstones. However, remember the first one we see. - if (FirstTombstone == -1) - FirstTombstone = BucketNo; - } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { - // If the full hash value matches, check deeply for a match. The common - // case here is that we are only looking at the buckets (for item info - // being non-null and for the full hash value) not at the items. This - // is important for cache locality. - - // Do the comparison like this because Name isn't necessarily - // null-terminated! - char *ItemStr = (char *)BucketItem + ItemSize; - if (Name == std::string_view(ItemStr, BucketItem->getKeyLength())) { - // We found a match! - return BucketNo; - } - } - - // Okay, we didn't find the item. Probe to the next bucket. - BucketNo = (BucketNo + ProbeAmt) & (NumBuckets - 1); - - // Use quadratic probing, it has fewer clumping artifacts than linear - // probing and has good cache behavior in the common case. - ++ProbeAmt; - } -} - -/// FindKey - Look up the bucket that contains the specified key. If it exists -/// in the map, return the bucket number of the key. Otherwise return -1. -/// This does not modify the map. -int StringMapImpl::FindKey(std::string_view Key) const { - if (NumBuckets == 0) - return -1; // Really empty table? - unsigned FullHashValue = xxh3_64bits(Key); - if (shouldReverseIterate()) - FullHashValue = ~FullHashValue; - unsigned BucketNo = FullHashValue & (NumBuckets - 1); - unsigned *HashTable = getHashTable(TheTable, NumBuckets); - - unsigned ProbeAmt = 1; - while (true) { - StringMapEntryBase *BucketItem = TheTable[BucketNo]; - // If we found an empty bucket, this key isn't in the table yet, return. - if (LLVM_LIKELY(!BucketItem)) - return -1; - - if (BucketItem == getTombstoneVal()) { - // Ignore tombstones. - } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { - // If the full hash value matches, check deeply for a match. The common - // case here is that we are only looking at the buckets (for item info - // being non-null and for the full hash value) not at the items. This - // is important for cache locality. - - // Do the comparison like this because NameStart isn't necessarily - // null-terminated! - char *ItemStr = (char *)BucketItem + ItemSize; - if (Key == std::string_view(ItemStr, BucketItem->getKeyLength())) { - // We found a match! - return BucketNo; - } - } - - // Okay, we didn't find the item. Probe to the next bucket. - BucketNo = (BucketNo + ProbeAmt) & (NumBuckets - 1); - - // Use quadratic probing, it has fewer clumping artifacts than linear - // probing and has good cache behavior in the common case. - ++ProbeAmt; - } -} - -/// RemoveKey - Remove the specified StringMapEntry from the table, but do not -/// delete it. This aborts if the value isn't in the table. -void StringMapImpl::RemoveKey(StringMapEntryBase *V) { - const char *VStr = (char *)V + ItemSize; - StringMapEntryBase *V2 = RemoveKey(std::string_view(VStr, V->getKeyLength())); - (void)V2; - assert(V == V2 && "Didn't find key?"); -} - -/// RemoveKey - Remove the StringMapEntry for the specified key from the -/// table, returning it. If the key is not in the table, this returns null. -StringMapEntryBase *StringMapImpl::RemoveKey(std::string_view Key) { - int Bucket = FindKey(Key); - if (Bucket == -1) - return nullptr; - - StringMapEntryBase *Result = TheTable[Bucket]; - TheTable[Bucket] = getTombstoneVal(); - --NumItems; - ++NumTombstones; - assert(NumItems + NumTombstones <= NumBuckets); - - return Result; -} - -/// RehashTable - Grow the table, redistributing values into the buckets with -/// the appropriate mod-of-hashtable-size. -unsigned StringMapImpl::RehashTable(unsigned BucketNo) { - unsigned NewSize; - // If the hash table is now more than 3/4 full, or if fewer than 1/8 of - // the buckets are empty (meaning that many are filled with tombstones), - // grow/rehash the table. - if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) { - NewSize = NumBuckets * 2; - } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <= - NumBuckets / 8)) { - NewSize = NumBuckets; - } else { - return BucketNo; - } - - unsigned NewBucketNo = BucketNo; - auto **NewTableArray = createTable(NewSize); - unsigned *NewHashArray = getHashTable(NewTableArray, NewSize); - unsigned *HashTable = getHashTable(TheTable, NumBuckets); - - // Rehash all the items into their new buckets. Luckily :) we already have - // the hash values available, so we don't have to rehash any strings. - for (unsigned I = 0, E = NumBuckets; I != E; ++I) { - StringMapEntryBase *Bucket = TheTable[I]; - if (Bucket && Bucket != getTombstoneVal()) { - // If the bucket is not available, probe for a spot. - unsigned FullHash = HashTable[I]; - unsigned NewBucket = FullHash & (NewSize - 1); - if (NewTableArray[NewBucket]) { - unsigned ProbeSize = 1; - do { - NewBucket = (NewBucket + ProbeSize++) & (NewSize - 1); - } while (NewTableArray[NewBucket]); - } - - // Finally found a slot. Fill it in. - NewTableArray[NewBucket] = Bucket; - NewHashArray[NewBucket] = FullHash; - if (I == BucketNo) - NewBucketNo = NewBucket; - } - } - - free(TheTable); - - TheTable = NewTableArray; - NumBuckets = NewSize; - NumTombstones = 0; - return NewBucketNo; -} diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMap.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMap.h deleted file mode 100644 index 323d22e744..0000000000 --- a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMap.h +++ /dev/null @@ -1,605 +0,0 @@ -//===- StringMap.h - String Hash table map interface ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file defines the StringMap class. -/// -//===----------------------------------------------------------------------===// - -#ifndef WPIUTIL_WPI_STRINGMAP_H -#define WPIUTIL_WPI_STRINGMAP_H - -#include "wpi/StringMapEntry.h" -#include "wpi/iterator.h" -#include "wpi/AllocatorBase.h" -#include "wpi/MemAlloc.h" -#include "wpi/SmallVector.h" -#include "wpi/iterator.h" -#include "wpi/iterator_range.h" -#include "wpi/PointerLikeTypeTraits.h" -#include -#include - -namespace wpi { - -template class StringMapConstIterator; -template class StringMapIterator; -template class StringMapKeyIterator; - -/// StringMapImpl - This is the base class of StringMap that is shared among -/// all of its instantiations. -class StringMapImpl { -protected: - // Array of NumBuckets pointers to entries, null pointers are holes. - // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed - // by an array of the actual hash values as unsigned integers. - StringMapEntryBase **TheTable = nullptr; - unsigned NumBuckets = 0; - unsigned NumItems = 0; - unsigned NumTombstones = 0; - unsigned ItemSize; - -protected: - explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) {} - StringMapImpl(StringMapImpl &&RHS) noexcept - : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), - NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), - ItemSize(RHS.ItemSize) { - RHS.TheTable = nullptr; - RHS.NumBuckets = 0; - RHS.NumItems = 0; - RHS.NumTombstones = 0; - } - - StringMapImpl(unsigned InitSize, unsigned ItemSize); - unsigned RehashTable(unsigned BucketNo = 0); - - /// LookupBucketFor - Look up the bucket that the specified string should end - /// up in. If it already exists as a key in the map, the Item pointer for the - /// specified bucket will be non-null. Otherwise, it will be null. In either - /// case, the FullHashValue field of the bucket will be set to the hash value - /// of the string. - unsigned LookupBucketFor(std::string_view Key); - - /// FindKey - Look up the bucket that contains the specified key. If it exists - /// in the map, return the bucket number of the key. Otherwise return -1. - /// This does not modify the map. - int FindKey(std::string_view Key) const; - - /// RemoveKey - Remove the specified StringMapEntry from the table, but do not - /// delete it. This aborts if the value isn't in the table. - void RemoveKey(StringMapEntryBase *V); - - /// RemoveKey - Remove the StringMapEntry for the specified key from the - /// table, returning it. If the key is not in the table, this returns null. - StringMapEntryBase *RemoveKey(std::string_view Key); - - /// Allocate the table with the specified number of buckets and otherwise - /// setup the map as empty. - void init(unsigned Size); - -public: - static constexpr uintptr_t TombstoneIntVal = - static_cast(-1) - << PointerLikeTypeTraits::NumLowBitsAvailable; - - static StringMapEntryBase *getTombstoneVal() { - return reinterpret_cast(TombstoneIntVal); - } - - unsigned getNumBuckets() const { return NumBuckets; } - unsigned getNumItems() const { return NumItems; } - - bool empty() const { return NumItems == 0; } - unsigned size() const { return NumItems; } - - void swap(StringMapImpl &Other) { - std::swap(TheTable, Other.TheTable); - std::swap(NumBuckets, Other.NumBuckets); - std::swap(NumItems, Other.NumItems); - std::swap(NumTombstones, Other.NumTombstones); - } -}; - -/// StringMap - This is an unconventional map that is specialized for handling -/// keys that are "strings", which are basically ranges of bytes. This does some -/// funky memory allocation and hashing things to make it extremely efficient, -/// storing the string data *after* the value in the map. -template -class LLVM_ALLOCATORHOLDER_EMPTYBASE StringMap - : public StringMapImpl, - private detail::AllocatorHolder { - using AllocTy = detail::AllocatorHolder; - -public: - using MapEntryTy = StringMapEntry; - - StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} - - explicit StringMap(unsigned InitialSize) - : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} - - explicit StringMap(AllocatorTy A) - : StringMapImpl(static_cast(sizeof(MapEntryTy))), AllocTy(A) {} - - StringMap(unsigned InitialSize, AllocatorTy A) - : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), - AllocTy(A) {} - - StringMap(std::initializer_list> List) - : StringMapImpl(List.size(), static_cast(sizeof(MapEntryTy))) { - insert(List); - } - - StringMap(StringMap &&RHS) - : StringMapImpl(std::move(RHS)), AllocTy(std::move(RHS.getAllocator())) {} - - StringMap(const StringMap &RHS) - : StringMapImpl(static_cast(sizeof(MapEntryTy))), - AllocTy(RHS.getAllocator()) { - if (RHS.empty()) - return; - - // Allocate TheTable of the same size as RHS's TheTable, and set the - // sentinel appropriately (and NumBuckets). - init(RHS.NumBuckets); - unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1), - *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1); - - NumItems = RHS.NumItems; - NumTombstones = RHS.NumTombstones; - for (unsigned I = 0, E = NumBuckets; I != E; ++I) { - StringMapEntryBase *Bucket = RHS.TheTable[I]; - if (!Bucket || Bucket == getTombstoneVal()) { - TheTable[I] = Bucket; - continue; - } - - TheTable[I] = MapEntryTy::create( - static_cast(Bucket)->getKey(), getAllocator(), - static_cast(Bucket)->getValue()); - HashTable[I] = RHSHashTable[I]; - } - - // Note that here we've copied everything from the RHS into this object, - // tombstones included. We could, instead, have re-probed for each key to - // instantiate this new object without any tombstone buckets. The - // assumption here is that items are rarely deleted from most StringMaps, - // and so tombstones are rare, so the cost of re-probing for all inputs is - // not worthwhile. - } - - StringMap &operator=(StringMap RHS) { - StringMapImpl::swap(RHS); - std::swap(getAllocator(), RHS.getAllocator()); - return *this; - } - - ~StringMap() { - // Delete all the elements in the map, but don't reset the elements - // to default values. This is a copy of clear(), but avoids unnecessary - // work not required in the destructor. - if (!empty()) { - for (unsigned I = 0, E = NumBuckets; I != E; ++I) { - StringMapEntryBase *Bucket = TheTable[I]; - if (Bucket && Bucket != getTombstoneVal()) { - static_cast(Bucket)->Destroy(getAllocator()); - } - } - } - free(TheTable); - } - - using AllocTy::getAllocator; - - using key_type = const char *; - using mapped_type = ValueTy; - using value_type = StringMapEntry; - using size_type = size_t; - - using const_iterator = StringMapConstIterator; - using iterator = StringMapIterator; - - iterator begin() { return iterator(TheTable, NumBuckets == 0); } - iterator end() { return iterator(TheTable + NumBuckets, true); } - const_iterator begin() const { - return const_iterator(TheTable, NumBuckets == 0); - } - const_iterator end() const { - return const_iterator(TheTable + NumBuckets, true); - } - - iterator_range> keys() const { - return make_range(StringMapKeyIterator(begin()), - StringMapKeyIterator(end())); - } - - iterator find(std::string_view Key) { - int Bucket = FindKey(Key); - if (Bucket == -1) - return end(); - return iterator(TheTable + Bucket, true); - } - - const_iterator find(std::string_view Key) const { - int Bucket = FindKey(Key); - if (Bucket == -1) - return end(); - return const_iterator(TheTable + Bucket, true); - } - - /// lookup - Return the entry for the specified key, or a default - /// constructed value if no such entry exists. - ValueTy lookup(std::string_view Key) const { - const_iterator Iter = find(Key); - if (Iter != end()) - return Iter->second; - return ValueTy(); - } - - /// at - Return the entry for the specified key, or abort if no such - /// entry exists. - const ValueTy &at(std::string_view Val) const { - auto Iter = this->find(std::move(Val)); - assert(Iter != this->end() && "StringMap::at failed due to a missing key"); - return Iter->second; - } - - /// Lookup the ValueTy for the \p Key, or create a default constructed value - /// if the key is not in the map. - ValueTy &operator[](std::string_view Key) { return try_emplace(Key).first->second; } - - /// contains - Return true if the element is in the map, false otherwise. - bool contains(std::string_view Key) const { return find(Key) != end(); } - - /// count - Return 1 if the element is in the map, 0 otherwise. - size_type count(std::string_view Key) const { return contains(Key) ? 1 : 0; } - - template - size_type count(const StringMapEntry &MapEntry) const { - return count(MapEntry.getKey()); - } - - /// equal - check whether both of the containers are equal. - bool operator==(const StringMap &RHS) const { - if (size() != RHS.size()) - return false; - - for (const auto &KeyValue : *this) { - auto FindInRHS = RHS.find(KeyValue.getKey()); - - if (FindInRHS == RHS.end()) - return false; - - if (!(KeyValue.getValue() == FindInRHS->getValue())) - return false; - } - - return true; - } - - bool operator!=(const StringMap &RHS) const { return !(*this == RHS); } - - /// insert - Insert the specified key/value pair into the map. If the key - /// already exists in the map, return false and ignore the request, otherwise - /// insert it and return true. - bool insert(MapEntryTy *KeyValue) { - unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); - StringMapEntryBase *&Bucket = TheTable[BucketNo]; - if (Bucket && Bucket != getTombstoneVal()) - return false; // Already exists in map. - - if (Bucket == getTombstoneVal()) - --NumTombstones; - Bucket = KeyValue; - ++NumItems; - assert(NumItems + NumTombstones <= NumBuckets); - - RehashTable(); - return true; - } - - /// insert - Inserts the specified key/value pair into the map if the key - /// isn't already in the map. The bool component of the returned pair is true - /// if and only if the insertion takes place, and the iterator component of - /// the pair points to the element with key equivalent to the key of the pair. - std::pair insert(std::pair KV) { - return try_emplace(KV.first, std::move(KV.second)); - } - - /// Inserts elements from range [first, last). If multiple elements in the - /// range have keys that compare equivalent, it is unspecified which element - /// is inserted . - template void insert(InputIt First, InputIt Last) { - for (InputIt It = First; It != Last; ++It) - insert(*It); - } - - /// Inserts elements from initializer list ilist. If multiple elements in - /// the range have keys that compare equivalent, it is unspecified which - /// element is inserted - void insert(std::initializer_list> List) { - insert(List.begin(), List.end()); - } - - /// Inserts an element or assigns to the current element if the key already - /// exists. The return type is the same as try_emplace. - template - std::pair insert_or_assign(std::string_view Key, V &&Val) { - auto Ret = try_emplace(Key, std::forward(Val)); - if (!Ret.second) - Ret.first->second = std::forward(Val); - return Ret; - } - - /// Emplace a new element for the specified key into the map if the key isn't - /// already in the map. The bool component of the returned pair is true - /// if and only if the insertion takes place, and the iterator component of - /// the pair points to the element with key equivalent to the key of the pair. - template - std::pair try_emplace(std::string_view Key, ArgsTy &&...Args) { - unsigned BucketNo = LookupBucketFor(Key); - StringMapEntryBase *&Bucket = TheTable[BucketNo]; - if (Bucket && Bucket != getTombstoneVal()) - return std::make_pair(iterator(TheTable + BucketNo, false), - false); // Already exists in map. - - if (Bucket == getTombstoneVal()) - --NumTombstones; - Bucket = - MapEntryTy::create(Key, getAllocator(), std::forward(Args)...); - ++NumItems; - assert(NumItems + NumTombstones <= NumBuckets); - - BucketNo = RehashTable(BucketNo); - return std::make_pair(iterator(TheTable + BucketNo, false), true); - } - - // clear - Empties out the StringMap - void clear() { - if (empty()) - return; - - // Zap all values, resetting the keys back to non-present (not tombstone), - // which is safe because we're removing all elements. - for (unsigned I = 0, E = NumBuckets; I != E; ++I) { - StringMapEntryBase *&Bucket = TheTable[I]; - if (Bucket && Bucket != getTombstoneVal()) { - static_cast(Bucket)->Destroy(getAllocator()); - } - Bucket = nullptr; - } - - NumItems = 0; - NumTombstones = 0; - } - - /// remove - Remove the specified key/value pair from the map, but do not - /// erase it. This aborts if the key is not in the map. - void remove(MapEntryTy *KeyValue) { RemoveKey(KeyValue); } - - void erase(iterator I) { - MapEntryTy &V = *I; - remove(&V); - V.Destroy(getAllocator()); - } - - bool erase(std::string_view Key) { - iterator I = find(Key); - if (I == end()) - return false; - erase(I); - return true; - } -}; - -template -class StringMapIterBase - : public iterator_facade_base { -protected: - StringMapEntryBase **Ptr = nullptr; - -public: - StringMapIterBase() = default; - - explicit StringMapIterBase(StringMapEntryBase **Bucket, - bool NoAdvance = false) - : Ptr(Bucket) { - if (!NoAdvance) - AdvancePastEmptyBuckets(); - } - - DerivedTy &operator=(const DerivedTy &Other) { - Ptr = Other.Ptr; - return static_cast(*this); - } - - friend bool operator==(const DerivedTy &LHS, const DerivedTy &RHS) { - return LHS.Ptr == RHS.Ptr; - } - - DerivedTy &operator++() { // Preincrement - ++Ptr; - AdvancePastEmptyBuckets(); - return static_cast(*this); - } - - DerivedTy operator++(int) { // Post-increment - DerivedTy Tmp(Ptr); - ++*this; - return Tmp; - } - - DerivedTy &operator--() { // Predecrement - --Ptr; - ReversePastEmptyBuckets(); - return static_cast(*this); - } - - DerivedTy operator--(int) { // Post-decrement - DerivedTy Tmp(Ptr); - --*this; - return Tmp; - } - -private: - void AdvancePastEmptyBuckets() { - while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) - ++Ptr; - } - void ReversePastEmptyBuckets() { - while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) - --Ptr; - } -}; - -template -class StringMapConstIterator - : public StringMapIterBase, - const StringMapEntry> { - using base = StringMapIterBase, - const StringMapEntry>; - -public: - StringMapConstIterator() = default; - explicit StringMapConstIterator(StringMapEntryBase **Bucket, - bool NoAdvance = false) - : base(Bucket, NoAdvance) {} - - const StringMapEntry &operator*() const { - return *static_cast *>(*this->Ptr); - } -}; - -template -class StringMapIterator : public StringMapIterBase, - StringMapEntry> { - using base = - StringMapIterBase, StringMapEntry>; - -public: - StringMapIterator() = default; - explicit StringMapIterator(StringMapEntryBase **Bucket, - bool NoAdvance = false) - : base(Bucket, NoAdvance) {} - - StringMapEntry &operator*() const { - return *static_cast *>(*this->Ptr); - } - - operator StringMapConstIterator() const { - return StringMapConstIterator(this->Ptr, true); - } -}; - -template -class StringMapKeyIterator - : public iterator_adaptor_base, - StringMapConstIterator, - std::forward_iterator_tag, std::string_view> { - using base = iterator_adaptor_base, - StringMapConstIterator, - std::forward_iterator_tag, std::string_view>; - -public: - StringMapKeyIterator() = default; - explicit StringMapKeyIterator(StringMapConstIterator Iter) - : base(std::move(Iter)) {} - - std::string_view operator*() const { return this->wrapped()->getKey(); } -}; - -template -bool operator==(const StringMap& lhs, const StringMap& rhs) { - // same instance? - if (&lhs == &rhs) return true; - - // first check that sizes are identical - if (lhs.size() != rhs.size()) return false; - - // copy into vectors and sort by key - SmallVector, 16> lhs_items; - lhs_items.reserve(lhs.size()); - for (auto i = lhs.begin(), end = lhs.end(); i != end; ++i) - lhs_items.push_back(i); - std::sort(lhs_items.begin(), lhs_items.end(), - [](const StringMapConstIterator& a, - const StringMapConstIterator& b) { - return a->getKey() < b->getKey(); - }); - - SmallVector, 16> rhs_items; - rhs_items.reserve(rhs.size()); - for (auto i = rhs.begin(), end = rhs.end(); i != end; ++i) - rhs_items.push_back(i); - std::sort(rhs_items.begin(), rhs_items.end(), - [](const StringMapConstIterator& a, - const StringMapConstIterator& b) { - return a->getKey() < b->getKey(); - }); - - // compare vector keys and values - for (auto a = lhs_items.begin(), b = rhs_items.begin(), - aend = lhs_items.end(), bend = rhs_items.end(); - a != aend && b != bend; ++a, ++b) { - if ((*a)->first() != (*b)->first() || (*a)->second != (*b)->second) - return false; - } - return true; -} - -template -inline bool operator!=(const StringMap& lhs, - const StringMap& rhs) { - return !(lhs == rhs); -} - -template -bool operator<(const StringMap& lhs, const StringMap& rhs) { - // same instance? - if (&lhs == &rhs) return false; - - // copy into vectors and sort by key - SmallVector lhs_keys; - lhs_keys.reserve(lhs.size()); - for (auto i = lhs.begin(), end = lhs.end(); i != end; ++i) - lhs_keys.push_back(i->getKey()); - std::sort(lhs_keys.begin(), lhs_keys.end()); - - SmallVector rhs_keys; - rhs_keys.reserve(rhs.size()); - for (auto i = rhs.begin(), end = rhs.end(); i != end; ++i) - rhs_keys.push_back(i->getKey()); - std::sort(rhs_keys.begin(), rhs_keys.end()); - - // use std::vector comparison - return lhs_keys < rhs_keys; -} - -template -inline bool operator<=(const StringMap& lhs, - const StringMap& rhs) { - return !(rhs < lhs); -} - -template -inline bool operator>(const StringMap& lhs, - const StringMap& rhs) { - return !(lhs <= rhs); -} - -template -inline bool operator>=(const StringMap& lhs, - const StringMap& rhs) { - return !(lhs < rhs); -} - -} // end namespace wpi - -#endif // WPIUTIL_WPI_STRINGMAP_H diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMapEntry.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMapEntry.h deleted file mode 100644 index 968989bc03..0000000000 --- a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMapEntry.h +++ /dev/null @@ -1,187 +0,0 @@ -//===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file defines the StringMapEntry class - it is intended to be a low -/// dependency implementation detail of StringMap that is more suitable for -/// inclusion in public headers than StringMap.h itself is. -/// -//===----------------------------------------------------------------------===// - -#ifndef WPIUTIL_WPI_STRINGMAPENTRY_H -#define WPIUTIL_WPI_STRINGMAPENTRY_H - -#include "wpi/MemAlloc.h" - -#include -#include -#include -#include - -namespace wpi { - -/// StringMapEntryBase - Shared base class of StringMapEntry instances. -class StringMapEntryBase { - size_t keyLength; - -public: - explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {} - - size_t getKeyLength() const { return keyLength; } - -protected: - /// Helper to tail-allocate \p Key. It'd be nice to generalize this so it - /// could be reused elsewhere, maybe even taking an wpi::function_ref to - /// type-erase the allocator and put it in a source file. - template - static void *allocateWithKey(size_t EntrySize, size_t EntryAlign, - std::string_view Key, AllocatorTy &Allocator); -}; - -// Define out-of-line to dissuade inlining. -template -void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign, - std::string_view Key, - AllocatorTy &Allocator) { - size_t KeyLength = Key.size(); - - // Allocate a new item with space for the string at the end and a null - // terminator. - size_t AllocSize = EntrySize + KeyLength + 1; - void *Allocation = Allocator.Allocate(AllocSize, EntryAlign); - assert(Allocation && "Unhandled out-of-memory"); - - // Copy the string information. - char *Buffer = reinterpret_cast(Allocation) + EntrySize; - if (KeyLength > 0) - ::memcpy(Buffer, Key.data(), KeyLength); - Buffer[KeyLength] = 0; // Null terminate for convenience of clients. - return Allocation; -} - -/// StringMapEntryStorage - Holds the value in a StringMapEntry. -/// -/// Factored out into a separate base class to make it easier to specialize. -/// This is primarily intended to support StringSet, which doesn't need a value -/// stored at all. -template -class StringMapEntryStorage : public StringMapEntryBase { -public: - ValueTy second; - - explicit StringMapEntryStorage(size_t keyLength) - : StringMapEntryBase(keyLength), second() {} - template - StringMapEntryStorage(size_t keyLength, InitTy &&...initVals) - : StringMapEntryBase(keyLength), - second(std::forward(initVals)...) {} - StringMapEntryStorage(StringMapEntryStorage &e) = delete; - - const ValueTy &getValue() const { return second; } - ValueTy &getValue() { return second; } - - void setValue(const ValueTy &V) { second = V; } -}; - -template <> -class StringMapEntryStorage : public StringMapEntryBase { -public: - explicit StringMapEntryStorage(size_t keyLength, - std::nullopt_t = std::nullopt) - : StringMapEntryBase(keyLength) {} - StringMapEntryStorage(StringMapEntryStorage &entry) = delete; - - std::nullopt_t getValue() const { return std::nullopt; } -}; - -/// StringMapEntry - This is used to represent one value that is inserted into -/// a StringMap. It contains the Value itself and the key: the string length -/// and data. -template -class StringMapEntry final : public StringMapEntryStorage { -public: - using StringMapEntryStorage::StringMapEntryStorage; - - using ValueType = ValueTy; - - std::string_view getKey() const { - return std::string_view(getKeyData(), this->getKeyLength()); - } - - /// getKeyData - Return the start of the string data that is the key for this - /// value. The string data is always stored immediately after the - /// StringMapEntry object. - const char *getKeyData() const { - return reinterpret_cast(this + 1); - } - - std::string_view first() const { - return std::string_view(getKeyData(), this->getKeyLength()); - } - - /// Create a StringMapEntry for the specified key construct the value using - /// \p InitiVals. - template - static StringMapEntry *create(std::string_view key, AllocatorTy &allocator, - InitTy &&... initVals) { - return new (StringMapEntryBase::allocateWithKey( - sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator)) - StringMapEntry(key.size(), std::forward(initVals)...); - } - - /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded - /// into a StringMapEntry, return the StringMapEntry itself. - static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) { - char *ptr = const_cast(keyData) - sizeof(StringMapEntry); - return *reinterpret_cast(ptr); - } - - /// Destroy - Destroy this StringMapEntry, releasing memory back to the - /// specified allocator. - template void Destroy(AllocatorTy &allocator) { - // Free memory referenced by the item. - size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1; - this->~StringMapEntry(); - allocator.Deallocate(static_cast(this), AllocSize, - alignof(StringMapEntry)); - } -}; - -// Allow structured bindings on StringMapEntry. -template -decltype(auto) get(const StringMapEntry &E) { - static_assert(Index < 2); - if constexpr (Index == 0) - return E.first(); - else - return (E.second); -} - -// Allow structured bindings on StringMapEntry. -template -decltype(auto) get(StringMapEntry &E) { - static_assert(Index < 2); - if constexpr (Index == 0) - return E.first(); - else - return (E.second); -} - -} // end namespace wpi - -namespace std { -template -struct tuple_size> - : std::integral_constant {}; - -template -struct tuple_element> - : std::conditional {}; -} // namespace std - -#endif // WPIUTIL_WPI_STRINGMAPENTRY_H diff --git a/wpiutil/src/test/native/cpp/llvm/StringMapTest.cpp b/wpiutil/src/test/native/cpp/StringMapTest.cpp similarity index 56% rename from wpiutil/src/test/native/cpp/llvm/StringMapTest.cpp rename to wpiutil/src/test/native/cpp/StringMapTest.cpp index 70896dac2b..04dffc503f 100644 --- a/wpiutil/src/test/native/cpp/llvm/StringMapTest.cpp +++ b/wpiutil/src/test/native/cpp/StringMapTest.cpp @@ -1,3 +1,7 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + //===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -6,27 +10,26 @@ // //===----------------------------------------------------------------------===// -#include "wpi/StringMap.h" -#include "gtest/gtest.h" -#include -#include +#include "wpi/StringMap.h" // NOLINT(build/include_order) + +#include #include +#include + +#include + using namespace wpi; namespace { -static_assert(sizeof(StringMap) < - sizeof(StringMap), - "Ensure empty base optimization happens with default allocator"); - // Test fixture class StringMapTest : public testing::Test { -protected: + protected: StringMap testMap; static const char testKey[]; static const uint32_t testValue; - static const char *testKeyFirst; + static const char* testKeyFirst; static size_t testKeyLength; static const std::string testKeyStr; @@ -57,7 +60,7 @@ protected: // Iterator tests StringMap::iterator it = testMap.begin(); - EXPECT_STREQ(testKey, it->first().data()); + EXPECT_STREQ(testKey, it->first.data()); EXPECT_EQ(testValue, it->second); ++it; EXPECT_TRUE(it == testMap.end()); @@ -76,26 +79,28 @@ protected: const char StringMapTest::testKey[] = "key"; const uint32_t StringMapTest::testValue = 1u; -const char *StringMapTest::testKeyFirst = testKey; +const char* StringMapTest::testKeyFirst = testKey; size_t StringMapTest::testKeyLength = sizeof(testKey) - 1; const std::string StringMapTest::testKeyStr(testKey); struct CountCopyAndMove { CountCopyAndMove() = default; - CountCopyAndMove(const CountCopyAndMove &) { copy = 1; } - CountCopyAndMove(CountCopyAndMove &&) { move = 1; } - void operator=(const CountCopyAndMove &) { ++copy; } - void operator=(CountCopyAndMove &&) { ++move; } + CountCopyAndMove(const CountCopyAndMove&) { copy = 1; } + CountCopyAndMove(CountCopyAndMove&&) { move = 1; } + void operator=(const CountCopyAndMove&) { ++copy; } + void operator=(CountCopyAndMove&&) { ++move; } int copy = 0; int move = 0; }; // Empty map tests. -TEST_F(StringMapTest, EmptyMapTest) { assertEmptyMap(); } +TEST_F(StringMapTest, EmptyMap) { + assertEmptyMap(); +} // Constant map tests. -TEST_F(StringMapTest, ConstEmptyMapTest) { - const StringMap &constTestMap = testMap; +TEST_F(StringMapTest, ConstEmptyMap) { + const StringMap& constTestMap = testMap; // Size tests EXPECT_EQ(0u, constTestMap.size()); @@ -106,11 +111,12 @@ TEST_F(StringMapTest, ConstEmptyMapTest) { // Lookup tests EXPECT_EQ(0u, constTestMap.count(testKey)); - EXPECT_EQ(0u, constTestMap.count(std::string_view(testKeyFirst, testKeyLength))); + EXPECT_EQ(0u, + constTestMap.count(std::string_view(testKeyFirst, testKeyLength))); EXPECT_EQ(0u, constTestMap.count(testKeyStr)); EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end()); - EXPECT_TRUE(constTestMap.find(std::string_view(testKeyFirst, testKeyLength)) == - constTestMap.end()); + EXPECT_TRUE(constTestMap.find(std::string_view( + testKeyFirst, testKeyLength)) == constTestMap.end()); EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end()); } @@ -122,63 +128,41 @@ TEST_F(StringMapTest, InitializerListCtor) { } // A map with a single entry. -TEST_F(StringMapTest, SingleEntryMapTest) { +TEST_F(StringMapTest, SingleEntryMap) { testMap[testKey] = testValue; assertSingleItemMap(); } // Test clear() method. -TEST_F(StringMapTest, ClearTest) { +TEST_F(StringMapTest, Clear) { testMap[testKey] = testValue; testMap.clear(); assertEmptyMap(); } // Test erase(iterator) method. -TEST_F(StringMapTest, EraseIteratorTest) { +TEST_F(StringMapTest, EraseIterator) { testMap[testKey] = testValue; testMap.erase(testMap.begin()); assertEmptyMap(); } // Test erase(value) method. -TEST_F(StringMapTest, EraseValueTest) { +TEST_F(StringMapTest, EraseValue) { testMap[testKey] = testValue; testMap.erase(testKey); assertEmptyMap(); } // Test inserting two values and erasing one. -TEST_F(StringMapTest, InsertAndEraseTest) { +TEST_F(StringMapTest, InsertAndErase) { testMap[testKey] = testValue; testMap["otherKey"] = 2; testMap.erase("otherKey"); assertSingleItemMap(); } -TEST_F(StringMapTest, SmallFullMapTest) { - // StringMap has a tricky corner case when the map is small (<8 buckets) and - // it fills up through a balanced pattern of inserts and erases. This can - // lead to inf-loops in some cases (PR13148) so we test it explicitly here. - wpi::StringMap Map(2); - - Map["eins"] = 1; - Map["zwei"] = 2; - Map["drei"] = 3; - Map.erase("drei"); - Map.erase("eins"); - Map["veir"] = 4; - Map["funf"] = 5; - - EXPECT_EQ(3u, Map.size()); - EXPECT_EQ(0, Map.lookup("eins")); - EXPECT_EQ(2, Map.lookup("zwei")); - EXPECT_EQ(0, Map.lookup("drei")); - EXPECT_EQ(4, Map.lookup("veir")); - EXPECT_EQ(5, Map.lookup("funf")); -} - -TEST_F(StringMapTest, CopyCtorTest) { +TEST_F(StringMapTest, SmallFullMap) { wpi::StringMap Map; Map["eins"] = 1; @@ -190,22 +174,41 @@ TEST_F(StringMapTest, CopyCtorTest) { Map["funf"] = 5; EXPECT_EQ(3u, Map.size()); - EXPECT_EQ(0, Map.lookup("eins")); - EXPECT_EQ(2, Map.lookup("zwei")); - EXPECT_EQ(0, Map.lookup("drei")); - EXPECT_EQ(4, Map.lookup("veir")); - EXPECT_EQ(5, Map.lookup("funf")); + EXPECT_FALSE(Map.contains("eins")); + EXPECT_EQ(2, Map["zwei"]); + EXPECT_FALSE(Map.contains("drei")); + EXPECT_EQ(4, Map["veir"]); + EXPECT_EQ(5, Map["funf"]); +} + +TEST_F(StringMapTest, CopyCtor) { + wpi::StringMap Map; + + Map["eins"] = 1; + Map["zwei"] = 2; + Map["drei"] = 3; + Map.erase("drei"); + Map.erase("eins"); + Map["veir"] = 4; + Map["funf"] = 5; + + EXPECT_EQ(3u, Map.size()); + EXPECT_FALSE(Map.contains("eins")); + EXPECT_EQ(2, Map["zwei"]); + EXPECT_FALSE(Map.contains("drei")); + EXPECT_EQ(4, Map["veir"]); + EXPECT_EQ(5, Map["funf"]); wpi::StringMap Map2(Map); EXPECT_EQ(3u, Map2.size()); - EXPECT_EQ(0, Map2.lookup("eins")); - EXPECT_EQ(2, Map2.lookup("zwei")); - EXPECT_EQ(0, Map2.lookup("drei")); - EXPECT_EQ(4, Map2.lookup("veir")); - EXPECT_EQ(5, Map2.lookup("funf")); + EXPECT_FALSE(Map2.contains("eins")); + EXPECT_EQ(2, Map2["zwei"]); + EXPECT_FALSE(Map2.contains("drei")); + EXPECT_EQ(4, Map2["veir"]); + EXPECT_EQ(5, Map2["funf"]); } -TEST_F(StringMapTest, AtTest) { +TEST_F(StringMapTest, At) { wpi::StringMap Map; // keys both found and not found on non-empty map @@ -218,7 +221,7 @@ TEST_F(StringMapTest, AtTest) { } // A more complex iteration test. -TEST_F(StringMapTest, IterationTest) { +TEST_F(StringMapTest, Iteration) { bool visited[100]; // Insert 100 numbers into the map @@ -234,7 +237,7 @@ TEST_F(StringMapTest, IterationTest) { ++it) { std::stringstream ss; ss << "key_" << it->second; - ASSERT_STREQ(ss.str().c_str(), it->first().data()); + ASSERT_STREQ(ss.str().c_str(), it->first.data()); visited[it->second] = true; } @@ -244,34 +247,23 @@ TEST_F(StringMapTest, IterationTest) { } } -// Test StringMapEntry::Create() method. -TEST_F(StringMapTest, StringMapEntryTest) { - MallocAllocator Allocator; - StringMap::value_type *entry = - StringMap::value_type::create( - std::string_view(testKeyFirst, testKeyLength), Allocator, 1u); - EXPECT_STREQ(testKey, entry->first().data()); - EXPECT_EQ(1u, entry->second); - entry->Destroy(Allocator); -} - // Test insert() method. -TEST_F(StringMapTest, InsertTest) { +TEST_F(StringMapTest, Insert) { SCOPED_TRACE("InsertTest"); - testMap.insert(StringMap::value_type::create( - std::string_view(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u)); + testMap.insert( + std::make_pair(std::string_view(testKeyFirst, testKeyLength), 1u)); assertSingleItemMap(); } // Test insert(pair) method -TEST_F(StringMapTest, InsertPairTest) { +TEST_F(StringMapTest, InsertPair) { bool Inserted; StringMap::iterator NewIt; std::tie(NewIt, Inserted) = testMap.insert(std::make_pair(testKeyFirst, testValue)); EXPECT_EQ(1u, testMap.size()); EXPECT_EQ(testValue, testMap[testKeyFirst]); - EXPECT_EQ(testKeyFirst, NewIt->first()); + EXPECT_EQ(testKeyFirst, NewIt->first); EXPECT_EQ(testValue, NewIt->second); EXPECT_TRUE(Inserted); @@ -284,28 +276,12 @@ TEST_F(StringMapTest, InsertPairTest) { EXPECT_EQ(NewIt, ExistingIt); } -// Test insert(pair) method when rehashing occurs -TEST_F(StringMapTest, InsertRehashingPairTest) { - // Check that the correct iterator is returned when the inserted element is - // moved to a different bucket during internal rehashing. This depends on - // the particular key, and the implementation of StringMap and HashString. - // Changes to those might result in this test not actually checking that. - StringMap t(0); - EXPECT_EQ(0u, t.getNumBuckets()); - - StringMap::iterator It = - t.insert(std::make_pair("abcdef", 42)).first; - EXPECT_EQ(16u, t.getNumBuckets()); - EXPECT_EQ("abcdef", It->first()); - EXPECT_EQ(42u, It->second); -} - -TEST_F(StringMapTest, InsertOrAssignTest) { +TEST_F(StringMapTest, InsertOrAssign) { struct A : CountCopyAndMove { - A(int v) : v(v) {} + explicit A(int v) : v(v) {} int v; }; - StringMap t(0); + StringMap t; auto try1 = t.insert_or_assign("A", A(1)); EXPECT_TRUE(try1.second); @@ -321,23 +297,9 @@ TEST_F(StringMapTest, InsertOrAssignTest) { EXPECT_EQ(0, try1.first->second.copy); } -TEST_F(StringMapTest, IterMapKeysSmallVector) { - StringMap Map; - Map["A"] = 1; - Map["B"] = 2; - Map["C"] = 3; - Map["D"] = 3; - - auto Keys = to_vector<4>(Map.keys()); - std::sort(Keys.begin(), Keys.end()); - - SmallVector Expected = {"A", "B", "C", "D"}; - EXPECT_EQ(Expected, Keys); -} - // Create a non-default constructable value struct StringMapTestStruct { - StringMapTestStruct(int i) : i(i) {} + explicit StringMapTestStruct(int i) : i(i) {} StringMapTestStruct() = delete; int i; }; @@ -352,39 +314,24 @@ TEST_F(StringMapTest, NonDefaultConstructable) { struct Immovable { Immovable() {} - Immovable(Immovable &&) = delete; // will disable the other special members + Immovable(Immovable&&) = delete; // will disable the other special members }; struct MoveOnly { int i; - MoveOnly(int i) : i(i) {} - MoveOnly(const Immovable &) : i(0) {} - MoveOnly(MoveOnly &&RHS) : i(RHS.i) {} - MoveOnly &operator=(MoveOnly &&RHS) { + explicit MoveOnly(int i) : i(i) {} + explicit MoveOnly(const Immovable&) : i(0) {} + MoveOnly(MoveOnly&& RHS) : i(RHS.i) {} + MoveOnly& operator=(MoveOnly&& RHS) { i = RHS.i; return *this; } -private: - MoveOnly(const MoveOnly &) = delete; - MoveOnly &operator=(const MoveOnly &) = delete; + private: + MoveOnly(const MoveOnly&) = delete; + MoveOnly& operator=(const MoveOnly&) = delete; }; -TEST_F(StringMapTest, MoveOnly) { - StringMap t; - t.insert(std::make_pair("Test", MoveOnly(42))); - std::string_view Key = "Test"; - StringMapEntry::create(Key, t.getAllocator(), MoveOnly(42)) - ->Destroy(t.getAllocator()); -} - -TEST_F(StringMapTest, CtorArg) { - std::string_view Key = "Test"; - MallocAllocator Allocator; - StringMapEntry::create(Key, Allocator, Immovable()) - ->Destroy(Allocator); -} - TEST_F(StringMapTest, MoveConstruct) { StringMap A; A["x"] = 42; @@ -412,7 +359,7 @@ TEST_F(StringMapTest, EqualEmpty) { StringMap B; ASSERT_TRUE(A == B); ASSERT_FALSE(A != B); - ASSERT_TRUE(A == A); // self check + ASSERT_TRUE(A == A); // self check } TEST_F(StringMapTest, EqualWithValues) { @@ -432,7 +379,7 @@ TEST_F(StringMapTest, EqualWithValues) { ASSERT_TRUE(B == A); ASSERT_FALSE(A != B); ASSERT_FALSE(B != A); - ASSERT_TRUE(A == A); // self check + ASSERT_TRUE(A == A); // self check } TEST_F(StringMapTest, NotEqualMissingKeys) { @@ -472,21 +419,21 @@ TEST_F(StringMapTest, NotEqualWithDifferentValues) { } struct Countable { - int &InstanceCount; + int& InstanceCount; int Number; - Countable(int Number, int &InstanceCount) + Countable(int Number, int& InstanceCount) : InstanceCount(InstanceCount), Number(Number) { ++InstanceCount; } - Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) { + Countable(Countable&& C) : InstanceCount(C.InstanceCount), Number(C.Number) { ++InstanceCount; C.Number = -1; } - Countable(const Countable &C) + Countable(const Countable& C) : InstanceCount(C.InstanceCount), Number(C.Number) { ++InstanceCount; } - Countable &operator=(Countable C) { + Countable& operator=(Countable C) { Number = C.Number; return *this; } @@ -519,7 +466,7 @@ TEST_F(StringMapTest, StructuredBindings) { StringMap A; A["a"] = 42; - for (auto &[Key, Value] : A) { + for (auto& [Key, Value] : A) { EXPECT_EQ("a", Key); EXPECT_EQ(42, Value); } @@ -529,7 +476,7 @@ TEST_F(StringMapTest, StructuredBindingsMoveOnly) { StringMap A; A.insert(std::make_pair("a", MoveOnly(42))); - for (auto &&[Key, Value] : A) { + for (auto&& [Key, Value] : A) { EXPECT_EQ("a", Key); EXPECT_EQ(42, Value.i); } @@ -542,16 +489,16 @@ struct CountCtorCopyAndMove { static unsigned Move; static unsigned Copy; int Data = 0; - CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; } + explicit CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; } CountCtorCopyAndMove() { Ctor++; } - CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; } - CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) { + CountCtorCopyAndMove(const CountCtorCopyAndMove&) { Copy++; } + CountCtorCopyAndMove& operator=(const CountCtorCopyAndMove&) { Copy++; return *this; } - CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; } - CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) { + CountCtorCopyAndMove(CountCtorCopyAndMove&&) { Move++; } + CountCtorCopyAndMove& operator=(const CountCtorCopyAndMove&&) { Move++; return *this; } @@ -560,30 +507,7 @@ unsigned CountCtorCopyAndMove::Copy = 0; unsigned CountCtorCopyAndMove::Move = 0; unsigned CountCtorCopyAndMove::Ctor = 0; -} // anonymous namespace - -// Make sure creating the map with an initial size of N actually gives us enough -// buckets to insert N items without increasing allocation size. -TEST(StringMapCustomTest, InitialSizeTest) { - // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an - // arbitrary prime, picked without any good reason. - for (auto Size : {1, 32, 67}) { - StringMap Map(Size); - auto NumBuckets = Map.getNumBuckets(); - CountCtorCopyAndMove::Move = 0; - CountCtorCopyAndMove::Copy = 0; - for (int i = 0; i < Size; ++i) - Map.insert(std::pair( - std::piecewise_construct, std::forward_as_tuple(std::to_string(i)), - std::forward_as_tuple(i))); - // After the initial move, the map will move the Elts in the Entry. - EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move); - // We copy once the pair from the Elts vector - EXPECT_EQ(0u, CountCtorCopyAndMove::Copy); - // Check that the map didn't grow - EXPECT_EQ(Map.getNumBuckets(), NumBuckets); - } -} +} // namespace TEST(StringMapCustomTest, BracketOperatorCtor) { StringMap Map; @@ -600,57 +524,18 @@ namespace { struct NonMoveableNonCopyableType { int Data = 0; NonMoveableNonCopyableType() = default; - NonMoveableNonCopyableType(int Data) : Data(Data) {} - NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete; - NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete; + explicit NonMoveableNonCopyableType(int Data) : Data(Data) {} + NonMoveableNonCopyableType(const NonMoveableNonCopyableType&) = delete; + NonMoveableNonCopyableType(NonMoveableNonCopyableType&&) = delete; }; -} // namespace +} // namespace // Test that we can "emplace" an element in the map without involving map/move -TEST(StringMapCustomTest, EmplaceTest) { +TEST(StringMapCustomTest, Emplace) { StringMap Map; Map.try_emplace("abcd", 42); EXPECT_EQ(1u, Map.count("abcd")); EXPECT_EQ(42, Map["abcd"].Data); } -// Test that StringMapEntryBase can handle size_t wide sizes. -TEST(StringMapCustomTest, StringMapEntryBaseSize) { - size_t LargeValue; - - // Test that the entry can represent max-unsigned. - if (sizeof(size_t) <= sizeof(unsigned)) - LargeValue = std::numeric_limits::max(); - else - LargeValue = std::numeric_limits::max() + 1ULL; - StringMapEntryBase LargeBase(LargeValue); - EXPECT_EQ(LargeValue, LargeBase.getKeyLength()); - - // Test that the entry can hold at least max size_t. - LargeValue = std::numeric_limits::max(); - StringMapEntryBase LargerBase(LargeValue); - LargeValue = std::numeric_limits::max(); - EXPECT_EQ(LargeValue, LargerBase.getKeyLength()); -} - -// Test that StringMapEntry can handle size_t wide sizes. -TEST(StringMapCustomTest, StringMapEntrySize) { - size_t LargeValue; - - // Test that the entry can represent max-unsigned. - if (sizeof(size_t) <= sizeof(unsigned)) - LargeValue = std::numeric_limits::max(); - else - LargeValue = std::numeric_limits::max() + 1ULL; - StringMapEntry LargeEntry(LargeValue); - std::string_view Key = LargeEntry.getKey(); - EXPECT_EQ(LargeValue, Key.size()); - - // Test that the entry can hold at least max size_t. - LargeValue = std::numeric_limits::max(); - StringMapEntry LargerEntry(LargeValue); - Key = LargerEntry.getKey(); - EXPECT_EQ(LargeValue, Key.size()); -} - -} // end anonymous namespace +} // namespace