LCOV - code coverage report
Current view: top level - port - cpl_json.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 37 37 100.0 %
Date: 2025-08-19 18:03:11 Functions: 54 60 90.0 %

          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 <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             :     {
      45             :     }
      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       10297 :     template <class T> void Set(const std::string &osName, const T &val)
     130             :     {
     131       10297 :         Delete(osName);
     132       10297 :         Add(osName, val);
     133       10297 :     }
     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        1860 :     template <class T> inline CPLJSONObject &operator=(const T &val)
     148             :     {
     149        1860 :         CPLAssert(!m_osKeyForSet.empty());
     150        1860 :         std::string osKeyForSet = m_osKeyForSet;
     151        1860 :         m_osKeyForSet.clear();
     152        1860 :         Set(osKeyForSet, val);
     153        3720 :         return *this;
     154             :     }
     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     1910901 :     JSONObjectH GetInternalHandle() const
     163             :     {
     164     1910901 :         return m_poJsonObject;
     165             :     }
     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      252963 :     std::string GetName() const
     194             :     {
     195      252963 :         return m_osKey;
     196             :     }
     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         544 :     template <class T> static CPLJSONArray Build(std::initializer_list<T> list)
     232             :     {
     233         544 :         CPLJSONArray oArray;
     234        2061 :         for (const auto &val : list)
     235        1517 :             oArray.Add(val);
     236         544 :         return oArray;
     237             :     }
     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       46662 :         ConstIterator(const CPLJSONArray &oSelf, bool bStart)
     250       46662 :             : m_oSelf(oSelf), m_nIdx(bStart ? 0 : oSelf.Size())
     251             :         {
     252       46662 :         }
     253             : 
     254       46662 :         ~ConstIterator() = default;
     255             : 
     256       92082 :         CPLJSONObject &operator*() const
     257             :         {
     258       92082 :             m_oObj = m_oSelf[m_nIdx];
     259       92082 :             return m_oObj;
     260             :         }
     261             : 
     262       85153 :         ConstIterator &operator++()
     263             :         {
     264       85153 :             m_nIdx++;
     265       85153 :             return *this;
     266             :         }
     267             : 
     268             :         bool operator==(const ConstIterator &it) const
     269             :         {
     270             :             return m_nIdx == it.m_nIdx;
     271             :         }
     272             : 
     273      108484 :         bool operator!=(const ConstIterator &it) const
     274             :         {
     275      108484 :             return m_nIdx != it.m_nIdx;
     276             :         }
     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       23331 :     ConstIterator begin() const
     297             :     {
     298       23331 :         return ConstIterator(*this, true);
     299             :     }
     300             : 
     301             :     /** Iterator to after last element */
     302       23331 :     ConstIterator end() const
     303             :     {
     304       23331 :         return ConstIterator(*this, false);
     305             :     }
     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         271 : inline CPLJSONObject &CPLJSONObject::operator=(std::initializer_list<T> list)
     346             : {
     347         271 :     return operator=(CPLJSONArray::Build(list));
     348             : }
     349             : 
     350             : /*! @endcond */
     351             : 
     352             : CPLStringList CPLParseKeyValueJson(const char *pszJson);
     353             : 
     354             : #endif  // CPL_JSON_H_INCLUDED

Generated by: LCOV version 1.14