aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDFJob_json.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-01-29 18:29:38 +0100
committerJay Berkenbilt <ejb@ql.org>2022-01-31 21:57:45 +0100
commit842a9d928e0061dfe04806eae2bc87ad4db47331 (patch)
treeb3dfe4e876bf9f411e2a98aae10d4b3bc4376196 /libqpdf/QPDFJob_json.cc
parent967a2b9f2842fc147ea14752ee4693ad94305aba (diff)
downloadqpdf-842a9d928e0061dfe04806eae2bc87ad4db47331.tar.zst
QPDFJob_json: add code to register handlers
Diffstat (limited to 'libqpdf/QPDFJob_json.cc')
-rw-r--r--libqpdf/QPDFJob_json.cc216
1 files changed, 168 insertions, 48 deletions
diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc
index 076b5a75..0b2f049c 100644
--- a/libqpdf/QPDFJob_json.cc
+++ b/libqpdf/QPDFJob_json.cc
@@ -1,9 +1,11 @@
#include <qpdf/QPDFJob.hh>
#include <qpdf/JSONHandler.hh>
+#include <qpdf/QPDFUsage.hh>
#include <memory>
#include <stdexcept>
#include <sstream>
+#include <cstring>
static JSON JOB_SCHEMA = JSON::parse(QPDFJob::json_job_schema_v1().c_str());
@@ -21,7 +23,22 @@ namespace
void usage(std::string const& message);
void initHandlers();
- JSONHandler jh;
+ typedef std::function<void()> bare_arg_handler_t;
+ typedef std::function<void(char const*)> param_arg_handler_t;
+
+ void addBare(std::string const& key, bare_arg_handler_t);
+ void addParameter(std::string const& key, bool required,
+ param_arg_handler_t);
+ void addChoices(std::string const& key,
+ bool required, char const** choices,
+ param_arg_handler_t);
+ void beginDict(std::string const& key,
+ bare_arg_handler_t start_fn,
+ bare_arg_handler_t end_fn);
+ void endDict();
+
+ std::list<std::shared_ptr<JSONHandler>> json_handlers;
+ JSONHandler* jh; // points to last of json_handlers
std::shared_ptr<QPDFJob::Config> c_main;
std::shared_ptr<QPDFJob::CopyAttConfig> c_copy_att;
std::shared_ptr<QPDFJob::AttConfig> c_att;
@@ -32,72 +49,175 @@ namespace
}
Handlers::Handlers(std::shared_ptr<QPDFJob::Config> c_main) :
+ jh(nullptr),
c_main(c_main)
{
initHandlers();
}
void
+Handlers::usage(std::string const& message)
+{
+ throw QPDFUsage(message);
+}
+
+void
Handlers::initHandlers()
{
-# include <qpdf/auto_job_json_init.hh>
- jh.addDictHandlers(
+ this->json_handlers.push_back(std::make_shared<JSONHandler>());
+ this->jh = this->json_handlers.back().get();
+ jh->addDictHandlers(
[](std::string const&){},
[this](std::string const&){c_main->checkConfiguration();});
- auto input = std::make_shared<JSONHandler>();
- auto input_file = std::make_shared<JSONHandler>();
- auto input_file_name = std::make_shared<JSONHandler>();
- auto output = std::make_shared<JSONHandler>();
- auto output_file = std::make_shared<JSONHandler>();
- auto output_file_name = std::make_shared<JSONHandler>();
- auto output_options = std::make_shared<JSONHandler>();
- auto output_options_qdf = std::make_shared<JSONHandler>();
+# include <qpdf/auto_job_json_init.hh>
- input->addDictHandlers(
- [](std::string const&){},
- [](std::string const&){});
- input_file->addDictHandlers(
- [](std::string const&){},
- [](std::string const&){});
- output->addDictHandlers(
- [](std::string const&){},
- [](std::string const&){});
- output_file->addDictHandlers(
- [](std::string const&){},
- [](std::string const&){});
- output_options->addDictHandlers(
- [](std::string const&){},
- [](std::string const&){});
-
- jh.addDictKeyHandler("input", input);
- input->addDictKeyHandler("file", input_file);
- input_file->addDictKeyHandler("name", input_file_name);
- jh.addDictKeyHandler("output", output);
- output->addDictKeyHandler("file", output_file);
- output_file->addDictKeyHandler("name", output_file_name);
- output->addDictKeyHandler("options", output_options);
- output_options->addDictKeyHandler("qdf", output_options_qdf);
-
- input_file_name->addStringHandler(
- [this](std::string const&, std::string const& v) {
- c_main->inputFile(v.c_str());
- });
- output_file_name->addStringHandler(
- [this](std::string const&, std::string const& v) {
- c_main->outputFile(v.c_str());
+ // QXXXQ
+ auto empty = [](){};
+ beginDict("input", empty, empty);
+ beginDict("file", empty, empty);
+ addParameter("name", true, [this](char const* p) {
+ c_main->inputFile(p);
+ });
+ endDict(); // input.file
+ endDict(); // input
+ beginDict("output", empty, empty);
+ beginDict("file", empty, empty);
+ addParameter("name", true, [this](char const* p) {
+ c_main->outputFile(p);
+ });
+ endDict(); // output.file
+ beginDict("options", empty, empty);
+ addBare("qdf", [this]() {
+ c_main->qdf();
+ });
+ char const* choices[] = {"disable", "preserve", "generate", 0};
+ addChoices("objectStreams", true, choices, [this](char const* p) {
+ c_main->objectStreams(p);
+ });
+ endDict(); // output.options
+ endDict(); // output
+ // /QXXXQ
+
+ if (this->json_handlers.size() != 1)
+ {
+ throw std::logic_error("QPDFJob_json: json_handlers size != 1 at end");
+ }
+}
+
+void
+Handlers::addBare(std::string const& key, bare_arg_handler_t fn)
+{
+ auto h = std::make_shared<JSONHandler>();
+ h->addBoolHandler([this, fn](std::string const& path, bool v){
+ if (! v)
+ {
+ usage(path + ": value must be true");
+ }
+ else
+ {
+ fn();
+ }
+ });
+ jh->addDictKeyHandler(key, h);
+}
+
+void
+Handlers::addParameter(std::string const& key,
+ bool required,
+ param_arg_handler_t fn)
+{
+ auto h = std::make_shared<JSONHandler>();
+ h->addStringHandler(
+ [fn](std::string const& path, std::string const& parameter){
+ fn(parameter.c_str());
});
- output_options_qdf->addBoolHandler(
- [this](std::string const&, bool v) {
- // QXXXQ require v to be true
- c_main->qdf();
+ if (! required)
+ {
+ h->addNullHandler(
+ [fn](std::string const& path){
+ fn(nullptr);
+ });
+ }
+ jh->addDictKeyHandler(key, h);
+}
+
+void
+Handlers::addChoices(std::string const& key,
+ bool required, char const** choices,
+ param_arg_handler_t fn)
+{
+ auto h = std::make_shared<JSONHandler>();
+ h->addStringHandler(
+ [fn, choices, this](
+ std::string const& path, std::string const& parameter){
+
+ char const* p = parameter.c_str();
+ bool matches = false;
+ for (char const** i = choices; *i; ++i)
+ {
+ if (strcmp(*i, p) == 0)
+ {
+ matches = true;
+ break;
+ }
+ }
+ if (! matches)
+ {
+ std::ostringstream msg;
+ msg << path + ": unexpected value; expected one of ";
+ bool first = true;
+ for (char const** i = choices; *i; ++i)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ msg << ", ";
+ }
+ msg << *i;
+ }
+ usage(msg.str());
+ }
+ fn(parameter.c_str());
});
+ if (! required)
+ {
+ h->addNullHandler(
+ [fn](std::string const& path){
+ fn(nullptr);
+ });
+ }
+ jh->addDictKeyHandler(key, h);
+}
+
+void
+Handlers::beginDict(std::string const& key,
+ bare_arg_handler_t start_fn,
+ bare_arg_handler_t end_fn)
+{
+ auto new_jh = std::make_shared<JSONHandler>();
+ new_jh->addDictHandlers(
+ [start_fn](std::string const&){ start_fn(); },
+ [end_fn](std::string const&){ end_fn(); });
+ this->jh->addDictKeyHandler(key, new_jh);
+ this->json_handlers.push_back(new_jh);
+ this->jh = new_jh.get();
+}
+
+void
+Handlers::endDict()
+{
+ this->json_handlers.pop_back();
+ this->jh = this->json_handlers.back().get();
}
void
Handlers::handle(JSON& j)
{
- jh.handle(".", j);
+ this->json_handlers.back()->handle(".", j);
}
void