/* SPDX-FileCopyrightText: 2024 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup bli */ #pragma once #include #include "BLI_array.hh" #include "BLI_implicit_sharing_ptr.hh" #include "BLI_virtual_array.hh" namespace blender { /** * Remembers the values in an array and allows checking if another array in the future has exactly * the same values. This is useful for checking if the topology of a mesh has changed. * * If possible, this class makes use of implicit-sharing to avoid creating unnecessary copies of * the data. This also allows detecting that the array is not changed in constant time in common * cases. */ template class ArrayState { private: /** * The actual values in the remembered array. This may point to data owned by #sharing_info_ or * #cached_values_. */ Span values_; /** (Shared) ownership of the array in case it supports implicit-sharing. */ ImplicitSharingPtr<> sharing_info_; /** Fallback-copy in the case when the array could not be shared. */ std::optional> cached_values_; public: ArrayState() = default; ArrayState(const VArray &values, const ImplicitSharingInfo *sharing_info) { if (values.is_span() && sharing_info) { /* Don't create a copy of the array and just take shared ownership. */ values_ = values.get_internal_span(); sharing_info->add_user(); sharing_info_ = ImplicitSharingPtr(sharing_info); return; } /* Create a copy of the array because sharing is not possible. */ cached_values_.emplace(values.size(), NoInitialization{}); values.materialize_to_uninitialized(*cached_values_); values_ = *cached_values_; } /** * True when the remembered array does not contain any values. */ bool is_empty() const { return values_.is_empty(); } /** * True when the remembered array contains the same values as the given array. * This is O(1) in the case when the array was shared and has not been modified. * If determining equality in constant time is not possible, the method falls back to comparing * the values individually which will take O(n) time. */ bool same_as(const VArray &other_values, const ImplicitSharingInfo *other_sharing_info) const { if (sharing_info_ && other_sharing_info) { if (sharing_info_ == other_sharing_info) { /* The data is still shared. */ return true; } } if (values_.size() != other_values.size()) { /* The arrays can't be the same if their sizes differ. */ return false; } /* Need to actually compare all elements. */ VArraySpan other_values_span(other_values); return values_ == other_values_span; } }; } // namespace blender