diff --git a/ChangeLog b/ChangeLog index e2b11d6f..41f94467 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2022-01-28 Jay Berkenbilt + + * Add QPDFUsage exception, which is thrown by JSONHandler, + QPDFArgParser, and QPDFJob to indicate command-line usage or job + configuration errors. + 2022-01-22 Jay Berkenbilt * Add QUtil::make_shared_cstr to return a std::shared_ptr diff --git a/include/qpdf/JSONHandler.hh b/include/qpdf/JSONHandler.hh index 0f75f946..73e8295f 100644 --- a/include/qpdf/JSONHandler.hh +++ b/include/qpdf/JSONHandler.hh @@ -28,7 +28,6 @@ #include #include #include -#include #include // This class allows a sax-like walk through a JSON object with @@ -39,15 +38,8 @@ class JSONHandler { public: - // Error exception is thrown if there are any errors validating - // the JSON object. - class QPDF_DLL_CLASS Error: public std::runtime_error - { - public: - QPDF_DLL - Error(std::string const&); - }; - + // A QPDFUsage exception is thrown if there are any errors + // validating the JSON object. QPDF_DLL JSONHandler(); @@ -55,10 +47,10 @@ class JSONHandler ~JSONHandler() = default; // Based on the type of handler, expect the object to be of a - // certain type. JSONHandler::Error is thrown otherwise. Multiple - // handlers may be registered, which allows the object to be of - // various types. If an anyHandler is added, no other handler will - // be called. There is no "final" handler -- if the top-level is a + // certain type. QPDFUsage is thrown otherwise. Multiple handlers + // may be registered, which allows the object to be of various + // types. If an anyHandler is added, no other handler will be + // called. There is no "final" handler -- if the top-level is a // dictionary or array, just use its end handler. typedef std::function #include #include -#include #include // This is not a general-purpose argument parser. It is tightly @@ -56,15 +55,6 @@ class QPDFArgParser { public: - // Usage exception is thrown if there are any errors parsing - // arguments - class QPDF_DLL_CLASS Usage: public std::runtime_error - { - public: - QPDF_DLL - Usage(std::string const&); - }; - // progname_env is used to override argv[0] when figuring out the // name of the executable for setting up completion. This may be // needed if the program is invoked by a wrapper. @@ -72,8 +62,8 @@ class QPDFArgParser QPDFArgParser(int argc, char* argv[], char const* progname_env); // Calls exit(0) if a help option is given or if in completion - // mode. If there are argument parsing errors, - // QPDFArgParser::Usage is thrown. + // mode. If there are argument parsing errors, QPDFUsage is + // thrown. QPDF_DLL void parseArgs(); diff --git a/include/qpdf/QPDFExc.hh b/include/qpdf/QPDFExc.hh index a156412b..faf5ddf6 100644 --- a/include/qpdf/QPDFExc.hh +++ b/include/qpdf/QPDFExc.hh @@ -39,7 +39,7 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error qpdf_offset_t offset, std::string const& message); QPDF_DLL - virtual ~QPDFExc() throw () + virtual ~QPDFExc() noexcept { } diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index 076501ff..e56626a7 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -43,15 +43,8 @@ class QPDFWriter; class QPDFJob { public: - // ConfigError exception is thrown if there are any usage-like - // errors when calling Config methods. - class QPDF_DLL_CLASS ConfigError: public std::runtime_error - { - public: - QPDF_DLL - ConfigError(std::string const&); - }; - + // QPDFUsage is thrown if there are any usage-like errors when + // calling Config methods. QPDF_DLL QPDFJob(); @@ -318,7 +311,9 @@ class QPDFJob friend class Config; // Return a top-level configuration item. See CONFIGURATION above - // for details. + // for details. If an invalid configuration is created (such as + // supplying contradictory options, omitting an input file, etc.), + // QPDFUsage is thrown. QPDF_DLL std::shared_ptr config(); @@ -404,6 +399,7 @@ class QPDFJob }; // Helper functions + static void usage(std::string const& msg); static JSON json_schema(std::set* keys = 0); static void parse_object_id( std::string const& objspec, bool& trailer, int& obj, int& gen); diff --git a/include/qpdf/QPDFSystemError.hh b/include/qpdf/QPDFSystemError.hh index 5d631b8b..16eb3583 100644 --- a/include/qpdf/QPDFSystemError.hh +++ b/include/qpdf/QPDFSystemError.hh @@ -36,7 +36,7 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error QPDFSystemError(std::string const& description, int system_errno); QPDF_DLL - virtual ~QPDFSystemError() throw (); + virtual ~QPDFSystemError() noexcept; // To get a complete error string, call what(), provided by // std::exception. The accessors below return the original values diff --git a/include/qpdf/QPDFUsage.hh b/include/qpdf/QPDFUsage.hh new file mode 100644 index 00000000..124bf188 --- /dev/null +++ b/include/qpdf/QPDFUsage.hh @@ -0,0 +1,39 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFUSAGE_HH +#define QPDFUSAGE_HH + +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error +{ + public: + QPDF_DLL + QPDFUsage(std::string const& msg); + QPDF_DLL + virtual ~QPDFUsage() noexcept = default; +}; + +#endif // QPDFUSAGE_HH diff --git a/libqpdf/JSONHandler.cc b/libqpdf/JSONHandler.cc index 5e3d9a8d..1d374e6a 100644 --- a/libqpdf/JSONHandler.cc +++ b/libqpdf/JSONHandler.cc @@ -1,11 +1,7 @@ #include #include #include - -JSONHandler::Error::Error(std::string const& msg) : - std::runtime_error(msg) -{ -} +#include JSONHandler::JSONHandler() : m(new Members()) @@ -16,6 +12,12 @@ JSONHandler::Members::Members() { } +void +JSONHandler::usage(std::string const& msg) +{ + throw QPDFUsage(msg); +} + void JSONHandler::addAnyHandler(json_handler_t fn) { @@ -128,9 +130,8 @@ JSONHandler::handle(std::string const& path, JSON j) else { QTC::TC("libtests", "JSONHandler unexpected key"); - throw Error( - "JSON handler found unexpected key " + k + - " in object at " + path); + usage("JSON handler found unexpected key " + k + + " in object at " + path); } } else @@ -163,7 +164,6 @@ JSONHandler::handle(std::string const& path, JSON j) // different if this code were trying to be part of a // general-purpose JSON package. QTC::TC("libtests", "JSONHandler unhandled value"); - throw Error("JSON handler: value at " + path + - " is not of expected type"); + usage("JSON handler: value at " + path + " is not of expected type"); } } diff --git a/libqpdf/QPDFArgParser.cc b/libqpdf/QPDFArgParser.cc index c423c7d3..4018d4e1 100644 --- a/libqpdf/QPDFArgParser.cc +++ b/libqpdf/QPDFArgParser.cc @@ -2,15 +2,11 @@ #include #include #include +#include #include #include #include -QPDFArgParser::Usage::Usage(std::string const& msg) : - std::runtime_error(msg) -{ -} - QPDFArgParser::Members::Members( int argc, char* argv[], char const* progname_env) : @@ -424,7 +420,7 @@ QPDFArgParser::usage(std::string const& message) // This will cause bash to fall back to regular file completion. exit(0); } - throw Usage(message); + throw QPDFUsage(message); } void diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index b0143449..8c4efc41 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -25,21 +25,16 @@ #include #include #include +#include #include #include #include #include - #include #include #include // JOB_SCHEMA_DATA -QPDFJob::ConfigError::ConfigError(std::string const& msg) : - std::runtime_error(msg) -{ -} - namespace { class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider @@ -451,6 +446,12 @@ QPDFJob::QPDFJob() : } +void +QPDFJob::usage(std::string const& msg) +{ + throw QPDFUsage(msg); +} + void QPDFJob::setMessagePrefix(std::string const& message_prefix) { @@ -548,7 +549,7 @@ QPDFJob::parseRotationParameter(std::string const& parameter) } else { - throw ConfigError("invalid parameter to rotate: " + parameter); + usage("invalid parameter to rotate: " + parameter); } } @@ -561,7 +562,7 @@ QPDFJob::parseNumrange(char const* range, int max) } catch (std::runtime_error& e) { - throw ConfigError(e.what()); + usage(e.what()); } return std::vector(); } @@ -645,10 +646,6 @@ QPDFJob::createsOutput() const void QPDFJob::checkConfiguration() { - auto usage = [](char const* msg){ - throw QPDFJob::ConfigError(msg); - }; - // QXXXQ messages are CLI-centric if (m->replace_input) { diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc index 36a2a2a6..8bf4c48b 100644 --- a/libqpdf/QPDFJob_argv.cc +++ b/libqpdf/QPDFJob_argv.cc @@ -480,7 +480,7 @@ ArgParser::parseOptions() { this->ap.parseArgs(); } - catch (QPDFArgParser::Usage& e) + catch (std::runtime_error& e) { usage(e.what()); } diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc index 74fff62d..53032cea 100644 --- a/libqpdf/QPDFJob_config.cc +++ b/libqpdf/QPDFJob_config.cc @@ -3,11 +3,6 @@ #include #include -static void usage(std::string const& msg) -{ - throw QPDFJob::ConfigError(msg); -} - QPDFJob::Config* QPDFJob::Config::inputFile(char const* filename) { diff --git a/libqpdf/QPDFSystemError.cc b/libqpdf/QPDFSystemError.cc index 65aeaab7..73bad61e 100644 --- a/libqpdf/QPDFSystemError.cc +++ b/libqpdf/QPDFSystemError.cc @@ -10,7 +10,7 @@ QPDFSystemError::QPDFSystemError(std::string const& description, { } -QPDFSystemError::~QPDFSystemError() throw () +QPDFSystemError::~QPDFSystemError() noexcept { } diff --git a/libqpdf/QPDFUsage.cc b/libqpdf/QPDFUsage.cc new file mode 100644 index 00000000..5390b388 --- /dev/null +++ b/libqpdf/QPDFUsage.cc @@ -0,0 +1,6 @@ +#include + +QPDFUsage::QPDFUsage(std::string const& msg) : + std::runtime_error(msg) +{ +} diff --git a/libqpdf/build.mk b/libqpdf/build.mk index 8cedb44a..e16ba5e1 100644 --- a/libqpdf/build.mk +++ b/libqpdf/build.mk @@ -89,6 +89,7 @@ SRCS_libqpdf = \ libqpdf/QPDFStreamFilter.cc \ libqpdf/QPDFSystemError.cc \ libqpdf/QPDFTokenizer.cc \ + libqpdf/QPDFUsage.cc \ libqpdf/QPDFWriter.cc \ libqpdf/QPDFXRefEntry.cc \ libqpdf/QPDF_Array.cc \ diff --git a/libtests/arg_parser.cc b/libtests/arg_parser.cc index 602a0f3f..e17ebdd1 100644 --- a/libtests/arg_parser.cc +++ b/libtests/arg_parser.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -225,7 +226,7 @@ int main(int argc, char* argv[]) { ap.parseArgs(); } - catch (QPDFArgParser::Usage& e) + catch (QPDFUsage& e) { std::cerr << "usage: " << e.what() << std::endl; exit(2); diff --git a/libtests/json_handler.cc b/libtests/json_handler.cc index 7f6349f9..c1af238f 100644 --- a/libtests/json_handler.cc +++ b/libtests/json_handler.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -120,7 +121,7 @@ static void test_errors() fn(); assert(false); } - catch (JSONHandler::Error& e) + catch (QPDFUsage& e) { std::cout << msg << ": " << e.what() << std::endl; } diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index 0e7eaf65..508fb579 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include @@ -48,11 +48,7 @@ int realmain(int argc, char* argv[]) j.initializeFromArgv(argc, argv); j.run(); } - catch (QPDFArgParser::Usage& e) - { - usageExit(e.what()); - } - catch (QPDFJob::ConfigError& e) + catch (QPDFUsage& e) { usageExit(e.what()); }