Commit 5de0cea9400db0b46551c214999b40e0b68a4e51

Authored by m-holger
1 parent e7989413

Enable QPDFObjectHandle FUTURE changes

include/qpdf/QPDFObjectHandle.hh
... ... @@ -23,27 +23,22 @@
23 23 #ifndef QPDFOBJECTHANDLE_HH
24 24 #define QPDFOBJECTHANDLE_HH
25 25  
26   -#ifdef QPDF_FUTURE
27   -# include <qpdf/QPDFObjectHandle_future.hh>
28   -#else
29   -
30   -# include <qpdf/Constants.h>
31   -# include <qpdf/DLL.h>
32   -# include <qpdf/Types.h>
33   -
34   -# include <functional>
35   -# include <map>
36   -# include <memory>
37   -# include <set>
38   -# include <string>
39   -# include <vector>
40   -
41   -# include <qpdf/Buffer.hh>
42   -# include <qpdf/InputSource.hh>
43   -# include <qpdf/JSON.hh>
44   -# include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
45   -# include <qpdf/QPDFObjGen.hh>
46   -# include <qpdf/QPDFTokenizer.hh>
  26 +#include <qpdf/Constants.h>
  27 +#include <qpdf/DLL.h>
  28 +#include <qpdf/Types.h>
  29 +
  30 +#include <functional>
  31 +#include <map>
  32 +#include <memory>
  33 +#include <set>
  34 +#include <string>
  35 +#include <vector>
  36 +
  37 +#include <qpdf/Buffer.hh>
  38 +#include <qpdf/InputSource.hh>
  39 +#include <qpdf/JSON.hh>
  40 +#include <qpdf/QPDFObjGen.hh>
  41 +#include <qpdf/QPDFTokenizer.hh>
47 42  
48 43 class Pipeline;
49 44 class QPDF;
... ... @@ -296,53 +291,58 @@ class QPDFObjectHandle
296 291 QPDF_DLL
297 292 QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
298 293  
  294 + QPDF_DLL
  295 + QPDFObjectHandle(QPDFObjectHandle&&) = default;
  296 + QPDF_DLL
  297 + QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
  298 +
299 299 // Return true if the QPDFObjectHandle is initialized. This allows object handles to be used in
300 300 // if statements with initializer.
301 301 QPDF_DLL
302 302 explicit inline operator bool() const noexcept;
303 303  
304   - [[deprecated("use operator bool()")]] QPDF_DLL inline bool isInitialized() const;
  304 + [[deprecated("use operator bool()")]] QPDF_DLL inline bool isInitialized() const noexcept;
305 305  
306 306 // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying
307 307 // object, meaning that changes to one are reflected in the other, or "if you paint one, the
308 308 // other one changes color." This does not perform a structural comparison of the contents of
309 309 // the objects.
310 310 QPDF_DLL
311   - bool isSameObjectAs(QPDFObjectHandle const&) const;
  311 + bool isSameObjectAs(QPDFObjectHandle const&) const noexcept;
312 312  
313 313 // Return type code and type name of underlying object. These are useful for doing rapid type
314 314 // tests (like switch statements) or for testing and debugging.
315 315 QPDF_DLL
316   - qpdf_object_type_e getTypeCode();
  316 + qpdf_object_type_e getTypeCode() const;
317 317 QPDF_DLL
318   - char const* getTypeName();
  318 + char const* getTypeName() const;
319 319  
320 320 // Exactly one of these will return true for any initialized object. Operator and InlineImage
321 321 // are only allowed in content streams.
322 322 QPDF_DLL
323   - bool isBool();
  323 + bool isBool() const;
324 324 QPDF_DLL
325   - bool isNull();
  325 + bool isNull() const;
326 326 QPDF_DLL
327   - bool isInteger();
  327 + bool isInteger() const;
328 328 QPDF_DLL
329   - bool isReal();
  329 + bool isReal() const;
330 330 QPDF_DLL
331   - bool isName();
  331 + bool isName() const;
332 332 QPDF_DLL
333   - bool isString();
  333 + bool isString() const;
334 334 QPDF_DLL
335   - bool isOperator();
  335 + bool isOperator() const;
336 336 QPDF_DLL
337   - bool isInlineImage();
  337 + bool isInlineImage() const;
338 338 QPDF_DLL
339   - bool isArray();
  339 + bool isArray() const;
340 340 QPDF_DLL
341   - bool isDictionary();
  341 + bool isDictionary() const;
342 342 QPDF_DLL
343   - bool isStream();
  343 + bool isStream() const;
344 344 QPDF_DLL
345   - bool isReserved();
  345 + bool isReserved() const;
346 346  
347 347 // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended
348 348 // for internal use, but it can be used as an efficient way to check for nulls that are not
... ... @@ -357,23 +357,23 @@ class QPDFObjectHandle
357 357 // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse
358 358 // such an object will throw a logic_error.
359 359 QPDF_DLL
360   - bool isDestroyed();
  360 + bool isDestroyed() const;
361 361  
362 362 // True for everything except array, dictionary, stream, word, and inline image.
363 363 QPDF_DLL
364   - bool isScalar();
  364 + bool isScalar() const;
365 365  
366 366 // True if the object is a name object representing the provided name.
367 367 QPDF_DLL
368   - bool isNameAndEquals(std::string const& name);
  368 + bool isNameAndEquals(std::string const& name) const;
369 369  
370 370 // True if the object is a dictionary of the specified type and subtype, if any.
371 371 QPDF_DLL
372   - bool isDictionaryOfType(std::string const& type, std::string const& subtype = "");
  372 + bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const;
373 373  
374 374 // True if the object is a stream of the specified type and subtype, if any.
375 375 QPDF_DLL
376   - bool isStreamOfType(std::string const& type, std::string const& subtype = "");
  376 + bool isStreamOfType(std::string const& type, std::string const& subtype = "") const;
377 377  
378 378 // Public factory methods
379 379  
... ... @@ -418,7 +418,7 @@ class QPDFObjectHandle
418 418 // object was created without parsing. If the object is in a stream, the offset is from the
419 419 // beginning of the stream. Otherwise, the offset is from the beginning of the file.
420 420 QPDF_DLL
421   - qpdf_offset_t getParsedOffset();
  421 + qpdf_offset_t getParsedOffset() const;
422 422  
423 423 // Older method: stream_or_array should be the value of /Contents from a page object. It's more
424 424 // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error
... ... @@ -590,7 +590,7 @@ class QPDFObjectHandle
590 590 QPDF_DLL
591 591 void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
592 592 QPDF_DLL
593   - bool hasObjectDescription();
  593 + bool hasObjectDescription() const;
594 594  
595 595 // Accessor methods
596 596 //
... ... @@ -640,57 +640,57 @@ class QPDFObjectHandle
640 640  
641 641 // Methods for bool objects
642 642 QPDF_DLL
643   - bool getBoolValue();
  643 + bool getBoolValue() const;
644 644 QPDF_DLL
645   - bool getValueAsBool(bool&);
  645 + bool getValueAsBool(bool&) const;
646 646  
647 647 // Methods for integer objects. Note: if an integer value is too big (too far away from zero in
648 648 // either direction) to fit in the requested return type, the maximum or minimum value for that
649 649 // return type may be returned. For example, on a system with 32-bit int, a numeric object with
650 650 // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
651 651 QPDF_DLL
652   - long long getIntValue();
  652 + long long getIntValue() const;
653 653 QPDF_DLL
654   - bool getValueAsInt(long long&);
  654 + bool getValueAsInt(long long&) const;
655 655 QPDF_DLL
656   - int getIntValueAsInt();
  656 + int getIntValueAsInt() const;
657 657 QPDF_DLL
658   - bool getValueAsInt(int&);
  658 + bool getValueAsInt(int&) const;
659 659 QPDF_DLL
660   - unsigned long long getUIntValue();
  660 + unsigned long long getUIntValue() const;
661 661 QPDF_DLL
662   - bool getValueAsUInt(unsigned long long&);
  662 + bool getValueAsUInt(unsigned long long&) const;
663 663 QPDF_DLL
664   - unsigned int getUIntValueAsUInt();
  664 + unsigned int getUIntValueAsUInt() const;
665 665 QPDF_DLL
666   - bool getValueAsUInt(unsigned int&);
  666 + bool getValueAsUInt(unsigned int&) const;
667 667  
668 668 // Methods for real objects
669 669 QPDF_DLL
670   - std::string getRealValue();
  670 + std::string getRealValue() const;
671 671 QPDF_DLL
672   - bool getValueAsReal(std::string&);
  672 + bool getValueAsReal(std::string&) const;
673 673  
674 674 // Methods that work for both integer and real objects
675 675 QPDF_DLL
676   - bool isNumber();
  676 + bool isNumber() const;
677 677 QPDF_DLL
678   - double getNumericValue();
  678 + double getNumericValue() const;
679 679 QPDF_DLL
680   - bool getValueAsNumber(double&);
  680 + bool getValueAsNumber(double&) const;
681 681  
682 682 // Methods for name objects. The returned name value is in qpdf's canonical form with all
683 683 // escaping resolved. See comments for newName() for details.
684 684 QPDF_DLL
685   - std::string getName();
  685 + std::string getName() const;
686 686 QPDF_DLL
687   - bool getValueAsName(std::string&);
  687 + bool getValueAsName(std::string&) const;
688 688  
689 689 // Methods for string objects
690 690 QPDF_DLL
691   - std::string getStringValue();
  691 + std::string getStringValue() const;
692 692 QPDF_DLL
693   - bool getValueAsString(std::string&);
  693 + bool getValueAsString(std::string&) const;
694 694  
695 695 // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise,
696 696 // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to
... ... @@ -698,19 +698,19 @@ class QPDFObjectHandle
698 698 // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range
699 699 // unmapped.
700 700 QPDF_DLL
701   - std::string getUTF8Value();
  701 + std::string getUTF8Value() const;
702 702 QPDF_DLL
703   - bool getValueAsUTF8(std::string&);
  703 + bool getValueAsUTF8(std::string&) const;
704 704  
705 705 // Methods for content stream objects
706 706 QPDF_DLL
707   - std::string getOperatorValue();
  707 + std::string getOperatorValue() const;
708 708 QPDF_DLL
709   - bool getValueAsOperator(std::string&);
  709 + bool getValueAsOperator(std::string&) const;
710 710 QPDF_DLL
711   - std::string getInlineImageValue();
  711 + std::string getInlineImageValue() const;
712 712 QPDF_DLL
713   - bool getValueAsInlineImage(std::string&);
  713 + bool getValueAsInlineImage(std::string&) const;
714 714  
715 715 // Methods for array objects; see also name and array objects.
716 716  
... ... @@ -725,26 +725,26 @@ class QPDFObjectHandle
725 725 QPDFArrayItems aitems();
726 726  
727 727 QPDF_DLL
728   - int getArrayNItems();
  728 + int getArrayNItems() const;
729 729 QPDF_DLL
730   - QPDFObjectHandle getArrayItem(int n);
  730 + QPDFObjectHandle getArrayItem(int n) const;
731 731 // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling
732 732 // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of
733 733 // nulls.
734 734 QPDF_DLL
735   - std::vector<QPDFObjectHandle> getArrayAsVector();
  735 + std::vector<QPDFObjectHandle> getArrayAsVector() const;
736 736 QPDF_DLL
737   - bool isRectangle();
  737 + bool isRectangle() const;
738 738 // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the
739 739 // rectangle [0, 0, 0, 0]
740 740 QPDF_DLL
741   - Rectangle getArrayAsRectangle();
  741 + Rectangle getArrayAsRectangle() const;
742 742 QPDF_DLL
743   - bool isMatrix();
  743 + bool isMatrix() const;
744 744 // If the array is an array of six numeric values, return as a matrix. Otherwise, return the
745 745 // matrix [1, 0, 0, 1, 0, 0]
746 746 QPDF_DLL
747   - Matrix getArrayAsMatrix();
  747 + Matrix getArrayAsMatrix() const;
748 748  
749 749 // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as
750 750 // canonical name strings starting with a leading slash and not containing any PDF syntax
... ... @@ -764,27 +764,27 @@ class QPDFObjectHandle
764 764 // Return true if key is present. Keys with null values are treated as if they are not present.
765 765 // This is as per the PDF spec.
766 766 QPDF_DLL
767   - bool hasKey(std::string const&);
  767 + bool hasKey(std::string const&) const;
768 768 // Return the value for the key. If the key is not present, null is returned.
769 769 QPDF_DLL
770   - QPDFObjectHandle getKey(std::string const&);
  770 + QPDFObjectHandle getKey(std::string const&) const;
771 771 // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access
772 772 // lower-level dictionaries, as in
773 773 // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font");
774 774 QPDF_DLL
775   - QPDFObjectHandle getKeyIfDict(std::string const&);
  775 + QPDFObjectHandle getKeyIfDict(std::string const&) const;
776 776 // Return all keys. Keys with null values are treated as if they are not present. This is as
777 777 // per the PDF spec.
778 778 QPDF_DLL
779   - std::set<std::string> getKeys();
  779 + std::set<std::string> getKeys() const;
780 780 // Return dictionary as a map. Entries with null values are included.
781 781 QPDF_DLL
782   - std::map<std::string, QPDFObjectHandle> getDictAsMap();
  782 + std::map<std::string, QPDFObjectHandle> getDictAsMap() const;
783 783  
784 784 // Methods for name and array objects. The name value is in qpdf's canonical form with all
785 785 // escaping resolved. See comments for newName() for details.
786 786 QPDF_DLL
787   - bool isOrHasName(std::string const&);
  787 + bool isOrHasName(std::string const&) const;
788 788  
789 789 // Make all resources in a resource dictionary indirect. This just goes through all entries of
790 790 // top-level subdictionaries and converts any direct objects to indirect objects. This can be
... ... @@ -834,7 +834,7 @@ class QPDFObjectHandle
834 834 // method returns a set of all the keys in all top-level subdictionaries. For resources
835 835 // dictionaries, this is the collection of names that may be referenced in the content stream.
836 836 QPDF_DLL
837   - std::set<std::string> getResourceNames();
  837 + std::set<std::string> getResourceNames() const;
838 838  
839 839 // Find a unique name within a resource dictionary starting with a given prefix. This method
840 840 // works by appending a number to the given prefix. It searches starting with min_suffix and
... ... @@ -849,7 +849,7 @@ class QPDFObjectHandle
849 849 std::string getUniqueResourceName(
850 850 std::string const& prefix,
851 851 int& min_suffix,
852   - std::set<std::string>* resource_names = nullptr);
  852 + std::set<std::string>* resource_names = nullptr) const;
853 853  
854 854 // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF
855 855 // object. Indirect objects always have an owning QPDF. Direct objects that are read from the
... ... @@ -969,7 +969,7 @@ class QPDFObjectHandle
969 969  
970 970 // Methods for stream objects
971 971 QPDF_DLL
972   - QPDFObjectHandle getDict();
  972 + QPDFObjectHandle getDict() const;
973 973  
974 974 // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode
975 975 // level, whether compression is enabled, and its ability to filter. Passing false will prevent
... ... @@ -1158,12 +1158,12 @@ class QPDFObjectHandle
1158 1158 inline int getGeneration() const;
1159 1159  
1160 1160 QPDF_DLL
1161   - std::string unparse();
  1161 + std::string unparse() const;
1162 1162 QPDF_DLL
1163   - std::string unparseResolved();
  1163 + std::string unparseResolved() const;
1164 1164 // For strings only, force binary representation. Otherwise, same as unparse.
1165 1165 QPDF_DLL
1166   - std::string unparseBinary();
  1166 + std::string unparseBinary() const;
1167 1167  
1168 1168 // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available
1169 1169 // JSON version. The JSON is generated as follows:
... ... @@ -1197,19 +1197,19 @@ class QPDFObjectHandle
1197 1197 // the object. The effect of dereference_indirect applies only to this object. It is not
1198 1198 // recursive.
1199 1199 QPDF_DLL
1200   - JSON getJSON(int json_version, bool dereference_indirect = false);
  1200 + JSON getJSON(int json_version, bool dereference_indirect = false) const;
