Coverage Report

Created: 2025-08-28 06:57

/src/gdal/port/cpl_json.h
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * Project:  Common Portability Library
3
 * Purpose:  Function wrapper for libjson-c access.
4
 * Author:   Dmitry Baryshnikov, dmitry.baryshnikov@nextgis.com
5
 *
6
 ******************************************************************************
7
 * Copyright (c) 2017-2018 NextGIS, <info@nextgis.com>
8
 *
9
 * SPDX-License-Identifier: MIT
10
 ****************************************************************************/
11
12
#ifndef CPL_JSON_H_INCLUDED
13
#define CPL_JSON_H_INCLUDED
14
15
#include "cpl_progress.h"
16
#include "cpl_string.h"
17
18
#include <cstdint>
19
#include <initializer_list>
20
#include <string>
21
#include <vector>
22
23
/**
24
 * \file cpl_json.h
25
 *
26
 * Interface for read and write JSON documents
27
 */
28
29
/*! @cond Doxygen_Suppress */
30
typedef void *JSONObjectH;
31
32
class CPLJSONObject;
33
class CPLJSONArray;
34
35
class CPLJSONObjectProxy
36
{
37
    CPLJSONObject &oObj;
38
    const std::string osName;
39
40
  public:
41
    explicit inline CPLJSONObjectProxy(CPLJSONObject &oObjIn,
42
                                       const std::string &osNameIn)
43
        : oObj(oObjIn), osName(osNameIn)
44
0
    {
45
0
    }
46
47
    template <class T> inline CPLJSONObjectProxy &operator=(const T &val);
48
};
49
50
/*! @endcond */
51
52
/**
53
 * @brief The CPLJSONArray class holds JSON object from CPLJSONDocument
54
 */
55
class CPL_DLL CPLJSONObject
56
{
57
    friend class CPLJSONArray;
58
    friend class CPLJSONDocument;
59
60
  public:
61
    /**
62
     * Json object types
63
     */
64
    enum class Type
65
    {
66
        Unknown,
67
        Null,
68
        Object,
69
        Array,
70
        Boolean,
71
        String,
72
        Integer,
73
        Long,
74
        Double
75
    };
76
77
    /**
78
     * Json object format to string options
79
     */
80
    enum class PrettyFormat
81
    {
82
        Plain,   ///< No extra whitespace or formatting applied
83
        Spaced,  ///< Minimal whitespace inserted
84
        Pretty   ///< Formatted output
85
    };
86
87
  public:
88
    /*! @cond Doxygen_Suppress */
89
    CPLJSONObject();
90
    explicit CPLJSONObject(const std::string &osName,
91
                           const CPLJSONObject &oParent);
92
    explicit CPLJSONObject(std::nullptr_t);
93
    explicit CPLJSONObject(const std::string &osVal);
94
    explicit CPLJSONObject(const char *pszValue);
95
    explicit CPLJSONObject(bool bVal);
96
    explicit CPLJSONObject(int nVal);
97
    explicit CPLJSONObject(int64_t nVal);
98
    explicit CPLJSONObject(uint64_t nVal);
99
    explicit CPLJSONObject(double dfVal);
100
    ~CPLJSONObject();
101
    CPLJSONObject(const CPLJSONObject &other);
102
    CPLJSONObject(CPLJSONObject &&other);
103
    CPLJSONObject &operator=(const CPLJSONObject &other);
104
    CPLJSONObject &operator=(CPLJSONObject &&other);
105
    CPLJSONObject &operator=(CPLJSONArray &&other);
106
107
    // This method is not thread-safe
108
    CPLJSONObject Clone() const;
109
110
  private:
111
    explicit CPLJSONObject(const std::string &osName, JSONObjectH poJsonObject);
112
    /*! @endcond */
113
114
  public:
115
    // setters
116
    void Add(const std::string &osName, const std::string &osValue);
117
    void Add(const std::string &osName, const char *pszValue);
118
    void Add(const std::string &osName, double dfValue);
119
    void Add(const std::string &osName, int nValue);
120
    void Add(const std::string &osName, GInt64 nValue);
121
    void Add(const std::string &osName, uint64_t nValue);
122
    void Add(const std::string &osName, const CPLJSONArray &oValue);
123
    void Add(const std::string &osName, const CPLJSONObject &oValue);
124
    void AddNoSplitName(const std::string &osName, const CPLJSONObject &oValue);
125
    void Add(const std::string &osName, bool bValue);
126
    void AddNull(const std::string &osName);
127
128
    /** Change value by key */
129
    template <class T> void Set(const std::string &osName, const T &val)
130
0
    {
131
0
        Delete(osName);
132
0
        Add(osName, val);
133
0
    }
Unexecuted instantiation: void CPLJSONObject::Set<char const*>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const* const&)
Unexecuted instantiation: void CPLJSONObject::Set<CPLJSONObject>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, CPLJSONObject const&)
Unexecuted instantiation: void CPLJSONObject::Set<char [18]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const (&) [18])
Unexecuted instantiation: void CPLJSONObject::Set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: void CPLJSONObject::Set<char [16]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const (&) [16])
Unexecuted instantiation: void CPLJSONObject::Set<char [15]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const (&) [15])
Unexecuted instantiation: void CPLJSONObject::Set<double>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double const&)
Unexecuted instantiation: void CPLJSONObject::Set<int>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int const&)
Unexecuted instantiation: void CPLJSONObject::Set<CPLJSONArray>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, CPLJSONArray const&)
134
135
    void SetNull(const std::string &osName);
