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-03-04 01:45:47 Functions: 68 74 91.9 %

          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       11065 :     template <class T> void Set(const std::string &osName, const T &val)
     139             :     {
     140       11065 :         Delete(osName);
     141       11065 :         Add(osName, val);
     142       11065 :     }
     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        2030 :     template <class T> inline CPLJSONObject &operator=(const T &val)
     157             :     {
     158        2030 :         CPLAssert(!m_osKeyForSet.empty());
     159        2030 :         std::string osKeyForSet = m_osKeyForSet;
     160        2030 :         m_osKeyForSet.clear();
     161        2030 :         Set(osKeyForSet, val);
     162        4060 :         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     2204790 :     JSONObjectH GetInternalHandle() const
     172             :     {
     173     2204790 :         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 operator[](const std::string &osName) const;
     199             :     Type GetType() const;
     200             : 
     201             :     /*! @cond Doxygen_Suppress */
     202      273053 :     std::string GetName() const
     203             :     {
     204      273053 :         return m_osKey;
     205             :     }
     206             : 
     207             :     /*! @endcond */
     208             : 
     209             :     std::vector<CPLJSONObject> GetChildren() const;
     210             :     bool IsValid() const;
     211             :     void Deinit();
     212             : 
     213             :   protected:
     214             :     /*! @cond Doxygen_Suppress */
     215             :     CPLJSONObject GetObjectByPath(const std::string &osPath,
     216             :                                   std::string &osName) const;
     217             :     /*! @endcond */
     218             : 
     219             :   private:
     220             :     JSONObjectH m_poJsonObject = nullptr;
     221             :     std::string m_osKey{};
     222             :     std::string m_osKeyForSet{};
     223             : };
     224             : 
     225             : /**
     226             :  * @brief The JSONArray class JSON array from JSONDocument
     227             :  */
     228             : class CPL_DLL CPLJSONArray : public CPLJSONObject
     229             : {
     230             :     friend class CPLJSONObject;
     231             :     friend class CPLJSONDocument;
     232             : 
     233             :   public:
     234             :     /*! @cond Doxygen_Suppress */
     235             :     CPLJSONArray();
     236             :     explicit CPLJSONArray(const std::string &osName);
     237             :     explicit CPLJSONArray(const CPLJSONObject &other);
     238             : 
     239             :     /** Constructor from a list of initial values */
     240         576 :     template <class T> static CPLJSONArray Build(std::initializer_list<T> list)
     241             :     {
     242         576 :         CPLJSONArray oArray;
     243        2179 :         for (const auto &val : list)
     244        1603 :             oArray.Add(val);
     245         576 :         return oArray;
     246             :     }
     247             : 
     248             :   private:
     249             :     explicit CPLJSONArray(const std::string &osName, JSONObjectH poJsonObject);
     250             : 
     251             :     class CPL_DLL ConstIterator
     252             :     {
     253             :         const CPLJSONArray &m_oSelf;
     254             :         int m_nIdx;
     255             :         mutable CPLJSONObject m_oObj{};
     256             : 
     257             :       public:
     258             :         using iterator_category = std::input_iterator_tag;
     259             :         using value_type = CPLJSONObject;
     260             :         using difference_type = std::ptrdiff_t;
     261             :         using pointer = CPLJSONObject *;
     262             :         using reference = CPLJSONObject &;
     263             : 
     264       56644 :         ConstIterator(const CPLJSONArray &oSelf, bool bStart)
     265       56644 :             : m_oSelf(oSelf), m_nIdx(bStart ? 0 : oSelf.Size())
     266             :         {
     267       56644 :         }
     268             : 
     269        2689 :         ConstIterator(const ConstIterator &) = default;
     270             : 
     271             :         ConstIterator &operator=(const ConstIterator &other)
     272             :         {
     273             :             if (this != &other)
     274             :             {
     275             :                 CPLAssert(&m_oSelf == &(other.m_oSelf));
     276             :                 m_nIdx = other.m_nIdx;
     277             :                 m_oObj = other.m_oObj;
     278             :             }
     279             :             return *this;
     280             :         }
     281             : 
     282       59333 :         ~ConstIterator() = default;
     283             : 
     284      104783 :         CPLJSONObject &operator*() const
     285             :         {
     286      104783 :             m_oObj = m_oSelf[m_nIdx];
     287      104783 :             return m_oObj;
     288             :         }
     289             : 
     290       97641 :         ConstIterator &operator++()
     291             :         {
     292       97641 :             m_nIdx++;
     293       97641 :             return *this;
     294             :         }
     295             : 
     296             :         bool operator==(const ConstIterator &it) const
     297             :         {
     298             :             return m_nIdx == it.m_nIdx;
     299             :         }
     300             : 
     301      126174 :         bool operator!=(const ConstIterator &it) const
     302             :         {
     303      126174 :             return m_nIdx != it.m_nIdx;
     304             :         }
     305             :     };
     306             : 
     307             :     /*! @endcond */
     308             :   public:
     309             :     int Size() const;
     310             : 
     311             :     //! Return the size of the array
     312          41 :     inline size_t size() const
     313             :     {
     314          41 :         return static_cast<size_t>(Size());
     315             :     }
     316             : 
     317             :     void AddNull();
     318             :     void Add(const CPLJSONObject &oValue);
     319             :     void Add(const std::string &osValue);
     320             : #if defined(DOXYGEN_SKIP) || __cplusplus >= 201703L ||                         \
     321             :     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
     322             : 
     323             :     void Add(std::string_view svValue);
     324             : #endif
     325             :     void Add(const char *pszValue);
     326             :     void Add(double dfValue);
     327             :     void Add(int nValue);
     328             :     void Add(GInt64 nValue);
     329             :     void Add(uint64_t nValue);
     330             :     void Add(bool bValue);
     331             : 
     332             :     CPLJSONObject operator[](int nIndex);
     333             :     const CPLJSONObject operator[](int nIndex) const;
     334             : 
     335             :     CPLJSONObject operator[](size_t nIndex);
     336             :     const CPLJSONObject operator[](size_t nIndex) const;
     337             : 
     338             :     /** Iterator to first element */
     339       28111 :     ConstIterator begin() const
     340             :     {
     341       28111 :         return ConstIterator(*this, true);
     342             :     }
     343             : 
     344             :     /** Iterator to after last element */
     345       28533 :     ConstIterator end() const
     346             :     {
     347       28533 :         return ConstIterator(*this, false);
     348             :     }
     349             : };
     350             : 
     351             : /**
     352             :  * @brief The CPLJSONDocument class Wrapper class around json-c library
     353             :  */
     354             : class CPL_DLL CPLJSONDocument
     355             : {
     356             :   public:
     357             :     /*! @cond Doxygen_Suppress */
     358             :     CPLJSONDocument();
     359             :     ~CPLJSONDocument();
     360             :     CPLJSONDocument(const CPLJSONDocument &other);
     361             :     CPLJSONDocument &operator=(const CPLJSONDocument &other);
     362             :     CPLJSONDocument(CPLJSONDocument &&other);
     363             :     CPLJSONDocument &operator=(CPLJSONDocument &&other);
     364             :     /*! @endcond */
     365             : 
     366             :     bool Save(const std::string &osPath) const;
     367             :     std::string SaveAsString() const;
     368             : 
     369             :     CPLJSONObject GetRoot();
     370             :     const CPLJSONObject GetRoot() const;
     371             :     void SetRoot(const CPLJSONObject &oRoot);
     372             :     bool Load(const std::string &osPath);
     373             :     bool LoadMemory(const std::string &osStr);
     374             :     bool LoadMemory(const GByte *pabyData, int nLength = -1);
     375             :     bool LoadChunks(const std::string &osPath, size_t nChunkSize = 16384,
     376             :                     GDALProgressFunc pfnProgress = nullptr,
     377             :                     void *pProgressArg = nullptr);
     378             :     bool LoadUrl(const std::string &osUrl, const char *const *papszOptions,
     379             :                  GDALProgressFunc pfnProgress = nullptr,
     380             :                  void *pProgressArg = nullptr);
     381             : 
     382             :   private:
     383             :     mutable JSONObjectH m_poRootJsonObject;
     384             : };
     385             : 
     386             : /*! @cond Doxygen_Suppress */
     387             : template <class T>
     388         289 : inline CPLJSONObject &CPLJSONObject::operator=(std::initializer_list<T> list)
     389             : {
     390         289 :     return operator=(CPLJSONArray::Build(list));
     391             : }
     392             : 
     393             : /*! @endcond */
     394             : 
     395             : CPLStringList CPLParseKeyValueJson(const char *pszJson);
     396             : 
     397             : #endif  // CPL_JSON_H_INCLUDED

Generated by: LCOV version 1.14