Commit e0720eaa78a56dafe5f5e572387b3a0cc8c88ec9

Authored by Jay Berkenbilt
1 parent 83be2191

Use the default logger for other writes to stdout/stderr

When there is no context for writing output or error messages, use the
default logger.
@@ -55,30 +55,10 @@ Output Capture @@ -55,30 +55,10 @@ Output Capture
55 55
56 See https://github.com/qpdf/qpdf/issues/691 56 See https://github.com/qpdf/qpdf/issues/691
57 57
58 -QPDFLogger maintains pipelines for info, warn, error, and save.  
59 -  
60 -There is a singleton, default QPDFLogger which all QPDF and QPDFJob  
61 -objects get on construction. In most cases, it is not necessary to  
62 -override this. Allow QPDFJob and QPDF to be passed a new logger  
63 -instance. QPDFJob should pass its QPDFLogger to all QPDF objects it  
64 -creates. The main uses cases for this would be for multithreading or  
65 -for having a library that uses QPDF privately and modifies logger  
66 -settings so that it wouldn't interfere with a downstream library or  
67 -application also using qpdf.  
68 -  
69 There needs to be a C API to QPDFLogger. Use functions like this: 58 There needs to be a C API to QPDFLogger. Use functions like this:
70 59
71 void set_info((*f)(char* data, unsigned int len, void* udata), void* udata); 60 void set_info((*f)(char* data, unsigned int len, void* udata), void* udata);
72 61
73 -We should probably deprecate the output/error setters in QPDF and  
74 -QPDFJob. In the meantime, document that they won't work anymore to set  
75 -different outputs with different QPDF objects. We may need to delete  
76 -rather than deprecate these methods.  
77 -  
78 -Find all places in the library that write to stdout/stderr/cout/cerr.  
79 -Also find places that raise exceptions if unable to warn. These should  
80 -use the global output writer.  
81 -  
82 62
83 QPDFPagesTree 63 QPDFPagesTree
84 ============= 64 =============
include/qpdf/QPDFLogger.hh
@@ -33,6 +33,19 @@ class QPDFLogger @@ -33,6 +33,19 @@ class QPDFLogger
33 QPDF_DLL 33 QPDF_DLL
34 QPDFLogger(); 34 QPDFLogger();
35 35
  36 + // Return the default logger. In general, you should use the
  37 + // default logger. You can also create your own loggers and use
  38 + // them QPDF and QPDFJob objects, but there are few reasons to do
  39 + // so. One reason may if you are using multiple QPDF or QPDFJob
  40 + // objects in different threads and want to capture output and
  41 + // errors to different streams. (Note that a single QPDF or
  42 + // QPDFJob can't be safely used from multiple threads, but it is
  43 + // safe to use separate QPDF and QPDFJob objects on separate
  44 + // threads.) Another possible reason would be if you are writing
  45 + // an application that uses the qpdf library directly and qpdf is
  46 + // also used by a downstream library or if you are using qpdf from
  47 + // a library and don't want to interfere with potential uses of
  48 + // qpdf by other libraries or applications.
36 QPDF_DLL 49 QPDF_DLL
37 static std::shared_ptr<QPDFLogger> defaultLogger(); 50 static std::shared_ptr<QPDFLogger> defaultLogger();
38 51
include/qpdf/QPDFObjectHandle.hh
@@ -1411,14 +1411,14 @@ class QPDFObjectHandle @@ -1411,14 +1411,14 @@ class QPDFObjectHandle
1411 // End legacy page helpers 1411 // End legacy page helpers
1412 1412
1413 // Issue a warning about this object if possible. If the object 1413 // Issue a warning about this object if possible. If the object
1414 - // has a description, a warning will be issued. Otherwise, if  
1415 - // throw_if_no_description is true, throw an exception. Otherwise  
1416 - // do nothing. Objects read normally from the file have 1414 + // has a description, a warning will be issued using the owning
  1415 + // QPDF as context. Otherwise, a message will be written to the
  1416 + // default logger's error stream, which is standard error if not
  1417 + // overridden. Objects read normally from the file have
