Commit 842a9d928e0061dfe04806eae2bc87ad4db47331

Authored by Jay Berkenbilt
1 parent 967a2b9f

QPDFJob_json: add code to register handlers

Showing 1 changed file with 168 additions and 48 deletions
libqpdf/QPDFJob_json.cc
1 #include <qpdf/QPDFJob.hh> 1 #include <qpdf/QPDFJob.hh>
2 #include <qpdf/JSONHandler.hh> 2 #include <qpdf/JSONHandler.hh>
  3 +#include <qpdf/QPDFUsage.hh>
3 4
4 #include <memory> 5 #include <memory>
5 #include <stdexcept> 6 #include <stdexcept>
6 #include <sstream> 7 #include <sstream>
  8 +#include <cstring>
7 9
8 static JSON JOB_SCHEMA = JSON::parse(QPDFJob::json_job_schema_v1().c_str()); 10 static JSON JOB_SCHEMA = JSON::parse(QPDFJob::json_job_schema_v1().c_str());
9 11
@@ -21,7 +23,22 @@ namespace @@ -21,7 +23,22 @@ namespace
21 void usage(std::string const& message); 23 void usage(std::string const& message);
22 void initHandlers(); 24 void initHandlers();
23 25
24 - JSONHandler jh; 26 + typedef std::function<void()> bare_arg_handler_t;
  27 + typedef std::function<void(char const*)> param_arg_handler_t;
  28 +
  29 + void addBare(std::string const& key, bare_arg_handler_t);
  30 + void addParameter(std::string const& key, bool required,
  31 + param_arg_handler_t);
  32 + void addChoices(std::string const& key,
  33 + bool required, char const** choices,
  34 + param_arg_handler_t);
  35 + void beginDict(std::string const& key,
  36 + bare_arg_handler_t start_fn,
  37 + bare_arg_handler_t end_fn);
  38 + void endDict();
  39 +
  40 + std::list<std::shared_ptr<JSONHandler>> json_handlers;
  41 + JSONHandler* jh; // points to last of json_handlers
25 std::shared_ptr<QPDFJob::Config> c_main; 42 std::shared_ptr<QPDFJob::Config> c_main;
26 std::shared_ptr<QPDFJob::CopyAttConfig> c_copy_att; 43 std::shared_ptr<QPDFJob::CopyAttConfig> c_copy_att;
27 std::shared_ptr<QPDFJob::AttConfig> c_att; 44 std::shared_ptr<QPDFJob::AttConfig> c_att;
@@ -32,72 +49,175 @@ namespace @@ -32,72 +49,175 @@ namespace
32 } 49 }
33 50
34 Handlers::Handlers(std::shared_ptr<QPDFJob::Config> c_main) : 51 Handlers::Handlers(std::shared_ptr<QPDFJob::Config> c_main) :
  52 + jh(nullptr),
35 c_main(c_main) 53 c_main(c_main)
36 { 54 {
37 initHandlers(); 55 initHandlers();
38 } 56 }
39 57
40 void 58 void
  59 +Handlers::usage(std::string const& message)
  60 +{
  61 + throw QPDFUsage(message);
  62 +}
  63 +
  64 +void
