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 7 2022-01-22 Jay Berkenbilt <ejb@ql.org>
2 8  
3 9 * Add QUtil::make_shared_cstr to return a std::shared_ptr<char>
... ...
include/qpdf/JSONHandler.hh
... ... @@ -28,7 +28,6 @@
28 28 #include <string>
29 29 #include <map>
30 30 #include <functional>
31   -#include <stdexcept>
32 31 #include <memory>
33 32  
34 33 // This class allows a sax-like walk through a JSON object with
... ... @@ -39,15 +38,8 @@
39 38 class JSONHandler
40 39 {
41 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 43 QPDF_DLL
52 44 JSONHandler();
53 45  
... ... @@ -55,10 +47,10 @@ class JSONHandler
55 47 ~JSONHandler() = default;
56 48  
57 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 54 // dictionary or array, just use its end handler.
63 55  
64 56 typedef std::function<void(
... ... @@ -106,6 +98,8 @@ class JSONHandler
106 98 private:
107 99 JSONHandler(JSONHandler const&) = delete;
108 100  
  101 + static void usage(std::string const& msg);
  102 +
109 103 struct Handlers
110 104 {
111 105 Handlers() :
... ...
include/qpdf/QPDFArgParser.hh
... ... @@ -29,7 +29,6 @@
29 29 #include <map>
30 30 #include <vector>
31 31 #include <functional>
32   -#include <stdexcept>
33 32 #include <sstream>
34 33  
35 34 // This is not a general-purpose argument parser. It is tightly
... ... @@ -56,15 +55,6 @@
56 55 class QPDFArgParser
57 56 {
58 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 58 // progname_env is used to override argv[0] when figuring out the
69 59 // name of the executable for setting up completion. This may be
70 60 // needed if the program is invoked by a wrapper.
... ... @@ -72,8 +62,8 @@ class QPDFArgParser
72 62 QPDFArgParser(int argc, char* argv[], char const* progname_env);
73 63  
74 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 67 QPDF_DLL
78 68 void parseArgs();
79 69  
... ...
include/qpdf/QPDFExc.hh
... ... @@ -39,7 +39,7 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
39 39 qpdf_offset_t offset,
40 40 std::string const& message);
41 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 43 class QPDFJob
44 44 {
45 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 48 QPDF_DLL
56 49 QPDFJob();
57 50  
... ... @@ -318,7 +311,9 @@ class QPDFJob
318 311 friend class Config;
319 312  
320 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 317 QPDF_DLL
323 318 std::shared_ptr<Config> config();
324 319  
... ... @@ -404,6 +399,7 @@ class QPDFJob
404 399 };
405 400  
406 401 // Helper functions
  402 + static void usage(std::string const& msg);
407 403 static JSON json_schema(std::set<std::string>* keys = 0);
408 404 static void parse_object_id(
409 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 36 QPDFSystemError(std::string const& description,
37 37 int system_errno);
38 38 QPDF_DLL
39   - virtual ~QPDFSystemError() throw ();
  39 + virtual ~QPDFSystemError() noexcept;
40 40  
41 41 // To get a complete error string, call what(), provided by
42 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 1 #include <qpdf/JSONHandler.hh>
2 2 #include <qpdf/QUtil.hh>
3 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 6 JSONHandler::JSONHandler() :
11 7 m(new Members())
... ... @@ -17,6 +13,12 @@ JSONHandler::Members::Members()
17 13 }
18 14  
19 15 void
  16 +JSONHandler::usage(std::string const& msg)
  17 +{
  18 + throw QPDFUsage(msg);
  19 +}
  20 +
  21 +void
20 22 JSONHandler::addAnyHandler(json_handler_t fn)
21 23 {
22 24 this->m->h.any_handler = fn;
... ... @@ -128,9 +130,8 @@ JSONHandler::handle(std::string const&amp; path, JSON j)
128 130 else
129 131 {
130 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 137 else
... ... @@ -163,7 +164,6 @@ JSONHandler::handle(std::string const&amp; path, JSON j)
163 164 // different if this code were trying to be part of a
164 165 // general-purpose JSON package.
165 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 2 #include <qpdf/QUtil.hh>
3 3 #include <qpdf/QIntC.hh>
4 4 #include <qpdf/QTC.hh>
  5 +#include <qpdf/QPDFUsage.hh>
5 6 #include <iostream>
6 7 #include <cstring>
7 8 #include <cstdlib>
8 9  
9   -QPDFArgParser::Usage::Usage(std::string const& msg) :
10   - std::runtime_error(msg)
11   -{
12   -}
13   -
14 10 QPDFArgParser::Members::Members(
15 11 int argc, char* argv[], char const* progname_env) :
16 12  
... ... @@ -424,7 +420,7 @@ QPDFArgParser::usage(std::string const&amp; message)
424 420 // This will cause bash to fall back to regular file completion.
425 421 exit(0);
426 422 }
427   - throw Usage(message);
  423 + throw QPDFUsage(message);
428 424 }
429 425  
430 426 void
... ...
libqpdf/QPDFJob.cc
... ... @@ -25,21 +25,16 @@
25 25 #include <qpdf/QPDFOutlineDocumentHelper.hh>
26 26 #include <qpdf/QPDFAcroFormDocumentHelper.hh>
27 27 #include <qpdf/QPDFExc.hh>
  28 +#include <qpdf/QPDFUsage.hh>
28 29 #include <qpdf/QPDFSystemError.hh>
29 30 #include <qpdf/QPDFCryptoProvider.hh>
30 31 #include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
31 32 #include <qpdf/QPDFArgParser.hh>
32   -
33 33 #include <qpdf/QPDFWriter.hh>
34 34 #include <qpdf/QIntC.hh>
35 35  
36 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 38 namespace
44 39 {
45 40 class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider
... ... @@ -452,6 +447,12 @@ QPDFJob::QPDFJob() :
452 447  
453 448  
454 449 void
  450 +QPDFJob::usage(std::string const& msg)
  451 +{
  452 + throw QPDFUsage(msg);
  453 +}
  454 +
  455 +void
455 456 QPDFJob::setMessagePrefix(std::string const& message_prefix)
456 457 {
457 458 this->m->message_prefix = message_prefix;
... ... @@ -548,7 +549,7 @@ QPDFJob::parseRotationParameter(std::string const&amp; parameter)
548 549 }
549 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 562 }
562 563 catch (std::runtime_error& e)
563 564 {
564   - throw ConfigError(e.what());
  565 + usage(e.what());
565 566 }
566 567 return std::vector<int>();
567 568 }
... ... @@ -645,10 +646,6 @@ QPDFJob::createsOutput() const
645 646 void
646 647 QPDFJob::checkConfiguration()
647 648 {
648   - auto usage = [](char const* msg){
649   - throw QPDFJob::ConfigError(msg);
650   - };
651   -
652 649 // QXXXQ messages are CLI-centric
653 650 if (m->replace_input)
654 651 {
... ...
libqpdf/QPDFJob_argv.cc
... ... @@ -480,7 +480,7 @@ ArgParser::parseOptions()
480 480 {
481 481 this->ap.parseArgs();
482 482 }
483   - catch (QPDFArgParser::Usage& e)
  483 + catch (std::runtime_error& e)
484 484 {
485 485 usage(e.what());
486 486 }
... ...
libqpdf/QPDFJob_config.cc
... ... @@ -3,11 +3,6 @@
3 3 #include <qpdf/QTC.hh>
4 4 #include <cstring>
5 5  
6   -static void usage(std::string const& msg)
7   -{
8   - throw QPDFJob::ConfigError(msg);
9   -}
10   -
11 6 QPDFJob::Config*
12 7 QPDFJob::Config::inputFile(char const* filename)
13 8 {
... ...
libqpdf/QPDFSystemError.cc
... ... @@ -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 89 libqpdf/QPDFStreamFilter.cc \
90 90 libqpdf/QPDFSystemError.cc \
91 91 libqpdf/QPDFTokenizer.cc \
  92 + libqpdf/QPDFUsage.cc \
92 93 libqpdf/QPDFWriter.cc \
93 94 libqpdf/QPDFXRefEntry.cc \
94 95 libqpdf/QPDF_Array.cc \
... ...
libtests/arg_parser.cc
1 1 #include <qpdf/QPDFArgParser.hh>
2 2 #include <qpdf/QUtil.hh>
  3 +#include <qpdf/QPDFUsage.hh>
3 4 #include <iostream>
4 5 #include <cstring>
5 6 #include <cassert>
... ... @@ -225,7 +226,7 @@ int main(int argc, char* argv[])
225 226 {
226 227 ap.parseArgs();
227 228 }
228   - catch (QPDFArgParser::Usage& e)
  229 + catch (QPDFUsage& e)
229 230 {
230 231 std::cerr << "usage: " << e.what() << std::endl;
231 232 exit(2);
... ...
libtests/json_handler.cc
1 1 #include <qpdf/JSONHandler.hh>
2 2 #include <qpdf/QUtil.hh>
  3 +#include <qpdf/QPDFUsage.hh>
3 4 #include <iostream>
4 5 #include <cassert>
5 6  
... ... @@ -120,7 +121,7 @@ static void test_errors()
120 121 fn();
121 122 assert(false);
122 123 }
123   - catch (JSONHandler::Error& e)
  124 + catch (QPDFUsage& e)
124 125 {
125 126 std::cout << msg << ": " << e.what() << std::endl;
126 127 }
... ...
qpdf/qpdf.cc
1 1 #include <qpdf/QPDFJob.hh>
2 2 #include <qpdf/QTC.hh>
3 3 #include <qpdf/QUtil.hh>
4   -#include <qpdf/QPDFArgParser.hh>
  4 +#include <qpdf/QPDFUsage.hh>
5 5  
6 6 #include <cstdio>
7 7 #include <cstdlib>
... ... @@ -48,11 +48,7 @@ int realmain(int argc, char* argv[])
48 48 j.initializeFromArgv(argc, argv);
49 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 53 usageExit(e.what());
58 54 }
... ...