1417 // descriptions. See comments on setObjectDescription for 1418 // descriptions. See comments on setObjectDescription for
1418 // additional details. 1419 // additional details.
1419 QPDF_DLL 1420 QPDF_DLL
1420 - void warnIfPossible(  
1421 - std::string const& warning, bool throw_if_no_description = false); 1421 + void warnIfPossible(std::string const& warning);
1422 1422
1423 // Initializers for objects. This Factory class gives the QPDF 1423 // Initializers for objects. This Factory class gives the QPDF
1424 // class specific permission to call factory methods without 1424 // class specific permission to call factory methods without
libqpdf/QPDFArgParser.cc
1 #include <qpdf/QPDFArgParser.hh> 1 #include <qpdf/QPDFArgParser.hh>
2 2
3 #include <qpdf/QIntC.hh> 3 #include <qpdf/QIntC.hh>
  4 +#include <qpdf/QPDFLogger.hh>
4 #include <qpdf/QPDFUsage.hh> 5 #include <qpdf/QPDFUsage.hh>
5 #include <qpdf/QTC.hh> 6 #include <qpdf/QTC.hh>
6 #include <qpdf/QUtil.hh> 7 #include <qpdf/QUtil.hh>
@@ -235,7 +236,7 @@ QPDFArgParser::argCompletionZsh() @@ -235,7 +236,7 @@ QPDFArgParser::argCompletionZsh()
235 void 236 void
236 QPDFArgParser::argHelp(std::string const& p) 237 QPDFArgParser::argHelp(std::string const& p)
237 { 238 {
238 - std::cout << getHelp(p); 239 + QPDFLogger::defaultLogger()->info(getHelp(p));
239 exit(0); 240 exit(0);
240 } 241 }
241 242
libqpdf/QPDFJob_argv.cc
@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 #include <qpdf/QPDFArgParser.hh> 14 #include <qpdf/QPDFArgParser.hh>
15 #include <qpdf/QPDFCryptoProvider.hh> 15 #include <qpdf/QPDFCryptoProvider.hh>
16 #include <qpdf/QPDFJob.hh> 16 #include <qpdf/QPDFJob.hh>
  17 +#include <qpdf/QPDFLogger.hh>