136
137
    CPLJSONObject operator[](const std::string &osName);
138
139
/*! @cond Doxygen_Suppress */
140
141
// GCC 9.4 seems to be confused by the template and doesn't realize it
142
// returns *this
143
#ifdef __GNUC__
144
#pragma GCC diagnostic push
145
#pragma GCC diagnostic ignored "-Weffc++"
146
#endif
147
    template <class T> inline CPLJSONObject &operator=(const T &val)
148
0
    {
149
0
        CPLAssert(!m_osKeyForSet.empty());
150
0
        std::string osKeyForSet = m_osKeyForSet;
151
0
        m_osKeyForSet.clear();
152
0
        Set(osKeyForSet, val);
153
0
        return *this;
154
0
    }
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<char [18]>(char const (&) [18])
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<char [16]>(char const (&) [16])
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<char [15]>(char const (&) [15])
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<double>(double const&)
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<int>(int const&)
Unexecuted instantiation: CPLJSONObject& CPLJSONObject::operator=<CPLJSONArray>(CPLJSONArray const&)
155
#ifdef __GNUC__
156
#pragma GCC diagnostic pop
157
#endif
158
159
    template <class T>
160
    inline CPLJSONObject &operator=(std::initializer_list<T> list);
161
162
    JSONObjectH GetInternalHandle() const
163
0
    {
164
0
        return m_poJsonObject;
165
0
    }
166
167
    /*! @endcond */
168
169
    // getters
170
    std::string GetString(const std::string &osName,
171
                          const std::string &osDefault = "") const;
172
    double GetDouble(const std::string &osName, double dfDefault = 0.0) const;
173
    int GetInteger(const std::string &osName, int nDefault = 0) const;
174
    GInt64 GetLong(const std::string &osName, GInt64 nDefault = 0) const;
175
    bool GetBool(const std::string &osName, bool bDefault = false) const;
176
    std::string ToString(const std::string &osDefault = "") const;
177
    double ToDouble(double dfDefault = 0.0) const;
178
    int ToInteger(int nDefault = 0) const;
179
    GInt64 ToLong(GInt64 nDefault = 0) const;
180
    bool ToBool(bool bDefault = false) const;
181
    CPLJSONArray ToArray() const;
182
    std::string Format(PrettyFormat eFormat) const;
183
184
    //
185
    void Delete(const std::string &osName);
186
    void DeleteNoSplitName(const std::string &osName);
187
    CPLJSONArray GetArray(const std::string &osName) const;
188
    CPLJSONObject GetObj(const std::string &osName) const;
189
    CPLJSONObject operator[](const std::string &osName) const;
190
    Type GetType() const;
191
192
    /*! @cond Doxygen_Suppress */
193
    std::string GetName() const
194
0
    {
195
0
        return m_osKey;
196
0
    }
197
198
    /*! @endcond */
199
200
    std::vector<CPLJSONObject> GetChildren() const;
201
    bool IsValid() const;
202
    void Deinit();
203
204
  protected:
205
    /*! @cond Doxygen_Suppress */
206
    CPLJSONObject GetObjectByPath(const std::string &osPath,
207
                                  std::string &osName) const;
208
    /*! @endcond */
209
210
  private:
211
    JSONObjectH m_poJsonObject = nullptr;
212
    std::string m_osKey{};
213
    std::string m_osKeyForSet{};
214
};
215
216
/**
217
 * @brief The JSONArray class JSON array from JSONDocument
218
 */
