Commit 0364024781ffa709a1a86ae9c6638f71df0317ca

Authored by Jay Berkenbilt
1 parent 764feb0f

Use QPDFUsage exception for cli, json, and QPDFJob errors

ChangeLog
  1 +2022-01-28 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add QPDFUsage exception, which is thrown by JSONHandler,
  4 + QPDFArgParser, and QPDFJob to indicate command-line usage or job
  5 + configuration errors.
  6 +
1 2022-01-22 Jay Berkenbilt <ejb@ql.org> 7 2022-01-22 Jay Berkenbilt <ejb@ql.org>
2 8
3 * Add QUtil::make_shared_cstr to return a std::shared_ptr<char> 9 * Add QUtil::make_shared_cstr to return a std::shared_ptr<char>
include/qpdf/JSONHandler.hh
@@ -28,7 +28,6 @@ @@ -28,7 +28,6 @@
28 #include <string> 28 #include <string>
29 #include <map> 29 #include <map>
30 #include <functional> 30 #include <functional>
31 -#include <stdexcept>  
32 #include <memory> 31 #include <memory>
33 32
34 // This class allows a sax-like walk through a JSON object with 33 // This class allows a sax-like walk through a JSON object with
@@ -39,15 +38,8 @@ @@ -39,15 +38,8 @@
39 class JSONHandler 38 class JSONHandler
40 { 39 {
41 public: 40 public:
42 - // Error exception is thrown if there are any errors validating  
43 - // the JSON object.  
44 - class QPDF_DLL_CLASS Error: public std::runtime_error  
45 - {  
46 - public:  
47 - QPDF_DLL  
48 - Error(std::string const&);  
49 - };  
50 - 41 + // A QPDFUsage exception is thrown if there are any errors
  42 + // validating the JSON object.
51 QPDF_DLL 43 QPDF_DLL
52 JSONHandler(); 44 JSONHandler();
53 45
@@ -55,10 +47,10 @@ class JSONHandler @@ -55,10 +47,10 @@ class JSONHandler
55 ~JSONHandler() = default; 47 ~JSONHandler() = default;
56 48
57 // Based on the type of handler, expect the object to be of a 49 // Based on the type of handler, expect the object to be of a
58 - // certain type. JSONHandler::Error is thrown otherwise. Multiple  
59 - // handlers may be registered, which allows the object to be of  
60 - // various types. If an anyHandler is added, no other handler will  
61 - // be called. There is no "final" handler -- if the top-level is a 50 + // certain type. QPDFUsage is thrown otherwise. Multiple handlers
  51 + // may be registered, which allows the object to be of various
  52 + // types. If an anyHandler is added, no other handler will be
  53 + // called. There is no "final" handler -- if the top-level is a
62 // dictionary or array, just use its end handler. 54 // dictionary or array, just use its end handler.
63 55
64 typedef std::function<void( 56 typedef std::function<void(
@@ -106,6 +98,8 @@ class JSONHandler @@ -106,6 +98,8 @@ class JSONHandler
106 private: 98 private:
107 JSONHandler(JSONHandler const&) = delete; 99 JSONHandler(JSONHandler const&) = delete;
108 100
  101 + static void usage(std::string const& msg);
  102 +
109 struct Handlers 103 struct Handlers
110 { 104 {
111 Handlers() : 105 Handlers() :
include/qpdf/QPDFArgParser.hh
@@ -29,7 +29,6 @@ @@ -29,7 +29,6 @@
29 #include <map> 29 #include <map>
30 #include <vector> 30 #include <vector>
31 #include <functional> 31 #include <functional>
32 -#include <stdexcept>  
33 #include <sstream> 32 #include <sstream>
34 33
35 // This is not a general-purpose argument parser. It is tightly 34 // This is not a general-purpose argument parser. It is tightly
@@ -56,15 +55,6 @@ @@ -56,15 +55,6 @@
56 class QPDFArgParser 55 class QPDFArgParser
57 { 56 {
58 public: 57 public:
59 - // Usage exception is thrown if there are any errors parsing  
60 - // arguments  
61 - class QPDF_DLL_CLASS Usage: public std::runtime_error  
62 - {  
63 - public:  
64 - QPDF_DLL  
65 - Usage(std::string const&);  
66 - };  
67 -  
68 // progname_env is used to override argv[0] when figuring out the 58 // progname_env is used to override argv[0] when figuring out the
69 // name of the executable for setting up completion. This may be 59 // name of the executable for setting up completion. This may be
70 // needed if the program is invoked by a wrapper. 60 // needed if the program is invoked by a wrapper.
@@ -72,8 +62,8 @@ class QPDFArgParser @@ -72,8 +62,8 @@ class QPDFArgParser
72 QPDFArgParser(int argc, char* argv[], char const* progname_env); 62 QPDFArgParser(int argc, char* argv[], char const* progname_env);
73 63
74 // Calls exit(0) if a help option is given or if in completion 64 // Calls exit(0) if a help option is given or if in completion
75 - // mode. If there are argument parsing errors,  
76 - // QPDFArgParser::Usage is thrown. 65 + // mode. If there are argument parsing errors, QPDFUsage is
  66 + // thrown.
77 QPDF_DLL 67 QPDF_DLL
78 void parseArgs(); 68 void parseArgs();
79 69
include/qpdf/QPDFExc.hh
@@ -39,7 +39,7 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error @@ -39,7 +39,7 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
39 qpdf_offset_t offset, 39 qpdf_offset_t offset,
40 std::string const& message); 40 std::string const& message);
41 QPDF_DLL 41 QPDF_DLL
42 - virtual ~QPDFExc() throw () 42 + virtual ~QPDFExc() noexcept
43 { 43 {
44 } 44 }
45 45
include/qpdf/QPDFJob.hh
@@ -43,15 +43,8 @@ class QPDFWriter; @@ -43,15 +43,8 @@ class QPDFWriter;
43 class QPDFJob 43 class QPDFJob
44 { 44 {
45 public: 45 public:
46 - // ConfigError exception is thrown if there are any usage-like  
47 - // errors when calling Config methods.  
48 - class QPDF_DLL_CLASS ConfigError: public std::runtime_error  
49 - {  
50 - public:  
51 - QPDF_DLL  
52 - ConfigError(std::string const&);  
53 - };  
54 - 46 + // QPDFUsage is thrown if there are any usage-like errors when
  47 + // calling Config methods.
55 QPDF_DLL 48 QPDF_DLL
56 QPDFJob(); 49 QPDFJob();
57 50
@@ -318,7 +311,9 @@ class QPDFJob @@ -318,7 +311,9 @@ class QPDFJob
318 friend class Config; 311 friend class Config;
319 312
320 // Return a top-level configuration item. See CONFIGURATION above 313 // Return a top-level configuration item. See CONFIGURATION above
321 - // for details. 314 + // for details. If an invalid configuration is created (such as
  315 + // supplying contradictory options, omitting an input file, etc.),
  316 + // QPDFUsage is thrown.
322 QPDF_DLL 317 QPDF_DLL
323 std::shared_ptr<Config> config(); 318 std::shared_ptr<Config> config();
324 319
@@ -404,6 +399,7 @@ class QPDFJob @@ -404,6 +399,7 @@ class QPDFJob
404 }; 399 };
405 400
406 // Helper functions 401 // Helper functions
  402 + static void usage(std::string const& msg);
407 static JSON json_schema(std::set<std::string>* keys = 0); 403 static JSON json_schema(std::set<std::string>* keys = 0);
408 static void parse_object_id( 404 static void parse_object_id(
409 std::string const& objspec, bool& trailer, int& obj, int& gen); 405 std::string const& objspec, bool& trailer, int& obj, int& gen);
include/qpdf/QPDFSystemError.hh
@@ -36,7 +36,7 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error @@ -36,7 +36,7 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
36 QPDFSystemError(std::string const& description, 36 QPDFSystemError(std::string const& description,
37 int system_errno); 37 int system_errno);
38 QPDF_DLL 38 QPDF_DLL
39 - virtual ~QPDFSystemError() throw (); 39 + virtual ~QPDFSystemError() noexcept;
40 40
41 // To get a complete error string, call what(), provided by 41 // To get a complete error string, call what(), provided by
42 // std::exception. The accessors below return the original values 42 // std::exception. The accessors below return the original values
include/qpdf/QPDFUsage.hh 0 → 100644
  1 +// Copyright (c) 2005-2021 Jay Berkenbilt
  2 +//
  3 +// This file is part of qpdf.
  4 +//
  5 +// Licensed under the Apache License, Version 2.0 (the "License");
  6 +// you may not use this file except in compliance with the License.
  7 +// You may obtain a copy of the License at
  8 +//
  9 +// http://www.apache.org/licenses/LICENSE-2.0
  10 +//
  11 +// Unless required by applicable law or agreed to in writing, software
  12 +// distributed under the License is distributed on an "AS IS" BASIS,
  13 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 +// See the License for the specific language governing permissions and
  15 +// limitations under the License.
  16 +//
  17 +// Versions of qpdf prior to version 7 were released under the terms
  18 +// of version 2.0 of the Artistic License. At your option, you may
  19 +// continue to consider qpdf to be licensed under those terms. Please
  20 +// see the manual for additional information.
  21 +
  22 +#ifndef QPDFUSAGE_HH
  23 +#define QPDFUSAGE_HH
  24 +
  25 +#include <qpdf/DLL.h>
  26 +
  27 +#include <string>
  28 +#include <stdexcept>
  29 +
  30 +class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error
  31 +{
  32 + public:
  33 + QPDF_DLL
  34 + QPDFUsage(std::string const& msg);
  35 + QPDF_DLL
  36 + virtual ~QPDFUsage() noexcept = default;
  37 +};
  38 +
  39 +#endif // QPDFUSAGE_HH
libqpdf/JSONHandler.cc
1 #include <qpdf/JSONHandler.hh> 1 #include <qpdf/JSONHandler.hh>
2 #include <qpdf/QUtil.hh> 2 #include <qpdf/QUtil.hh>
3 #include <qpdf/QTC.hh> 3 #include <qpdf/QTC.hh>
4 -  
5 -JSONHandler::Error::Error(std::string const& msg) :  
6 - std::runtime_error(msg)  
7 -{  
8 -} 4 +#include <qpdf/QPDFUsage.hh>
9 5
10 JSONHandler::JSONHandler() : 6 JSONHandler::JSONHandler() :
11 m(new Members()) 7 m(new Members())
@@ -17,6 +13,12 @@ JSONHandler::Members::Members() @@ -17,6 +13,12 @@ JSONHandler::Members::Members()
17 } 13 }
18 14
19 void 15 void
  16 +JSONHandler::usage(std::string const& msg)
  17 +{
  18 + throw QPDFUsage(msg);
  19 +}
  20 +
  21 +void
20 JSONHandler::addAnyHandler(json_handler_t fn) 22 JSONHandler::addAnyHandler(json_handler_t fn)
21 { 23 {
22 this->m->h.any_handler = fn; 24 this->m->h.any_handler = fn;
@@ -128,9 +130,8 @@ JSONHandler::handle(std::string const&amp; path, JSON j) @@ -128,9 +130,8 @@ JSONHandler::handle(std::string const&amp; path, JSON j)
128 else 130 else
129 { 131 {
130 QTC::TC("libtests", "JSONHandler unexpected key"); 132 QTC::TC("libtests", "JSONHandler unexpected key");
131 - throw Error(  
132 - "JSON handler found unexpected key " + k +  
133 - " in object at " + path); 133 + usage("JSON handler found unexpected key " + k +
  134 + " in object at " + path);
134 } 135 }
135 } 136 }
136 else 137 else
@@ -163,7 +164,6 @@ JSONHandler::handle(std::string const&amp; path, JSON j) @@ -163,7 +164,6 @@ JSONHandler::handle(std::string const&amp; path, JSON j)
163 // different if this code were trying to be part of a 164 // different if this code were trying to be part of a
164 // general-purpose JSON package. 165 // general-purpose JSON package.
165 QTC::TC("libtests", "JSONHandler unhandled value"); 166 QTC::TC("libtests", "JSONHandler unhandled value");
166 - throw Error("JSON handler: value at " + path +  
167 - " is not of expected type"); 167 + usage("JSON handler: value at " + path + " is not of expected type");
168 } 168 }
169 } 169 }
libqpdf/QPDFArgParser.cc
@@ -2,15 +2,11 @@ @@ -2,15 +2,11 @@
2 #include <qpdf/QUtil.hh> 2 #include <qpdf/QUtil.hh>
3 #include <qpdf/QIntC.hh> 3 #include <qpdf/QIntC.hh>
4 #include <qpdf/QTC.hh> 4 #include <qpdf/QTC.hh>
  5 +#include <qpdf/QPDFUsage.hh>
