aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/qpdf/JSONHandler.hh
blob: d7f08ead69e14cb225253305ab03ed684736f1ce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef JSONHANDLER_HH
#define JSONHANDLER_HH

#include <qpdf/DLL.h>
#include <qpdf/PointerHolder.hh>
#include <qpdf/JSON.hh>
#include <string>
#include <map>
#include <functional>
#include <memory>

// This class allows a sax-like walk through a JSON object with
// functionality that mostly mirrors QPDFArgParser. It is primarily
// here to facilitate automatic generation of some of the code to help
// keep QPDFJob json consistent with command-line arguments.

class JSONHandler
{
  public:
    // A QPDFUsage exception is thrown if there are any errors
    // validating the JSON object.
    QPDF_DLL
    JSONHandler();

    QPDF_DLL
    ~JSONHandler() = default;

    // Based on the type of handler, expect the object to be of 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<void(
        std::string const& path, JSON value)> json_handler_t;
    typedef std::function<void(
        std::string const& path)> void_handler_t;
    typedef std::function<void(
        std::string const& path, std::string const& value)> string_handler_t;
    typedef std::function<void(
        std::string const& path, bool value)> bool_handler_t;

    // If an any handler is added, it will be called for any value
    // including null, and no other handler will be called.
    QPDF_DLL
    void addAnyHandler(json_handler_t fn);

    // If any of the remaining handlers are registered, each
    // registered handle will be called.
    QPDF_DLL
    void addNullHandler(void_handler_t fn);
    QPDF_DLL
    void addStringHandler(string_handler_t fn);
    QPDF_DLL
    void addNumberHandler(string_handler_t fn);
    QPDF_DLL
    void addBoolHandler(bool_handler_t fn);

    QPDF_DLL
    void addDictHandlers(json_handler_t start_fn, void_handler_t end_fn);
    QPDF_DLL
    void addDictKeyHandler(
        std::string const& key, std::shared_ptr<JSONHandler>);
    QPDF_DLL
    void addFallbackDictHandler(std::shared_ptr<JSONHandler>);

    QPDF_DLL
    void addArrayHandlers(json_handler_t start_fn,
                          void_handler_t end_fn,
                          std::shared_ptr<JSONHandler> item_handlers);

    // Apply handlers recursively to a JSON object.
    QPDF_DLL
    void handle(std::string const& path, JSON j);

  private:
    JSONHandler(JSONHandler const&) = delete;

    static void usage(std::string const& msg);

    struct Handlers
    {
        Handlers() :
            any_handler(nullptr),
            null_handler(nullptr),
            string_handler(nullptr),
            number_handler(nullptr),
            bool_handler(nullptr),
            dict_start_handler(nullptr),
            dict_end_handler(nullptr),
            array_start_handler(nullptr),
            array_end_handler(nullptr),
            final_handler(nullptr)
        {
        }

        json_handler_t any_handler;
        void_handler_t null_handler;
        string_handler_t string_handler;
        string_handler_t number_handler;
        bool_handler_t bool_handler;
        json_handler_t dict_start_handler;
        void_handler_t dict_end_handler;
        json_handler_t array_start_handler;
        void_handler_t array_end_handler;
        void_handler_t final_handler;
        std::map<std::string, std::shared_ptr<JSONHandler>> dict_handlers;
        std::shared_ptr<JSONHandler> fallback_dict_handler;
        std::shared_ptr<JSONHandler> array_item_handler;
    };

    class Members
    {
        friend class JSONHandler;

      public:
        QPDF_DLL
        ~Members() = default;

      private:
        Members();
        Members(Members const&) = delete;

        Handlers h;
    };
    PointerHolder<Members> m;
};

#endif // JSONHANDLER_HH