PoDoFo 1.2.0
Loading...
Searching...
No Matches
PdfObject.h
1// SPDX-FileCopyrightText: 2005 Dominik Seichter <domseichter@web.de>
2// SPDX-FileCopyrightText: 2020 Francesco Pretto <ceztko@gmail.com>
3// SPDX-License-Identifier: LGPL-2.0-or-later OR MPL-2.0
4
5#ifndef PDF_OBJECT_H
6#define PDF_OBJECT_H
7
8#include "PdfVariant.h"
9#include "PdfObjectStream.h"
10
11namespace PoDoFo {
12
13class PdfEncrypt;
14class PdfIndirectObjectList;
15class PdfDictionary;
16class PdfArray;
17class PdfDocument;
18class PdfDataContainer;
19
30class PODOFO_API PdfObject
31{
32 friend class PdfIndirectObjectList;
33 friend class PdfArray;
34 friend class PdfDictionary;
35 friend class PdfDocument;
36 friend class PdfObjectStream;
37 friend class PdfObjectOutputStream;
38 friend class PdfDataContainer;
39 friend class PdfDictionaryElement;
40 friend class PdfArrayElement;
41 friend class PdfTokenizer;
42 PODOFO_PRIVATE_FRIEND(class PdfStreamedObjectStream);
43 PODOFO_PRIVATE_FRIEND(class PdfObjectStreamParser);
44 PODOFO_PRIVATE_FRIEND(class PdfCompressedObject);
45 PODOFO_PRIVATE_FRIEND(class PdfParser);
46 PODOFO_PRIVATE_FRIEND(class PdfParserObject);
47 PODOFO_PRIVATE_FRIEND(class PdfWriter);
48 PODOFO_PRIVATE_FRIEND(class PdfImmediateWriter);
49 PODOFO_PRIVATE_FRIEND(class PdfXRef);
50 PODOFO_PRIVATE_FRIEND(class PdfXRefStream);
51
52public:
53 static const PdfObject Null;
54
55public:
56
58 PdfObject();
59
61 PdfObject(std::nullptr_t);
62
63 virtual ~PdfObject();
64
68 PdfObject(const PdfVariant& var);
69 PdfObject(PdfVariant&& var) noexcept;
70
74 PdfObject(bool b);
75
80
84 PdfObject(double d);
85
89 PdfObject(const PdfString& str);
90
94 PdfObject(const PdfName& name);
95
100
104 PdfObject(const PdfArray& arr);
105 PdfObject(PdfArray&& arr) noexcept;
106
111 PdfObject(PdfDictionary&& dict) noexcept;
112
116 PdfObject(const PdfObject& rhs);
117 PdfObject(PdfObject&& rhs) noexcept;
118
119public:
122 PdfDataType GetDataType() const;
123
126 std::string_view GetDataTypeString() const;
127
129 bool IsBool() const;
130
132 bool IsNumber() const;
133
137 bool IsRealStrict() const;
138
140 bool IsNumberOrReal() const;
141
143 bool IsString() const;
144
146 bool IsName() const;
147
149 bool IsArray() const;
150
152 bool IsDictionary() const;
153
155 bool IsRawData() const;
156
158 bool IsNull() const;
159
161 bool IsReference() const;
162
166 std::string ToString(PdfWriteFlags writeFlags = PdfWriteFlags::None) const;
167 void ToString(std::string& str, PdfWriteFlags writeFlags = PdfWriteFlags::None) const;
168
171 bool GetBool() const;
172 bool TryGetBool(bool& value) const;
173
178 int64_t GetNumberLenient() const;
179 bool TryGetNumberLenient(int64_t& value) const;
180
185 int64_t GetNumber() const;
186 bool TryGetNumber(int64_t& value) const;
187
192 double GetReal() const;
193 bool TryGetReal(double& value) const;
194
199 double GetRealStrict() const;
200 bool TryGetRealStrict(double& value) const;
201
203 const PdfString& GetString() const;
204 bool TryGetString(PdfString& str) const;
205 bool TryGetString(const PdfString*& str) const;
206
208 const PdfName& GetName() const;
209 bool TryGetName(PdfName& name) const;
210 bool TryGetName(const PdfName*& name) const;
211
214 PdfReference GetReference() const;
215 bool TryGetReference(PdfReference& ref) const;
216
219 const PdfArray& GetArray() const;
220 PdfArray& GetArray();
221 bool TryGetArray(const PdfArray*& arr) const;
222 bool TryGetArray(PdfArray*& arr);
223 bool TryGetArray(PdfArray& arr) const;
224
227 const PdfDictionary& GetDictionary() const;
228 PdfDictionary& GetDictionary();
229 bool TryGetDictionary(const PdfDictionary*& dict) const;
230 bool TryGetDictionary(PdfDictionary*& dict);
231 bool TryGetDictionary(PdfDictionary& dict) const;
232
238 void SetBool(bool b);
239
245 void SetNumber(int64_t l);
246
252 void SetReal(double d);
253
259 void SetName(const PdfName& name);
260
266 void SetString(const PdfString& str);
267
268 void SetReference(const PdfReference& ref);
269
270 void ForceCreateStream();
271
279 const PdfStatefulEncrypt* encrypt, charbuff& buffer) const;
280
285 PdfObjectStream& GetOrCreateStream();
286
287 /* Remove the object stream, if it has one
288 */
289 void RemoveStream();
290
293 const PdfObjectStream& MustGetStream() const;
294
297 PdfObjectStream& MustGetStream();
298
305 virtual bool TryUnload();
306
311 bool HasStream() const;
312
313 bool IsIndirect() const;
314
315 const PdfVariant& GetVariant() const;
316
317public:
321 bool operator<(const PdfObject& rhs) const;
322
325 bool operator==(const PdfObject& rhs) const;
326
329 bool operator!=(const PdfObject& rhs) const;
330
332 bool operator==(const PdfVariant& rhs) const;
333
335 bool operator!=(const PdfVariant& rhs) const;
336
341 PdfObject& operator=(const PdfObject& rhs);
342 PdfObject& operator=(PdfObject&& rhs) noexcept;
343
344 operator const PdfVariant& () const;
345
346public:
358 inline bool IsDirty() const { return m_IsDirty; }
359
362 PdfDocument* GetDocument() const;
363
366 PdfDocument& MustGetDocument() const;
367
370 inline const PdfReference& GetIndirectReference() const { return m_IndirectReference; }
371
372 const PdfDataContainer* GetParent() const;
373
377 inline bool IsDelayedLoadDone() const { return m_IsDelayedLoadDone; }
378
379 inline bool IsDelayedLoadStreamDone() const { return m_IsDelayedLoadStreamDone; }
380
381 const PdfObjectStream* GetStream() const;
382 PdfObjectStream* GetStream();
383
384private:
385 PdfObject(PdfVariant&& var, const PdfReference& indirectReference, bool isDirty);
386
387 PdfObject(PdfArray* arr);
388
389 // To be called by PdfArray, which places the objects itself, sparing a SetParent() call
390 PdfObject(PdfDataContainer& parent, std::nullptr_t);
391 PdfObject(PdfDataContainer& parent, const PdfObject& rhs);
392 PdfObject(PdfDataContainer& parent, PdfObject&& rhs) noexcept;
393
394protected:
401 void DelayedLoad() const;
402
416 virtual void delayedLoad();
417
418 void DelayedLoadStream() const;
419
420 virtual void delayedLoadStream();
421
423 virtual bool removeStream();
424
425 virtual bool HasStreamToParse() const;
426
430 void SetDirty();
431
432 void resetDirty();
433
438 void SetDocument(PdfDocument* document);
439
440 void SetVariantOwner();
441
448 void RelocateBackPointers();
449
450 void FreeStream();
451
452 PdfObjectStream& getOrCreateStream();
453
454 void forceCreateStream();
455
456 PdfObjectStream* getStream();
457
458 void EnableDelayedLoadingStream();
459
460 void MakeDelayedLoadingStreamDone();
461
462 inline void SetIndirectReference(const PdfReference& reference) { m_IndirectReference = reference; }
463
471 void EnableDelayedLoading();
472
475 virtual void SetRevised();
476
477private:
478 void DelayedLoad(bool throwOnError) const;
479 void DelayedLoadStream(bool throwOnError) const;
480
481 // To be called privately by various classes
482 PdfVariant& GetVariantUnsafe() { return m_Variant; }
483 const PdfReference& GetReferenceUnsafe() const { return m_Variant.GetReferenceUnsafe(); }
484 const PdfDictionary& GetDictionaryUnsafe() const { return m_Variant.GetDictionaryUnsafe(); }
485 const PdfArray& GetArrayUnsafe() const { return m_Variant.GetArrayUnsafe(); }
486 PdfDictionary& GetDictionaryUnsafe() { return m_Variant.GetDictionaryUnsafe(); }
487 PdfArray& GetArrayUnsafe() { return m_Variant.GetArrayUnsafe(); }
488 void WriteFinal(OutputStream& stream, PdfWriteFlags writeMode,
489 const PdfStatefulEncrypt* encrypt, charbuff& buffer);
490
491 // To be called by PdfStreamedObjectStream
492 void SetNumberNoDirtySet(int64_t l);
493
494 // To be called by PdfImmediateWriter
495 void SetImmutable();
496 void WriteHeader(OutputStream& stream, PdfWriteFlags writeMode, charbuff& buffer) const;
497
498 // To be called by PdfDataContainer
499 bool IsImmutable() const { return m_IsImmutable; }
500
501 // NOTE: It also doesn't dirty set the moved "obj"
502 void AssignNoDirtySet(PdfObject&& rhs);
503 void AssignNoDirtySet(PdfVariant&& rhs);
504 void AssignNoDirtySet(const PdfObject& rhs);
505
506 void SetParent(PdfDataContainer& parent);
507
508private:
509 void write(OutputStream& stream, bool skipLengthFix,
510 PdfWriteFlags writeMode, const PdfStatefulEncrypt* encrypt, charbuff& buffer) const;
511
512 void assertMutable() const;
513
514 void assign(const PdfObject& rhs);
515
516 void moveFrom(PdfObject&& rhs) noexcept;
517
518 void setVariantOwnerIfNeeded();
519
520 void ResetDirty();
521
522 void setDirty();
523
524 // See PdfVariant.h for a detailed explanation of this member, which is
525 // here to prevent accidental construction of a PdfObject of integer type
526 // when passing a pointer. */
527 template<typename T>
528 PdfObject(T*) = delete;
529
530 void copyStreamFrom(const PdfObject& obj);
531
532 // Shared initialization between all the ctors
533 void initObject();
534
535 void initContainedObject();
536
537protected:
538 PdfVariant m_Variant;
539
540private:
541 PdfReference m_IndirectReference;
542 // A contained object takes the document from its container,
543 // m_isContained tells which one of them is stored
544 union
545 {
546 PdfDataContainer* m_Parent;
547 PdfDocument* m_Document;
548 };
549 std::unique_ptr<PdfObjectStream> m_Stream;
550 bool m_isContained;
551 bool m_IsDirty; // Indicates if this object was modified after construction
552 // Tracks whether deferred loading is still pending (in which case it'll be
553 // false). If true, deferred loading is not required or has been completed.
554 mutable bool m_IsDelayedLoadDone;
555 mutable bool m_IsDelayedLoadStreamDone;
556 bool m_IsImmutable;
557};
558
560 template <typename T>
562 {
563 using TRet = T;
564
565 static TRet Get(const PdfObject& obj)
566 {
567 (void)obj;
568 static_assert(always_false<T>, "Unsupported type");
569 return TRet{ };
570 }
571
572 static TRet Get(const PdfObject& obj, const T& defVal)
573 {
574 (void)obj;
575 (void)defVal;
576 static_assert(always_false<T>, "Unsupported type");
577 return TRet{ };
578 }
579
580 static bool TryGet(const PdfObject& obj, T& value)
581 {
582 (void)obj;
583 (void)value;
584 static_assert(always_false<T>, "Unsupported type");
585 return false;
586 }
587 };
588
589 template <>
590 struct ObjectAdapter<bool>
591 {
592 using TRet = bool;
593
594 static bool Get(const PdfObject& obj)
595 {
596 return obj.GetBool();
597 }
598
599 static bool Get(const PdfObject& obj, bool fallback)
600 {
601 bool ret;
602 if (obj.TryGetBool(ret))
603 return ret;
604 else
605 return fallback;
606 }
607
608 static bool TryGet(const PdfObject& obj, bool& value)
609 {
610 return obj.TryGetBool(value);
611 }
612 };
613
614 template <>
615 struct ObjectAdapter<int64_t>
616 {
617 using TRet = int64_t;
618
619 static int64_t Get(const PdfObject& obj)
620 {
621 return obj.GetNumber();
622 }
623
624 static int64_t Get(const PdfObject& obj, int64_t fallback)
625 {
626 int64_t ret;
627 if (obj.TryGetNumber(ret))
628 return ret;
629 else
630 return fallback;
631 }
632
633 static bool TryGet(const PdfObject& obj, int64_t& value)
634 {
635 return obj.TryGetNumber(value);
636 }
637 };
638
639 template <>
640 struct ObjectAdapter<double>
641 {
642 using TRet = double;
643
644 static double Get(const PdfObject& obj)
645 {
646 return obj.GetReal();
647 }
648
649 static double Get(const PdfObject& obj, double fallback)
650 {
651 double ret;
652 if (obj.TryGetReal(ret))
653 return ret;
654 else
655 return fallback;
656 }
657
658 static bool TryGet(const PdfObject& obj, double& value)
659 {
660 return obj.TryGetReal(value);
661 }
662 };
663
664 template <>
665 struct ObjectAdapter<PdfReference>
666 {
667 using TRet = PdfReference;
668
669 static PdfReference Get(const PdfObject& obj)
670 {
671 return obj.GetReference();
672 }
673
674 static PdfReference Get(const PdfObject& obj, const PdfReference& fallback)
675 {
676 PdfReference ret;
677 if (obj.TryGetReference(ret))
678 return ret;
679 else
680 return fallback;
681 }
682
683 static bool TryGet(const PdfObject& obj, PdfReference& value)
684 {
685 return obj.TryGetReference(value);
686 }
687 };
688
689 template <>
690 struct ObjectAdapter<PdfName>
691 {
692 using TRet = const PdfName&;
693
694 static const PdfName& Get(const PdfObject& obj)
695 {
696 return obj.GetName();
697 }
698
699 static const PdfName& Get(const PdfObject& obj, const PdfName& fallback)
700 {
701 const PdfName* ret;
702 if (obj.TryGetName(ret))
703 return *ret;
704 else
705 return fallback;
706 }
707
708 static bool TryGet(const PdfObject& obj, PdfName& value)
709 {
710 return obj.TryGetName(value);
711 }
712 };
713
714 template <>
715 struct ObjectAdapter<const PdfName*>
716 {
717 using TRet = const PdfName*;
718
719 static const PdfName* Get(const PdfObject& obj)
720 {
721 const PdfName* ret;
722 (void)obj.TryGetName(ret);
723 return ret;
724 }
725
726 static const PdfName* Get(const PdfObject& obj, const PdfName* fallback)
727 {
728 const PdfName* ret;
729 if (obj.TryGetName(ret))
730 return ret;
731 else
732 return fallback;
733 }
734
735 static bool TryGet(const PdfObject& obj, const PdfName*& value)
736 {
737 return obj.TryGetName(value);
738 }
739 };
740
741 template <>
742 struct ObjectAdapter<PdfString>
743 {
744 using TRet = const PdfString&;
745
746 static const PdfString& Get(const PdfObject& obj)
747 {
748 return obj.GetString();
749 }
750
751 static const PdfString& Get(const PdfObject& obj, const PdfString& fallback)
752 {
753 const PdfString* ret;
754 if (obj.TryGetString(ret))
755 return *ret;
756 else
757 return fallback;
758 }
759
760 static bool TryGet(const PdfObject& obj, PdfString& value)
761 {
762 return obj.TryGetString(value);
763 }
764 };
765
766 template <>
767 struct ObjectAdapter<const PdfString*>
768 {
769 using TRet = const PdfString*;
770
771 static const PdfString* Get(PdfObject& obj)
772 {
773 const PdfString* ret;
774 (void)obj.TryGetString(ret);
775 return ret;
776 }
777
778 static const PdfString* Get(const PdfObject& obj, const PdfString* fallback)
779 {
780 const PdfString* ret;
781 if (obj.TryGetString(ret))
782 return ret;
783 else
784 return fallback;
785 }
786
787 static bool TryGet(const PdfObject& obj, const PdfString*& value)
788 {
789 return obj.TryGetString(value);
790 }
791 };
792
793 template <>
794 struct ObjectAdapter<PdfDictionary*>
795 {
796 using TRet = PdfDictionary*;
797
798 static PdfDictionary* Get(PdfObject& obj)
799 {
800 PdfDictionary* ret;
801 (void)obj.TryGetDictionary(ret);
802 return ret;
803 }
804
805 static PdfDictionary* Get(PdfObject& obj, PdfDictionary* fallback)
806 {
807 PdfDictionary* ret;
808 if (obj.TryGetDictionary(ret))
809 return ret;
810 else
811 return fallback;
812 }
813
814 static bool TryGet(PdfObject& obj, PdfDictionary*& value)
815 {
816 return obj.TryGetDictionary(value);
817 }
818 };
819
820 template <>
821 struct ObjectAdapter<const PdfDictionary*>
822 {
823 using TRet = const PdfDictionary*;
824
825 static const PdfDictionary* Get(const PdfObject& obj)
826 {
827 const PdfDictionary* ret;
828 (void)obj.TryGetDictionary(ret);
829 return ret;
830 }
831
832 static const PdfDictionary* Get(const PdfObject& obj, const PdfDictionary* fallback)
833 {
834 const PdfDictionary* ret;
835 if (obj.TryGetDictionary(ret))
836 return ret;
837 else
838 return fallback;
839 }
840
841 static bool TryGet(const PdfObject& obj, const PdfDictionary*& value)
842 {
843 return obj.TryGetDictionary(value);
844 }
845 };
846
847 template <>
848 struct ObjectAdapter<PdfDictionary>
849 {
850 using TRet = PdfDictionary&;
851
852 static PdfDictionary& Get(PdfObject& obj)
853 {
854 return obj.GetDictionary();
855 }
856
857 static PdfDictionary& Get(PdfObject& obj, PdfDictionary& fallback)
858 {
859 PdfDictionary* ret;
860 if (obj.TryGetDictionary(ret))
861 return *ret;
862 else
863 return fallback;
864 }
865
866 static bool TryGet(const PdfObject& obj, PdfDictionary& value)
867 {
868 return obj.TryGetDictionary(value);
869 }
870 };
871
872 template <>
873 struct ObjectAdapter<PdfArray*>
874 {
875 using TRet = PdfArray*;
876
877 static PdfArray* Get(PdfObject& obj)
878 {
879 PdfArray* ret;
880 (void)obj.TryGetArray(ret);
881 return ret;
882 }
883
884 static PdfArray* Get(PdfObject& obj, PdfArray* fallback)
885 {
886 PdfArray* ret;
887 if (obj.TryGetArray(ret))
888 return ret;
889 else
890 return fallback;
891 }
892
893 static bool TryGet(PdfObject& obj, PdfArray*& value)
894 {
895 return obj.TryGetArray(value);
896 }
897 };
898
899 template <>
900 struct ObjectAdapter<const PdfArray*>
901 {
902 using TRet = const PdfArray*;
903
904 static const PdfArray* Get(const PdfObject& obj)
905 {
906 const PdfArray* ret;
907 (void)obj.TryGetArray(ret);
908 return ret;
909 }
910
911 static const PdfArray* Get(PdfObject& obj, const PdfArray* fallback)
912 {
913 const PdfArray* ret;
914 if (obj.TryGetArray(ret))
915 return ret;
916 else
917 return fallback;
918 }
919
920 static bool TryGet(const PdfObject& obj, const PdfArray*& value)
921 {
922 return obj.TryGetArray(value);
923 }
924 };
925
926 template <>
927 struct ObjectAdapter<PdfArray>
928 {
929 using TRet = PdfArray&;
930
931 static PdfArray& Get(PdfObject& obj)
932 {
933 return obj.GetArray();
934 }
935
936 static PdfArray& Get(PdfObject& obj, PdfArray& fallback)
937 {
938 PdfArray* ret;
939 if (obj.TryGetArray(ret))
940 return *ret;
941 else
942 return fallback;
943 }
944
945 static bool TryGet(const PdfObject& obj, PdfArray& value)
946 {
947 return obj.TryGetArray(value);
948 }
949 };
950
951 // Comparator to enable heterogeneous lookup with
952 // both objects and references
953 // See https://stackoverflow.com/a/31924435/213871
954 struct PODOFO_API PdfObjectInequality final
955 {
956 using is_transparent = std::true_type;
957
958 bool operator()(const PdfObject* lhs, const PdfObject* rhs) const
959 {
960 return lhs->GetIndirectReference() < rhs->GetIndirectReference();
961 }
962 bool operator()(const PdfObject* lhs, const PdfReference& rhs) const
963 {
964 return lhs->GetIndirectReference() < rhs;
965 }
966 bool operator()(const PdfReference& lhs, const PdfObject* rhs) const
967 {
968 return lhs < rhs->GetIndirectReference();
969 }
970 bool operator()(const PdfObject& lhs, const PdfObject& rhs) const
971 {
972 return lhs.GetIndirectReference() < rhs.GetIndirectReference();
973 }
974 bool operator()(const PdfObject& lhs, const PdfReference& rhs) const
975 {
976 return lhs.GetIndirectReference() < rhs;
977 }
978 bool operator()(const PdfReference& lhs, const PdfObject& rhs) const
979 {
980 return lhs < rhs.GetIndirectReference();
981 }
982 };
983}
984
985#endif // PDF_OBJECT_H
An interface for writing blocks of data to a data source.
Definition OutputStream.h:15
This class represents a PdfArray Use it for all arrays that are written to a PDF file.
Definition PdfArray.h:77
A PdfDataProvider object with a PdfObject owner, specialized in holding objects.
Definition PdfDataContainer.h:18
The PDF dictionary data type of PoDoFo (inherits from PdfDataContainer, the base class for such repre...
Definition PdfDictionary.h:77
PdfDocument is the core interface for working with PDF documents.
Definition PdfDocument.h:108
A list of PdfObjects that constitutes the indirect object list of the document The PdfParser will rea...
Definition PdfIndirectObjectList.h:34
This class represents a PdfName.
Definition PdfName.h:21
A PDF stream can be appended to any PdfObject and can contain arbitrary data.
Definition PdfObjectStream.h:82
This class represents a PDF indirect Object in memory.
Definition PdfObject.h:31
bool IsDelayedLoadDone() const
Returns true if delayed loading is disabled, or if it is enabled and loading has completed.
Definition PdfObject.h:377
PdfObject(std::nullptr_t)
Create a "null" PDF object.
bool IsDirty() const
The dirty flag is set if this variant has been modified after construction.
Definition PdfObject.h:358
const PdfReference & GetIndirectReference() const
Get an indirect reference to this object.
Definition PdfObject.h:370
A reference is a pointer to a object in the PDF file of the form "4 0 R", where 4 is the object numbe...
Definition PdfReference.h:20
A string that can be written to a PDF document.
Definition PdfString.h:21
A simple tokenizer for PDF files and PDF content streams.
Definition PdfTokenizer.h:47
A variant data type which supports all data types supported by the PDF standard.
Definition PdfVariant.h:29
Convenient type for char array storage and/or buffer with std::string compatibility.
Definition basetypes.h:30
All classes, functions, types and enums of PoDoFo are members of these namespace.
Definition basetypes.h:13
PdfDataType
Every PDF datatype that can occur in a PDF file is referenced by an own enum (e.g.
Definition PdfDeclarations.h:152
@ Null
The null datatype is always null.
PdfWriteFlags
Specify additional options for writing the PDF.
Definition PdfDeclarations.h:136
Templatized object type getter helper.
Definition PdfObject.h:562