17 #include <qpdf/QTC.hh> 18 #include <qpdf/QTC.hh>
18 #include <qpdf/QUtil.hh> 19 #include <qpdf/QUtil.hh>
19 20
@@ -104,10 +105,10 @@ void @@ -104,10 +105,10 @@ void
104 ArgParser::argVersion() 105 ArgParser::argVersion()
105 { 106 {
106 auto whoami = this->ap.getProgname(); 107 auto whoami = this->ap.getProgname();
107 - std::cout << whoami << " version " << QPDF::QPDFVersion() << std::endl  
108 - << "Run " << whoami  
109 - << " --copyright to see copyright and license information."  
110 - << std::endl; 108 + *QPDFLogger::defaultLogger()->getInfo()
  109 + << whoami << " version " << QPDF::QPDFVersion() << "\n"
  110 + << "Run " << whoami
  111 + << " --copyright to see copyright and license information.\n";
111 } 112 }
112 113
113 void 114 void
@@ -117,48 +118,35 @@ ArgParser::argCopyright() @@ -117,48 +118,35 @@ ArgParser::argCopyright()
117 // Make sure the output looks right on an 80-column display. 118 // Make sure the output looks right on an 80-column display.
118 // 1 2 3 4 5 6 7 8 119 // 1 2 3 4 5 6 7 8
119 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 120 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
120 - std::cout 121 + *QPDFLogger::defaultLogger()->getInfo()
121 << this->ap.getProgname() 122 << this->ap.getProgname()
122 - << " version " << QPDF::QPDFVersion() << std::endl  
123 - << std::endl  
124 - << "Copyright (c) 2005-2022 Jay Berkenbilt"  
125 - << std::endl  
126 - << "QPDF is licensed under the Apache License, Version 2.0 (the \"License\");"  
127 - << std::endl  
128 - << "you may not use this file except in compliance with the License."  
129 - << std::endl  
130 - << "You may obtain a copy of the License at"  
131 - << std::endl  
132 - << std::endl  
133 - << " http://www.apache.org/licenses/LICENSE-2.0"  
134 - << std::endl  
135 - << std::endl  
136 - << "Unless required by applicable law or agreed to in writing, software"  
137 - << std::endl  
138 - << "distributed under the License is distributed on an \"AS IS\" BASIS,"  
139 - << std::endl  
140 - << "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."  
141 - << std::endl  
142 - << "See the License for the specific language governing permissions and"  
143 - << std::endl  
144 - << "limitations under the License."  
145 - << std::endl  
146 - << std::endl  
147 - << "Versions of qpdf prior to version 7 were released under the terms"  
148 - << std::endl  
149 - << "of version 2.0 of the Artistic License. At your option, you may"  
150 - << std::endl  
151 - << "continue to consider qpdf to be licensed under those terms. Please"  
152 - << std::endl  
153 - << "see the manual for additional information."  
154 - << std::endl; 123 + << " version " << QPDF::QPDFVersion() << "\n"
  124 + << "\n"
  125 + << "Copyright (c) 2005-2022 Jay Berkenbilt\n"
  126 + << "QPDF is licensed under the Apache License, Version 2.0 (the \"License\");\n"
  127 + << "you may not use this file except in compliance with the License.\n"
  128 + << "You may obtain a copy of the License at\n"
  129 + << "\n"
  130 + << " http://www.apache.org/licenses/LICENSE-2.0\n"
  131 + << "\n"
  132 + << "Unless required by applicable law or agreed to in writing, software\n"
  133 + << "distributed under the License is distributed on an \"AS IS\" BASIS,\n"
  134 + << "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
  135 + << "See the License for the specific language governing permissions and\n"
  136 + << "limitations under the License.\n"
  137 + << "\n"
  138 + << "Versions of qpdf prior to version 7 were released under the terms\n"
  139 + << "of version 2.0 of the Artistic License. At your option, you may\n"
  140 + << "continue to consider qpdf to be licensed under those terms. Please\n"
  141 + << "see the manual for additional information.\n";
155 // clang-format on 142 // clang-format on
156 } 143 }
157 144
158 void 145 void
159 ArgParser::argJsonHelp() 146 ArgParser::argJsonHelp()
160 { 147 {
161 - std::cout << QPDFJob::json_out_schema_v1() << std::endl; 148 + *QPDFLogger::defaultLogger()->getInfo()
  149 + << QPDFJob::json_out_schema_v1() << "\n";
162 } 150 }
163 151
164 void 152 void
@@ -166,10 +154,10 @@ ArgParser::argShowCrypto() @@ -166,10 +154,10 @@ ArgParser::argShowCrypto()
166 { 154 {
167 auto crypto = QPDFCryptoProvider::getRegisteredImpls(); 155 auto crypto = QPDFCryptoProvider::getRegisteredImpls();
168 std::string default_crypto = QPDFCryptoProvider::getDefaultProvider(); 156 std::string default_crypto = QPDFCryptoProvider::getDefaultProvider();
169 - std::cout << default_crypto << std::endl; 157 + *QPDFLogger::defaultLogger()->getInfo() << default_crypto << "\n";
170 for (auto const& iter: crypto) { 158 for (auto const& iter: crypto) {
171 if (iter != default_crypto) { 159 if (iter != default_crypto) {
172 - std::cout << iter << std::endl; 160 + *QPDFLogger::defaultLogger()->getInfo() << iter << "\n";
173 } 161 }
174 } 162 }
175 } 163 }
@@ -407,7 +395,8 @@ ArgParser::argEndCopyAttachment() @@ -407,7 +395,8 @@ ArgParser::argEndCopyAttachment()
407 void 395 void
408 ArgParser::argJobJsonHelp() 396 ArgParser::argJobJsonHelp()
409 { 397 {
410 - std::cout << QPDFJob::job_json_schema_v1() << std::endl; 398 + *QPDFLogger::defaultLogger()->getInfo()
  399 + << QPDFJob::job_json_schema_v1() << "\n";
411 } 400 }
412 401
413 void 402 void
libqpdf/QPDFJob_config.cc
1 #include <qpdf/QPDFJob.hh> 1 #include <qpdf/QPDFJob.hh>
2 2
  3 +#include <qpdf/QPDFLogger.hh>
