aboutsummaryrefslogtreecommitdiffstats
path: root/include/qpdf/JSONHandler.hh
blob: 73e8295f2d554889a55ce34d01625835cd71be89 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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 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(void_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(void_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;
        void_handler_t dict_start_handler;
        void_handler_t dict_end_handler;
        void_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