LCOV - code coverage report
Current view: top level - port - cpl_json.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 40 40 100.0 %
Date: 2026-05-11 17:34:11 Functions: 69 74 93.2 %

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

Generated by: LCOV version 1.14