Commit eb481eb698947d88be0724e84f518a70a0468cc9
1 parent
c95f0211
Prepare release notes for 10.6 (so far)
Showing
8 changed files
with
424 additions
and
17 deletions
ChangeLog
| ... | ... | @@ -68,7 +68,7 @@ |
| 68 | 68 | object. |
| 69 | 69 | |
| 70 | 70 | * A light C API around basic QPDFJob functionality is in |
| 71 | - include/qpdf/qpdf-job-c.h.p | |
| 71 | + include/qpdf/qpdfjob-c.h.p | |
| 72 | 72 | |
| 73 | 73 | * Add new functions version of QUtil::call_main_from_wmain that |
| 74 | 74 | takes a constant argv array. |
| ... | ... | @@ -79,10 +79,10 @@ |
| 79 | 79 | description to --help and the manual. |
| 80 | 80 | |
| 81 | 81 | * The --json flag now takes a version number as an optional |
| 82 | - parameter. The default will remain version 1 for compatibility. | |
| 83 | - This enables future code to use --json=latest to always get the | |
| 84 | - latest version or to use a specific version. At this time, there's | |
| 85 | - only version 1, but a version 2 may appear in a future qpdf. | |
| 82 | + parameter. The default will remain version 1 for compatibility | |
| 83 | + until the release of qpdf 11, after which it will become "latest". | |
| 84 | + At this time, there's only version 1, but a version 2 may appear | |
| 85 | + in a future qpdf. | |
| 86 | 86 | |
| 87 | 87 | 2022-01-28 Jay Berkenbilt <ejb@ql.org> |
| 88 | 88 | ... | ... |
TODO
| ... | ... | @@ -9,15 +9,6 @@ |
| 9 | 9 | make qpdf more contributor-friendly. Look |
| 10 | 10 | https://bestpractices.coreinfrastructure.org/en |
| 11 | 11 | |
| 12 | -* Remember for release notes: starting in qpdf 11, the default value | |
| 13 | - for the --json keyword will be "latest". If you are depending on | |
| 14 | - version 1, change your code to specify --json=1, which works | |
| 15 | - starting with 10.6.0. | |
| 16 | - | |
| 17 | -* Write up something about preparing for the PointerHolder to | |
| 18 | - shared_ptr migration. Clearly document the deprecations and how to | |
| 19 | - deal with them. | |
| 20 | - | |
| 21 | 12 | Output JSON v2 |
| 22 | 13 | ============== |
| 23 | 14 | |
| ... | ... | @@ -332,6 +323,9 @@ Other notes: |
| 332 | 323 | PointerHolder to std::shared_ptr |
| 333 | 324 | ================================ |
| 334 | 325 | |
| 326 | +Remember to update the smart-pointers section of the manual in | |
| 327 | +design.rst. | |
| 328 | + | |
| 335 | 329 | Once all deprecation warnings are cleared up (changing getPointer() to |
| 336 | 330 | get() and getRefcount() to use_count()), the only real issues are that |
| 337 | 331 | implicit assignment of a pointer to a shared_ptr doesn't work while it | ... | ... |
cSpell.json
job.sums
| ... | ... | @@ -14,4 +14,4 @@ libqpdf/qpdf/auto_job_json_decl.hh c5e3fd38a3b0c569eb0c6b4c60953a09cd6bc7d3361a3 |
| 14 | 14 | libqpdf/qpdf/auto_job_json_init.hh b070350d304d137ba594c1ba40b373137e8459735f04b8ca0f8a2ffd1908c69e |
| 15 | 15 | libqpdf/qpdf/auto_job_schema.hh 18a3780671d95224cb9a27dcac627c421cae509d59f33a63e6bda0ab53cce923 |
| 16 | 16 | manual/_ext/qpdf.py e9ac9d6c70642a3d29281ee5ad92ae2422dee8be9306fb8a0bc9dba0ed5e28f3 |
| 17 | -manual/cli.rst 3746df6c4f115387cca0d921f25619a6b8407fc10b0e4c9dcf40b0b1656c6f8a | |
| 17 | +manual/cli.rst 2dd5e5a9c0440aea65ed0a2bf6239aa6662afdb463224aafdc116a8a676dbc20 | ... | ... |
manual/cli.rst
| ... | ... | @@ -3154,7 +3154,10 @@ Related Options |
| 3154 | 3154 | supported value is ``1``, but it's possible that a new JSON output |
| 3155 | 3155 | version will be added in a future version. You can also specify |
| 3156 | 3156 | ``latest`` to use the latest JSON version. For backward |
| 3157 | - compatibility, the default value is ``1``. Use the | |
| 3157 | + compatibility, the default value will remain ``1`` until qpdf | |
| 3158 | + version 11, after which point it will become ``latest``. In all | |
| 3159 | + case, you can tell what version of the JSON output you have from | |
| 3160 | + the ``"version"`` key in the output. Use the | |
| 3158 | 3161 | :qpdf:ref:`--json-help` option to get a description of the JSON |
| 3159 | 3162 | object. |
| 3160 | 3163 | ... | ... |
manual/design.rst
| ... | ... | @@ -745,3 +745,221 @@ C API object handle methods returned error codes like the other methods |
| 745 | 745 | and set return values in passed-in pointers, but this would complicate |
| 746 | 746 | both the implementation and the use of the library for a case that is |
| 747 | 747 | actually quite rare and largely avoidable. |
| 748 | + | |
| 749 | +.. _smart-pointers: | |
| 750 | + | |
| 751 | +Smart Pointers | |
| 752 | +-------------- | |
| 753 | + | |
| 754 | +This section describes changes to the use of smart pointers in qpdf in | |
| 755 | +versions 10.6.0 and 11.0.0. | |
| 756 | + | |
| 757 | +Starting in qpdf 11, ``PointerHolder`` will be replaced with | |
| 758 | +``std::shared_ptr`` in qpdf's public API. A backward-compatible | |
| 759 | +``PointerHolder`` will be provided that should make it possible for | |
| 760 | +most code to remain unchanged. This new ``PointerHolder`` will be | |
| 761 | +marked deprecated but will provide a way to suppress the deprecation | |
| 762 | +warnings. Code that works with containers of ``PointerHolder`` may | |
| 763 | +have to be modified, though no qpdf interfaces do this. | |
| 764 | + | |
| 765 | +The remainder of this section describes how to prepare if you want to | |
| 766 | +eliminate ``PointerHolder`` from your code or what to do if you want | |
| 767 | +to stick with the old interfaces. | |
| 768 | + | |
| 769 | +Changes in 10.6.0 | |
| 770 | +~~~~~~~~~~~~~~~~~ | |
| 771 | + | |
| 772 | +In qpdf 10.6.0, two ``PointerHolder`` methods have been deprecated and | |
| 773 | +replaced with methods that are compatible with ``std::shared_ptr``: | |
| 774 | + | |
| 775 | +- ``getPointer()`` -- use ``get()`` instead | |
| 776 | + | |
| 777 | +- ``getRefcount()`` -- use ``use_count()`` instead | |
| 778 | + | |
| 779 | +If you build your code with deprecation warnings enabled and you want | |
| 780 | +to suppress these deprecation warnings for now, you can ``#define | |
| 781 | +NO_POINTERHOLDER_DEPRECATION`` before including any qpdf header files. | |
| 782 | +It may be possible to leave it this way long-term to facilitate | |
| 783 | +supporting older versions of qpdf without conditional compilation. | |
| 784 | + | |
| 785 | +``PointerHolder`` has had a long-standing bug: a ``const | |
| 786 | +PointerHolder<T>`` would only provide a ``T const*`` with its | |
| 787 | +``getPointer`` method. This is incorrect and is now how standard C++ | |
| 788 | +smart pointers or regular pointers behave. The correct semantics | |
| 789 | +would be that a ``const PointerHolder<T>`` would not accept a new | |
| 790 | +pointer after being created but would still allow you to modify the | |
| 791 | +item being pointed to. If you don't want to mutate the thing it points | |
| 792 | +to, use ``PointerHolder<T const>`` instead. The new ``get()`` method | |
| 793 | +behaves correctly. It is therefore not exactly the same as | |
| 794 | +``getPointer()``, but it does behave the way ``get()`` behaves with | |
| 795 | +``std::shared_ptr``. This shouldn't make any difference to any | |
| 796 | +correctly written code. | |
| 797 | + | |
| 798 | + | |
| 799 | +How to Prepare | |
| 800 | +~~~~~~~~~~~~~~ | |
| 801 | + | |
| 802 | +If you don't need to support versions of qpdf prior to 10.6, you can | |
| 803 | +just replace all occurrences of ``getPointer()`` with ``get()`` and | |
| 804 | +all occurrences of ``getRefcount()`` with ``use_count()``. That's | |
| 805 | +about all you will be able to do prior to qpdf 11. | |
| 806 | + | |
| 807 | +If you need to support older versions, you have two choices: | |
| 808 | + | |
| 809 | +- ``#define NO_POINTERHOLDER_DEPRECATION`` and leave everything the | |
| 810 | + way it was. You can just wait until qpdf 11. | |
| 811 | + | |
| 812 | +- Write code that uses ``get()`` but falls back to ``getPointer()`` if | |
| 813 | + ``QPDF_MAJOR_VERSION`` is not defined. The symbols | |
| 814 | + ``QPDF_MAJOR_VERSION``, ``QPDF_MINOR_VERSION``, and | |
| 815 | + ``QPDF_PATCH_VERSION`` were introduced with 10.6.0, so just checking | |
| 816 | + for whether ``QPDF_MAJOR_VERSION`` is defined is sufficient for | |
| 817 | + telling if you're running a version before 10.6.0. If you do this, | |
| 818 | + once qpdf 11 comes out, you will already know all the places that | |
| 819 | + have to be handled specially. | |
| 820 | + | |
| 821 | +If you are somehow relying on the fact that a ``const | |
| 822 | +PointerHolder<T>`` always gave back a ``T const*`` and are | |
| 823 | +dereferencing a ``const PointerHolder<T>`` to call methods that only | |
| 824 | +have ``const`` versions in ``T``, you may have to change from | |
| 825 | +``const PointerHolder<T>`` to ``PointerHolder<T const>``. This won't | |
| 826 | +be an issue for anything in the qpdf API, and if you are using qpdf | |
| 827 | +``PointerHolder`` objects for any other reason, you should just | |
| 828 | +replace them with ``std::shared_ptr``. | |
| 829 | + | |
| 830 | +What to Expect | |
| 831 | +~~~~~~~~~~~~~~ | |
| 832 | + | |
| 833 | +Note: if you are reading this in the 10.6 manual and 11 is out, you | |
| 834 | +should read it in the manual for qpdf 11 instead. Some early tests | |
| 835 | +have been done to try to ensure the accuracy of this information, but | |
| 836 | +it may change once the work is actually completed. | |
| 837 | + | |
| 838 | +When ``PointerHolder`` disappears from qpdf's API in qpdf 11, you will | |
| 839 | +have a few options: | |
| 840 | + | |
| 841 | +- Use the new ``PointerHolder``, which is derived from | |
| 842 | + ``std::shared_ptr`` and which has methods to make it | |
| 843 | + interchangeable. For things that use ``PointerHolder<T>`` directly, | |
| 844 | + this should "just work," though you will have to ``#define | |
| 845 | + NO_POINTERHOLDER_DEPRECATION`` if you don't want deprecation | |
| 846 | + warnings. | |
| 847 | + | |
| 848 | +- Replace all uses of ``PointerHolder<T>`` with ``std::shared_ptr<T>`` | |
| 849 | + and deal with the required changes, outlined below. This is the | |
| 850 | + recommended course of action. You will need conditional compilation | |
| 851 | + if you want to simultaneously support order code. Stay tuned for the | |
| 852 | + qpdf 11 documentation for specifics. | |
| 853 | + | |
| 854 | +While ``PointerHolder<T>`` and ``std::shared_ptr<T>`` will be mutually | |
| 855 | +assignable and convertible, this does not apply to containers of those | |
| 856 | +objects. The qpdf API doesn't have any containers of | |
| 857 | +``PointerHolder``, so this would have to be in your own code. You can | |
| 858 | +prepare yourself for the change by using ``auto`` and ``decltype`` | |
| 859 | +whenever possible so that a change to the underlying type of something | |
| 860 | +won't require source changes. | |
| 861 | + | |
| 862 | +Required Changes in qpdf 11 | |
| 863 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 864 | + | |
| 865 | +This section describes unavoidable changes when replacing | |
| 866 | +``PointerHolder`` with ``std::shared_ptr`` rather than continuing to | |
| 867 | +use the backward compatible API. Nothing here is needed (or can be | |
| 868 | +done) prior to qpdf 11, so consider this to be a preview. | |
| 869 | + | |
| 870 | +- Change ``getPointer`` to ``get`` and ``getRefcount`` to | |
| 871 | + ``use_count`` as above. If your starting point is no deprecation | |
| 872 | + warnings with qpdf 10.6, this will already be true. | |
| 873 | + | |
| 874 | +- Array allocations will have to be rewritten. | |
| 875 | + | |
| 876 | + To allocate a ``PointerHolder`` to an array: | |
| 877 | + | |
| 878 | + .. code-block:: c++ | |
| 879 | + | |
| 880 | + PointerHolder<X> p(true, new X[n]); | |
| 881 | + | |
| 882 | + To allocate a ``std::shared_ptr`` to an array: | |
| 883 | + | |
| 884 | + .. code-block:: c++ | |
| 885 | + | |
| 886 | + auto p = std::shared_ptr<X>(new X[n], std::default_delete<X[]>()); | |
| 887 | + | |
| 888 | + To allocate a ``std::unique_ptr`` to an array: | |
| 889 | + | |
| 890 | + .. code-block:: c++ | |
| 891 | + | |
| 892 | + auto p = std::make_unique<X[]>(n); | |
| 893 | + // or | |
| 894 | + auto p = std::unique_ptr<X[]>(new X[n]); | |
| 895 | + | |
| 896 | + The second form may be needed if ``X`` has a private constructor | |
| 897 | + from this context. | |
| 898 | + | |
| 899 | + C++-17 has a better way to allocate ``std::shared_ptr`` to an array, | |
| 900 | + but qpdf is still allowing C++-14 to be used. You can use whatever | |
| 901 | + method to handle shared arrays that is supported in your | |
| 902 | + environment. There are no shared arrays in qpdf's public API except | |
| 903 | + for some ``QUtil`` helper methods that are not essential for use of | |
| 904 | + qpdf features. | |
| 905 | + | |
| 906 | +- ``PointerHolder<T>`` can have plain pointers directly assigned to | |
| 907 | + it, while ``std::shared_ptr<T>`` cannot. This makes code like this | |
| 908 | + possible: | |
| 909 | + | |
| 910 | + .. code-block:: c++ | |
| 911 | + | |
| 912 | + PointerHolder<X> x_p; | |
| 913 | + X* x = new X(); | |
| 914 | + x_p = x; | |
| 915 | + | |
| 916 | + It also makes it possible to pass a plain pointer to a function | |
| 917 | + expecting a ``PointerHolder``, thereby transferring "ownership" of | |
| 918 | + the pointer into the function. | |
| 919 | + | |
| 920 | + Code like that is a risky because you can leak memory if an | |
| 921 | + exception is thrown between creation of the X and assignment of it | |
| 922 | + into the ``PointerHolder``. In any case, ``std::shared_ptr`` does | |
| 923 | + not allow that, so you need one of these instead: | |
| 924 | + | |
| 925 | + .. code-block:: c++ | |
| 926 | + | |
| 927 | + auto x_p = std::make_shared<X>(); | |
| 928 | + X* x = x_p.get(); | |
| 929 | + // or, less safe, but closer: | |
| 930 | + std::shared_ptr<X> x_p; | |
| 931 | + X* x = new X(); | |
| 932 | + x_p = std::shared_ptr<X>(x); | |
| 933 | + | |
| 934 | + Also, code like this: | |
| 935 | + | |
| 936 | + .. code-block:: c++ | |
| 937 | + | |
| 938 | + PointerHolder<Base> base_p; | |
| 939 | + Derived* derived = new Derived(); | |
| 940 | + base_p = derived; | |
| 941 | + | |
| 942 | + needs to be replaced with something like this instead: | |
| 943 | + | |
| 944 | + .. code-block:: c++ | |
| 945 | + | |
| 946 | + std::shared_ptr<Base> base_p; | |
| 947 | + Derived* derived = new Derived(); | |
| 948 | + base_p = std::shared_ptr<Base>(derived); | |
| 949 | + | |
| 950 | +Historical Background | |
| 951 | +~~~~~~~~~~~~~~~~~~~~~ | |
| 952 | + | |
| 953 | +Since its inception, the qpdf library used its own smart pointer | |
| 954 | +class, ``PointerHolder``. The ``PointerHolder`` class was originally | |
| 955 | +created long before ``std::shared_ptr`` existed, and qpdf itself | |
| 956 | +didn't start requiring a C++-11 compiler version 9.1.0 released in | |
| 957 | +late 2019. | |
| 958 | + | |
| 959 | +``PointerHolder`` is a reference-counted smart pointer with semantics | |
| 960 | +almost identical to ``std::shared_ptr`` except that it is not | |
| 961 | +thread-safe. It has a few interface differences that prevent | |
| 962 | +``std::shared_ptr`` from being a drop-in replacement. However, given | |
| 963 | +the value of using standard library smart pointers, qpdf is taking the | |
| 964 | +plunge for version 11 and switching over to standard library smart | |
| 965 | +pointers. | ... | ... |
manual/qpdf-job.rst
| ... | ... | @@ -14,7 +14,10 @@ executable is available from inside the C++ library using the |
| 14 | 14 | |
| 15 | 15 | - Use from the C++ API with ``QPDFJob::initializeFromArgv`` |
| 16 | 16 | |
| 17 | - - Use from the C API with ``qpdfjob_run_from_argv`` from :file:`qpdfjob-c.h` | |
| 17 | + - Use from the C API with ``qpdfjob_run_from_argv`` from | |
| 18 | + :file:`qpdfjob-c.h`. If you are calling from a Windows-style main | |
| 19 | + and have an argv array of ``wchar_t``, you can use | |
| 20 | + ``qpdfjob_run_from_wide_argv``. | |
| 18 | 21 | |
| 19 | 22 | - The job JSON file format |
| 20 | 23 | |
| ... | ... | @@ -135,6 +138,13 @@ C++ code: |
| 135 | 138 | return 0; |
| 136 | 139 | } |
| 137 | 140 | |
| 141 | +Note the ``QPDFUsage`` exception above. This is thrown whenever a | |
| 142 | +configuration error occurs. These exactly correspond to usage messages | |
| 143 | +issued by the :command:`qpdf` CLI for things like omitting an output | |
| 144 | +file, specifying `--pages` multiple times, or other invalid | |
| 145 | +combinations of options. ``QPDFUsage`` is thrown by the argv and JSON | |
| 146 | +interfaces as well as the native ``QPDFJob`` interface. | |
| 147 | + | |
| 138 | 148 | It is also possible to mix and match command-line options and JSON |
| 139 | 149 | from the CLI. For example, you could create a file called |
| 140 | 150 | :file:`my-options.json` containing the following: | ... | ... |
manual/release-notes.rst
| ... | ... | @@ -6,6 +6,187 @@ 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 | +10.6.0: XXX | |
| 10 | + - Deprecations/future replacement of ``PointerHolder`` | |
| 11 | + | |
| 12 | + The next major release of qpdf will replace ``PointerHolder`` with | |
| 13 | + ``std::shared_ptr`` across all of qpdf's public API. In | |
| 14 | + preparation for this change, the following ``PointerHolder`` | |
| 15 | + methods have been deprecated in favor of interfaces that more | |
| 16 | + closely match ``std::shared_ptr``: | |
| 17 | + | |
| 18 | + - ``getPointer()`` -- use ``get()`` instead; this also fixes | |
| 19 | + ``const`` semantics as discussed in | |
| 20 | + :file:`include/qpdf/PointerHolder.hh`. | |
| 21 | + | |
| 22 | + - ``getRefcount()`` -- use ``use_count()`` instead | |
| 23 | + | |
| 24 | + If you build your code with deprecation warnings enabled and you | |
| 25 | + want to suppress these deprecation warnings for now, you can | |
| 26 | + ``#define NO_POINTERHOLDER_DEPRECATION`` before including any qpdf | |
| 27 | + header files. Code that does this will *require no changes* prior | |
| 28 | + to qpdf 11 and may or may not require changes after qpdf 11. | |
| 29 | + | |
| 30 | + For a detailed discussion of this change and how to prepare for | |
| 31 | + it, see :ref:`smart-pointers`. | |
| 32 | + | |
| 33 | + - Preparation for a new JSON output version | |
| 34 | + | |
| 35 | + - The :qpdf:ref:`--json` option takes an optional parameter | |
| 36 | + indicating the version of the JSON output. At present, there is | |
| 37 | + only one JSON version (``1``), but there are plans for an | |
| 38 | + updated version in a coming release. Until the release of qpdf | |
| 39 | + 11, the default value of ``--json`` is ``1`` for compatibility. | |
| 40 | + Once qpdf 11 is out, the default version will be ``latest``. If | |
| 41 | + you are depending on the exact format of ``--json`` for code, | |
| 42 | + you should start using ``--json=1`` in preparation. | |
| 43 | + | |
| 44 | + - New QPDFJob API exposes CLI functionality | |
| 45 | + | |
| 46 | + Prior to qpdf 10.6, a lot of the functionality implemented by the | |
| 47 | + qpdf CLI executable was built into the executable itself and not | |
| 48 | + available from the library. qpdf 10.6 introduces a new object, | |
| 49 | + ``QPDFJob``, that exposes all of the command-line functionality. | |
| 50 | + This includes a native ``QPDFJob`` API with fluent interfaces that | |
| 51 | + mirror the command-line syntax, a JSON syntax for specifying the | |
| 52 | + equivalent of a command-line invocation, and the ability to run a | |
| 53 | + qpdf "job" by passing a null-terminated array of qpdf command-line | |
| 54 | + options. The command-line argument array and JSON methods of | |
| 55 | + invoking ``QPDFJob`` are also exposed to the C API. For details, | |
| 56 | + see :ref:`qpdf-job`. | |
| 57 | + | |
| 58 | + - Other Library Enhancements | |
| 59 | + | |
| 60 | + - New ``QPDFObjectHandle`` literal syntax using C++'s user-defined | |
| 61 | + literal syntax. You can use | |
| 62 | + | |
| 63 | + .. code-block:: c++ | |
| 64 | + | |
| 65 | + auto oh = "<</Some (valid) /PDF (object)>>"_qpdf; | |
| 66 | + | |
| 67 | + to create a QPDFObjectHandle. It is a shorthand for | |
| 68 | + ``QPDFObjectHandle::parse``. | |
| 69 | + | |
| 70 | + - Preprocessor symbols ``QPDF_MAJOR_VERSION``, | |
| 71 | + ``QPDF_MINOR_VERSION``, and ``QPDF_PATCH_VERSION`` are now | |
| 72 | + available and can be used to make it easier to write code that | |
| 73 | + supports multiple versions of qpdf. You don't have to include | |
| 74 | + any new header files to get these, which makes it possible to | |
| 75 | + write code like this: | |
| 76 | + | |
| 77 | + .. code-block:: c++ | |
| 78 | + | |
| 79 | + #if !defined(QPDF_MAJOR_VERSION) || QPDF_MAJOR_VERSION < 11 | |
| 80 | + // do something using qpdf 10 or older API | |
| 81 | + #else | |
| 82 | + // do something using qpdf 11 or newer API | |
| 83 | + #endif | |
| 84 | + | |
| 85 | + Since this was introduced only in qpdf version 10.6.0, testing | |
| 86 | + for an undefined value of ``QPDF_MAJOR_VERSION`` is equivalent | |
| 87 | + to detecting a version prior to 10.6.0. | |
| 88 | + | |
| 89 | + The symbol ``QPDF_VERSION`` is also defined as a string | |
| 90 | + containing the same version number that is returned by | |
| 91 | + ``QPDF::QPDFVersion``. Note that ``QPDF_VERSION`` may differ | |
| 92 | + from ``QPDF::QPDFVersion()`` if your header files and library | |
| 93 | + are out of sync with each other. | |
| 94 | + | |
| 95 | + - The method ``QPDF::QPDFVersion`` and corresponding C API call | |
| 96 | + ``qpdf_get_qpdf_version`` are now both guaranteed to return a | |
| 97 | + reference (or pointer) to a static string, so you don't have to | |
| 98 | + copy these if you are using them in your software. They have | |
| 99 | + always returned static values. Now the fact that they return | |
| 100 | + static values is part of the API contract and can be safely | |
| 101 | + relied upon. | |
| 102 | + | |
| 103 | + - New accessor methods for ``QPDFObjectHandle``. In addition to | |
| 104 | + the traditional ones, such as ``getIntValue``, ``getName``, | |
| 105 | + etc., there are a family of new accessors whose names are of the | |
| 106 | + form ``getValueAsX``. The difference in behavior is as follows: | |
| 107 | + | |
| 108 | + - The older accessor methods, which will continue to be | |
| 109 | + supported, return the value of the object if it is the | |
| 110 | + expected type. Otherwise, they return a fallback value and | |
| 111 | + issue a warning. | |
| 112 | + | |
| 113 | + - The newer accessor methods return a boolean indicating whether | |
| 114 | + or not the object is of the expected type. If it is, a | |
| 115 | + reference of the correct type is returned. | |
| 116 | + | |
| 117 | + In many cases, the new interfaces will enable more compact code | |
| 118 | + and will also never generate type warnings. Thanks to M. Holger | |
| 119 | + for contributing these accessors. Search for ``getValueAs`` in | |
| 120 | + :file:`include/qpdf/QPDFObjectHandle.hh` for a complete list. | |
| 121 | + | |
| 122 | + These are also exposed in the C API in functions whose names | |
| 123 | + start with ``qpdf_oh_get_value_as``. | |
| 124 | + | |
| 125 | + - New convenience methods in ``QPDFObjectHandle``: | |
| 126 | + ``isDictionaryOfType``, ``isStreamOfType``, and | |
| 127 | + ``isNameAndEquals`` allow more compact querying of dictionaries. | |
| 128 | + Also added to the C API: ``qpdf_oh_is_dictionary_of_type`` and | |
| 129 | + ``qpdf_oh_is_name_and_equals``. Thanks to M. Holger for the | |
| 130 | + contribution. | |
| 131 | + | |
| 132 | + - New functions added to ``QUtil``: ``make_shared_cstr`` and | |
| 133 | + ``make_unique_cstr`` copy ``std::string`` to | |
| 134 | + ``std::shared_ptr<char>`` and ``std::unique_ptr<char[]>``. These | |
| 135 | + are alternatives to the existing ``QUtil::copy_string`` function | |
| 136 | + which offer other ways to get a C string with safer memory | |
| 137 | + management. | |
| 138 | + | |
| 139 | + - New function ``QUtil::file_can_be_opened`` tests to see whether | |
| 140 | + a file can actually be opened by attempting to open it and close | |
| 141 | + it again. | |
| 142 | + | |
| 143 | + - There is a new version of ``QUtil::call_main_from_wmain`` that | |
| 144 | + takes a ``const`` argv array and calls a main that takes a | |
| 145 | + ``const`` argv array. | |
| 146 | + | |
| 147 | + - ``QPDF::emptyPDF`` has been exposed to the C API as | |
| 148 | + ``qpdf_empty_pdf``. This makes it possible to create PDF from | |
| 149 | + scratch with the C API. | |
| 150 | + | |
| 151 | + - New C API functions ``qpdf_oh_get_binary_utf8_value`` and | |
| 152 | + ``qpdf_oh_new_binary_unicode_string`` take length parameters, | |
| 153 | + which makes it possible to handle UTF-8-encoded C strings with | |
| 154 | + embedded NUL characters. Thanks to M. Holger for the | |
| 155 | + contribution. | |
| 156 | + | |
| 157 | + - The ``JSON`` object in the qpdf library has been enhanced to | |
| 158 | + include a parser and the ability to get values out of the | |
| 159 | + ``JSON`` object. Previously it was a write-only interface. Even | |
| 160 | + so, qpdf's ``JSON`` object is not intended to be a | |
| 161 | + general-purpose JSON implementation as discussed in | |
| 162 | + :file:`include/qpdf/JSON.hh`. | |
| 163 | + | |
| 164 | + - The ``JSON`` object's "schema" checking functionality now allows | |
| 165 | + for optional keys. Note that this "schema" functionality doesn't | |
| 166 | + conform to any type of standard. It's just there to help with | |
| 167 | + error reporting with qpdf's own JSON support. | |
| 168 | + | |
| 169 | + - Documentation Enhancements | |
| 170 | + | |
| 171 | + - Documentation for the command-line tool has been completely | |
| 172 | + rewritten. This includes a top-to-bottom rewrite of :ref:`using` | |
| 173 | + in the manual. Command-line arguments are now indexed, and | |
| 174 | + internal links can appear to them within the documentation. | |
| 175 | + | |
| 176 | + - The output of ``qpdf --help`` is generated from the manual and | |
| 177 | + is divided into help topics that parallel the sections of the | |
| 178 | + manual. When you run ``qpdf --help``, instead of getting a Great | |
| 179 | + Wall of Text, you are given basic usage information and a list | |
| 180 | + of help topics. It is possible to request help for any | |
| 181 | + individual topic or any specific command-line option, or you can | |
| 182 | + get a dump of all available help text. The manual continues to | |
| 183 | + contain a greater level of detail and more examples. | |
| 184 | + | |
| 185 | + - Bug Fixes | |
| 186 | + | |
| 187 | + - Some characters were not correctly translated from PDF doc | |
| 188 | + encoding to Unicode. | |
| 189 | + | |
| 9 | 190 | 10.5.0: December 21, 2021 |
| 10 | 191 | - Packaging changes |
| 11 | 192 | ... | ... |