// Copyright (C) 2020-2021 Jakub Melka // // This file is part of Pdf4Qt. // // Pdf4Qt is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // with the written consent of the copyright owner, any later version. // // Pdf4Qt is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Pdf4Qt. If not, see . #ifndef PDFOBJECTUTILS_H #define PDFOBJECTUTILS_H #include "pdfobject.h" #include namespace pdf { class PDFObjectStorage; /// Utilities for manipulation with objects class PDFObjectUtils { public: /// Returns list of references referenced by \p objects. So, all references, which are present /// in objects, appear in the result set, including objects, which are referenced by referenced /// objects (so, transitive closure above reference graph is returned). /// \param objects Objects /// \param storage Storage static std::set getReferences(const std::vector& objects, const PDFObjectStorage& storage); static PDFObject replaceReferences(const PDFObject& object, const std::map& referenceMapping); private: PDFObjectUtils() = delete; }; /// Storage, which can mark objects (for example, when we want to mark already visited objects /// during parsing some complex structure, such as tree) class PDFMarkedObjectsContext { public: inline explicit PDFMarkedObjectsContext() = default; inline bool isMarked(PDFObjectReference reference) const { return m_markedReferences.count(reference); } inline void mark(PDFObjectReference reference) { m_markedReferences.insert(reference); } inline void unmark(PDFObjectReference reference) { m_markedReferences.erase(reference); } private: std::set m_markedReferences; }; /// Class for marking/unmarking objects functioning as guard. If not already marked, then /// during existence of this guard, object is marked and then it is unmarked. If it is /// already marked, then nothing happens and locked flag is set to false. class PDFMarkedObjectsLock { public: explicit inline PDFMarkedObjectsLock(PDFMarkedObjectsContext* context, PDFObjectReference reference) : m_context(context), m_reference(reference), m_locked(!reference.isValid() || !context->isMarked(reference)) { if (m_locked && reference.isValid()) { context->mark(reference); } } explicit inline PDFMarkedObjectsLock(PDFMarkedObjectsContext* context, const PDFObject& object) : PDFMarkedObjectsLock(context, object.isReference() ? object.getReference() : PDFObjectReference()) { } inline ~PDFMarkedObjectsLock() { if (m_locked && m_reference.isValid()) { m_context->unmark(m_reference); } } explicit operator bool() const { return m_locked; } private: PDFMarkedObjectsContext* m_context; PDFObjectReference m_reference; bool m_locked; }; } // namespace pdf #endif // PDFOBJECTUTILS_H