3 #include <qpdf/QTC.hh> 4 #include <qpdf/QTC.hh>
4 #include <qpdf/QUtil.hh> 5 #include <qpdf/QUtil.hh>
5 6
@@ -648,9 +649,10 @@ QPDFJob::Config::passwordFile(std::string const&amp; parameter) @@ -648,9 +649,10 @@ QPDFJob::Config::passwordFile(std::string const&amp; parameter)
648 o.m->password = QUtil::make_shared_cstr(lines.front()); 649 o.m->password = QUtil::make_shared_cstr(lines.front());
649 650
650 if (lines.size() > 1) { 651 if (lines.size() > 1) {
651 - std::cerr << this->o.m->message_prefix  
652 - << ": WARNING: all but the first line of"  
653 - << " the password file are ignored" << std::endl; 652 + *QPDFLogger::defaultLogger()->getError()
  653 + << this->o.m->message_prefix
  654 + << ": WARNING: all but the first line of"
  655 + << " the password file are ignored\n";
654 } 656 }
655 } 657 }
656 return this; 658 return this;
libqpdf/QPDFObjectHandle.cc
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 #include <qpdf/Pl_QPDFTokenizer.hh> 5 #include <qpdf/Pl_QPDFTokenizer.hh>
6 #include <qpdf/QPDF.hh> 6 #include <qpdf/QPDF.hh>
7 #include <qpdf/QPDFExc.hh> 7 #include <qpdf/QPDFExc.hh>
  8 +#include <qpdf/QPDFLogger.hh>
