// SPDX-FileCopyrightText: Copyright (C) 2016 swift Project Community / Contributors // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1 //! \file #ifndef SWIFT_MISC_MEMOTABLE_H #define SWIFT_MISC_MEMOTABLE_H #include "misc/dictionary.h" #include "misc/sequence.h" namespace swift::misc { /*! * A data memoization pattern useful for compressing JSON representations of containers. */ template class CMemoTable { public: //! Return the index of a value, inserting it if it is not already in the table. int getIndex(const T &value) { int &index = m_dict[value]; if (!index) { m_list.push_back(value); index = m_list.size(); } return index - 1; } //! Return the values in the table as a flat list. const CSequence &getTable() const { return m_list; } private: CSequence m_list; CDictionary m_dict; }; /*! * Helper class for memoizing members of a value object. */ template struct CMemoHelper { //! Memoizer for Ts. Other types are passed through. class CMemoizer : private CMemoTable... { public: //! If T is in Ts, return the index of member in the memo table. Otherwise, return member. template decltype(auto) maybeMemoize(const T &member) { if constexpr ((std::is_same_v || ...)) { return this->CMemoTable::getIndex(member); } else { return std::as_const(member); } } //! Return the values in the T table as a flat list. template const CSequence &getTable() const { return this->CMemoTable::getTable(); } }; //! Unmemoizer for Ts. Other types are passed through. class CUnmemoizer : private CSequence... { public: //! Return reference to the flat list T table. template CSequence &getTable() { return *this; } //! If T is in Ts, return proxy that will assign to member through the value at the given index in the flat //! list. Otherwise, return member as std::reference_wrapper. template auto maybeUnmemoize(T &member) const { if constexpr ((std::is_same_v || ...)) { struct Memo // clazy:exclude=rule-of-three { int index; T &member; const CSequence &list; int &get() { return index; } ~Memo() { if (index >= 0) { member = list[index]; } } }; return Memo { -1, member, static_cast &>(*this) }; } else { return std::ref(member); } } }; }; } // namespace swift::misc #endif