Line data Source code
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 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #ifndef CPL_JSON_H_INCLUDED
29 : #define CPL_JSON_H_INCLUDED
30 :
31 : #include "cpl_progress.h"
32 : #include "cpl_string.h"
33 :
34 : #include <cstdint>
35 : #include <string>
36 : #include <vector>
37 :
38 : /**
39 : * \file cpl_json.h
40 : *
41 : * Interface for read and write JSON documents
42 : */
43 :
44 : /*! @cond Doxygen_Suppress */
45 : typedef void *JSONObjectH;
46 :
47 : CPL_C_START
48 :
49 : class CPLJSONArray;
50 :
51 : /*! @endcond */
52 :
53 : /**
54 : * @brief The CPLJSONArray class holds JSON object from CPLJSONDocument
55 : */
56 : class CPL_DLL CPLJSONObject
57 : {
58 : friend class CPLJSONArray;
59 : friend class CPLJSONDocument;
60 :
61 : public:
62 : /**
63 : * Json object types
64 : */
65 : enum class Type
66 : {
67 : Unknown,
68 : Null,
69 : Object,
70 : Array,
71 : Boolean,
72 : String,
73 : Integer,
74 : Long,
75 : Double
76 : };
77 :
78 : /**
79 : * Json object format to string options
80 : */
81 : enum class PrettyFormat
82 : {
83 : Plain, ///< No extra whitespace or formatting applied
84 : Spaced, ///< Minimal whitespace inserted
85 : Pretty ///< Formatted output
86 : };
87 :
88 : public:
89 : /*! @cond Doxygen_Suppress */
90 : CPLJSONObject();
91 : explicit CPLJSONObject(const std::string &osName,
92 : const CPLJSONObject &oParent);
93 : explicit CPLJSONObject(std::nullptr_t);
94 : explicit CPLJSONObject(const std::string &osVal);
95 : explicit CPLJSONObject(const char *pszValue);
96 : explicit CPLJSONObject(bool bVal);
97 : explicit CPLJSONObject(int nVal);
98 : explicit CPLJSONObject(int64_t nVal);
99 : explicit CPLJSONObject(uint64_t nVal);
100 : explicit CPLJSONObject(double dfVal);
101 : ~CPLJSONObject();
102 : CPLJSONObject(const CPLJSONObject &other);
103 : CPLJSONObject(CPLJSONObject &&other);
104 : CPLJSONObject &operator=(const CPLJSONObject &other);
105 : CPLJSONObject &operator=(CPLJSONObject &&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 : void Set(const std::string &osName, const std::string &osValue);
129 : void Set(const std::string &osName, const char *pszValue);
130 : void Set(const std::string &osName, double dfValue);
131 : void Set(const std::string &osName, int nValue);
132 : void Set(const std::string &osName, GInt64 nValue);
133 : void Set(const std::string &osName, uint64_t nValue);
134 : void Set(const std::string &osName, bool bValue);
135 : void SetNull(const std::string &osName);
136 :
137 : /*! @cond Doxygen_Suppress */
138 1000166 : JSONObjectH GetInternalHandle() const
139 : {
140 1000166 : return m_poJsonObject;
141 : }
142 :
143 : /*! @endcond */
144 :
145 : // getters
146 : std::string GetString(const std::string &osName,
147 : const std::string &osDefault = "") const;
148 : double GetDouble(const std::string &osName, double dfDefault = 0.0) const;
149 : int GetInteger(const std::string &osName, int nDefault = 0) const;
150 : GInt64 GetLong(const std::string &osName, GInt64 nDefault = 0) const;
151 : bool GetBool(const std::string &osName, bool bDefault = false) const;
152 : std::string ToString(const std::string &osDefault = "") const;
153 : double ToDouble(double dfDefault = 0.0) const;
154 : int ToInteger(int nDefault = 0) const;
155 : GInt64 ToLong(GInt64 nDefault = 0) const;
156 : bool ToBool(bool bDefault = false) const;
157 : CPLJSONArray ToArray() const;
158 : std::string Format(PrettyFormat eFormat) const;
159 :
160 : //
161 : void Delete(const std::string &osName);
162 : void DeleteNoSplitName(const std::string &osName);
163 : CPLJSONArray GetArray(const std::string &osName) const;
164 : CPLJSONObject GetObj(const std::string &osName) const;
165 : CPLJSONObject operator[](const std::string &osName) const;
166 : Type GetType() const;
167 :
168 : /*! @cond Doxygen_Suppress */
169 251811 : std::string GetName() const
170 : {
171 251811 : return m_osKey;
172 : }
173 :
174 : /*! @endcond */
175 :
176 : std::vector<CPLJSONObject> GetChildren() const;
177 : bool IsValid() const;
178 : void Deinit();
179 :
180 : protected:
181 : /*! @cond Doxygen_Suppress */
182 : CPLJSONObject GetObjectByPath(const std::string &osPath,
183 : std::string &osName) const;
184 : /*! @endcond */
185 :
186 : private:
187 : JSONObjectH m_poJsonObject = nullptr;
188 : std::string m_osKey{};
189 : };
190 :
191 : /**
192 : * @brief The JSONArray class JSON array from JSONDocument
193 : */
194 : class CPL_DLL CPLJSONArray : public CPLJSONObject
195 : {
196 : friend class CPLJSONObject;
197 : friend class CPLJSONDocument;
198 :
199 : public:
200 : /*! @cond Doxygen_Suppress */
201 : CPLJSONArray();
202 : explicit CPLJSONArray(const std::string &osName);
203 : explicit CPLJSONArray(const CPLJSONObject &other);
204 :
205 : private:
206 : explicit CPLJSONArray(const std::string &osName, JSONObjectH poJsonObject);
207 :
208 : class CPL_DLL ConstIterator
209 : {
210 : const CPLJSONArray &m_oSelf;
211 : int m_nIdx;
212 : mutable CPLJSONObject m_oObj{};
213 :
214 : public:
215 39604 : ConstIterator(const CPLJSONArray &oSelf, bool bStart)
216 39604 : : m_oSelf(oSelf), m_nIdx(bStart ? 0 : oSelf.Size())
217 : {
218 39604 : }
219 :
220 39604 : ~ConstIterator() = default;
221 :
222 45109 : CPLJSONObject &operator*() const
223 : {
224 45109 : m_oObj = m_oSelf[m_nIdx];
225 45109 : return m_oObj;
226 : }
227 :
228 38758 : ConstIterator &operator++()
229 : {
230 38758 : m_nIdx++;
231 38758 : return *this;
232 : }
233 :
234 : bool operator==(const ConstIterator &it) const
235 : {
236 : return m_nIdx == it.m_nIdx;
237 : }
238 :
239 58560 : bool operator!=(const ConstIterator &it) const
240 : {
241 58560 : return m_nIdx != it.m_nIdx;
242 : }
243 : };
244 :
245 : /*! @endcond */
246 : public:
247 : int Size() const;
248 : void AddNull();
249 : void Add(const CPLJSONObject &oValue);
250 : void Add(const std::string &osValue);
251 : void Add(const char *pszValue);
252 : void Add(double dfValue);
253 : void Add(int nValue);
254 : void Add(GInt64 nValue);
255 : void Add(uint64_t nValue);
256 : void Add(bool bValue);
257 : CPLJSONObject operator[](int nIndex);
258 : const CPLJSONObject operator[](int nIndex) const;
259 :
260 : /** Iterator to first element */
261 19802 : ConstIterator begin() const
262 : {
263 19802 : return ConstIterator(*this, true);
264 : }
265 :
266 : /** Iterator to after last element */
267 19802 : ConstIterator end() const
268 : {
269 19802 : return ConstIterator(*this, false);
270 : }
271 : };
272 :
273 : /**
274 : * @brief The CPLJSONDocument class Wrapper class around json-c library
275 : */
276 : class CPL_DLL CPLJSONDocument
277 : {
278 : public:
279 : /*! @cond Doxygen_Suppress */
280 : CPLJSONDocument();
281 : ~CPLJSONDocument();
282 : CPLJSONDocument(const CPLJSONDocument &other);
283 : CPLJSONDocument &operator=(const CPLJSONDocument &other);
284 : CPLJSONDocument(CPLJSONDocument &&other);
285 : CPLJSONDocument &operator=(CPLJSONDocument &&other);
286 : /*! @endcond */
287 :
288 : bool Save(const std::string &osPath) const;
289 : std::string SaveAsString() const;
290 :
291 : CPLJSONObject GetRoot();
292 : const CPLJSONObject GetRoot() const;
293 : void SetRoot(const CPLJSONObject &oRoot);
294 : bool Load(const std::string &osPath);
295 : bool LoadMemory(const std::string &osStr);
296 : bool LoadMemory(const GByte *pabyData, int nLength = -1);
297 : bool LoadChunks(const std::string &osPath, size_t nChunkSize = 16384,
298 : GDALProgressFunc pfnProgress = nullptr,
299 : void *pProgressArg = nullptr);
300 : bool LoadUrl(const std::string &osUrl, const char *const *papszOptions,
301 : GDALProgressFunc pfnProgress = nullptr,
302 : void *pProgressArg = nullptr);
303 :
304 : private:
305 : mutable JSONObjectH m_poRootJsonObject;
306 : };
307 :
308 : CPL_C_END
309 :
310 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
311 : extern "C++"
312 : {
313 : CPLStringList CPLParseKeyValueJson(const char *pszJson);
314 : }
315 : #endif
316 :
317 : #endif // CPL_JSON_H_INCLUDED
|