8 #include <qpdf/QPDFMatrix.hh> 9 #include <qpdf/QPDFMatrix.hh>
9 #include <qpdf/QPDFPageObjectHelper.hh> 10 #include <qpdf/QPDFPageObjectHelper.hh>
10 #include <qpdf/QPDF_Array.hh> 11 #include <qpdf/QPDF_Array.hh>
@@ -578,13 +579,12 @@ QPDFObjectHandle::getIntValueAsInt() @@ -578,13 +579,12 @@ QPDFObjectHandle::getIntValueAsInt()
578 if (v < INT_MIN) { 579 if (v < INT_MIN) {
579 QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN"); 580 QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN");
580 warnIfPossible( 581 warnIfPossible(
581 - "requested value of integer is too small; returning INT_MIN",  
582 - false); 582 + "requested value of integer is too small; returning INT_MIN");
583 result = INT_MIN; 583 result = INT_MIN;
584 } else if (v > INT_MAX) { 584 } else if (v > INT_MAX) {
585 QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX"); 585 QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX");
586 warnIfPossible( 586 warnIfPossible(
587 - "requested value of integer is too big; returning INT_MAX", false); 587 + "requested value of integer is too big; returning INT_MAX");
588 result = INT_MAX; 588 result = INT_MAX;
589 } else { 589 } else {
590 result = static_cast<int>(v); 590 result = static_cast<int>(v);
@@ -610,7 +610,7 @@ QPDFObjectHandle::getUIntValue() @@ -610,7 +610,7 @@ QPDFObjectHandle::getUIntValue()
610 if (v < 0) { 610 if (v < 0) {
611 QTC::TC("qpdf", "QPDFObjectHandle uint returning 0"); 611 QTC::TC("qpdf", "QPDFObjectHandle uint returning 0");
612 warnIfPossible( 612 warnIfPossible(
613 - "unsigned value request for negative number; returning 0", false); 613 + "unsigned value request for negative number; returning 0");
614 } else { 614 } else {
615 result = static_cast<unsigned long long>(v); 615 result = static_cast<unsigned long long>(v);
616 } 616 }
@@ -635,15 +635,12 @@ QPDFObjectHandle::getUIntValueAsUInt() @@ -635,15 +635,12 @@ QPDFObjectHandle::getUIntValueAsUInt()
635 if (v < 0) { 635 if (v < 0) {
636 QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0"); 636 QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0");
637 warnIfPossible( 637 warnIfPossible(
638 - "unsigned integer value request for negative number; returning 0",  
639 - false); 638 + "unsigned integer value request for negative number; returning 0");
640 result = 0; 639 result = 0;
641 } else if (v > UINT_MAX) { 640 } else if (v > UINT_MAX) {
642 QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX"); 641 QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX");
643 - warnIfPossible(  
644 - "requested value of unsigned integer is too big;"  
645 - " returning UINT_MAX",  
646 - false); 642 + warnIfPossible("requested value of unsigned integer is too big;"
  643 + " returning UINT_MAX");
647 result = UINT_MAX; 644 result = UINT_MAX;
648 } else { 645 } else {
649 result = static_cast<unsigned int>(v); 646 result = static_cast<unsigned int>(v);
@@ -3000,16 +2997,15 @@ QPDFObjectHandle::typeWarning( @@ -3000,16 +2997,15 @@ QPDFObjectHandle::typeWarning(
3000 } 2997 }
3001 2998
3002 void 2999 void
3003 -QPDFObjectHandle::warnIfPossible(  
3004 - std::string const& warning, bool throw_if_no_description) 3000 +QPDFObjectHandle::warnIfPossible(std::string const& warning)
3005 { 3001 {
3006 QPDF* context = 0; 3002 QPDF* context = 0;
3007 std::string description; 3003 std::string description;
3008 dereference(); 3004 dereference();
3009 if (this->obj->getDescription(context, description)) { 3005 if (this->obj->getDescription(context, description)) {
3010 warn(context, QPDFExc(qpdf_e_damaged_pdf, "", description, 0, warning)); 3006 warn(context, QPDFExc(qpdf_e_damaged_pdf, "", description, 0, warning));
3011 - } else if (throw_if_no_description) {  
3012 - throw std::runtime_error(warning); 3007 + } else {
  3008 + *QPDFLogger::defaultLogger()->getError() << warning << "\n";
3013 } 3009 }
3014 } 3010 }
3015 3011
libqpdf/qpdf-c.cc
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 #include <qpdf/Pl_Discard.hh> 6 #include <qpdf/Pl_Discard.hh>
7 #include <qpdf/QIntC.hh> 7 #include <qpdf/QIntC.hh>
8 #include <qpdf/QPDFExc.hh> 8 #include <qpdf/QPDFExc.hh>
  9 +#include <qpdf/QPDFLogger.hh>
9 #include <qpdf/QPDFWriter.hh> 10 #include <qpdf/QPDFWriter.hh>
10 #include <qpdf/QTC.hh> 11 #include <qpdf/QTC.hh>
11 #include <qpdf/QUtil.hh> 12 #include <qpdf/QUtil.hh>
@@ -185,8 +186,9 @@ qpdf_cleanup(qpdf_data* qpdf) @@ -185,8 +186,9 @@ qpdf_cleanup(qpdf_data* qpdf)
185 qpdf_oh_release_all(*qpdf); 186 qpdf_oh_release_all(*qpdf);
186 if ((*qpdf)->error.get()) { 187 if ((*qpdf)->error.get()) {
187 QTC::TC("qpdf", "qpdf-c cleanup warned about unhandled error"); 188 QTC::TC("qpdf", "qpdf-c cleanup warned about unhandled error");
188 - std::cerr << "WARNING: application did not handle error: "  
189 - << (*qpdf)->error->what() << std::endl; 189 + *QPDFLogger::defaultLogger()->getWarn()
  190 + << "WARNING: application did not handle error: "
  191 + << (*qpdf)->error->what() << "\n";
190 } 192 }
191 delete *qpdf; 193 delete *qpdf;
192 *qpdf = 0; 194 *qpdf = 0;
@@ -898,7 +900,8 @@ trap_oh_errors( @@ -898,7 +900,8 @@ trap_oh_errors(
898 " to ERROR HANDLING in qpdf-c.h")); 900 " to ERROR HANDLING in qpdf-c.h"));
899 qpdf->oh_error_occurred = true; 901 qpdf->oh_error_occurred = true;
900 } 902 }
901 - std::cerr << qpdf->error->what() << std::endl; 903 + *QPDFLogger::defaultLogger()->getError()
  904 + << qpdf->error->what() << "\n";
