Commit 0364024781ffa709a1a86ae9c6638f71df0317ca
1 parent
764feb0f
Use QPDFUsage exception for cli, json, and QPDFJob errors
Showing
18 changed files
with
99 additions
and
81 deletions
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
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& 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& 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& 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& 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
libqpdf/QPDFJob_config.cc
libqpdf/QPDFSystemError.cc
libqpdf/QPDFUsage.cc
0 → 100644
libqpdf/build.mk
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 | } | ... | ... |