1201 1201  
1202 1202 // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient
1203 1203 // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the
1204 1204 // documentation for getJSON and JSON::write for further detail.
1205 1205 QPDF_DLL
1206   - void
1207   - writeJSON(int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0);
  1206 + void writeJSON(
  1207 + int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const;
1208 1208  
1209 1209 // Deprecated version uses v1 for backward compatibility.
1210 1210 // ABI: remove for qpdf 12
1211 1211 [[deprecated("Use getJSON(int version)")]] QPDF_DLL JSON
1212   - getJSON(bool dereference_indirect = false);
  1212 + getJSON(bool dereference_indirect = false) const;
1213 1213  
1214 1214 // This method can be called on a stream to get a more extended JSON representation of the
1215 1215 // stream that includes the stream's data. The JSON object returned is always a dictionary whose
... ... @@ -1262,7 +1262,7 @@ class QPDFObjectHandle
1262 1262 // normally from the file have descriptions. See comments on setObjectDescription for additional
1263 1263 // details.
1264 1264 QPDF_DLL
1265   - void warnIfPossible(std::string const& warning);
  1265 + void warnIfPossible(std::string const& warning) const;
1266 1266  
1267 1267 // Provide access to specific classes for recursive disconnected().
1268 1268 class DisconnectAccess
... ... @@ -1285,55 +1285,55 @@ class QPDFObjectHandle
1285 1285 void assertInitialized() const;
1286 1286  
1287 1287 QPDF_DLL
1288   - void assertNull();
  1288 + void assertNull() const;
1289 1289 QPDF_DLL
1290   - void assertBool();
  1290 + void assertBool() const;
1291 1291 QPDF_DLL
1292   - void assertInteger();
  1292 + void assertInteger() const;
1293 1293 QPDF_DLL
1294   - void assertReal();
  1294 + void assertReal() const;
1295 1295 QPDF_DLL
1296   - void assertName();
  1296 + void assertName() const;
1297 1297 QPDF_DLL
1298   - void assertString();
  1298 + void assertString() const;
1299 1299 QPDF_DLL
1300   - void assertOperator();
  1300 + void assertOperator() const;
1301 1301 QPDF_DLL
1302   - void assertInlineImage();
  1302 + void assertInlineImage() const;
1303 1303 QPDF_DLL
1304   - void assertArray();
  1304 + void assertArray() const;
1305 1305 QPDF_DLL
1306   - void assertDictionary();
  1306 + void assertDictionary() const;
1307 1307 QPDF_DLL
1308   - void assertStream();
  1308 + void assertStream() const;
1309 1309 QPDF_DLL
1310   - void assertReserved();
  1310 + void assertReserved() const;
1311 1311  
1312 1312 QPDF_DLL
1313   - void assertIndirect();
  1313 + void assertIndirect() const;
1314 1314 QPDF_DLL
1315   - void assertScalar();
  1315 + void assertScalar() const;
1316 1316 QPDF_DLL
1317   - void assertNumber();
  1317 + void assertNumber() const;
1318 1318  
1319 1319 // The isPageObject method checks the /Type key of the object. This is not completely reliable
1320 1320 // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is
1321 1321 // slightly more accepting but may still return false here when treating the object as a page
1322 1322 // would work. Use this sparingly.
1323 1323 QPDF_DLL
1324   - bool isPageObject();
  1324 + bool isPageObject() const;
1325 1325 QPDF_DLL
1326   - bool isPagesObject();
  1326 + bool isPagesObject() const;
1327 1327 QPDF_DLL
1328   - void assertPageObject();
  1328 + void assertPageObject() const;
1329 1329  
1330 1330 QPDF_DLL
1331   - bool isFormXObject();
  1331 + bool isFormXObject() const;
1332 1332  
1333 1333 // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as
1334 1334 // images.
1335 1335 QPDF_DLL
1336   - bool isImage(bool exclude_imagemask = true);
  1336 + bool isImage(bool exclude_imagemask = true) const;
1337 1337  
1338 1338 // The following methods do not form part of the public API and are for internal use only.
1339 1339  
... ... @@ -1362,7 +1362,7 @@ class QPDFObjectHandle
1362 1362 return obj.get();
1363 1363 }
1364 1364  
1365   - void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false);
  1365 + void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const;
1366 1366  
1367 1367 private:
1368 1368 QPDF_Array* asArray() const;
... ... @@ -1401,7 +1401,7 @@ class QPDFObjectHandle
1401 1401 std::shared_ptr<QPDFObject> obj;
1402 1402 };
1403 1403  
1404   -# ifndef QPDF_NO_QPDF_STRING
  1404 +#ifndef QPDF_NO_QPDF_STRING
1405 1405 // This is short for QPDFObjectHandle::parse, so you can do
1406 1406  
1407 1407 // auto oh = "<< /Key (value) >>"_qpdf;
... ... @@ -1410,14 +1410,14 @@ class QPDFObjectHandle
1410 1410 // from being here.
1411 1411  
1412 1412 /* clang-format off */
1413   -// Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
1414   -// of the file as a string if clang-format removes the space after "operator", and as of
1415   -// clang-format 15, there's no way to prevent it from doing so.
1416   -QPDF_DLL
1417   -QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
  1413 + // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
  1414 + // of the file as a string if clang-format removes the space after "operator", and as of
  1415 + // clang-format 15, there's no way to prevent it from doing so.
  1416 + QPDF_DLL
  1417 + QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
1418 1418 /* clang-format on */
1419 1419  
1420   -# endif // QPDF_NO_QPDF_STRING
  1420 +#endif // QPDF_NO_QPDF_STRING
1421 1421  
1422 1422 class QPDFObjectHandle::QPDFDictItems
1423 1423 {
... ... @@ -1634,7 +1634,7 @@ QPDFObjectHandle::isIndirect() const
1634 1634 }
1635 1635  
1636 1636 inline bool
1637   -QPDFObjectHandle::isInitialized() const
  1637 +QPDFObjectHandle::isInitialized() const noexcept