5 #include <iostream> 6 #include <iostream>
6 #include <cstring> 7 #include <cstring>
7 #include <cstdlib> 8 #include <cstdlib>
8 9
9 -QPDFArgParser::Usage::Usage(std::string const& msg) :  
10 - std::runtime_error(msg)  
11 -{  
12 -}  
13 -  
14 QPDFArgParser::Members::Members( 10 QPDFArgParser::Members::Members(
15 int argc, char* argv[], char const* progname_env) : 11 int argc, char* argv[], char const* progname_env) :
16 12
@@ -424,7 +420,7 @@ QPDFArgParser::usage(std::string const&amp; message) @@ -424,7 +420,7 @@ QPDFArgParser::usage(std::string const&amp; message)
424 // This will cause bash to fall back to regular file completion. 420 // This will cause bash to fall back to regular file completion.
425 exit(0); 421 exit(0);
426 } 422 }
427 - throw Usage(message); 423 + throw QPDFUsage(message);
428 } 424 }
429 425
430 void 426 void
libqpdf/QPDFJob.cc
@@ -25,21 +25,16 @@ @@ -25,21 +25,16 @@
25 #include <qpdf/QPDFOutlineDocumentHelper.hh> 25 #include <qpdf/QPDFOutlineDocumentHelper.hh>
26 #include <qpdf/QPDFAcroFormDocumentHelper.hh> 26 #include <qpdf/QPDFAcroFormDocumentHelper.hh>
27 #include <qpdf/QPDFExc.hh> 27 #include <qpdf/QPDFExc.hh>
  28 +#include <qpdf/QPDFUsage.hh>
