| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #pragma once |
| |
| #include <cstddef> |
| #include <functional> |
| #include <map> |
| #include <string> |
| #include <type_traits> |
| |
| #include "flutter/fml/hash_combine.h" |
| #include "flutter/fml/macros.h" |
| |
| namespace impeller { |
| |
| struct UniqueID { |
| size_t id; |
| |
| UniqueID(); |
| |
| constexpr bool operator==(const UniqueID& other) const { |
| return id == other.id; |
| } |
| }; |
| |
| class ComparableBase {}; |
| |
| template <class Type> |
| class Comparable : ComparableBase { |
| public: |
| virtual std::size_t GetHash() const = 0; |
| |
| virtual bool IsEqual(const Type& other) const = 0; |
| }; |
| |
| template < |
| class ComparableType, |
| class = std::enable_if_t<std::is_base_of_v<ComparableBase, ComparableType>>> |
| struct ComparableHash { |
| std::size_t operator()(const ComparableType& object) const { |
| return object.GetHash(); |
| } |
| }; |
| |
| template < |
| class ComparableType, |
| class = std::enable_if_t<std::is_base_of_v<ComparableBase, ComparableType>>> |
| struct ComparableEqual { |
| bool operator()(const ComparableType& lhs, const ComparableType& rhs) const { |
| return lhs.IsEqual(rhs); |
| } |
| }; |
| |
| template < |
| class ComparableType, |
| class = std::enable_if_t<std::is_base_of_v<ComparableBase, ComparableType>>> |
| bool DeepComparePointer(const std::shared_ptr<ComparableType>& lhs, |
| const std::shared_ptr<ComparableType>& rhs) { |
| if (lhs == rhs) { |
| return true; |
| } |
| |
| if (lhs && rhs) { |
| return lhs->IsEqual(*rhs); |
| } |
| |
| return false; |
| } |
| |
| template < |
| class Key, |
| class ComparableType, |
| class = std::enable_if_t<std::is_base_of_v<ComparableBase, ComparableType>>> |
| bool DeepCompareMap(const std::map<Key, std::shared_ptr<ComparableType>>& lhs, |
| const std::map<Key, std::shared_ptr<ComparableType>>& rhs) { |
| if (lhs.size() != rhs.size()) { |
| return false; |
| } |
| |
| for (auto i = lhs.begin(), j = rhs.begin(); i != lhs.end(); i++, j++) { |
| if (i->first != j->first) { |
| return false; |
| } |
| |
| if (!DeepComparePointer(i->second, j->second)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| } // namespace impeller |
| |
| namespace std { |
| |
| template <> |
| struct hash<impeller::UniqueID> { |
| constexpr std::size_t operator()(const impeller::UniqueID& id) { |
| return id.id; |
| } |
| }; |
| |
| template <> |
| struct less<impeller::UniqueID> { |
| constexpr bool operator()(const impeller::UniqueID& lhs, |
| const impeller::UniqueID& rhs) const { |
| return lhs.id < rhs.id; |
| } |
| }; |
| |
| } // namespace std |