902 } 905 }
903 return fallback(); 906 return fallback();
904 } 907 }
libqpdf/qpdfjob-c.cc
1 #include <qpdf/qpdfjob-c.h> 1 #include <qpdf/qpdfjob-c.h>
2 2
3 #include <qpdf/QPDFJob.hh> 3 #include <qpdf/QPDFJob.hh>
  4 +#include <qpdf/QPDFLogger.hh>
4 #include <qpdf/QPDFUsage.hh> 5 #include <qpdf/QPDFUsage.hh>
5 #include <qpdf/QUtil.hh> 6 #include <qpdf/QUtil.hh>
6 7
@@ -19,7 +20,8 @@ qpdfjob_run_from_argv(char const* const argv[]) @@ -19,7 +20,8 @@ qpdfjob_run_from_argv(char const* const argv[])
19 j.initializeFromArgv(argv); 20 j.initializeFromArgv(argv);
20 j.run(); 21 j.run();
21 } catch (std::exception& e) { 22 } catch (std::exception& e) {
22 - std::cerr << whoami << ": " << e.what() << std::endl; 23 + *QPDFLogger::defaultLogger()->getError()
  24 + << whoami << ": " << e.what() << "\n";
23 return QPDFJob::EXIT_ERROR; 25 return QPDFJob::EXIT_ERROR;
24 } 26 }
25 return j.getExitCode(); 27 return j.getExitCode();
@@ -48,7 +50,8 @@ qpdfjob_run_from_json(char const* json) @@ -48,7 +50,8 @@ qpdfjob_run_from_json(char const* json)
48 j.initializeFromJson(json); 50 j.initializeFromJson(json);
49 j.run(); 51 j.run();
50 } catch (std::exception& e) { 52 } catch (std::exception& e) {
51 - std::cerr << "qpdfjob json: " << e.what() << std::endl; 53 + *QPDFLogger::defaultLogger()->getError()
  54 + << "qpdfjob json: " << e.what() << "\n";
52 return QPDFJob::EXIT_ERROR; 55 return QPDFJob::EXIT_ERROR;
53 } 56 }
54 return j.getExitCode(); 57 return j.getExitCode();
manual/release-notes.rst
@@ -120,6 +120,11 @@ For a detailed list of changes, please see the file @@ -120,6 +120,11 @@ For a detailed list of changes, please see the file
120 - See :ref:`breaking-crypto-api` for specific details, and see 120 - See :ref:`breaking-crypto-api` for specific details, and see
121 :ref:`weak-crypto` for a general discussion. 121 :ref:`weak-crypto` for a general discussion.
122 122
  123 + - QPDFObjectHandle::warnIfPossible no longer takes an optional
  124 + argument to throw an exception if there is no description. If
  125 + there is no description, it writes to the default logger's error
  126 + stream.
  127 +