28 #include <qpdf/QPDFSystemError.hh> 29 #include <qpdf/QPDFSystemError.hh>
29 #include <qpdf/QPDFCryptoProvider.hh> 30 #include <qpdf/QPDFCryptoProvider.hh>
30 #include <qpdf/QPDFEmbeddedFileDocumentHelper.hh> 31 #include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
31 #include <qpdf/QPDFArgParser.hh> 32 #include <qpdf/QPDFArgParser.hh>
32 -  
33 #include <qpdf/QPDFWriter.hh> 33 #include <qpdf/QPDFWriter.hh>
34 #include <qpdf/QIntC.hh> 34 #include <qpdf/QIntC.hh>
35 35
36 #include <qpdf/auto_job_schema.hh> // JOB_SCHEMA_DATA 36 #include <qpdf/auto_job_schema.hh> // JOB_SCHEMA_DATA
37 37
38 -QPDFJob::ConfigError::ConfigError(std::string const& msg) :  
39 - std::runtime_error(msg)  
40 -{  
41 -}  
42 -  
43 namespace 38 namespace
44 { 39 {
45 class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider 40 class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider
@@ -452,6 +447,12 @@ QPDFJob::QPDFJob() : @@ -452,6 +447,12 @@ QPDFJob::QPDFJob() :
452 447
453 448
454 void 449 void
  450 +QPDFJob::usage(std::string const& msg)
  451 +{
  452 + throw QPDFUsage(msg);
  453 +}
  454 +
  455 +void
455 QPDFJob::setMessagePrefix(std::string const& message_prefix) 456 QPDFJob::setMessagePrefix(std::string const& message_prefix)
456 { 457 {
457 this->m->message_prefix = message_prefix; 458 this->m->message_prefix = message_prefix;
@@ -548,7 +549,7 @@ QPDFJob::parseRotationParameter(std::string const&amp; parameter) @@ -548,7 +549,7 @@ QPDFJob::parseRotationParameter(std::string const&amp; parameter)
548 } 549 }
549 else 550 else
550 { 551 {
551 - throw ConfigError("invalid parameter to rotate: " + parameter); 552 + usage("invalid parameter to rotate: " + parameter);
552 } 553 }
553 } 554 }
554 555
@@ -561,7 +562,7 @@ QPDFJob::parseNumrange(char const* range, int max) @@ -561,7 +562,7 @@ QPDFJob::parseNumrange(char const* range, int max)
561 } 562 }
562 catch (std::runtime_error& e) 563 catch (std::runtime_error& e)
563 { 564 {
564 - throw ConfigError(e.what()); 565 + usage(e.what());
565 } 566 }
566 return std::vector<int>(); 567 return std::vector<int>();
567 } 568 }
@@ -645,10 +646,6 @@ QPDFJob::createsOutput() const @@ -645,10 +646,6 @@ QPDFJob::createsOutput() const
645 void 646 void
646 QPDFJob::checkConfiguration() 647 QPDFJob::checkConfiguration()
647 { 648 {
648 - auto usage = [](char const* msg){  
649 - throw QPDFJob::ConfigError(msg);  
650 - };  
651 -  
652 // QXXXQ messages are CLI-centric 649 // QXXXQ messages are CLI-centric
653 if (m->replace_input) 650 if (m->replace_input)
654 { 651 {
libqpdf/QPDFJob_argv.cc
@@ -480,7 +480,7 @@ ArgParser::parseOptions() @@ -480,7 +480,7 @@ ArgParser::parseOptions()
480 { 480 {
481 this->ap.parseArgs(); 481 this->ap.parseArgs();
482 } 482 }
483 - catch (QPDFArgParser::Usage& e) 483 + catch (std::runtime_error& e)
484 { 484 {
485 usage(e.what()); 485 usage(e.what());
486 } 486 }
libqpdf/QPDFJob_config.cc
@@ -3,11 +3,6 @@ @@ -3,11 +3,6 @@
3 #include <qpdf/QTC.hh> 3 #include <qpdf/QTC.hh>
4 #include <cstring> 4 #include <cstring>
5 5
6 -static void usage(std::string const& msg)  
7 -{  
8 - throw QPDFJob::ConfigError(msg);  
9 -}  
10 -  
11 QPDFJob::Config* 6 QPDFJob::Config*
12 QPDFJob::Config::inputFile(char const* filename) 7 QPDFJob::Config::inputFile(char const* filename)
13 { 8 {
libqpdf/QPDFSystemError.cc
@@ -10,7 +10,7 @@ QPDFSystemError::QPDFSystemError(std::string const&amp; description, @@ -10,7 +10,7 @@ QPDFSystemError::QPDFSystemError(std::string const&amp; description,
10 { 10 {
11 } 11 }
12 12
13 -QPDFSystemError::~QPDFSystemError() throw () 13 +QPDFSystemError::~QPDFSystemError() noexcept
14 { 14 {
15 } 15 }
16 16
libqpdf/QPDFUsage.cc 0 → 100644
  1 +#include <qpdf/QPDFUsage.hh>
  2 +
  3 +QPDFUsage::QPDFUsage(std::string const& msg) :
  4 + std::runtime_error(msg)
  5 +{
  6 +}
libqpdf/build.mk
@@ -89,6 +89,7 @@ SRCS_libqpdf = \ @@ -89,6 +89,7 @@ SRCS_libqpdf = \
89 libqpdf/QPDFStreamFilter.cc \ 89 libqpdf/QPDFStreamFilter.cc \
90 libqpdf/QPDFSystemError.cc \ 90 libqpdf/QPDFSystemError.cc \
91 libqpdf/QPDFTokenizer.cc \ 91 libqpdf/QPDFTokenizer.cc \
  92 + libqpdf/QPDFUsage.cc \
92 libqpdf/QPDFWriter.cc \ 93 libqpdf/QPDFWriter.cc \
93 libqpdf/QPDFXRefEntry.cc \ 94 libqpdf/QPDFXRefEntry.cc \
94 libqpdf/QPDF_Array.cc \ 95 libqpdf/QPDF_Array.cc \
libtests/arg_parser.cc
1 #include <qpdf/QPDFArgParser.hh> 1 #include <qpdf/QPDFArgParser.hh>
2 #include <qpdf/QUtil.hh> 2 #include <qpdf/QUtil.hh>
  3 +#include <qpdf/QPDFUsage.hh>
3 #include <iostream> 4 #include <iostream>
4 #include <cstring> 5 #include <cstring>
5 #include <cassert> 6 #include <cassert>
@@ -225,7 +226,7 @@ int main(int argc, char* argv[]) @@ -225,7 +226,7 @@ int main(int argc, char* argv[])
225 { 226 {
226 ap.parseArgs(); 227 ap.parseArgs();
227 } 228 }
228 - catch (QPDFArgParser::Usage& e) 229 + catch (QPDFUsage& e)
229 { 230 {
230 std::cerr << "usage: " << e.what() << std::endl; 231 std::cerr << "usage: " << e.what() << std::endl;
231 exit(2); 232 exit(2);
libtests/json_handler.cc
1 #include <qpdf/JSONHandler.hh> 1 #include <qpdf/JSONHandler.hh>
2 #include <qpdf/QUtil.hh> 2 #include <qpdf/QUtil.hh>
  3 +#include <qpdf/QPDFUsage.hh>
3 #include <iostream> 4 #include <iostream>
4 #include <cassert> 5 #include <cassert>
5 6
@@ -120,7 +121,7 @@ static void test_errors() @@ -120,7 +121,7 @@ static void test_errors()
120 fn(); 121 fn();
121 assert(false); 122 assert(false);
122 } 123 }
123 - catch (JSONHandler::Error& e) 124 + catch (QPDFUsage& e)
124 { 125 {
125 std::cout << msg << ": " << e.what() << std::endl; 126 std::cout << msg << ": " << e.what() << std::endl;
126 } 127 }
qpdf/qpdf.cc
1 #include <qpdf/QPDFJob.hh> 1 #include <qpdf/QPDFJob.hh>
2 #include <qpdf/QTC.hh> 2 #include <qpdf/QTC.hh>
3 #include <qpdf/QUtil.hh> 3 #include <qpdf/QUtil.hh>
4 -#include <qpdf/QPDFArgParser.hh> 4 +#include <qpdf/QPDFUsage.hh>
5 5
6 #include <cstdio> 6 #include <cstdio>
7 #include <cstdlib> 7 #include <cstdlib>
@@ -48,11 +48,7 @@ int realmain(int argc, char* argv[]) @@ -48,11 +48,7 @@ int realmain(int argc, char* argv[])
48 j.initializeFromArgv(argc, argv); 48 j.initializeFromArgv(argc, argv);
49 j.run(); 49 j.run();
50 } 50 }
51 - catch (QPDFArgParser::Usage& e)  
52 - {  
53 - usageExit(e.what());  
54 - }  
55 - catch (QPDFJob::ConfigError& e) 51 + catch (QPDFUsage& e)
56 { 52 {
57 usageExit(e.what()); 53 usageExit(e.what());
58 } 54 }