41 Handlers::initHandlers() 65 Handlers::initHandlers()
42 { 66 {
43 -# include <qpdf/auto_job_json_init.hh>  
44 - jh.addDictHandlers( 67 + this->json_handlers.push_back(std::make_shared<JSONHandler>());
  68 + this->jh = this->json_handlers.back().get();
  69 + jh->addDictHandlers(
45 [](std::string const&){}, 70 [](std::string const&){},
46 [this](std::string const&){c_main->checkConfiguration();}); 71 [this](std::string const&){c_main->checkConfiguration();});
47 72
48 - auto input = std::make_shared<JSONHandler>();  
49 - auto input_file = std::make_shared<JSONHandler>();  
50 - auto input_file_name = std::make_shared<JSONHandler>();  
51 - auto output = std::make_shared<JSONHandler>();  
52 - auto output_file = std::make_shared<JSONHandler>();  
53 - auto output_file_name = std::make_shared<JSONHandler>();  
54 - auto output_options = std::make_shared<JSONHandler>();  
55 - auto output_options_qdf = std::make_shared<JSONHandler>(); 73 +# include <qpdf/auto_job_json_init.hh>
56 74
57 - input->addDictHandlers(  
58 - [](std::string const&){},  
59 - [](std::string const&){});  
60 - input_file->addDictHandlers(  
61 - [](std::string const&){},  
62 - [](std::string const&){});  
63 - output->addDictHandlers(  
64 - [](std::string const&){},  
65 - [](std::string const&){});  
66 - output_file->addDictHandlers(  
67 - [](std::string const&){},  
68 - [](std::string const&){});  
69 - output_options->addDictHandlers(  
70 - [](std::string const&){},  
71 - [](std::string const&){});  
72 -  
73 - jh.addDictKeyHandler("input", input);  
74 - input->addDictKeyHandler("file", input_file);  
75 - input_file->addDictKeyHandler("name", input_file_name);  
76 - jh.addDictKeyHandler("output", output);  
77 - output->addDictKeyHandler("file", output_file);  
78 - output_file->addDictKeyHandler("name", output_file_name);  
79 - output->addDictKeyHandler("options", output_options);  
80 - output_options->addDictKeyHandler("qdf", output_options_qdf);  
81 -  
82 - input_file_name->addStringHandler(  
83 - [this](std::string const&, std::string const& v) {  
84 - c_main->inputFile(v.c_str());  
85 - });  
86 - output_file_name->addStringHandler(  
87 - [this](std::string const&, std::string const& v) {  
88 - c_main->outputFile(v.c_str()); 75 + // QXXXQ
  76 + auto empty = [](){};
  77 + beginDict("input", empty, empty);
  78 + beginDict("file", empty, empty);
  79 + addParameter("name", true, [this](char const* p) {
  80 + c_main->inputFile(p);
  81 + });
  82 + endDict(); // input.file
  83 + endDict(); // input
  84 + beginDict("output", empty, empty);
  85 + beginDict("file", empty, empty);
  86 + addParameter("name", true, [this](char const* p) {
  87 + c_main->outputFile(p);
  88 + });
  89 + endDict(); // output.file
  90 + beginDict("options", empty, empty);
  91 + addBare("qdf", [this]() {
  92 + c_main->qdf();
  93 + });
  94 + char const* choices[] = {"disable", "preserve", "generate", 0};
  95 + addChoices("objectStreams", true, choices, [this](char const* p) {
  96 + c_main->objectStreams(p);
  97 + });
  98 + endDict(); // output.options
  99 + endDict(); // output
  100 + // /QXXXQ
  101 +
  102 + if (this->json_handlers.size() != 1)
  103 + {
  104 + throw std::logic_error("QPDFJob_json: json_handlers size != 1 at end");
  105 + }
  106 +}
  107 +
  108 +void
  109 +Handlers::addBare(std::string const& key, bare_arg_handler_t fn)
  110 +{
  111 + auto h = std::make_shared<JSONHandler>();
  112 + h->addBoolHandler([this, fn](std::string const& path, bool v){
  113 + if (! v)
  114 + {
  115 + usage(path + ": value must be true");
  116 + }
  117 + else
  118 + {
  119 + fn();
  120 + }
  121 + });
  122 + jh->addDictKeyHandler(key, h);
  123 +}
  124 +
  125 +void
  126 +Handlers::addParameter(std::string const& key,
  127 + bool required,
  128 + param_arg_handler_t fn)
  129 +{
  130 + auto h = std::make_shared<JSONHandler>();
  131 + h->addStringHandler(
  132 + [fn](std::string const& path, std::string const& parameter){
  133 + fn(parameter.c_str());
89 }); 134 });
90 - output_options_qdf->addBoolHandler(  
91 - [this](std::string const&, bool v) {  
92 - // QXXXQ require v to be true  
93 - c_main->qdf(); 135 + if (! required)
  136 + {
  137 + h->addNullHandler(
  138 + [fn](std::string const& path){
  139 + fn(nullptr);
  140 + });
  141 + }
  142 + jh->addDictKeyHandler(key, h);
  143 +}
  144 +
  145 +void
  146 +Handlers::addChoices(std::string const& key,
  147 + bool required, char const** choices,
  148 + param_arg_handler_t fn)
  149 +{
  150 + auto h = std::make_shared<JSONHandler>();
  151 + h->addStringHandler(
  152 + [fn, choices, this](
  153 + std::string const& path, std::string const& parameter){
  154 +
  155 + char const* p = parameter.c_str();
  156 + bool matches = false;
  157 + for (char const** i = choices; *i; ++i)
  158 + {
  159 + if (strcmp(*i, p) == 0)
  160 + {
  161 + matches = true;
  162 + break;
  163 + }
  164 + }
  165 + if (! matches)
  166 + {
  167 + std::ostringstream msg;
  168 + msg << path + ": unexpected value; expected one of ";
  169 + bool first = true;
  170 + for (char const** i = choices; *i; ++i)
  171 + {
  172 + if (first)
  173 + {
  174 + first = false;
  175 + }
  176 + else
  177 + {
  178 + msg << ", ";
  179 + }
  180 + msg << *i;
  181 + }
  182 + usage(msg.str());
  183 + }
  184 + fn(parameter.c_str());
94 }); 185 });
  186 + if (! required)
  187 + {
  188 + h->addNullHandler(
  189 + [fn](std::string const& path){
  190 + fn(nullptr);
  191 + });
  192 + }
  193 + jh->addDictKeyHandler(key, h);
  194 +}
  195 +
  196 +void
  197 +Handlers::beginDict(std::string const& key,
  198 + bare_arg_handler_t start_fn,
  199 + bare_arg_handler_t end_fn)
  200 +{
  201 + auto new_jh = std::make_shared<JSONHandler>();
  202 + new_jh->addDictHandlers(
  203 + [start_fn](std::string const&){ start_fn(); },
  204 + [end_fn](std::string const&){ end_fn(); });
  205 + this->jh->addDictKeyHandler(key, new_jh);
  206 + this->json_handlers.push_back(new_jh);
  207 + this->jh = new_jh.get();
  208 +}
  209 +
  210 +void
  211 +Handlers::endDict()
  212 +{
  213 + this->json_handlers.pop_back();
  214 + this->jh = this->json_handlers.back().get();
95 } 215 }
96 216
97 void 217 void
98 Handlers::handle(JSON& j) 218 Handlers::handle(JSON& j)
99 { 219 {
100 - jh.handle(".", j); 220 + this->json_handlers.back()->handle(".", j);
101 } 221 }
102 222
103 void 223 void