123 - CLI Enhancements 128 - CLI Enhancements
124 129
125 - ``qpdf --list-attachments --verbose`` include some additional 130 - ``qpdf --list-attachments --verbose`` include some additional
@@ -139,6 +144,20 @@ For a detailed list of changes, please see the file @@ -139,6 +144,20 @@ For a detailed list of changes, please see the file
139 144
140 - Library Enhancements 145 - Library Enhancements
141 146
  147 + - A new object ``QPDFLogger`` has been added. Details are in
  148 + :file:`include/qpdf/QPDFLogger.hh`.
  149 +
  150 + - ``QPDF`` and ``QPDFJob`` both use the default logger by
  151 + default but can have their loggers overridden. The
  152 + ``setOutputStreams`` method is deprecated in both classes.
  153 +
  154 + - A few things from ``QPDFObjectHandle`` that used to be
  155 + exceptions now write errors with the default logger.
  156 +
  157 + - By configuring the default logger, it is possible to capture
  158 + output and errors that slipped through the cracks with
  159 + ``setOutputStreams``.
  160 +
142 - New methods ``insertItemAndGet``, ``appendItemAndGet``, 161 - New methods ``insertItemAndGet``, ``appendItemAndGet``,
143 ``eraseItemAndGet``, ``replaceKeyAndGet``, and 162 ``eraseItemAndGet``, ``replaceKeyAndGet``, and
144 ``removeKeyAndGet`` return the newly added or removed object. 163 ``removeKeyAndGet`` return the newly added or removed object.
qpdf/qtest/error-condition.test
@@ -111,11 +111,11 @@ $td-&gt;runtest(&quot;C API: no recovery&quot;, @@ -111,11 +111,11 @@ $td-&gt;runtest(&quot;C API: no recovery&quot;,
111 111
112 $td->runtest("integer type checks", 112 $td->runtest("integer type checks",
113 {$td->COMMAND => "test_driver 62 minimal.pdf"}, 113 {$td->COMMAND => "test_driver 62 minimal.pdf"},
114 - {$td->STRING => "test 62 done\n", $td->EXIT_STATUS => 0}, 114 + {$td->FILE => "test62.out", $td->EXIT_STATUS => 0},
115 $td->NORMALIZE_NEWLINES); 115 $td->NORMALIZE_NEWLINES);
116 $td->runtest("getValueAs... accessor checks", 116 $td->runtest("getValueAs... accessor checks",
117 {$td->COMMAND => "test_driver 85 -"}, 117 {$td->COMMAND => "test_driver 85 -"},
118 - {$td->STRING => "test 85 done\n", $td->EXIT_STATUS => 0}, 118 + {$td->FILE => "test85.out", $td->EXIT_STATUS => 0},
119 $td->NORMALIZE_NEWLINES); 119 $td->NORMALIZE_NEWLINES);
120 120
121 $n_tests += @badfiles + 11; 121 $n_tests += @badfiles + 11;
qpdf/qtest/qpdf/test62.out 0 → 100644
  1 +requested value of integer is too big; returning INT_MAX
  2 +requested value of unsigned integer is too big; returning UINT_MAX
  3 +unsigned value request for negative number; returning 0
  4 +requested value of integer is too small; returning INT_MIN
  5 +unsigned integer value request for negative number; returning 0
  6 +requested value of integer is too big; returning INT_MAX
  7 +test 62 done
qpdf/qtest/qpdf/test85.out 0 → 100644
  1 +requested value of integer is too big; returning INT_MAX
  2 +requested value of integer is too small; returning INT_MIN
  3 +unsigned value request for negative number; returning 0
  4 +unsigned integer value request for negative number; returning 0
  5 +requested value of unsigned integer is too big; returning UINT_MAX
  6 +test 85 done