//======================================================================== // // Ref.h // // Copyright 1996-2003 Glyph & Cog, LLC // //======================================================================== //======================================================================== // // Modified under the Poppler project - http://poppler.freedesktop.org // // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // // Copyright (C) 2007 Julien Rebetez // Copyright (C) 2008 Kees Cook // Copyright (C) 2008, 2010, 2017-2021, 2023-2026 Albert Astals Cid // Copyright (C) 2009 Jakub Wilk // Copyright (C) 2012 Fabio D'Urso // Copyright (C) 2013 Thomas Freitag // Copyright (C) 2013, 2017, 2018 Adrian Johnson // Copyright (C) 2013 Adrian Perez de Castro // Copyright (C) 2016, 2020 Jakub Alba // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by the LiMux project of the city of Munich // Copyright (C) 2018 Adam Reichold // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by Technische Universität Dresden // Copyright (C) 2023 Oliver Sander // Copyright (C) 2024-2026 g10 Code GmbH, Author: Sune Stolborg Vuorela // Copyright (C) 2025 Jonathan Hähne // Copyright (C) 2025 Arnav V // Copyright (C) 2026 Adam Sampson // Copyright (C) 2026 Stefan Brüns // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git // //======================================================================== #ifndef REF_H #define REF_H #include #include #include struct Ref { int num; // object number int gen; // generation number static constexpr Ref INVALID() { return { .num = -1, .gen = -1 }; }; }; inline bool operator==(const Ref lhs, const Ref rhs) noexcept { return lhs.num == rhs.num && lhs.gen == rhs.gen; } inline bool operator!=(const Ref lhs, const Ref rhs) noexcept { return lhs.num != rhs.num || lhs.gen != rhs.gen; } inline bool operator<(const Ref lhs, const Ref rhs) noexcept { if (lhs.num != rhs.num) { return lhs.num < rhs.num; } return lhs.gen < rhs.gen; } struct RefRecursionChecker { RefRecursionChecker() = default; RefRecursionChecker(const RefRecursionChecker &) = delete; RefRecursionChecker &operator=(const RefRecursionChecker &) = delete; bool insert(Ref ref) { if (ref == Ref::INVALID()) { return true; } // insert returns std::pair // where the bool is whether the insert succeeded return alreadySeenRefs.insert(ref.num).second; } void remove(Ref ref) { alreadySeenRefs.erase(ref.num); } private: std::set alreadySeenRefs; }; struct RefRecursionCheckerRemover { // Removes ref from c when this object is removed RefRecursionCheckerRemover(RefRecursionChecker &c, Ref r) : checker(c), ref(r) { } ~RefRecursionCheckerRemover() { checker.remove(ref); } RefRecursionCheckerRemover(const RefRecursionCheckerRemover &) = delete; RefRecursionCheckerRemover &operator=(const RefRecursionCheckerRemover &) = delete; private: RefRecursionChecker &checker; Ref ref; }; namespace std { template<> struct hash { using argument_type = Ref; using result_type = size_t; result_type operator()(const argument_type ref) const noexcept { return std::hash {}(ref.num) ^ (std::hash {}(ref.gen) << 1); } }; } #endif