219
class CPL_DLL CPLJSONArray : public CPLJSONObject
220
{
221
    friend class CPLJSONObject;
222
    friend class CPLJSONDocument;
223
224
  public:
225
    /*! @cond Doxygen_Suppress */
226
    CPLJSONArray();
227
    explicit CPLJSONArray(const std::string &osName);
228
    explicit CPLJSONArray(const CPLJSONObject &other);
229
230
    /** Constructor from a list of initial values */
231
    template <class T> static CPLJSONArray Build(std::initializer_list<T> list)
232
0
    {
233
0
        CPLJSONArray oArray;
234
0
        for (const auto &val : list)
235
0
            oArray.Add(val);
236
0
        return oArray;
237
0
    }
238
239
  private:
240
    explicit CPLJSONArray(const std::string &osName, JSONObjectH poJsonObject);
241
242
    class CPL_DLL ConstIterator
243
    {
244
        const CPLJSONArray &m_oSelf;
245
        int m_nIdx;
246
        mutable CPLJSONObject m_oObj{};
247
248
      public:
249
        ConstIterator(const CPLJSONArray &oSelf, bool bStart)
250
0
            : m_oSelf(oSelf), m_nIdx(bStart ? 0 : oSelf.Size())
251
0
        {
252
0
        }
253
254
0
        ~ConstIterator() = default;
255
256
        CPLJSONObject &operator*() const
257
0
        {
258
0
            m_oObj = m_oSelf[m_nIdx];
259
0
            return m_oObj;
260
0
        }
261
262
        ConstIterator &operator++()
263
0
        {
264
0
            m_nIdx++;
265
0
            return *this;
266
0
        }
267
268
        bool operator==(const ConstIterator &it) const
269
0
        {
270
0
            return m_nIdx == it.m_nIdx;
271
0
        }
272
273
        bool operator!=(const ConstIterator &it) const
274
0
        {
275
0
            return m_nIdx != it.m_nIdx;
276
0
        }
277
    };
278
279
    /*! @endcond */
280
  public:
281
    int Size() const;
282
    void AddNull();
283
    void Add(const CPLJSONObject &oValue);
284
    void Add(const std::string &osValue);
285
    void Add(const char *pszValue);
286
    void Add(double dfValue);
287
    void Add(int nValue);
288
    void Add(GInt64 nValue);
289
    void Add(uint64_t nValue);
290
    void Add(bool bValue);
291
292
    CPLJSONObject operator[](int nIndex);
293
    const CPLJSONObject operator[](int nIndex) const;
294
295
    /** Iterator to first element */
296
    ConstIterator begin() const
297
0
    {
298
0
        return ConstIterator(*this, true);
299
0
    }
300
301
    /** Iterator to after last element */
302
    ConstIterator end() const
303
0
    {
304
0
        return ConstIterator(*this, false);
305
0
    }
306
};
307
308
/**
309
 * @brief The CPLJSONDocument class Wrapper class around json-c library
310
 */
311
class CPL_DLL CPLJSONDocument
312
{
313
  public:
314
    /*! @cond Doxygen_Suppress */
315
    CPLJSONDocument();
316
    ~CPLJSONDocument();
317
    CPLJSONDocument(const CPLJSONDocument &other);
318
    CPLJSONDocument &operator=(const CPLJSONDocument &other);
319
    CPLJSONDocument(CPLJSONDocument &&other);
320
    CPLJSONDocument &operator=(CPLJSONDocument &&other);
321
    /*! @endcond */
322
323
    bool Save(const std::string &osPath) const;
324
    std::string SaveAsString() const;
325
326
    CPLJSONObject GetRoot();
327
    const CPLJSONObject GetRoot() const;
328
    void SetRoot(const CPLJSONObject &oRoot);
329
    bool Load(const std::string &osPath);
330
    bool LoadMemory(const std::string &osStr);
331
    bool LoadMemory(const GByte *pabyData, int nLength = -1);
332
    bool LoadChunks(const std::string &osPath, size_t nChunkSize = 16384,
333
                    GDALProgressFunc pfnProgress = nullptr,
334
                    void *pProgressArg = nullptr);
335
    bool LoadUrl(const std::string &osUrl, const char *const *papszOptions,
336
                 GDALProgressFunc pfnProgress = nullptr,
337
                 void *pProgressArg = nullptr);
338
339
  private:
340
    mutable JSONObjectH m_poRootJsonObject;
341
};
342
343
/*! @cond Doxygen_Suppress */
344
template <class T>
345
inline CPLJSONObject &CPLJSONObject::operator=(std::initializer_list<T> list)
346
0
{
347
0
    return operator=(CPLJSONArray::Build(list));
348
0
}
349
350
/*! @endcond */
351
352
CPLStringList CPLParseKeyValueJson(const char *pszJson);
353
354
#endif  // CPL_JSON_H_INCLUDED