Commit 7de0b3f3c083990842523112959f8e27a0d2e5a0

Authored by Jay Berkenbilt
1 parent 12f7a446

JSONHandler: add fallback handler support

.idea/dictionaries/ejb.xml
1 <component name="ProjectDictionaryState"> 1 <component name="ProjectDictionaryState">
2 <dictionary name="ejb"> 2 <dictionary name="ejb">
3 <words> 3 <words>
  4 + <w>phour</w>
4 <w>whoami</w> 5 <w>whoami</w>
5 </words> 6 </words>
6 </dictionary> 7 </dictionary>
libqpdf/JSONHandler.cc
@@ -17,10 +17,10 @@ struct Handlers @@ -17,10 +17,10 @@ struct Handlers
17 JSONHandler::void_handler_t dict_end_handler{nullptr}; 17 JSONHandler::void_handler_t dict_end_handler{nullptr};
18 JSONHandler::json_handler_t array_start_handler{nullptr}; 18 JSONHandler::json_handler_t array_start_handler{nullptr};
19 JSONHandler::void_handler_t array_end_handler{nullptr}; 19 JSONHandler::void_handler_t array_end_handler{nullptr};
20 - JSONHandler::void_handler_t final_handler{nullptr};  
21 std::map<std::string, std::shared_ptr<JSONHandler>> dict_handlers; 20 std::map<std::string, std::shared_ptr<JSONHandler>> dict_handlers;
22 std::shared_ptr<JSONHandler> fallback_dict_handler; 21 std::shared_ptr<JSONHandler> fallback_dict_handler;
23 std::shared_ptr<JSONHandler> array_item_handler; 22 std::shared_ptr<JSONHandler> array_item_handler;
  23 + std::shared_ptr<JSONHandler> fallback_handler;
24 }; 24 };
25 25
26 class JSONHandler::Members 26 class JSONHandler::Members
@@ -111,6 +111,12 @@ JSONHandler::addArrayHandlers( @@ -111,6 +111,12 @@ JSONHandler::addArrayHandlers(
111 } 111 }
112 112
113 void 113 void
  114 +JSONHandler::addFallbackHandler(std::shared_ptr<JSONHandler> h)
  115 +{
  116 + m->h.fallback_handler = std::move(h);
  117 +}
  118 +
  119 +void
114 JSONHandler::handle(std::string const& path, JSON j) 120 JSONHandler::handle(std::string const& path, JSON j)
115 { 121 {
116 if (m->h.any_handler) { 122 if (m->h.any_handler) {
@@ -169,6 +175,11 @@ JSONHandler::handle(std::string const&amp; path, JSON j) @@ -169,6 +175,11 @@ JSONHandler::handle(std::string const&amp; path, JSON j)
169 return; 175 return;
170 } 176 }
171 177
  178 + if (m->h.fallback_handler) {
  179 + m->h.fallback_handler->handle(path, j);
  180 + return;
  181 + }
  182 +
172 // It would be nice to include information about what type the object was and what types were 183 // It would be nice to include information about what type the object was and what types were
173 // allowed, but we're relying on schema validation to make sure input is properly structured 184 // allowed, but we're relying on schema validation to make sure input is properly structured
174 // before calling the handlers. It would be different if this code were trying to be part of a 185 // before calling the handlers. It would be different if this code were trying to be part of a
libqpdf/qpdf/JSONHandler.hh
@@ -45,6 +45,9 @@ class JSONHandler @@ -45,6 +45,9 @@ class JSONHandler
45 void addArrayHandlers( 45 void addArrayHandlers(
46 json_handler_t start_fn, void_handler_t end_fn, std::shared_ptr<JSONHandler> item_handlers); 46 json_handler_t start_fn, void_handler_t end_fn, std::shared_ptr<JSONHandler> item_handlers);
47 47
  48 + // If no handlers is called, the fallback handler will be used to try to handle the item.
  49 + void addFallbackHandler(std::shared_ptr<JSONHandler>);
  50 +
48 // Apply handlers recursively to a JSON object. 51 // Apply handlers recursively to a JSON object.
49 void handle(std::string const& path, JSON j); 52 void handle(std::string const& path, JSON j);
50 53
libtests/json_handler.cc
@@ -77,6 +77,7 @@ make_all_handler() @@ -77,6 +77,7 @@ make_all_handler()
77 auto h5s = std::make_shared<JSONHandler>(); 77 auto h5s = std::make_shared<JSONHandler>();
78 h->addDictKeyHandler("five", h5s); 78 h->addDictKeyHandler("five", h5s);
79 h5s->addArrayHandlers(print_json, make_print_message("array end"), h5); 79 h5s->addArrayHandlers(print_json, make_print_message("array end"), h5);
  80 + h5s->addFallbackHandler(h5);
80 auto h6 = std::make_shared<JSONHandler>(); 81 auto h6 = std::make_shared<JSONHandler>();
81 h6->addDictHandlers(print_json, make_print_message("dict end")); 82 h6->addDictHandlers(print_json, make_print_message("dict end"));
82 auto h6a = std::make_shared<JSONHandler>(); 83 auto h6a = std::make_shared<JSONHandler>();
@@ -109,6 +110,11 @@ test_all() @@ -109,6 +110,11 @@ test_all()
109 "six": {"a": {"b": "quack", "Q": "baaa"}, "b": "moo"} 110 "six": {"a": {"b": "quack", "Q": "baaa"}, "b": "moo"}
110 })"); 111 })");
111 h->handle(".", j); 112 h->handle(".", j);
  113 + std::cerr << "-- fallback --" << std::endl;
  114 + j = JSON::parse(R"({
  115 + "five": "not-array"
  116 +})");
  117 + h->handle(".", j);
112 } 118 }
113 119
114 static void 120 static void
libtests/qtest/json_handler/json_handler.out
@@ -63,6 +63,12 @@ @@ -63,6 +63,12 @@
63 .three: bool: true 63 .three: bool: true
64 .two: number: 3.14 64 .two: number: 3.14
65 .: json: dict end 65 .: json: dict end
  66 +-- fallback --
  67 +.: json: {
  68 + "five": "not-array"
  69 +}
  70 +.five: string: not-array
  71 +.: json: dict end
66 -- errors -- 72 -- errors --
67 bad type at top: JSON handler: value at . is not of expected type 73 bad type at top: JSON handler: value at . is not of expected type
68 .: json: { 74 .: json: {