1638 1638 {
1639 1639 return obj != nullptr;
1640 1640 }
... ... @@ -1645,5 +1645,4 @@ operator bool() const noexcept
1645 1645 return static_cast<bool>(obj);
1646 1646 }
1647 1647  
1648   -#endif // QPDF_FUTURE
1649 1648 #endif // QPDFOBJECTHANDLE_HH
... ...
include/qpdf/QPDFObjectHandle_future.hh
1   -// Copyright (c) 2005-2021 Jay Berkenbilt
2   -// Copyright (c) 2022-2025 Jay Berkenbilt and Manfred Holger
3   -//
4   -// This file is part of qpdf.
5   -//
6   -// Licensed under the Apache License, Version 2.0 (the "License");
7   -// you may not use this file except in compliance with the License.
8   -// You may obtain a copy of the License at
9   -//
10   -// http://www.apache.org/licenses/LICENSE-2.0
11   -//
12   -// Unless required by applicable law or agreed to in writing, software
13   -// distributed under the License is distributed on an "AS IS" BASIS,
14   -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   -// See the License for the specific language governing permissions and
16   -// limitations under the License.
17   -//
18   -// Versions of qpdf prior to version 7 were released under the terms
19   -// of version 2.0 of the Artistic License. At your option, you may
20   -// continue to consider qpdf to be licensed under those terms. Please
21   -// see the manual for additional information.
22   -
23   -#ifndef QPDFOBJECTHANDLE_FUTURE_HH
24   -#define QPDFOBJECTHANDLE_FUTURE_HH
25   -
26   -#include <qpdf/Constants.h>
27   -#include <qpdf/DLL.h>
28   -#include <qpdf/Types.h>
29   -
30   -#include <functional>
31   -#include <map>
32   -#include <memory>
33   -#include <set>
34   -#include <string>
35   -#include <vector>
36   -
37   -#include <qpdf/Buffer.hh>
38   -#include <qpdf/InputSource.hh>
39   -#include <qpdf/JSON.hh>
40   -#include <qpdf/QPDFObjGen.hh>
41   -#include <qpdf/QPDFTokenizer.hh>
42   -
43   -class Pipeline;
44   -class QPDF;
45   -class QPDF_Array;
46   -class QPDF_Bool;
47   -class QPDF_Dictionary;
48   -class QPDF_InlineImage;
49   -class QPDF_Integer;
50   -class QPDF_Name;
51   -class QPDF_Null;
52   -class QPDF_Operator;
53   -class QPDF_Real;
54   -class QPDF_Reserved;
55   -class QPDF_Stream;
56   -class QPDF_String;
57   -class QPDFObject;
58   -class QPDFTokenizer;
59   -class QPDFExc;
60   -class Pl_QPDFTokenizer;
61   -class QPDFMatrix;
62   -class QPDFParser;
63   -
64   -class QPDFObjectHandle
65   -{
66   - friend class QPDFParser;
67   -
68   - public:
69   - // This class is used by replaceStreamData. It provides an alternative way of associating
70   - // stream data with a stream. See comments on replaceStreamData and newStream for additional
71   - // details.
72   - class QPDF_DLL_CLASS StreamDataProvider
73   - {
74   - public:
75   - QPDF_DLL
76   - StreamDataProvider(bool supports_retry = false);
77   -
78   - QPDF_DLL
79   - virtual ~StreamDataProvider();
80   - // The implementation of this function must write stream data to the given pipeline. The
81   - // stream data must conform to whatever filters are explicitly associated with the stream.
82   - // QPDFWriter may, in some cases, add compression, but if it does, it will update the
83   - // filters as needed. Every call to provideStreamData for a given stream must write the same
84   - // data. Note that, when writing linearized files, qpdf will call your provideStreamData
85   - // twice, and if it generates different output, you risk generating invalid output or having
86   - // qpdf throw an exception. The object ID and generation passed to this method are those
87   - // that belong to the stream on behalf of which the provider is called. They may be ignored
88   - // or used by the implementation for indexing or other purposes. This information is made
89   - // available just to make it more convenient to use a single StreamDataProvider object to
90   - // provide data for multiple streams.
91   -
92   - // A few things to keep in mind:
93   - //
94   - // * Stream data providers must not modify any objects since they may be called after some
95   - // parts of the file have already been written.
96   - //
97   - // * Since qpdf may call provideStreamData multiple times when writing linearized files, if
98   - // the work done by your stream data provider is slow or computationally intensive, you
99   - // might want to implement your own cache.
100   - //
101   - // * Once you have called replaceStreamData, the original stream data is no longer directly
102   - // accessible from the stream, but this is easy to work around by copying the stream to
103   - // a separate QPDF object. The qpdf library implements this very efficiently without
104   - // actually making a copy of the stream data. You can find examples of this pattern in
105   - // some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc.
106   -
107   - // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or
108   - // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by
109   - // allowing an alternative provideStreamData to be implemented. You must implement at least
110   - // one of the versions of provideStreamData below. If you implement the version that
111   - // supports retry and returns a value, you should pass true as the value of supports_retry
112   - // in the base class constructor. This will cause the library to call that version of the
113   - // method, which should also return a boolean indicating whether it ran without errors.
114   - QPDF_DLL
115   - virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
116   - QPDF_DLL
117   - virtual bool provideStreamData(
118   - QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
119   - QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline);
120   - QPDF_DLL virtual bool provideStreamData(
121   - int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
122   - QPDF_DLL
123   - bool supportsRetry();
124   -
125   - private:
126   - bool supports_retry;
127   - };
128   -
129   - // The TokenFilter class provides a way to filter content streams in a lexically aware fashion.
130   - // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter
131   - // methods or can be applied on the spot by filterPageContents. You may also use
132   - // Pl_QPDFTokenizer directly if you need full control.
133   - //
134   - // The handleToken method is called for each token, including the eof token, and then handleEOF
135   - // is called at the very end. Handlers may call write (or writeToken) to pass data downstream.
136   - // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of
137   - // using TokenFilters.
138   - //
139   - // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you
140   - // get the canonical, "parsed" representation of the token. For a string, this means that there
141   - // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits)
142   - // has been resolved. qpdf's internal representation of a name includes the leading slash. As
143   - // such, you can't write the value of token.getValue() directly to output that is supposed to be
144   - // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can
145   - // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new
146   - // string or name token from a canonical representation, use
147   - // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or
148   - // QPDFTokenizer::Token(QPDFTokenizer::tt_name,
149   - // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can
150   - // still write them with writeToken(). Example:
151   - // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain"))
152   - // would write `/text#2fplain`, and
153   - // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`.
154   - class QPDF_DLL_CLASS TokenFilter
155   - {
156   - public:
157   - QPDF_DLL
158   - TokenFilter() = default;
159   - QPDF_DLL
160   - virtual ~TokenFilter() = default;
161   - virtual void handleToken(QPDFTokenizer::Token const&) = 0;
162   - QPDF_DLL
163   - virtual void handleEOF();
164   -
165   - class PipelineAccessor
166   - {
167   - friend class Pl_QPDFTokenizer;
168   -
169   - private:
170   - static void
171   - setPipeline(TokenFilter* f, Pipeline* p)
172   - {
173   - f->setPipeline(p);
174   - }
175   - };
176   -
177   - protected:
178   - QPDF_DLL
179   - void write(char const* data, size_t len);
180   - QPDF_DLL
181   - void write(std::string const& str);
182   - QPDF_DLL
183   - void writeToken(QPDFTokenizer::Token const&);
184   -
185   - private:
186   - QPDF_DLL_PRIVATE
187   - void setPipeline(Pipeline*);
188   -
189   - Pipeline* pipeline;
190   - };
191   -
192   - // This class is used by parse to decrypt strings when reading an object that contains encrypted
193   - // strings.
194   - class StringDecrypter
195   - {
196   - public:
197   - QPDF_DLL
198   - virtual ~StringDecrypter() = default;
199   - virtual void decryptString(std::string& val) = 0;
200   - };
201   -
202   - // This class is used by parsePageContents. Callers must instantiate a subclass of this with
203   - // handlers defined to accept QPDFObjectHandles that are parsed from the stream.
204   - class QPDF_DLL_CLASS ParserCallbacks
205   - {
206   - public:
207   - QPDF_DLL
208   - virtual ~ParserCallbacks() = default;
209   - // One of the handleObject methods must be overridden.
210   - QPDF_DLL
211   - virtual void handleObject(QPDFObjectHandle);
212   - QPDF_DLL
213   - virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length);
214   -
215   - virtual void handleEOF() = 0;
216   -
217   - // Override this if you want to know the full size of the contents, possibly after
218   - // concatenation of multiple streams. This is called before the first call to handleObject.
219   - QPDF_DLL
220   - virtual void contentSize(size_t);
221   -
222   - protected:
223   - // Implementors may call this method during parsing to terminate parsing early. This method
224   - // throws an exception that is caught by parsePageContents, so its effect is immediate.
225   - QPDF_DLL
226   - void terminateParsing();
227   - };
228   -
229   - // Convenience object for rectangles
230   - class Rectangle
231   - {
232   - public:
233   - Rectangle() :
234   - llx(0.0),
235   - lly(0.0),
236   - urx(0.0),
237   - ury(0.0)
238   - {
239   - }
240   - Rectangle(double llx, double lly, double urx, double ury) :
241   - llx(llx),
242   - lly(lly),
243   - urx(urx),
244   - ury(ury)
245   - {
246   - }
247   -
248   - double llx;
249   - double lly;
250   - double urx;
251   - double ury;
252   - };
253   -
254   - // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't
255   - // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity
256   - // transform matrix and this one is all zeroes.
257   - class Matrix
258   - {
259   - public:
260   - Matrix() :
261   - a(0.0),
262   - b(0.0),
263   - c(0.0),
264   - d(0.0),
265   - e(0.0),
266   - f(0.0)
267   - {
268   - }
269   - Matrix(double a, double b, double c, double d, double e, double f) :
270   - a(a),
271   - b(b),
272   - c(c),
273   - d(d),
274   - e(e),
275   - f(f)
276   - {
277   - }
278   -
279   - double a;
280   - double b;
281   - double c;
282   - double d;
283   - double e;
284   - double f;
285   - };
286   -
287   - QPDF_DLL
288   - QPDFObjectHandle() = default;
289   - QPDF_DLL
290   - QPDFObjectHandle(QPDFObjectHandle const&) = default;
291   - QPDF_DLL
292   - QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
293   -
294   - QPDF_DLL
295   - QPDFObjectHandle(QPDFObjectHandle&&) = default;
296   - QPDF_DLL
297   - QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
298   -
299   - // Return true if the QPDFObjectHandle is initialized. This allows object handles to be used in
300   - // if statements with initializer.
301   - QPDF_DLL
302   - explicit inline operator bool() const noexcept;
303   -
304   - [[deprecated("use operator bool()")]] QPDF_DLL inline bool isInitialized() const noexcept;
305   -
306   - // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying
307   - // object, meaning that changes to one are reflected in the other, or "if you paint one, the
308   - // other one changes color." This does not perform a structural comparison of the contents of
309   - // the objects.
310   - QPDF_DLL
311   - bool isSameObjectAs(QPDFObjectHandle const&) const noexcept;
312   -
313   - // Return type code and type name of underlying object. These are useful for doing rapid type
314   - // tests (like switch statements) or for testing and debugging.
315   - QPDF_DLL
316   - qpdf_object_type_e getTypeCode() const;
317   - QPDF_DLL
318   - char const* getTypeName() const;
319   -
320   - // Exactly one of these will return true for any initialized object. Operator and InlineImage
321   - // are only allowed in content streams.
322   - QPDF_DLL
323   - bool isBool() const;
324   - QPDF_DLL
325   - bool isNull() const;
326   - QPDF_DLL
327   - bool isInteger() const;
328   - QPDF_DLL
329   - bool isReal() const;
330   - QPDF_DLL
331   - bool isName() const;
332   - QPDF_DLL
333   - bool isString() const;
334   - QPDF_DLL
335   - bool isOperator() const;
336   - QPDF_DLL
337   - bool isInlineImage() const;
338   - QPDF_DLL
339   - bool isArray() const;
340   - QPDF_DLL
341   - bool isDictionary() const;
342   - QPDF_DLL
343   - bool isStream() const;
344   - QPDF_DLL
345   - bool isReserved() const;
346   -
347   - // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended
348   - // for internal use, but it can be used as an efficient way to check for nulls that are not
349   - // indirect objects.
350   - QPDF_DLL
351   - bool isDirectNull() const;
352   -
353   - // This returns true in addition to the query for the specific type for indirect objects.
354   - QPDF_DLL
355   - inline bool isIndirect() const;
356   -
357   - // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse
358   - // such an object will throw a logic_error.
359   - QPDF_DLL
360   - bool isDestroyed() const;
361   -
362   - // True for everything except array, dictionary, stream, word, and inline image.
363   - QPDF_DLL
364   - bool isScalar() const;
365   -
366   - // True if the object is a name object representing the provided name.
367   - QPDF_DLL
368   - bool isNameAndEquals(std::string const& name) const;
369   -
370   - // True if the object is a dictionary of the specified type and subtype, if any.
371   - QPDF_DLL
372   - bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const;
373   -
374   - // True if the object is a stream of the specified type and subtype, if any.
375   - QPDF_DLL
376   - bool isStreamOfType(std::string const& type, std::string const& subtype = "") const;
377   -
378   - // Public factory methods
379   -
380   - // Wrap an object in an array if it is not already an array. This is a helper for cases in which
381   - // something in a PDF may either be a single item or an array of items, which is a common idiom.
382   - QPDF_DLL
383   - QPDFObjectHandle wrapInArray();
384   -
385   - // Construct an object of any type from a string representation of the object. Throws QPDFExc
386   - // with an empty filename and an offset into the string if there is an error. Any indirect
387   - // object syntax (obj gen R) will cause a logic_error exception to be thrown. If
388   - // object_description is provided, it will appear in the message of any QPDFExc exception thrown
389   - // for invalid syntax. See also the global `operator ""_qpdf` defined below.
390   - QPDF_DLL
391   - static QPDFObjectHandle
392   - parse(std::string const& object_str, std::string const& object_description = "");
393   -
394   - // Construct an object of any type from a string representation of the object. Indirect object
395   - // syntax (obj gen R) is allowed and will create indirect references within the passed-in
396   - // context. If object_description is provided, it will appear in the message of any QPDFExc
397   - // exception thrown for invalid syntax. Note that you can't parse an indirect object reference
398   - // all by itself as parse will stop at the end of the first complete object, which will just be
399   - // the first number and will report that there is trailing data at the end of the string.
400   - QPDF_DLL
401   - static QPDFObjectHandle
402   - parse(QPDF* context, std::string const& object_str, std::string const& object_description = "");
403   -
404   - // Construct an object as above by reading from the given InputSource at its current position
405   - // and using the tokenizer you supply. Indirect objects and encrypted strings are permitted.
406   - // This method was intended to be called by QPDF for parsing objects that are ready from the
407   - // object's input stream.
408   - QPDF_DLL
409   - static QPDFObjectHandle parse(
410   - std::shared_ptr<InputSource> input,
411   - std::string const& object_description,
412   - QPDFTokenizer&,
413   - bool& empty,
414   - StringDecrypter* decrypter,
415   - QPDF* context);
416   -
417   - // Return the offset where the object was found when parsed. A negative value means that the
418   - // object was created without parsing. If the object is in a stream, the offset is from the
419   - // beginning of the stream. Otherwise, the offset is from the beginning of the file.
420   - QPDF_DLL
421   - qpdf_offset_t getParsedOffset() const;
422   -
423   - // Older method: stream_or_array should be the value of /Contents from a page object. It's more
424   - // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error
425   - // messages will also be more useful because the page object information will be known.
426   - QPDF_DLL
427   - static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks);
428   -
429   - // When called on a stream or stream array that is some page's content streams, do the same as
430   - // pipePageContents. This method is a lower level way to do what
431   - // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a
432   - // contents object that is disconnected from a page object. The description argument should
433   - // describe the containing page and is used in error messages. The all_description argument is
434   - // initialized to something that could be used to describe the result of the pipeline. It is the
435   - // description amended with the identifiers of the underlying objects. Please note that if there
436   - // is an array of content streams, p->finish() is called after each stream. If you pass a
437   - // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an
438   - // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the
439   - // end.
440   - QPDF_DLL
441   - void
442   - pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description);
443   -
444   - // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream
445   - // data is passed through the token filter after all original filters but before content stream
446   - // normalization if requested. This is a low-level interface to add it to a stream. You will
447   - // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be
448   - // applied to a page object, and which will automatically handle the case of pages whose
449   - // contents are split across multiple streams.
450   - QPDF_DLL
451   - void addTokenFilter(std::shared_ptr<TokenFilter> token_filter);
452   -
453   - // Legacy helpers for parsing content streams. These methods are not going away, but newer code
454   - // should call the correspond methods in QPDFPageObjectHelper instead. The specification and
455   - // behavior of these methods are the same as the identically named methods in that class, but
456   - // newer functionality will be added there.
457   - QPDF_DLL
458   - void parsePageContents(ParserCallbacks* callbacks);
459   - QPDF_DLL
460   - void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr);
461   - // See comments for QPDFPageObjectHelper::pipeContents.
462   - QPDF_DLL
463   - void pipePageContents(Pipeline* p);
464   - QPDF_DLL
465   - void addContentTokenFilter(std::shared_ptr<TokenFilter> token_filter);
466   - // End legacy content stream helpers
467   -
468   - // Called on a stream to filter the stream as if it were page contents. This can be used to
469   - // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream.
470   - QPDF_DLL
471   - void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr);
472   - // Called on a stream to parse the stream as page contents. This can be used to parse a form
473   - // XObject.
474   - QPDF_DLL
475   - void parseAsContents(ParserCallbacks* callbacks);
476   -
477   - // Type-specific factories
478   - QPDF_DLL
479   - static QPDFObjectHandle newNull();
480   - QPDF_DLL
481   - static QPDFObjectHandle newBool(bool value);
482   - QPDF_DLL
483   - static QPDFObjectHandle newInteger(long long value);
484   - QPDF_DLL
485   - static QPDFObjectHandle newReal(std::string const& value);
486   - QPDF_DLL
487   - static QPDFObjectHandle
488   - newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true);
489   - // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes,
490   - // excluding the NUL character, and starting with a slash. Name objects as represented in the
491   - // PDF specification can contain characters escaped with #, but such escaping is not of concern
492   - // when calling QPDFObjectHandle methods not directly relating to parsing. For example,
493   - // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return
494   - // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse()
495   - // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and
496   - // modifying objects, you want to work with the internal, canonical representation. For names
497   - // containing alphanumeric characters, dashes, and underscores, there is no difference between
498   - // the two representations. For a lengthy discussion, see
499   - // https://github.com/qpdf/qpdf/discussions/625.
500   - QPDF_DLL
501   - static QPDFObjectHandle newName(std::string const& name);
502   - QPDF_DLL
503   - static QPDFObjectHandle newString(std::string const& str);
504   - // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in
505   - // PDF files outside of content streams, such as in document metadata form field values, page
506   - // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16
507   - // as needed to successfully encode all the characters.
508   - QPDF_DLL
509   - static QPDFObjectHandle newUnicodeString(std::string const& utf8_str);
510   - QPDF_DLL
511   - static QPDFObjectHandle newOperator(std::string const&);
512   - QPDF_DLL
513   - static QPDFObjectHandle newInlineImage(std::string const&);
514   - QPDF_DLL
515   - static QPDFObjectHandle newArray();
516   - QPDF_DLL
517   - static QPDFObjectHandle newArray(std::vector<QPDFObjectHandle> const& items);
518   - QPDF_DLL
519   - static QPDFObjectHandle newArray(Rectangle const&);
520   - QPDF_DLL
521   - static QPDFObjectHandle newArray(Matrix const&);
522   - QPDF_DLL
523   - static QPDFObjectHandle newArray(QPDFMatrix const&);
524   - QPDF_DLL
525   - static QPDFObjectHandle newDictionary();
526   - QPDF_DLL
527   - static QPDFObjectHandle newDictionary(std::map<std::string, QPDFObjectHandle> const& items);
528   -
529   - // Create an array from a rectangle. Equivalent to the rectangle form of newArray.
530   - QPDF_DLL
531   - static QPDFObjectHandle newFromRectangle(Rectangle const&);
532   - // Create an array from a matrix. Equivalent to the matrix form of newArray.
533   - QPDF_DLL
534   - static QPDFObjectHandle newFromMatrix(Matrix const&);
535   - QPDF_DLL
536   - static QPDFObjectHandle newFromMatrix(QPDFMatrix const&);
537   -
538   - // Note: new stream creation methods have were added to the QPDF class starting with
539   - // version 11.2.0. The ones in this class are here for backward compatibility.
540   -
541   - // Create a new stream and associate it with the given qpdf object. A subsequent call must be
542   - // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be
543   - // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively,
544   - // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can
545   - // call QPDF::newStream() instead.
546   - QPDF_DLL
547   - static QPDFObjectHandle newStream(QPDF* qpdf);
548   -
549   - // Create a new stream and associate it with the given qpdf object. Use the given buffer as the
550   - // stream data. The stream dictionary's /Length key will automatically be set to the size of the
551   - // data buffer. If additional keys are required, the stream's dictionary may be retrieved by
552   - // calling getDict(), and the resulting dictionary may be modified. This method is just a
553   - // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience
554   - // methods for streams that require no parameters beyond the stream length. Note that you don't
555   - // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will
556   - // automatically compress uncompressed stream data. Example programs are provided that
557   - // illustrate this. From QPDF 11.2, you can call QPDF::newStream()
558   - // instead.
559   - QPDF_DLL
560   - static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr<Buffer> data);
561   -
562   - // Create new stream with data from string. This method will create a copy of the data rather
563   - // than using the user-provided buffer as in the std::shared_ptr<Buffer> version of newStream.
564   - // From QPDF 11.2, you can call QPDF::newStream() instead.
565   - QPDF_DLL
566   - static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data);
567   -
568   - // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is
569   - // going to be added to the QPDF object. Normally you don't have to use this type since you can
570   - // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects
571   - // with circular references, you may need to create a reserved object so that you can have a
572   - // reference to it and then replace the object later. Reserved objects have the special
573   - // property that they can't be resolved to direct objects. This makes it possible to replace a
574   - // reserved object with a new object while preserving existing references to them. When you are
575   - // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this
576   - // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a
577   - // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call
578   - // QPDF::newReserved() instead.
579   - QPDF_DLL
580   - static QPDFObjectHandle newReserved(QPDF* qpdf);
581   -
582   - // Provide an owning qpdf and object description. The library does this automatically with
583   - // objects that are read from the input PDF and with objects that are created programmatically
584   - // and inserted into the QPDF as a new indirect object. Most end user code will not need to call
585   - // this. If an object has an owning qpdf and object description, it enables qpdf to give
586   - // warnings with proper context in some cases where it would otherwise raise exceptions. It is
587   - // okay to add objects without an owning_qpdf to objects that have one, but it is an error to
588   - // have a QPDF contain objects with owning_qpdf set to something else. To add objects from
589   - // another qpdf, use copyForeignObject instead.
590   - QPDF_DLL
591   - void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
592   - QPDF_DLL
593   - bool hasObjectDescription() const;
594   -
595   - // Accessor methods
596   - //
597   - // (Note: this comment is referenced in qpdf-c.h and the manual.)
598   - //
599   - // In PDF files, objects have specific types, but there is nothing that prevents PDF files from
600   - // containing objects of types that aren't expected by the specification.
601   - //
602   - // There are two flavors of accessor methods:
603   - //
604   - // * getSomethingValue() returns the value and issues a type warning if the type is incorrect.
605   - //
606   - // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns
607   - // true and initializes a reference of the appropriate type. These methods never issue type
608   - // warnings.
609   - //
610   - // The getSomethingValue() accessors and some of the other methods expect objects of a
611   - // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as
612   - // trying to get a dictionary key from an array, trying to get the string value of a number,
613   - // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using
614   - // the following behavior:
615   - //
616   - // * Requesting a value of the wrong type (int value from string, array item from a scalar or
617   - // dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for
618   - // number, the empty string for string, or the null object for an object handle.
619   - //
620   - // * Accessing an array item that is out of bounds will return a null object.
621   - //
622   - // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to
623   - // a scalar or array) will be ignored.
624   - //
625   - // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5,
626   - // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code
627   - // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case
628   - // for all objects whose origin was a PDF file), the warning is issued using the normal warning
629   - // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them.
630   - // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created
631   - // programmatically), an exception will be thrown.
632   - //
633   - // The way to avoid getting any type warnings or exceptions, even when working with malformed
634   - // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for
635   - // example, make sure that isString() returns true before calling getStringValue()) and to
636   - // always be sure that any array indices are in bounds.
637   - //
638   - // For additional discussion and rationale for this behavior, see the section in the QPDF manual
639   - // entitled "Object Accessor Methods".
640   -
641   - // Methods for bool objects
642   - QPDF_DLL
643   - bool getBoolValue() const;
644   - QPDF_DLL
645   - bool getValueAsBool(bool&) const;
646   -
647   - // Methods for integer objects. Note: if an integer value is too big (too far away from zero in
648   - // either direction) to fit in the requested return type, the maximum or minimum value for that
649   - // return type may be returned. For example, on a system with 32-bit int, a numeric object with
650   - // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
651   - QPDF_DLL
652   - long long getIntValue() const;
653   - QPDF_DLL
654   - bool getValueAsInt(long long&) const;
655   - QPDF_DLL
656   - int getIntValueAsInt() const;
657   - QPDF_DLL
658   - bool getValueAsInt(int&) const;
659   - QPDF_DLL
660   - unsigned long long getUIntValue() const;
661   - QPDF_DLL
662   - bool getValueAsUInt(unsigned long long&) const;
663   - QPDF_DLL
664   - unsigned int getUIntValueAsUInt() const;
665   - QPDF_DLL
666   - bool getValueAsUInt(unsigned int&) const;
667   -
668   - // Methods for real objects
669   - QPDF_DLL
670   - std::string getRealValue() const;
671   - QPDF_DLL
672   - bool getValueAsReal(std::string&) const;
673   -
674   - // Methods that work for both integer and real objects
675   - QPDF_DLL
676   - bool isNumber() const;
677   - QPDF_DLL
678   - double getNumericValue() const;
679   - QPDF_DLL
680   - bool getValueAsNumber(double&) const;
681   -
682   - // Methods for name objects. The returned name value is in qpdf's canonical form with all
683   - // escaping resolved. See comments for newName() for details.
684   - QPDF_DLL
685   - std::string getName() const;
686   - QPDF_DLL
687   - bool getValueAsName(std::string&) const;
688   -
689   - // Methods for string objects
690   - QPDF_DLL
691   - std::string getStringValue() const;
692   - QPDF_DLL
693   - bool getValueAsString(std::string&) const;
694   -
695   - // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise,
696   - // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to
697   - // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters
698   - // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range
699   - // unmapped.
700   - QPDF_DLL
701   - std::string getUTF8Value() const;
702   - QPDF_DLL
703   - bool getValueAsUTF8(std::string&) const;
704   -
705   - // Methods for content stream objects
706   - QPDF_DLL
707   - std::string getOperatorValue() const;
708   - QPDF_DLL
709   - bool getValueAsOperator(std::string&) const;
710   - QPDF_DLL
711   - std::string getInlineImageValue() const;
712   - QPDF_DLL
713   - bool getValueAsInlineImage(std::string&) const;
714   -
715   - // Methods for array objects; see also name and array objects.
716   -
717   - // Return an object that enables iteration over members. You can do
718   - //
719   - // for (auto iter: obj.aitems())
720   - // {
721   - // // iter is an array element
722   - // }
723   - class QPDFArrayItems;
724   - QPDF_DLL
725   - QPDFArrayItems aitems();
726   -
727   - QPDF_DLL
728   - int getArrayNItems() const;
729   - QPDF_DLL
730   - QPDFObjectHandle getArrayItem(int n) const;
731   - // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling
732   - // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of
733   - // nulls.
734   - QPDF_DLL
735   - std::vector<QPDFObjectHandle> getArrayAsVector() const;
736   - QPDF_DLL
737   - bool isRectangle() const;
738   - // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the
739   - // rectangle [0, 0, 0, 0]
740   - QPDF_DLL
741   - Rectangle getArrayAsRectangle() const;
742   - QPDF_DLL
743   - bool isMatrix() const;
744   - // If the array is an array of six numeric values, return as a matrix. Otherwise, return the
745   - // matrix [1, 0, 0, 1, 0, 0]
746   - QPDF_DLL
747   - Matrix getArrayAsMatrix() const;
748   -
749   - // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as
750   - // canonical name strings starting with a leading slash and not containing any PDF syntax
751   - // escaping. See comments for getName() for details.
752   -
753   - // Return an object that enables iteration over members. You can do
754   - //
755   - // for (auto iter: obj.ditems())
756   - // {
757   - // // iter.first is the key
758   - // // iter.second is the value
759   - // }
760   - class QPDFDictItems;
761   - QPDF_DLL
762   - QPDFDictItems ditems();
763   -
764   - // Return true if key is present. Keys with null values are treated as if they are not present.
765   - // This is as per the PDF spec.
766   - QPDF_DLL
767   - bool hasKey(std::string const&) const;
768   - // Return the value for the key. If the key is not present, null is returned.
769   - QPDF_DLL
770   - QPDFObjectHandle getKey(std::string const&) const;
771   - // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access
772   - // lower-level dictionaries, as in
773   - // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font");
774   - QPDF_DLL
775   - QPDFObjectHandle getKeyIfDict(std::string const&) const;
776   - // Return all keys. Keys with null values are treated as if they are not present. This is as
777   - // per the PDF spec.
778   - QPDF_DLL
779   - std::set<std::string> getKeys() const;
780   - // Return dictionary as a map. Entries with null values are included.
781   - QPDF_DLL
782   - std::map<std::string, QPDFObjectHandle> getDictAsMap() const;
783   -
784   - // Methods for name and array objects. The name value is in qpdf's canonical form with all
785   - // escaping resolved. See comments for newName() for details.
786   - QPDF_DLL
787   - bool isOrHasName(std::string const&) const;
788   -
789   - // Make all resources in a resource dictionary indirect. This just goes through all entries of
790   - // top-level subdictionaries and converts any direct objects to indirect objects. This can be
791   - // useful to call before mergeResources if it is going to be called multiple times to prevent
792   - // resources from being copied multiple times.
793   - QPDF_DLL
794   - void makeResourcesIndirect(QPDF& owning_qpdf);
795   -
796   - // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in
797   - // dictionary subitems are resolved, and "conflicts" is initialized to a map such that
798   - // conflicts[resource_type][old_key] == [new_key]
799   - //
800   - // See also makeResourcesIndirect, which can be useful to call before calling this.
801   - //
802   - // This method does nothing if both this object and the other object are not dictionaries.
803   - // Otherwise, it has following behavior, where "object" refers to the object whose method is
804   - // invoked, and "other" refers to the argument:
805   - //
806   - // * For each key in "other" whose value is an array:
807   - // * If "object" does not have that entry, shallow copy it.
808   - // * Otherwise, if "object" has an array in the same place, append to that array any objects
809   - // in "other"'s array that are not already present.
810   - // * For each key in "other" whose value is a dictionary:
811   - // * If "object" does not have that entry, shallow copy it.
812   - // * Otherwise, for each key in the subdictionary:
813   - // * If key is not present in "object"'s entry, shallow copy it if direct or just add it if
814   - // indirect.
815   - // * Otherwise, if conflicts are being detected:
816   - // * If there is a key (oldkey) already in the dictionary that points to the same indirect
817   - // destination as key, indicate that key was replaced by oldkey. This would happen if
818   - // these two resource dictionaries have previously been merged.
819   - // * Otherwise pick a new key (newkey) that is unique within the resource dictionary,
820   - // store that in the resource dictionary with key's destination as its destination, and
821   - // indicate that key was replaced by newkey.
822   - //
823   - // The primary purpose of this method is to facilitate merging of resource dictionaries that are
824   - // supposed to have the same scope as each other. For example, this can be used to merge a form
825   - // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The
826   - // "conflicts" parameter may be previously initialized. This method adds to whatever is already
827   - // there, which can be useful when merging with multiple things.
828   - QPDF_DLL
829   - void mergeResources(
830   - QPDFObjectHandle other,
831   - std::map<std::string, std::map<std::string, std::string>>* conflicts = nullptr);
832   -
833   - // Get all resource names from a resource dictionary. If this object is a dictionary, this
834   - // method returns a set of all the keys in all top-level subdictionaries. For resources
835   - // dictionaries, this is the collection of names that may be referenced in the content stream.
836   - QPDF_DLL
837   - std::set<std::string> getResourceNames() const;
838   -
839   - // Find a unique name within a resource dictionary starting with a given prefix. This method
840   - // works by appending a number to the given prefix. It searches starting with min_suffix and
841   - // sets min_suffix to selected value upon return. This can be used to increase efficiency if
842   - // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next
843   - // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling
844   - // this multiple times on the same resource dictionary, you can initialize resource_names by
845   - // calling getResourceNames(), incrementally update it as you add resources, and keep passing it
846   - // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time
847   - // it's called.
848   - QPDF_DLL
849   - std::string getUniqueResourceName(
850   - std::string const& prefix,
851   - int& min_suffix,
852   - std::set<std::string>* resource_names = nullptr) const;
853   -
854   - // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF
855   - // object. Indirect objects always have an owning QPDF. Direct objects that are read from the
856   - // input source will also have an owning QPDF. Programmatically created objects will only have
857   - // one if setObjectDescription was called.
858   - //
859   - // When the QPDF object that owns an object is destroyed, the object is changed into a null, and
860   - // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the
861   - // life of the QPDF. If in doubt, ask for it each time you need it.
862   -
863   - // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it
864   - // returns a null pointer. Use this when you are able to handle the case of an object that
865   - // doesn't have an owning QPDF.
866   - QPDF_DLL
867   - QPDF* getOwningQPDF() const;
868   - // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a
869   - // runtime_error. Use this when you know the object has to have an owning QPDF, such as when
870   - // it's a known indirect object. Since streams are always indirect objects, this method can be
871   - // used safely for streams. If error_msg is specified, it will be used at the contents of the
872   - // runtime_error if there is now owner.
873   - QPDF_DLL
874   - QPDF& getQPDF(std::string const& error_msg = "") const;
875   -
876   - // Create a shallow copy of an object as a direct object, but do not traverse across indirect
877   - // object boundaries. That means that, for dictionaries and arrays, any keys or items that were
878   - // indirect objects will still be indirect objects that point to the same place. In the
879   - // strictest sense, this is not a shallow copy because it recursively descends arrays and
880   - // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You
881   - // can't copy a stream this way. See copyStream() instead.
882   - QPDF_DLL
883   - QPDFObjectHandle shallowCopy();
884   -
885   - // Create a true shallow copy of an array or dictionary, just copying the immediate items
886   - // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in
887   - // the copy, you are modifying the original, which is almost never what you want. However, if
888   - // your intention is merely to *replace* top-level items or keys and not to modify lower-level
889   - // items in the copy, this method is much faster than shallowCopy().
890   - QPDF_DLL
891   - QPDFObjectHandle unsafeShallowCopy();
892   -
893   - // Create a copy of this stream. The new stream and the old stream are independent: after the
894   - // copy, either the original or the copy's dictionary or data can be modified without affecting
895   - // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's
896   - // data are made. If the source stream's data is already being provided by a StreamDataProvider,
897   - // the new stream will use the same one, so you have to make sure your StreamDataProvider can
898   - // handle that case. But if you're already using a StreamDataProvider, you probably don't need
899   - // to call this method.
900   - QPDF_DLL
901   - QPDFObjectHandle copyStream();
902   -
903   - // Mutator methods.
904   -
905   - // Since qpdf 11: for mutators that may add or remove an item, there are additional versions
906   - // whose names contain "AndGet" that return the added or removed item. For example:
907   - //
908   - // auto new_dict = dict.replaceKeyAndGetNew(
909   - // "/New", QPDFObjectHandle::newDictionary());
910   - //
911   - // auto old_value = dict.replaceKeyAndGetOld(
912   - // "/New", "(something)"_qpdf);
913   -
914   - // Recursively copy this object, making it direct. An exception is thrown if a loop is detected.
915   - // With allow_streams true, keep indirect object references to streams. Otherwise, throw an
916   - // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream
917   - // is found, the resulting object is still associated with the containing qpdf. When
918   - // allow_streams is false, the object will no longer be connected to the original QPDF object
919   - // after this call completes successfully.
920   - QPDF_DLL
921   - void makeDirect(bool allow_streams = false);
922   -
923   - // Mutator methods for array objects
924   - QPDF_DLL
925   - void setArrayItem(int, QPDFObjectHandle const&);
926   - QPDF_DLL
927   - void setArrayFromVector(std::vector<QPDFObjectHandle> const& items);
928   - // Insert an item before the item at the given position ("at") so that it has that position
929   - // after insertion. If "at" is equal to the size of the array, insert the item at the end.
930   - QPDF_DLL
931   - void insertItem(int at, QPDFObjectHandle const& item);
932   - // Like insertItem but return the item that was inserted.
933   - QPDF_DLL
934   - QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item);
935   - // Append an item to an array.
936   - QPDF_DLL
937   - void appendItem(QPDFObjectHandle const& item);
938   - // Append an item, and return the newly added item.
939   - QPDF_DLL
940   - QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item);
941   - // Remove the item at that position, reducing the size of the array by one.
942   - QPDF_DLL
943   - void eraseItem(int at);
944   - // Erase and item and return the item that was removed.
945   - QPDF_DLL
946   - QPDFObjectHandle eraseItemAndGetOld(int at);
947   -
948   - // Mutator methods for dictionary objects
949   -
950   - // Replace value of key, adding it if it does not exist. If value is null, remove the key.
951   - QPDF_DLL
952   - void replaceKey(std::string const& key, QPDFObjectHandle const& value);
953   - // Replace value of key and return the value.
954   - QPDF_DLL
955   - QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value);
956   - // Replace value of key and return the old value, or null if the key was previously not present.
957   - QPDF_DLL
958   - QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value);
959   - // Remove key, doing nothing if key does not exist.
960   - QPDF_DLL
961   - void removeKey(std::string const& key);
962   - // Remove key and return the old value. If the old value didn't exist, return a null object.
963   - QPDF_DLL
964   - QPDFObjectHandle removeKeyAndGetOld(std::string const& key);
965   -
966   - // ABI: Remove in qpdf 12
967   - [[deprecated("use replaceKey -- it does the same thing")]] QPDF_DLL void
968   - replaceOrRemoveKey(std::string const& key, QPDFObjectHandle const&);
969   -
970   - // Methods for stream objects
971   - QPDF_DLL
972   - QPDFObjectHandle getDict() const;
973   -
974   - // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode
975   - // level, whether compression is enabled, and its ability to filter. Passing false will prevent
976   - // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding
977   - // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and
978   - // recompressing a stream that it knows how to operate on for any application-specific reason,
979   - // such as that you have already optimized its filtering. Note that this doesn't affect any
980   - // other ways to get the stream's data, such as pipeStreamData or getStreamData.
981   - QPDF_DLL
982   - void setFilterOnWrite(bool);
983   - QPDF_DLL
984   - bool getFilterOnWrite();
985   -
986   - // If addTokenFilter has been called for this stream, then the original data should be
987   - // considered to be modified. This means we should avoid optimizations such as not filtering a
988   - // stream that is already compressed.
989   - QPDF_DLL
990   - bool isDataModified();
991   -
992   - // Returns filtered (uncompressed) stream data. Throws an exception if the stream is filtered
993   - // and we can't decode it.
994   - QPDF_DLL
995   - std::shared_ptr<Buffer> getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized);
996   -
997   - // Returns unfiltered (raw) stream data.
998   - QPDF_DLL
999   - std::shared_ptr<Buffer> getRawStreamData();
1000   -
1001   - // Write stream data through the given pipeline. A null pipeline value may be used if all you
1002   - // want to do is determine whether a stream is filterable and would be filtered based on the
1003   - // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags
1004   - // alter the behavior in the following way:
1005   - //
1006   - // encode_flags:
1007   - //
1008   - // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are
1009   - // applied.
1010   - //
1011   - // qpdf_sf_normalize -- tokenize as content stream and normalize tokens
1012   - //
1013   - // decode_level:
1014   - //
1015   - // qpdf_dl_none -- do not decode any streams.
1016   - //
1017   - // qpdf_dl_generalized -- decode supported general-purpose filters. This includes
1018   - // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode.
1019   - //
1020   - // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy
1021   - // specialized filters. This includes /RunLengthDecode.
1022   - //
1023   - // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported
1024   - // lossy filters. This includes /DCTDecode.
1025   - //
1026   - // If, based on the flags and the filters and decode parameters, we determine that we know how
1027   - // to apply all requested filters, do so and return true if we are successful.
1028   - //
1029   - // The exact meaning of the return value differs the different versions of this function, but
1030   - // for any version, the meaning has been the same. For the main version, added in qpdf 10, the
1031   - // return value indicates whether the overall operation succeeded. The filter parameter, if
1032   - // specified, will be set to whether or not filtering was attempted. If filtering was not
1033   - // requested, this value will be false even if the overall operation succeeded.
1034   - //
1035   - // If filtering is requested but this method returns false, it means there was some error in the
1036   - // filtering, in which case the resulting data is likely partially filtered and/or incomplete
1037   - // and may not be consistent with the configured filters. QPDFWriter handles this by attempting
1038   - // to get the stream data without filtering, but callers should consider a false return value
1039   - // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry
1040   - // in that case, pass true as the value of will_retry. This changes the warning issued by the
1041   - // library to indicate that the operation will be retried without filtering to avoid data loss.
1042   -
1043   - // Return value is overall success, even if filtering is not requested.
1044   - QPDF_DLL
1045   - bool pipeStreamData(
1046   - Pipeline*,
1047   - bool* filtering_attempted,
1048   - int encode_flags,
1049   - qpdf_stream_decode_level_e decode_level,
1050   - bool suppress_warnings = false,
1051   - bool will_retry = false);
1052   -
1053   - // Legacy version. Return value is whether filtering was attempted. There is no way to determine
1054   - // success if filtering was not attempted.
1055   - QPDF_DLL
1056   - bool pipeStreamData(
1057   - Pipeline*,
1058   - int encode_flags,
1059   - qpdf_stream_decode_level_e decode_level,
1060   - bool suppress_warnings = false,
1061   - bool will_retry = false);
1062   -
1063   - // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows:
1064   - // filter = false -> encode_flags = 0
1065   - // filter = true -> decode_level = qpdf_dl_generalized
1066   - // normalize = true -> encode_flags |= qpdf_sf_normalize
1067   - // compress = true -> encode_flags |= qpdf_sf_compress
1068   - // Return value is whether filtering was attempted.
1069   - QPDF_DLL
1070   - bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress);
1071   -
1072   - // Replace a stream's dictionary. The new dictionary must be consistent with the stream's data.
1073   - // This is most appropriately used when creating streams from scratch that will use a stream
1074   - // data provider and therefore start with an empty dictionary. It may be more convenient in
1075   - // this case than calling getDict and modifying it for each key. The pdf-create example does
1076   - // this.
1077   - QPDF_DLL
1078   - void replaceDict(QPDFObjectHandle const&);
1079   -
1080   - // REPLACING STREAM DATA
1081   -
1082   - // Note about all replaceStreamData methods: whatever values are passed as filter and
1083   - // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object
1084   - // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf
1085   - // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing
1086   - // values untouched.
1087   -
1088   - // Replace this stream's stream data with the given data buffer. The stream's /Length key is
1089   - // replaced with the length of the data buffer. The stream is interpreted as if the data read
1090   - // from the file, after any decryption filters have been applied, is as presented.
1091   - QPDF_DLL
1092   - void replaceStreamData(
1093   - std::shared_ptr<Buffer> data,
1094   - QPDFObjectHandle const& filter,
1095   - QPDFObjectHandle const& decode_parms);
1096   -
1097   - // Replace the stream's stream data with the given string. This method will create a copy of the
1098   - // data rather than using the user-provided buffer as in the std::shared_ptr<Buffer> version of
1099   - // replaceStreamData.
1100   - QPDF_DLL
1101   - void replaceStreamData(
1102   - std::string const& data,
1103   - QPDFObjectHandle const& filter,
1104   - QPDFObjectHandle const& decode_parms);
1105   -
1106   - // As above, replace this stream's stream data. Instead of directly providing a buffer with the
1107   - // stream data, call the given provider's provideStreamData method. See comments on the
1108   - // StreamDataProvider class (defined above) for details on the method. The data must be
1109   - // consistent with filter and decode_parms as provided. Although it is more complex to use this
1110   - // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid
1111   - // allocating memory for the stream data. Example programs are provided that use both forms of
1112   - // replaceStreamData.
1113   -
1114   - // Note about stream length: for any given stream, the provider must provide the same amount of
1115   - // data each time it is called. This is critical for making linearization work properly.
1116   - // Versions of qpdf before 3.0.0 required a length to be specified here. Starting with
1117   - // version 3.0.0, this is no longer necessary (or permitted). The first time the stream data
1118   - // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is
1119   - // enforced that the length be the same as the first time.
1120   -
1121   - // If you have gotten a compile error here while building code that worked with older versions
1122   - // of qpdf, just omit the length parameter. You can also simplify your code by not having to
1123   - // compute the length in advance.
1124   - QPDF_DLL
1125   - void replaceStreamData(
1126   - std::shared_ptr<StreamDataProvider> provider,
1127   - QPDFObjectHandle const& filter,
1128   - QPDFObjectHandle const& decode_parms);
1129   -
1130   - // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider.
1131   -
1132   - // The provider should write the stream data to the pipeline. For a one-liner to replace stream
1133   - // data with the contents of a file, pass QUtil::file_provider(filename) as provider.
1134   - QPDF_DLL
1135   - void replaceStreamData(
1136   - std::function<void(Pipeline*)> provider,
1137   - QPDFObjectHandle const& filter,
1138   - QPDFObjectHandle const& decode_parms);
1139   - // The provider should write the stream data to the pipeline, returning true if it succeeded
1140   - // without errors.
1141   - QPDF_DLL
1142   - void replaceStreamData(
1143   - std::function<bool(Pipeline*, bool suppress_warnings, bool will_retry)> provider,
1144   - QPDFObjectHandle const& filter,
1145   - QPDFObjectHandle const& decode_parms);
1146   -
1147   - // Access object ID and generation. For direct objects, return object ID 0.
1148   -
1149   - // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to
1150   - // the pattern of depending on object ID or generation without the other. In general, when
1151   - // keeping track of object IDs, it's better to use QPDFObjGen instead.
1152   -
1153   - QPDF_DLL
1154   - QPDFObjGen getObjGen() const;
1155   - QPDF_DLL
1156   - inline int getObjectID() const;
1157   - QPDF_DLL
1158   - inline int getGeneration() const;
1159   -
1160   - QPDF_DLL
1161   - std::string unparse() const;
1162   - QPDF_DLL
1163   - std::string unparseResolved() const;
1164   - // For strings only, force binary representation. Otherwise, same as unparse.
1165   - QPDF_DLL
1166   - std::string unparseBinary() const;
1167   -
1168   - // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available
1169   - // JSON version. The JSON is generated as follows:
1170   - // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their
1171   - // native JSON types.
1172   - // * Names are encoded as strings representing the canonical representation (after parsing #xx)
1173   - // and preceded by a slash, just as unparse() returns. For example, the JSON for the
1174   - // PDF-syntax name /Text#2fPlain would be "/Text/Plain".
1175   - // * Indirect references are encoded as strings containing "obj gen R"
1176   - // * Strings
1177   - // * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters
1178   - // encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode
1179   - // mappings are not reversible. There is no way to tell the difference between a string that
1180   - // looks like a name or indirect object from an actual name or indirect object.
1181   - // * JSON v2:
1182   - // * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally
1183   - // mapped to Unicode (which is all strings without undefined characters) are represented
1184   - // as "u:" followed by the UTF-8 encoded string. Example:
1185   - // "u:potato".
1186   - // * All other strings are represented as "b:" followed by a hexadecimal encoding of the
1187   - // string. Example: "b:0102cacb"
1188   - // * Streams
1189   - // * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a
1190   - // dictionary other than context.
1191   - // * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the
1192   - // stream's dictionary. Since "dict" does not otherwise represent anything, this is
1193   - // unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data.
1194   - // * Object types that are only valid in content streams (inline image, operator) are serialized
1195   - // as "null". Attempting to serialize a "reserved" object is an error.
1196   - // If dereference_indirect is true and this is an indirect object, show the actual contents of
1197   - // the object. The effect of dereference_indirect applies only to this object. It is not
1198   - // recursive.
1199   - QPDF_DLL
1200   - JSON getJSON(int json_version, bool dereference_indirect = false) const;
1201   -
1202   - // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient
1203   - // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the
1204   - // documentation for getJSON and JSON::write for further detail.
1205   - QPDF_DLL
1206   - void writeJSON(
1207   - int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const;
1208   -
1209   - // Deprecated version uses v1 for backward compatibility.
1210   - // ABI: remove for qpdf 12
1211   - [[deprecated("Use getJSON(int version)")]] QPDF_DLL JSON
1212   - getJSON(bool dereference_indirect = false) const;
1213   -
1214   - // This method can be called on a stream to get a more extended JSON representation of the
1215   - // stream that includes the stream's data. The JSON object returned is always a dictionary whose
1216   - // "dict" key is an encoding of the stream's dictionary. The representation of the data is
1217   - // determined by the json_data field.
1218   - //
1219   - // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file.
1220   - //
1221   - // If json_data is qpdf_sj_none, stream data is not represented.
1222   - //
1223   - // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on
1224   - // the value of decode_level, which has the same meaning as with pipeStreamData.
1225   - //
1226   - // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data"
1227   - // field of the dictionary that is returned.
1228   - //
1229   - // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be
1230   - // supplied. The value of data_filename is stored in the resulting json in the "datafile" key
1231   - // but is not otherwise use. The stream data itself (raw or filtered depending on decode level),
1232   - // is written to the pipeline via pipeStreamData().
1233   - //
1234   - // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must
1235   - // remain valid until after the JSON object is written.
1236   - QPDF_DLL
1237   - JSON getStreamJSON(
1238   - int json_version,
1239   - qpdf_json_stream_data_e json_data,
1240   - qpdf_stream_decode_level_e decode_level,
1241   - Pipeline* p,
1242   - std::string const& data_filename);
1243   -
1244   - // Legacy helper methods for commonly performed operations on pages. Newer code should use
1245   - // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as
1246   - // the identically named methods in that class, but newer functionality will be added there.
1247   - QPDF_DLL
1248   - std::map<std::string, QPDFObjectHandle> getPageImages();
1249   - QPDF_DLL
1250   - std::vector<QPDFObjectHandle> getPageContents();
1251   - QPDF_DLL
1252   - void addPageContents(QPDFObjectHandle contents, bool first);
1253   - QPDF_DLL
1254   - void rotatePage(int angle, bool relative);
1255   - QPDF_DLL
1256   - void coalesceContentStreams();
1257   - // End legacy page helpers
1258   -
1259   - // Issue a warning about this object if possible. If the object has a description, a warning
1260   - // will be issued using the owning QPDF as context. Otherwise, a message will be written to the
1261   - // default logger's error stream, which is standard error if not overridden. Objects read
1262   - // normally from the file have descriptions. See comments on setObjectDescription for additional
1263   - // details.
1264   - QPDF_DLL
1265   - void warnIfPossible(std::string const& warning) const;
1266   -
1267   - // Provide access to specific classes for recursive disconnected().
1268   - class DisconnectAccess
1269   - {
1270   - friend class QPDF_Dictionary;
1271   - friend class QPDF_Stream;
1272   -
1273   - private:
1274   - static void
1275   - disconnect(QPDFObjectHandle o)
1276   - {
1277   - o.disconnect();
1278   - }
1279   - };
1280   -
1281   - // Convenience routine: Throws if the assumption is violated. Your code will be better if you
1282   - // call one of the isType methods and handle the case of the type being wrong, but these can be
1283   - // convenient if you have already verified the type.
1284   - QPDF_DLL
1285   - void assertInitialized() const;
1286   -
1287   - QPDF_DLL
1288   - void assertNull() const;
1289   - QPDF_DLL
1290   - void assertBool() const;
1291   - QPDF_DLL
1292   - void assertInteger() const;
1293   - QPDF_DLL
1294   - void assertReal() const;
1295   - QPDF_DLL
1296   - void assertName() const;
1297   - QPDF_DLL
1298   - void assertString() const;
1299   - QPDF_DLL
1300   - void assertOperator() const;
1301   - QPDF_DLL
1302   - void assertInlineImage() const;
1303   - QPDF_DLL
1304   - void assertArray() const;
1305   - QPDF_DLL
1306   - void assertDictionary() const;
1307   - QPDF_DLL
1308   - void assertStream() const;
1309   - QPDF_DLL
1310   - void assertReserved() const;
1311   -
1312   - QPDF_DLL
1313   - void assertIndirect() const;
1314   - QPDF_DLL
1315   - void assertScalar() const;
1316   - QPDF_DLL
1317   - void assertNumber() const;
1318   -
1319   - // The isPageObject method checks the /Type key of the object. This is not completely reliable
1320   - // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is
1321   - // slightly more accepting but may still return false here when treating the object as a page
1322   - // would work. Use this sparingly.
1323   - QPDF_DLL
1324   - bool isPageObject() const;
1325   - QPDF_DLL
1326   - bool isPagesObject() const;
1327   - QPDF_DLL
1328   - void assertPageObject() const;
1329   -
1330   - QPDF_DLL
1331   - bool isFormXObject() const;
1332   -
1333   - // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as
1334   - // images.
1335   - QPDF_DLL
1336   - bool isImage(bool exclude_imagemask = true) const;
1337   -
1338   - // The following methods do not form part of the public API and are for internal use only.
1339   -
1340   - QPDFObjectHandle(std::shared_ptr<QPDFObject> const& obj) :
1341   - obj(obj)
1342   - {
1343   - }
1344   - std::shared_ptr<QPDFObject>
1345   - getObj()
1346   - {
1347   - return obj;
1348   - }
1349   - std::shared_ptr<QPDFObject>
1350   - getObj() const
1351   - {
1352   - return obj;
1353   - }
1354   - QPDFObject*
1355   - getObjectPtr()
1356   - {
1357   - return obj.get();
1358   - }
1359   - QPDFObject* const
1360   - getObjectPtr() const
1361   - {
1362   - return obj.get();
1363   - }
1364   -
1365   - void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const;
1366   -
1367   - private:
1368   - QPDF_Array* asArray() const;
1369   - QPDF_Bool* asBool() const;
1370   - QPDF_Dictionary* asDictionary() const;
1371   - QPDF_InlineImage* asInlineImage() const;
1372   - QPDF_Integer* asInteger() const;
1373   - QPDF_Name* asName() const;
1374   - QPDF_Null* asNull() const;
1375   - QPDF_Operator* asOperator() const;
1376   - QPDF_Real* asReal() const;
1377   - QPDF_Reserved* asReserved() const;
1378   - QPDF_Stream* asStream() const;
1379   - QPDF_Stream* asStreamWithAssert() const;
1380   - QPDF_String* asString() const;
1381   -
1382   - void typeWarning(char const* expected_type, std::string const& warning) const;
1383   - void objectWarning(std::string const& warning) const;
1384   - void assertType(char const* type_name, bool istype) const;
1385   - void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams);
1386   - void disconnect();
1387   - void setParsedOffset(qpdf_offset_t offset);
1388   - void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks);
1389   - static void parseContentStream_data(
1390   - std::shared_ptr<Buffer>,
1391   - std::string const& description,
1392   - ParserCallbacks* callbacks,
1393   - QPDF* context);
1394   - std::vector<QPDFObjectHandle>
1395   - arrayOrStreamToStreamArray(std::string const& description, std::string& all_description);
1396   - static void warn(QPDF*, QPDFExc const&);
1397   - void checkOwnership(QPDFObjectHandle const&) const;
1398   -
1399   - // Moving members of QPDFObjectHandle into a smart pointer incurs a substantial performance
1400   - // penalty since QPDFObjectHandle objects are copied around so frequently.
1401   - std::shared_ptr<QPDFObject> obj;
1402   -};
1403   -
1404   -#ifndef QPDF_NO_QPDF_STRING
1405   -// This is short for QPDFObjectHandle::parse, so you can do
1406   -
1407   -// auto oh = "<< /Key (value) >>"_qpdf;
1408   -
1409   -// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration
1410   -// from being here.
1411   -
1412   -/* clang-format off */
1413   - // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
1414   - // of the file as a string if clang-format removes the space after "operator", and as of
1415   - // clang-format 15, there's no way to prevent it from doing so.
1416   - QPDF_DLL
1417   - QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
1418   -/* clang-format on */
1419   -
1420   -#endif // QPDF_NO_QPDF_STRING
1421   -
1422   -class QPDFObjectHandle::QPDFDictItems
1423   -{
1424   - // This class allows C++-style iteration, including range-for iteration, around dictionaries.
1425   - // You can write
1426   -
1427   - // for (auto iter: QPDFDictItems(dictionary_obj))
1428   - // {
1429   - // // iter.first is a string
1430   - // // iter.second is a QPDFObjectHandle
1431   - // }
1432   -
1433   - // See examples/pdf-name-number-tree.cc for a demonstration of using this API.
1434   -
1435   - public:
1436   - QPDF_DLL
1437   - QPDFDictItems(QPDFObjectHandle const& oh);
1438   -
1439   - class iterator
1440   - {
1441   - friend class QPDFDictItems;
1442   -
1443   - public:
1444   - typedef std::pair<std::string, QPDFObjectHandle> T;
1445   - using iterator_category = std::bidirectional_iterator_tag;
1446   - using value_type = T;
1447   - using difference_type = long;
1448   - using pointer = T*;
1449   - using reference = T&;
1450   -
1451   - QPDF_DLL
1452   - virtual ~iterator() = default;
1453   - QPDF_DLL
1454   - iterator& operator++();
1455   - QPDF_DLL
1456   - iterator
1457   - operator++(int)
1458   - {
1459   - iterator t = *this;
1460   - ++(*this);
1461   - return t;
1462   - }
1463   - QPDF_DLL
1464   - iterator& operator--();
1465   - QPDF_DLL
1466   - iterator
1467   - operator--(int)
1468   - {
1469   - iterator t = *this;
1470   - --(*this);
1471   - return t;
1472   - }
1473   - QPDF_DLL
1474   - reference operator*();
1475   - QPDF_DLL
1476   - pointer operator->();
1477   - QPDF_DLL
1478   - bool operator==(iterator const& other) const;
1479   - QPDF_DLL
1480   - bool
1481   - operator!=(iterator const& other) const
1482   - {
1483   - return !operator==(other);
1484   - }
1485   -
1486   - private:
1487   - iterator(QPDFObjectHandle& oh, bool for_begin);
1488   - void updateIValue();
1489   -
1490   - class Members
1491   - {
1492   - friend class QPDFDictItems::iterator;
1493   -
1494   - public:
1495   - QPDF_DLL
1496   - ~Members() = default;
1497   -
1498   - private:
1499   - Members(QPDFObjectHandle& oh, bool for_begin);
1500   - Members() = delete;
1501   - Members(Members const&) = delete;
1502   -
1503   - QPDFObjectHandle& oh;
1504   - std::set<std::string> keys;
1505   - std::set<std::string>::iterator iter;
1506   - bool is_end;
1507   - };
1508   - std::shared_ptr<Members> m;
1509   - value_type ivalue;
1510   - };
1511   -
1512   - QPDF_DLL
1513   - iterator begin();
1514   - QPDF_DLL
1515   - iterator end();
1516   -
1517   - private:
1518   - QPDFObjectHandle oh;
1519   -};
1520   -
1521   -class QPDFObjectHandle::QPDFArrayItems
1522   -{
1523   - // This class allows C++-style iteration, including range-for iteration, around arrays. You can
1524   - // write
1525   -
1526   - // for (auto iter: QPDFArrayItems(array_obj))
1527   - // {
1528   - // // iter is a QPDFObjectHandle
1529   - // }
1530   -
1531   - // See examples/pdf-name-number-tree.cc for a demonstration of using this API.
1532   -
1533   - public:
1534   - QPDF_DLL
1535   - QPDFArrayItems(QPDFObjectHandle const& oh);
1536   -
1537   - class iterator
1538   - {
1539   - friend class QPDFArrayItems;
1540   -
1541   - public:
1542   - typedef QPDFObjectHandle T;
1543   - using iterator_category = std::bidirectional_iterator_tag;
1544   - using value_type = T;
1545   - using difference_type = long;
1546   - using pointer = T*;
1547   - using reference = T&;
1548   -
1549   - QPDF_DLL
1550   - virtual ~iterator() = default;
1551   - QPDF_DLL
1552   - iterator& operator++();
1553   - QPDF_DLL
1554   - iterator
1555   - operator++(int)
1556   - {
1557   - iterator t = *this;
1558   - ++(*this);
1559   - return t;
1560   - }
1561   - QPDF_DLL
1562   - iterator& operator--();
1563   - QPDF_DLL
1564   - iterator
1565   - operator--(int)
1566   - {
1567   - iterator t = *this;
1568   - --(*this);
1569   - return t;
1570   - }
1571   - QPDF_DLL
1572   - reference operator*();
1573   - QPDF_DLL
1574   - pointer operator->();
1575   - QPDF_DLL
1576   - bool operator==(iterator const& other) const;
1577   - QPDF_DLL
1578   - bool
1579   - operator!=(iterator const& other) const
1580   - {
1581   - return !operator==(other);
1582   - }
1583   -
1584   - private:
1585   - iterator(QPDFObjectHandle& oh, bool for_begin);
1586   - void updateIValue();
1587   -
1588   - class Members
1589   - {
1590   - friend class QPDFArrayItems::iterator;
1591   -
1592   - public:
1593   - QPDF_DLL
1594   - ~Members() = default;
1595   -
1596   - private:
1597   - Members(QPDFObjectHandle& oh, bool for_begin);
1598   - Members() = delete;
1599   - Members(Members const&) = delete;
1600   -
1601   - QPDFObjectHandle& oh;
1602   - int item_number;
1603   - bool is_end;
1604   - };
1605   - std::shared_ptr<Members> m;
1606   - value_type ivalue;
1607   - };
1608   -
1609   - QPDF_DLL
1610   - iterator begin();
1611   - QPDF_DLL
1612   - iterator end();
1613   -
1614   - private:
1615   - QPDFObjectHandle oh;
1616   -};
1617   -
1618   -inline int
1619   -QPDFObjectHandle::getObjectID() const
1620   -{
1621   - return getObjGen().getObj();
1622   -}
1623   -
1624   -inline int
1625   -QPDFObjectHandle::getGeneration() const
1626   -{
1627   - return getObjGen().getGen();
1628   -}
1629   -
1630   -inline bool
1631   -QPDFObjectHandle::isIndirect() const
1632   -{
1633   - return (obj != nullptr) && (getObjectID() != 0);
1634   -}
1635   -
1636   -inline bool
1637   -QPDFObjectHandle::isInitialized() const noexcept
1638   -{
1639   - return obj != nullptr;
1640   -}
1641   -
1642   -inline QPDFObjectHandle::
1643   -operator bool() const noexcept
1644   -{
1645   - return static_cast<bool>(obj);
1646   -}
1647   -
1648   -#endif // QPDFOBJECTHANDLE_FUTURE_HH
libqpdf/QPDFObjectHandle.cc
... ... @@ -221,19 +221,11 @@ LastChar::getLastChar()
221 221 return this->last_char;
222 222 }
223 223  
224   -#ifndef QPDF_FUTURE
225   -bool
226   -QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const
227   -{
228   - return this->obj == rhs.obj;
229   -}
230   -#else
231 224 bool
232 225 QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const noexcept
233 226 {
234 227 return this->obj == rhs.obj;
235 228 }
236   -#endif
237 229 void
238 230 QPDFObjectHandle::disconnect()
239 231 {
... ... @@ -245,24 +237,14 @@ QPDFObjectHandle::disconnect()
245 237 }
246 238 }
247 239  
248   -#ifndef QPDF_FUTURE
249   -qpdf_object_type_e
250   -QPDFObjectHandle::getTypeCode()
251   -#else
252 240 qpdf_object_type_e
253 241 QPDFObjectHandle::getTypeCode() const
254   -#endif
255 242 {
256 243 return obj ? obj->getResolvedTypeCode() : ::ot_uninitialized;
257 244 }
258 245  
259   -#ifndef QPDF_FUTURE
260   -char const*
261   -QPDFObjectHandle::getTypeName()
262   -#else
263 246 char const*
264 247 QPDFObjectHandle::getTypeName() const
265   -#endif
266 248 {
267 249 static constexpr std::array<char const*, 15> tn{
268 250 "uninitialized",
... ... @@ -363,24 +345,14 @@ QPDFObjectHandle::asString() const
363 345 return obj ? obj->as<QPDF_String>() : nullptr;
364 346 }
365 347  
366   -#ifndef QPDF_FUTURE
367   -bool
368   -QPDFObjectHandle::isDestroyed()
369   -#else
370 348 bool
371 349 QPDFObjectHandle::isDestroyed() const
372   -#endif
373 350 {
374 351 return obj && obj->getResolvedTypeCode() == ::ot_destroyed;
375 352 }
376 353  
377   -#ifndef QPDF_FUTURE
378   -bool
379   -QPDFObjectHandle::isBool()
380   -#else
381 354 bool
382 355 QPDFObjectHandle::isBool() const
383   -#endif
384 356 {
385 357 return obj && obj->getResolvedTypeCode() == ::ot_boolean;
386 358 }
... ... @@ -393,57 +365,32 @@ QPDFObjectHandle::isDirectNull() const
393 365 return (obj && getObjectID() == 0 && obj->getTypeCode() == ::ot_null);
394 366 }
395 367  
396   -#ifndef QPDF_FUTURE
397   -bool
398   -QPDFObjectHandle::isNull()
399   -#else
400 368 bool
401 369 QPDFObjectHandle::isNull() const
402   -#endif
403 370 {
404 371 return obj && obj->getResolvedTypeCode() == ::ot_null;
405 372 }
406 373  
407   -#ifndef QPDF_FUTURE
408   -bool
409   -QPDFObjectHandle::isInteger()
410   -#else
411 374 bool
412 375 QPDFObjectHandle::isInteger() const
413   -#endif
414 376 {
415 377 return obj && obj->getResolvedTypeCode() == ::ot_integer;
416 378 }
417 379  
418   -#ifndef QPDF_FUTURE
419   -bool
420   -QPDFObjectHandle::isReal()
421   -#else
422 380 bool
423 381 QPDFObjectHandle::isReal() const
424   -#endif
425 382 {
426 383 return obj && obj->getResolvedTypeCode() == ::ot_real;
427 384 }
428 385  
429   -#ifndef QPDF_FUTURE
430   -bool
431   -QPDFObjectHandle::isNumber()
432   -#else
433 386 bool
434 387 QPDFObjectHandle::isNumber() const
435   -#endif
436 388 {
437 389 return (isInteger() || isReal());
438 390 }
439 391  
440   -#ifndef QPDF_FUTURE
441   -double
442   -QPDFObjectHandle::getNumericValue()
443   -#else
444 392 double
445 393 QPDFObjectHandle::getNumericValue() const
446   -#endif
447 394 {
448 395 if (isInteger()) {
449 396 return static_cast<double>(getIntValue());
... ... @@ -456,13 +403,8 @@ QPDFObjectHandle::getNumericValue() const
456 403 }
457 404 }
458 405  
459   -#ifndef QPDF_FUTURE
460   -bool
461   -QPDFObjectHandle::getValueAsNumber(double& value)
462   -#else
463 406 bool
464 407 QPDFObjectHandle::getValueAsNumber(double& value) const
465   -#endif
466 408 {
467 409 if (!isNumber()) {
468 410 return false;
... ... @@ -471,148 +413,83 @@ QPDFObjectHandle::getValueAsNumber(double&amp; value) const
471 413 return true;
472 414 }
473 415  
474   -#ifndef QPDF_FUTURE
475   -bool
476   -QPDFObjectHandle::isName()
477   -#else
478 416 bool
479 417 QPDFObjectHandle::isName() const
480   -#endif
481 418 {
482 419 return obj && obj->getResolvedTypeCode() == ::ot_name;
483 420 }
484 421  
485   -#ifndef QPDF_FUTURE
486   -bool
487   -QPDFObjectHandle::isString()
488   -#else
489 422 bool
490 423 QPDFObjectHandle::isString() const
491   -#endif
492 424 {
493 425 return obj && obj->getResolvedTypeCode() == ::ot_string;
494 426 }
495 427  
496   -#ifndef QPDF_FUTURE
497   -bool
498   -QPDFObjectHandle::isOperator()
499   -#else
500 428 bool
501 429 QPDFObjectHandle::isOperator() const
502   -#endif
503 430 {
504 431 return obj && obj->getResolvedTypeCode() == ::ot_operator;
505 432 }
506 433  
507   -#ifndef QPDF_FUTURE
508   -bool
509   -QPDFObjectHandle::isInlineImage()
510   -#else
511 434 bool
512 435 QPDFObjectHandle::isInlineImage() const
513   -#endif
514 436 {
515 437 return obj && obj->getResolvedTypeCode() == ::ot_inlineimage;
516 438 }
517 439  
518   -#ifndef QPDF_FUTURE
519   -bool
520   -QPDFObjectHandle::isArray()
521   -#else
522 440 bool
523 441 QPDFObjectHandle::isArray() const
524   -#endif
525 442 {
526 443 return obj && obj->getResolvedTypeCode() == ::ot_array;
527 444 }
528 445  
529   -#ifndef QPDF_FUTURE
530   -bool
531   -QPDFObjectHandle::isDictionary()
532   -#else
533 446 bool
534 447 QPDFObjectHandle::isDictionary() const
535   -#endif
536 448 {
537 449 return obj && obj->getResolvedTypeCode() == ::ot_dictionary;
538 450 }
539 451  
540   -#ifndef QPDF_FUTURE
541   -bool
542   -QPDFObjectHandle::isStream()
543   -#else
544 452 bool
545 453 QPDFObjectHandle::isStream() const
546   -#endif
547 454 {
548 455 return obj && obj->getResolvedTypeCode() == ::ot_stream;
549 456 }
550 457  
551   -#ifndef QPDF_FUTURE
552   -bool
553   -QPDFObjectHandle::isReserved()
554   -#else
555 458 bool
556 459 QPDFObjectHandle::isReserved() const
557   -#endif
558 460 {
559 461 return obj && obj->getResolvedTypeCode() == ::ot_reserved;
560 462 }
561 463  
562   -#ifndef QPDF_FUTURE
563   -bool
564   -QPDFObjectHandle::isScalar()
565   -#else
566 464 bool
567 465 QPDFObjectHandle::isScalar() const
568   -#endif
569 466 {
570 467 return isBool() || isInteger() || isName() || isNull() || isReal() || isString();
571 468 }
572 469  
573   -#ifndef QPDF_FUTURE
574   -bool
575   -QPDFObjectHandle::isNameAndEquals(std::string const& name)
576   -#else
577 470 bool
578 471 QPDFObjectHandle::isNameAndEquals(std::string const& name) const
579   -#endif
580 472 {
581 473 return isName() && (getName() == name);
582 474 }
583 475  
584   -#ifndef QPDF_FUTURE
585   -bool
586   -QPDFObjectHandle::isDictionaryOfType(std::string const& type, std::string const& subtype)
587   -#else
588 476 bool
589 477 QPDFObjectHandle::isDictionaryOfType(std::string const& type, std::string const& subtype) const
590   -#endif
591 478 {
592 479 return isDictionary() && (type.empty() || getKey("/Type").isNameAndEquals(type)) &&
593 480 (subtype.empty() || getKey("/Subtype").isNameAndEquals(subtype));
594 481 }
595 482  
596   -#ifndef QPDF_FUTURE
597   -bool
598   -QPDFObjectHandle::isStreamOfType(std::string const& type, std::string const& subtype)
599   -#else
600 483 bool
601 484 QPDFObjectHandle::isStreamOfType(std::string const& type, std::string const& subtype) const
602   -#endif
603 485 {
604 486 return isStream() && getDict().isDictionaryOfType(type, subtype);
605 487 }
606 488  
607 489 // Bool accessors
608 490  
609   -#ifndef QPDF_FUTURE
610   -bool
611   -QPDFObjectHandle::getBoolValue()
612   -#else
613 491 bool
614 492 QPDFObjectHandle::getBoolValue() const
615   -#endif
616 493 {
617 494 auto boolean = asBool();
618 495 if (boolean) {
... ... @@ -624,13 +501,8 @@ QPDFObjectHandle::getBoolValue() const
624 501 }
625 502 }
626 503  
627   -#ifndef QPDF_FUTURE
628   -bool
629   -QPDFObjectHandle::getValueAsBool(bool& value)
630   -#else
631 504 bool
632 505 QPDFObjectHandle::getValueAsBool(bool& value) const
633   -#endif
634 506 {
635 507 auto boolean = asBool();
636 508 if (boolean == nullptr) {
... ... @@ -642,13 +514,8 @@ QPDFObjectHandle::getValueAsBool(bool&amp; value) const
642 514  
643 515 // Integer accessors
644 516  
645   -#ifndef QPDF_FUTURE
646   -long long
647   -QPDFObjectHandle::getIntValue()
648   -#else
649 517 long long
650 518 QPDFObjectHandle::getIntValue() const
651   -#endif
652 519 {
653 520 auto integer = asInteger();
654 521 if (integer) {
... ... @@ -660,13 +527,8 @@ QPDFObjectHandle::getIntValue() const
660 527 }
661 528 }
662 529  
663   -#ifndef QPDF_FUTURE
664   -bool
665   -QPDFObjectHandle::getValueAsInt(long long& value)
666   -#else
667 530 bool
668 531 QPDFObjectHandle::getValueAsInt(long long& value) const
669   -#endif
670 532 {
671 533 auto integer = asInteger();
672 534 if (integer == nullptr) {
... ... @@ -676,13 +538,8 @@ QPDFObjectHandle::getValueAsInt(long long&amp; value) const
676 538 return true;
677 539 }
678 540  
679   -#ifndef QPDF_FUTURE
680   -int
681   -QPDFObjectHandle::getIntValueAsInt()
682   -#else
683 541 int
684 542 QPDFObjectHandle::getIntValueAsInt() const
685   -#endif
686 543 {
687 544 int result = 0;
688 545 long long v = getIntValue();
... ... @@ -700,13 +557,8 @@ QPDFObjectHandle::getIntValueAsInt() const
700 557 return result;
701 558 }
702 559  
703   -#ifndef QPDF_FUTURE
704   -bool
705   -QPDFObjectHandle::getValueAsInt(int& value)
706   -#else
707 560 bool
708 561 QPDFObjectHandle::getValueAsInt(int& value) const
709   -#endif
710 562 {
711 563 if (!isInteger()) {
712 564 return false;
... ... @@ -715,13 +567,8 @@ QPDFObjectHandle::getValueAsInt(int&amp; value) const
715 567 return true;
716 568 }
717 569  
718   -#ifndef QPDF_FUTURE
719   -unsigned long long
720   -QPDFObjectHandle::getUIntValue()
721   -#else
722 570 unsigned long long
723 571 QPDFObjectHandle::getUIntValue() const
724   -#endif
725 572 {
726 573 long long v = getIntValue();
727 574 if (v < 0) {
... ... @@ -733,13 +580,8 @@ QPDFObjectHandle::getUIntValue() const
733 580 }
734 581 }
735 582  
736   -#ifndef QPDF_FUTURE
737   -bool
738   -QPDFObjectHandle::getValueAsUInt(unsigned long long& value)
739   -#else
740 583 bool
741 584 QPDFObjectHandle::getValueAsUInt(unsigned long long& value) const
742   -#endif
743 585 {
744 586 if (!isInteger()) {
745 587 return false;
... ... @@ -748,13 +590,8 @@ QPDFObjectHandle::getValueAsUInt(unsigned long long&amp; value) const
748 590 return true;
749 591 }
750 592  
751   -#ifndef QPDF_FUTURE
752   -unsigned int
753   -QPDFObjectHandle::getUIntValueAsUInt()
754   -#else
755 593 unsigned int
756 594 QPDFObjectHandle::getUIntValueAsUInt() const
757   -#endif
758 595 {
759 596 long long v = getIntValue();
760 597 if (v < 0) {
... ... @@ -770,13 +607,8 @@ QPDFObjectHandle::getUIntValueAsUInt() const
770 607 }
771 608 }
772 609  
773   -#ifndef QPDF_FUTURE
774   -bool
775   -QPDFObjectHandle::getValueAsUInt(unsigned int& value)
776   -#else
777 610 bool
778 611 QPDFObjectHandle::getValueAsUInt(unsigned int& value) const
779   -#endif
780 612 {
781 613 if (!isInteger()) {
782 614 return false;
... ... @@ -787,13 +619,8 @@ QPDFObjectHandle::getValueAsUInt(unsigned int&amp; value) const
787 619  
788 620 // Real accessors
789 621  
790   -#ifndef QPDF_FUTURE
791   -std::string
792   -QPDFObjectHandle::getRealValue()
793   -#else
794 622 std::string
795 623 QPDFObjectHandle::getRealValue() const
796   -#endif
797 624 {
798 625 if (isReal()) {
799 626 return obj->getStringValue();
... ... @@ -804,13 +631,8 @@ QPDFObjectHandle::getRealValue() const
804 631 }
805 632 }
806 633  
807   -#ifndef QPDF_FUTURE
808   -bool
809   -QPDFObjectHandle::getValueAsReal(std::string& value)
810   -#else
811 634 bool
812 635 QPDFObjectHandle::getValueAsReal(std::string& value) const
813   -#endif
814 636 {
815 637 if (!isReal()) {
816 638 return false;
... ... @@ -821,13 +643,8 @@ QPDFObjectHandle::getValueAsReal(std::string&amp; value) const
821 643  
822 644 // Name accessors
823 645  
824   -#ifndef QPDF_FUTURE
825   -std::string
826   -QPDFObjectHandle::getName()
827   -#else
828 646 std::string
829 647 QPDFObjectHandle::getName() const
830   -#endif
831 648 {
832 649 if (isName()) {
833 650 return obj->getStringValue();
... ... @@ -838,13 +655,8 @@ QPDFObjectHandle::getName() const
838 655 }
839 656 }
840 657  
841   -#ifndef QPDF_FUTURE
842   -bool
843   -QPDFObjectHandle::getValueAsName(std::string& value)
844   -#else
845 658 bool
846 659 QPDFObjectHandle::getValueAsName(std::string& value) const
847   -#endif
848 660 {
849 661 if (!isName()) {
850 662 return false;
... ... @@ -855,13 +667,8 @@ QPDFObjectHandle::getValueAsName(std::string&amp; value) const
855 667  
856 668 // String accessors
857 669  
858   -#ifndef QPDF_FUTURE
859   -std::string
860   -QPDFObjectHandle::getStringValue()
861   -#else
862 670 std::string
863 671 QPDFObjectHandle::getStringValue() const
864   -#endif
865 672 {
866 673 if (isString()) {
867 674 return obj->getStringValue();
... ... @@ -872,13 +679,8 @@ QPDFObjectHandle::getStringValue() const
872 679 }
873 680 }
874 681  
875   -#ifndef QPDF_FUTURE
876   -bool
877   -QPDFObjectHandle::getValueAsString(std::string& value)
878   -#else
879 682 bool
880 683 QPDFObjectHandle::getValueAsString(std::string& value) const
881   -#endif
882 684 {
883 685 if (!isString()) {
884 686 return false;
... ... @@ -887,13 +689,8 @@ QPDFObjectHandle::getValueAsString(std::string&amp; value) const
887 689 return true;
888 690 }
889 691  
890   -#ifndef QPDF_FUTURE
891   -std::string
892   -QPDFObjectHandle::getUTF8Value()
893   -#else
894 692 std::string
895 693 QPDFObjectHandle::getUTF8Value() const
896   -#endif
897 694 {
898 695 auto str = asString();
899 696 if (str) {
... ... @@ -905,13 +702,8 @@ QPDFObjectHandle::getUTF8Value() const
905 702 }
906 703 }
907 704  
908   -#ifndef QPDF_FUTURE
909   -bool
910   -QPDFObjectHandle::getValueAsUTF8(std::string& value)
911   -#else
912 705 bool
913 706 QPDFObjectHandle::getValueAsUTF8(std::string& value) const
914   -#endif
915 707 {
916 708 auto str = asString();
917 709 if (str == nullptr) {
... ... @@ -923,13 +715,8 @@ QPDFObjectHandle::getValueAsUTF8(std::string&amp; value) const
923 715  
924 716 // Operator and Inline Image accessors
925 717  
926   -#ifndef QPDF_FUTURE
927   -std::string
928   -QPDFObjectHandle::getOperatorValue()
929   -#else
930 718 std::string
931 719 QPDFObjectHandle::getOperatorValue() const
932   -#endif
933 720 {
934 721 if (isOperator()) {
935 722 return obj->getStringValue();
... ... @@ -940,13 +727,8 @@ QPDFObjectHandle::getOperatorValue() const
940 727 }
941 728 }
942 729  
943   -#ifndef QPDF_FUTURE
944   -bool
945   -QPDFObjectHandle::getValueAsOperator(std::string& value)
946   -#else
947 730 bool
948 731 QPDFObjectHandle::getValueAsOperator(std::string& value) const
949   -#endif
950 732 {
951 733 if (!isOperator()) {
952 734 return false;
... ... @@ -955,13 +737,8 @@ QPDFObjectHandle::getValueAsOperator(std::string&amp; value) const
955 737 return true;
956 738 }
957 739  
958   -#ifndef QPDF_FUTURE
959   -std::string
960   -QPDFObjectHandle::getInlineImageValue()
961   -#else
962 740 std::string
963 741 QPDFObjectHandle::getInlineImageValue() const
964   -#endif
965 742 {
966 743 if (isInlineImage()) {
967 744 return obj->getStringValue();
... ... @@ -972,13 +749,8 @@ QPDFObjectHandle::getInlineImageValue() const
972 749 }
973 750 }
974 751  
975   -#ifndef QPDF_FUTURE
976   -bool
977   -QPDFObjectHandle::getValueAsInlineImage(std::string& value)
978   -#else
979 752 bool
980 753 QPDFObjectHandle::getValueAsInlineImage(std::string& value) const
981   -#endif
982 754 {
983 755 if (!isInlineImage()) {
984 756 return false;
... ... @@ -995,13 +767,8 @@ QPDFObjectHandle::aitems()
995 767 return *this;
996 768 }
997 769  
998   -#ifndef QPDF_FUTURE
999   -int
1000   -QPDFObjectHandle::getArrayNItems()
1001   -#else
1002 770 int
1003 771 QPDFObjectHandle::getArrayNItems() const
1004   -#endif
1005 772 {
1006 773 if (auto array = asArray()) {
1007 774 return array->size();
... ... @@ -1012,13 +779,8 @@ QPDFObjectHandle::getArrayNItems() const
1012 779 }
1013 780 }
1014 781  
1015   -#ifndef QPDF_FUTURE
1016   -QPDFObjectHandle
1017   -QPDFObjectHandle::getArrayItem(int n)
1018   -#else
1019 782 QPDFObjectHandle
1020 783 QPDFObjectHandle::getArrayItem(int n) const
1021   -#endif
1022 784 {
1023 785 if (auto array = asArray()) {
1024 786 auto result = array->at(n);
... ... @@ -1036,13 +798,8 @@ QPDFObjectHandle::getArrayItem(int n) const
1036 798 return QPDF_Null::create(obj, msg, "");
1037 799 }
1038 800  
1039   -#ifndef QPDF_FUTURE
1040   -bool
1041   -QPDFObjectHandle::isRectangle()
1042   -#else
1043 801 bool
1044 802 QPDFObjectHandle::isRectangle() const
1045   -#endif
1046 803 {
1047 804 if (auto array = asArray()) {
1048 805 for (int i = 0; i < 4; ++i) {
... ... @@ -1055,13 +812,8 @@ QPDFObjectHandle::isRectangle() const
1055 812 return false;
1056 813 }
1057 814  
1058   -#ifndef QPDF_FUTURE
1059   -bool
1060   -QPDFObjectHandle::isMatrix()
1061   -#else
1062 815 bool
1063 816 QPDFObjectHandle::isMatrix() const
1064   -#endif
1065 817 {
1066 818 if (auto array = asArray()) {
1067 819 for (int i = 0; i < 6; ++i) {
... ... @@ -1074,13 +826,8 @@ QPDFObjectHandle::isMatrix() const
1074 826 return false;
1075 827 }
1076 828  
1077   -#ifndef QPDF_FUTURE
1078   -QPDFObjectHandle::Rectangle
1079   -QPDFObjectHandle::getArrayAsRectangle()
1080   -#else
1081 829 QPDFObjectHandle::Rectangle
1082 830 QPDFObjectHandle::getArrayAsRectangle() const
1083   -#endif
1084 831 {
1085 832 if (auto array = asArray()) {
1086 833 if (array->size() != 4) {
... ... @@ -1101,13 +848,8 @@ QPDFObjectHandle::getArrayAsRectangle() const
1101 848 return {};
1102 849 }
1103 850  
1104   -#ifndef QPDF_FUTURE
1105   -QPDFObjectHandle::Matrix
1106   -QPDFObjectHandle::getArrayAsMatrix()
1107   -#else
1108 851 QPDFObjectHandle::Matrix
1109 852 QPDFObjectHandle::getArrayAsMatrix() const
1110   -#endif
1111 853 {
1112 854 if (auto array = asArray()) {
1113 855 if (array->size() != 6) {
... ... @@ -1124,13 +866,8 @@ QPDFObjectHandle::getArrayAsMatrix() const
1124 866 return {};
1125 867 }
1126 868  
1127   -#ifndef QPDF_FUTURE
1128   -std::vector<QPDFObjectHandle>
1129   -QPDFObjectHandle::getArrayAsVector()
1130   -#else
1131 869 std::vector<QPDFObjectHandle>
1132 870 QPDFObjectHandle::getArrayAsVector() const
1133   -#endif
1134 871 {
1135 872 auto array = asArray();
1136 873 if (array) {
... ... @@ -1238,13 +975,8 @@ QPDFObjectHandle::ditems()
1238 975 return {*this};
1239 976 }
1240 977  
1241   -#ifndef QPDF_FUTURE
1242   -bool
1243   -QPDFObjectHandle::hasKey(std::string const& key)
1244   -#else
1245 978 bool
1246 979 QPDFObjectHandle::hasKey(std::string const& key) const
1247   -#endif
1248 980 {
1249 981 auto dict = asDictionary();
1250 982 if (dict) {
... ... @@ -1256,13 +988,8 @@ QPDFObjectHandle::hasKey(std::string const&amp; key) const
1256 988 }
1257 989 }
1258 990  
1259   -#ifndef QPDF_FUTURE
1260   -QPDFObjectHandle
1261   -QPDFObjectHandle::getKey(std::string const& key)
1262   -#else
1263 991 QPDFObjectHandle
1264 992 QPDFObjectHandle::getKey(std::string const& key) const
1265   -#endif
1266 993 {
1267 994 if (auto dict = asDictionary()) {
1268 995 return dict->getKey(key);
... ... @@ -1274,24 +1001,14 @@ QPDFObjectHandle::getKey(std::string const&amp; key) const
1274 1001 }
1275 1002 }
1276 1003  
1277   -#ifndef QPDF_FUTURE
1278   -QPDFObjectHandle
1279   -QPDFObjectHandle::getKeyIfDict(std::string const& key)
1280   -#else
1281 1004 QPDFObjectHandle
1282 1005 QPDFObjectHandle::getKeyIfDict(std::string const& key) const
1283   -#endif
1284 1006 {
1285 1007 return isNull() ? newNull() : getKey(key);
1286 1008 }
1287 1009  
1288   -#ifndef QPDF_FUTURE
1289   -std::set<std::string>
1290   -QPDFObjectHandle::getKeys()
1291   -#else
1292 1010 std::set<std::string>
1293 1011 QPDFObjectHandle::getKeys() const
1294   -#endif
1295 1012 {
1296 1013 std::set<std::string> result;
1297 1014 auto dict = asDictionary();
... ... @@ -1304,13 +1021,8 @@ QPDFObjectHandle::getKeys() const
1304 1021 return result;
1305 1022 }
1306 1023  
1307   -#ifndef QPDF_FUTURE
1308   -std::map<std::string, QPDFObjectHandle>
1309   -QPDFObjectHandle::getDictAsMap()
1310   -#else
1311 1024 std::map<std::string, QPDFObjectHandle>
1312 1025 QPDFObjectHandle::getDictAsMap() const
1313   -#endif
1314 1026 {
1315 1027 std::map<std::string, QPDFObjectHandle> result;
1316 1028 auto dict = asDictionary();
... ... @@ -1324,13 +1036,9 @@ QPDFObjectHandle::getDictAsMap() const
1324 1036 }
1325 1037  
1326 1038 // Array and Name accessors
1327   -#ifndef QPDF_FUTURE
1328   -bool
1329   -QPDFObjectHandle::isOrHasName(std::string const& value)
1330   -#else
  1039 +
1331 1040 bool
1332 1041 QPDFObjectHandle::isOrHasName(std::string const& value) const
1333   -#endif
1334 1042 {
1335 1043 if (isNameAndEquals(value)) {
1336 1044 return true;
... ... @@ -1458,13 +1166,8 @@ QPDFObjectHandle::mergeResources(
1458 1166 }
1459 1167 }
1460 1168  
1461   -#ifndef QPDF_FUTURE
1462   -std::set<std::string>
1463   -QPDFObjectHandle::getResourceNames()
1464   -#else
1465 1169 std::set<std::string>
1466 1170 QPDFObjectHandle::getResourceNames() const
1467   -#endif
1468 1171 {
1469 1172 // Return second-level dictionary keys
1470 1173 std::set<std::string> result;
... ... @@ -1482,16 +1185,9 @@ QPDFObjectHandle::getResourceNames() const
1482 1185 return result;
1483 1186 }
1484 1187  
1485   -#ifndef QPDF_FUTURE
1486   -std::string
1487   -QPDFObjectHandle::getUniqueResourceName(
1488   - std::string const& prefix, int& min_suffix, std::set<std::string>* namesp)
1489   -#else
1490 1188 std::string
1491 1189 QPDFObjectHandle::getUniqueResourceName(
1492 1190 std::string const& prefix, int& min_suffix, std::set<std::string>* namesp) const
1493   -#endif
1494   -
1495 1191 {
1496 1192 std::set<std::string> names = (namesp ? *namesp : getResourceNames());
1497 1193 int max_suffix = min_suffix + QIntC::to_int(names.size());
... ... @@ -1573,13 +1269,9 @@ QPDFObjectHandle::replaceOrRemoveKey(std::string const&amp; key, QPDFObjectHandle co
1573 1269 }
1574 1270  
1575 1271 // Stream accessors
1576   -#ifndef QPDF_FUTURE
1577   -QPDFObjectHandle
1578   -QPDFObjectHandle::getDict()
1579   -#else
  1272 +
1580 1273 QPDFObjectHandle
1581 1274 QPDFObjectHandle::getDict() const
1582   -#endif
1583 1275 {
1584 1276 return asStreamWithAssert()->getDict();
1585 1277 }
... ... @@ -1894,13 +1586,8 @@ QPDFObjectHandle::coalesceContentStreams()
1894 1586 new_contents.replaceStreamData(provider, newNull(), newNull());
1895 1587 }
1896 1588  
1897   -#ifndef QPDF_FUTURE
1898   -std::string
1899   -QPDFObjectHandle::unparse()
1900   -#else
1901 1589 std::string
1902 1590 QPDFObjectHandle::unparse() const
1903   -#endif
1904 1591 {
1905 1592 if (this->isIndirect()) {
1906 1593 return getObjGen().unparse(' ') + " R";
... ... @@ -1909,13 +1596,8 @@ QPDFObjectHandle::unparse() const
1909 1596 }
1910 1597 }
1911 1598  
1912   -#ifndef QPDF_FUTURE
1913   -std::string
1914   -QPDFObjectHandle::unparseResolved()
1915   -#else
1916 1599 std::string
1917 1600 QPDFObjectHandle::unparseResolved() const
1918   -#endif
1919 1601 {
1920 1602 if (!obj) {
1921 1603 throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle");
... ... @@ -1923,13 +1605,8 @@ QPDFObjectHandle::unparseResolved() const
1923 1605 return obj->unparse();
1924 1606 }
1925 1607  
1926   -#ifndef QPDF_FUTURE
1927   -std::string
1928   -QPDFObjectHandle::unparseBinary()
1929   -#else
1930 1608 std::string
1931 1609 QPDFObjectHandle::unparseBinary() const
1932   -#endif
1933 1610 {
1934 1611 if (auto str = asString()) {
1935 1612 return str->unparse(true);
... ... @@ -1939,24 +1616,14 @@ QPDFObjectHandle::unparseBinary() const
1939 1616 }
1940 1617  
1941 1618 // Deprecated versionless getJSON to be removed in qpdf 12
1942   -#ifndef QPDF_FUTURE
1943   -JSON
1944   -QPDFObjectHandle::getJSON(bool dereference_indirect)
1945   -#else
1946 1619 JSON
1947 1620 QPDFObjectHandle::getJSON(bool dereference_indirect) const
1948   -#endif
1949 1621 {
1950 1622 return getJSON(1, dereference_indirect);
1951 1623 }
1952 1624  
1953   -#ifndef QPDF_FUTURE
1954   -JSON
1955   -QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
1956   -#else
1957 1625 JSON
1958 1626 QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) const
1959   -#endif
1960 1627 {
1961 1628 if ((!dereference_indirect) && isIndirect()) {
1962 1629 return JSON::makeString(unparse());
... ... @@ -1971,13 +1638,8 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) const
1971 1638 }
1972 1639 }
1973 1640  
1974   -#ifndef QPDF_FUTURE
1975   -void
1976   -QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect)
1977   -#else
1978 1641 void
1979 1642 QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect) const
1980   -#endif
1981 1643 {
1982 1644 if (!dereference_indirect && isIndirect()) {
1983 1645 p << "\"" << getObjGen().unparse(' ') << " R\"";
... ... @@ -1988,14 +1650,9 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer&amp; p, bool dereference_
1988 1650 }
1989 1651 }
1990 1652  
1991   -#ifndef QPDF_FUTURE
1992   -void
1993   -QPDFObjectHandle::writeJSON(int json_version, Pipeline* p, bool dereference_indirect, size_t depth)
1994   -#else
1995 1653 void
1996 1654 QPDFObjectHandle::writeJSON(
1997 1655 int json_version, Pipeline* p, bool dereference_indirect, size_t depth) const
1998   -#endif
1999 1656 {
2000 1657 JSON::Writer jw{p, depth};
2001 1658 writeJSON(json_version, jw, dereference_indirect);
... ... @@ -2229,13 +1886,8 @@ QPDFObjectHandle::parse(
2229 1886 .parse(empty, false);
2230 1887 }
2231 1888  
2232   -#ifndef QPDF_FUTURE
2233   -qpdf_offset_t
2234   -QPDFObjectHandle::getParsedOffset()
2235   -#else
2236 1889 qpdf_offset_t
2237 1890 QPDFObjectHandle::getParsedOffset() const
2238   -#endif
2239 1891 {
2240 1892 return obj ? obj->getParsedOffset() : -1;
2241 1893 }
... ... @@ -2420,13 +2072,8 @@ QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const&amp; obj
2420 2072 }
2421 2073 }
2422 2074  
2423   -#ifndef QPDF_FUTURE
2424   -bool
2425   -QPDFObjectHandle::hasObjectDescription()
2426   -#else
2427 2075 bool
2428 2076 QPDFObjectHandle::hasObjectDescription() const
2429   -#endif
2430 2077 {
2431 2078 return obj && obj->hasDescription();
2432 2079 }
... ... @@ -2550,13 +2197,8 @@ QPDFObjectHandle::typeWarning(char const* expected_type, std::string const&amp; warn
2550 2197 QPDFObjectHandle(*this).getTypeName() + ": " + warning));
2551 2198 }
2552 2199  
2553   -#ifndef QPDF_FUTURE
2554   -void
2555   -QPDFObjectHandle::warnIfPossible(std::string const& warning)
2556   -#else
2557 2200 void
2558 2201 QPDFObjectHandle::warnIfPossible(std::string const& warning) const
2559   -#endif
2560 2202 {
2561 2203 QPDF* context = nullptr;
2562 2204 std::string description;
... ... @@ -2588,180 +2230,100 @@ QPDFObjectHandle::assertType(char const* type_name, bool istype) const
2588 2230 }
2589 2231 }
2590 2232  
2591   -#ifndef QPDF_FUTURE
2592   -void
2593   -QPDFObjectHandle::assertNull()
2594   -#else
2595 2233 void
2596 2234 QPDFObjectHandle::assertNull() const
2597   -#endif
2598 2235 {
2599 2236 assertType("null", isNull());
2600 2237 }
2601 2238  
2602   -#ifndef QPDF_FUTURE
2603   -void
2604   -QPDFObjectHandle::assertBool()
2605   -#else
2606 2239 void
2607 2240 QPDFObjectHandle::assertBool() const
2608   -#endif
2609 2241 {
2610 2242 assertType("boolean", isBool());
2611 2243 }
2612 2244  
2613   -#ifndef QPDF_FUTURE
2614   -void
2615   -QPDFObjectHandle::assertInteger()
2616   -#else
2617 2245 void
2618 2246 QPDFObjectHandle::assertInteger() const
2619   -#endif
2620 2247 {
2621 2248 assertType("integer", isInteger());
2622 2249 }
2623 2250  
2624   -#ifndef QPDF_FUTURE
2625   -void
2626   -QPDFObjectHandle::assertReal()
2627   -#else
2628 2251 void
2629 2252 QPDFObjectHandle::assertReal() const
2630   -#endif
2631 2253 {
2632 2254 assertType("real", isReal());
2633 2255 }
2634 2256  
2635   -#ifndef QPDF_FUTURE
2636   -void
2637   -QPDFObjectHandle::assertName()
2638   -#else
2639 2257 void
2640 2258 QPDFObjectHandle::assertName() const
2641   -#endif
2642 2259 {
2643 2260 assertType("name", isName());
2644 2261 }
2645 2262  
2646   -#ifndef QPDF_FUTURE
2647   -void
2648   -QPDFObjectHandle::assertString()
2649   -#else
2650 2263 void
2651 2264 QPDFObjectHandle::assertString() const
2652   -#endif
2653 2265 {
2654 2266 assertType("string", isString());
2655 2267 }
2656 2268  
2657   -#ifndef QPDF_FUTURE
2658   -void
2659   -QPDFObjectHandle::assertOperator()
2660   -#else
2661 2269 void
2662 2270 QPDFObjectHandle::assertOperator() const
2663   -#endif
2664 2271 {
2665 2272 assertType("operator", isOperator());
2666 2273 }
2667 2274  
2668   -#ifndef QPDF_FUTURE
2669   -void
2670   -QPDFObjectHandle::assertInlineImage()
2671   -#else
2672 2275 void
2673 2276 QPDFObjectHandle::assertInlineImage() const
2674   -#endif
2675 2277 {
2676 2278 assertType("inlineimage", isInlineImage());
2677 2279 }
2678 2280  
2679   -#ifndef QPDF_FUTURE
2680   -void
2681   -QPDFObjectHandle::assertArray()
2682   -#else
2683 2281 void
2684 2282 QPDFObjectHandle::assertArray() const
2685   -#endif
2686 2283 {
2687 2284 assertType("array", isArray());
2688 2285 }
2689 2286  
2690   -#ifndef QPDF_FUTURE
2691   -void
2692   -QPDFObjectHandle::assertDictionary()
2693   -#else
2694 2287 void
2695 2288 QPDFObjectHandle::assertDictionary() const
2696   -#endif
2697 2289 {
2698 2290 assertType("dictionary", isDictionary());
2699 2291 }
2700 2292  
2701   -#ifndef QPDF_FUTURE
2702   -void
2703   -QPDFObjectHandle::assertStream()
2704   -#else
2705 2293 void
2706 2294 QPDFObjectHandle::assertStream() const
2707   -#endif
2708 2295 {
2709 2296 assertType("stream", isStream());
2710 2297 }
2711 2298  
2712   -#ifndef QPDF_FUTURE
2713   -void
2714   -QPDFObjectHandle::assertReserved()
2715   -#else
2716 2299 void
2717 2300 QPDFObjectHandle::assertReserved() const
2718   -#endif
2719 2301 {
2720 2302 assertType("reserved", isReserved());
2721 2303 }
2722 2304  
2723   -#ifndef QPDF_FUTURE
2724   -void
2725   -QPDFObjectHandle::assertIndirect()
2726   -#else
2727 2305 void
2728 2306 QPDFObjectHandle::assertIndirect() const
2729   -#endif
2730 2307 {
2731 2308 if (!isIndirect()) {
2732 2309 throw std::logic_error("operation for indirect object attempted on direct object");
2733 2310 }
2734 2311 }
2735 2312  
2736   -#ifndef QPDF_FUTURE
2737   -void
2738   -QPDFObjectHandle::assertScalar()
2739   -#else
2740 2313 void
2741 2314 QPDFObjectHandle::assertScalar() const
2742   -#endif
2743 2315 {
2744 2316 assertType("scalar", isScalar());
2745 2317 }
2746 2318  
2747   -#ifndef QPDF_FUTURE
2748   -void
2749   -QPDFObjectHandle::assertNumber()
2750   -#else
2751 2319 void
2752 2320 QPDFObjectHandle::assertNumber() const
2753   -#endif
2754 2321 {
2755 2322 assertType("number", isNumber());
2756 2323 }
2757 2324  
2758   -#ifndef QPDF_FUTURE
2759   -bool
2760   -QPDFObjectHandle::isPageObject()
2761   -#else
2762 2325 bool
2763 2326 QPDFObjectHandle::isPageObject() const
2764   -#endif
2765 2327 {
2766 2328 // See comments in QPDFObjectHandle.hh.
2767 2329 if (getOwningQPDF() == nullptr) {
... ... @@ -2772,13 +2334,8 @@ QPDFObjectHandle::isPageObject() const
2772 2334 return isDictionaryOfType("/Page");
2773 2335 }
2774 2336  
2775   -#ifndef QPDF_FUTURE
2776   -bool
2777   -QPDFObjectHandle::isPagesObject()
2778   -#else
2779 2337 bool
2780 2338 QPDFObjectHandle::isPagesObject() const
2781   -#endif
2782 2339 {
2783 2340 if (getOwningQPDF() == nullptr) {
2784 2341 return false;
... ... @@ -2788,24 +2345,14 @@ QPDFObjectHandle::isPagesObject() const
2788 2345 return isDictionaryOfType("/Pages");
2789 2346 }
2790 2347  
2791   -#ifndef QPDF_FUTURE
2792   -bool
2793   -QPDFObjectHandle::isFormXObject()
2794   -#else
2795 2348 bool
2796 2349 QPDFObjectHandle::isFormXObject() const
2797   -#endif
2798 2350 {
2799 2351 return isStreamOfType("", "/Form");
2800 2352 }
2801 2353  
2802   -#ifndef QPDF_FUTURE
2803   -bool
2804   -QPDFObjectHandle::isImage(bool exclude_imagemask)
2805   -#else
2806 2354 bool
2807 2355 QPDFObjectHandle::isImage(bool exclude_imagemask) const
2808   -#endif
2809 2356 {
2810 2357 return (
2811 2358 isStreamOfType("", "/Image") &&
... ... @@ -2827,13 +2374,8 @@ QPDFObjectHandle::checkOwnership(QPDFObjectHandle const&amp; item) const
2827 2374 }
2828 2375 }
2829 2376  
2830   -#ifndef QPDF_FUTURE
2831   -void
2832   -QPDFObjectHandle::assertPageObject()
2833   -#else
2834 2377 void
2835 2378 QPDFObjectHandle::assertPageObject() const
2836   -#endif
2837 2379 {
2838 2380 if (!isPageObject()) {
2839 2381 throw std::runtime_error("page operation called on non-Page object");
... ...
manual/release-notes.rst
... ... @@ -6,17 +6,8 @@ Release Notes
6 6 For a detailed list of changes, please see the file
7 7 :file:`ChangeLog` in the source distribution.
8 8  
9   -If you are a developer and want to test your code against future API
10   -changes that are under consideration, you can build qpdf locally and
11   -enable the ``FUTURE`` build option (see :ref:`build-options`).
12 9  
13 10 Planned changes for future 12.x (subject to change):
14   - - ``QPDFObjectHandle`` will support move construction/assignment.
15   - This change will be invisible to most developers but may break
16   - your code if you rely on specific behavior around how many
17   - references to a QPDFObjectHandle's underlying object exist. You
18   - would have to write code specifically to do that, so if you're not
19   - sure, then you shouldn't have to worry.
20 11  
21 12 - ``Buffer`` copy constructor and assignment operator will be
22 13 removed. ``Buffer`` copy operations are expensive as they always
... ... @@ -30,6 +21,17 @@ Planned changes for future 12.x (subject to change):
30 21 .. x.y.z: not yet released
31 22  
32 23 12.0.0: not yet released
  24 + - Library Enhancements
  25 +
  26 + - ``QPDFObjectHandle`` supports move construction/assignment.
  27 + This change is invisible to most developers but may break
  28 + your code if you rely on specific behavior around how many
  29 + references to a QPDFObjectHandle's underlying object exist. You
  30 + would have to write code specifically to do that, so if you're not
  31 + sure, then you shouldn't have to worry.
  32 +
  33 + - Most ``QPDFObjectHandle`` accessor methods are now const qualified.
  34 +
33 35 - Build Changes
34 36  
35 37 - If ``POINTERHOLDER_TRANSITION`` is not defined, define it to
... ...