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-02-12 06:20:29 Functions: 65 71 91.5 %

          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             : #include <vector>
      23             : 
      24             : /**
      25             :  * \file cpl_json.h
      26             :  *
      27             :  * Interface for read and write JSON documents
      28             :  */
      29             : 
      30             : /*! @cond Doxygen_Suppress */
      31             : typedef void *JSONObjectH;
      32             : 
      33             : class CPLJSONObject;
      34             : class CPLJSONArray;
      35             : 
      36             : class CPLJSONObjectProxy
      37             : {
      38             :     CPLJSONObject &oObj;
      39             :     const std::string osName;
      40             : 
      41             :   public:
      42             :     explicit inline CPLJSONObjectProxy(CPLJSONObject &oObjIn,
      43             :                                        const std::string &osNameIn)
      44             :         : oObj(oObjIn), osName(osNameIn)
      45             :     {
      46             :     }
      47             : 
      48             :     template <class T> inline CPLJSONObjectProxy &operator=(const T &val);
      49             : };
      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             :     CPLJSONObject &operator=(CPLJSONArray &&other);
     107             : 
     108             :     // This method is not thread-safe
     109             :     CPLJSONObject Clone() const;
     110             : 
     111             :   private:
     112             :     explicit CPLJSONObject(const std::string &osName, JSONObjectH poJsonObject);
     113             :     /*! @endcond */
     114             : 
     115             :   public:
     116             :     // setters
     117             :     void Add(const std::string &osName, const std::string &osValue);
     118             :     void Add(const std::string &osName, const char *pszValue);
     119             :     void Add(const std::string &osName, double dfValue);
     120             :     void Add(const std::string &osName, int nValue);
     121             :     void Add(const std::string &osName, GInt64 nValue);
     122             :     void Add(const std::string &osName, uint64_t nValue);
     123             :     void Add(const std::string &osName, const CPLJSONArray &oValue);
     124             :     void Add(const std::string &osName, const CPLJSONObject &oValue);
     125             :     void AddNoSplitName(const std::string &osName, const CPLJSONObject &oValue);
     126             :     void Add(const std::string &osName, bool bValue);
     127             :     void AddNull(const std::string &osName);
     128             : 
     129             :     /** Change value by key */
     130       10900 :     template <class T> void Set(const std::string &osName, const T &val)
     131             :     {
     132       10900 :         Delete(osName);
     133       10900 :         Add(osName, val);
     134       10900 :     }
     135             : 
     136             :     void SetNull(const std::string &osName);
     137             : 
     138             :     CPLJSONObject operator[](const std::string &osName);
     139             : 
     140             : /*! @cond Doxygen_Suppress */
     141             : 
     142             : // GCC 9.4 seems to be confused by the template and doesn't realize it
     143             : // returns *this
     144             : #ifdef __GNUC__
     145             : #pragma GCC diagnostic push
     146             : #pragma GCC diagnostic ignored "-Weffc++"
     147             : #endif
     148        2030 :     template <class T> inline CPLJSONObject &operator=(const T &val)
     149             :     {
     150        2030 :         CPLAssert(!m_osKeyForSet.empty());
     151        2030 :         std::string osKeyForSet = m_osKeyForSet;
     152        2030 :         m_osKeyForSet.clear();
     153        2030 :         Set(osKeyForSet, val);
     154        4060 :         return *this;
     155             :     }
     156             : #ifdef __GNUC__
     157             : #pragma GCC diagnostic pop
     158             : #endif
     159             : 
     160             :     template <class T>
     161             :     inline CPLJSONObject &operator=(std::initializer_list<T> list);
     162             : 
     163     2187520 :     JSONObjectH GetInternalHandle() const
     164             :     {
     165     2187520 :         return m_poJsonObject;
     166             :     }
     167             : 
     168             :     /*! @endcond */
     169             : 
     170             :     // getters
     171             :     std::string GetString(const std::string &osName,
     172             :                           const std::string &osDefault = "") const;
     173             :     double GetDouble(const std::string &osName, double dfDefault = 0.0) const;
     174             :     int GetInteger(const std::string &osName, int nDefault = 0) const;
     175             :     GInt64 GetLong(const std::string &osName, GInt64 nDefault = 0) const;
     176             :     bool GetBool(const std::string &osName, bool bDefault = false) const;
     177             :     std::string ToString(const std::string &osDefault = "") const;
     178             :     double ToDouble(double dfDefault = 0.0) const;
     179             :     int ToInteger(int nDefault = 0) const;
     180             :     GInt64 ToLong(GInt64 nDefault = 0) const;
     181             :     bool ToBool(bool bDefault = false) const;
     182             :     CPLJSONArray ToArray() const;
     183             :     std::string Format(PrettyFormat eFormat) const;
     184             : 
     185             :     //
     186             :     void Delete(const std::string &osName);
     187             :     void DeleteNoSplitName(const std::string &osName);
     188             :     CPLJSONArray GetArray(const std::string &osName) const;
     189             :     CPLJSONObject GetObj(const std::string &osName) const;
     190             :     CPLJSONObject operator[](const std::string &osName) const;
     191             :     Type GetType() const;
     192             : 
     193             :     /*! @cond Doxygen_Suppress */
     194      271964 :     std::string GetName() const
     195             :     {
     196      271964 :         return m_osKey;
     197             :     }
     198             : 
     199             :     /*! @endcond */
     200             : 
     201             :     std::vector<CPLJSONObject> GetChildren() const;
     202             :     bool IsValid() const;
     203             :     void Deinit();
     204             : 
     205             :   protected:
     206             :     /*! @cond Doxygen_Suppress */
     207             :     CPLJSONObject GetObjectByPath(const std::string &osPath,
     208             :                                   std::string &osName) const;
     209             :     /*! @endcond */
     210             : 
     211             :   private:
     212             :     JSONObjectH m_poJsonObject = nullptr;
     213             :     std::string m_osKey{};
     214             :     std::string m_osKeyForSet{};
     215             : };
     216             : 
     217             : /**
     218             :  * @brief The JSONArray class JSON array from JSONDocument
     219             :  */
     220             : class CPL_DLL CPLJSONArray : public CPLJSONObject
     221             : {
     222             :     friend class CPLJSONObject;
     223             :     friend class CPLJSONDocument;
     224             : 
     225             :   public:
     226             :     /*! @cond Doxygen_Suppress */
     227             :     CPLJSONArray();
     228             :     explicit CPLJSONArray(const std::string &osName);
     229             :     explicit CPLJSONArray(const CPLJSONObject &other);
     230             : 
     231             :     /** Constructor from a list of initial values */
     232         576 :     template <class T> static CPLJSONArray Build(std::initializer_list<T> list)
     233             :     {
     234         576 :         CPLJSONArray oArray;
     235        2179 :         for (const auto &val : list)
     236        1603 :             oArray.Add(val);
     237         576 :         return oArray;
     238             :     }
     239             : 
     240             :   private:
     241             :     explicit CPLJSONArray(const std::string &osName, JSONObjectH poJsonObject);
     242             : 
     243             :     class CPL_DLL ConstIterator
     244             :     {
     245             :         const CPLJSONArray &m_oSelf;
     246             :         int m_nIdx;
     247             :         mutable CPLJSONObject m_oObj{};
     248             : 
     249             :       public:
     250             :         using iterator_category = std::input_iterator_tag;
     251             :         using value_type = CPLJSONObject;
     252             :         using difference_type = std::ptrdiff_t;
     253             :         using pointer = CPLJSONObject *;
     254             :         using reference = CPLJSONObject &;
     255             : 
     256       55322 :         ConstIterator(const CPLJSONArray &oSelf, bool bStart)
     257       55322 :             : m_oSelf(oSelf), m_nIdx(bStart ? 0 : oSelf.Size())
     258             :         {
     259       55322 :         }
     260             : 
     261        2221 :         ConstIterator(const ConstIterator &) = default;
     262             : 
     263             :         ConstIterator &operator=(const ConstIterator &other)
     264             :         {
     265             :             if (this != &other)
     266             :             {
     267             :                 CPLAssert(&m_oSelf == &(other.m_oSelf));
     268             :                 m_nIdx = other.m_nIdx;
     269             :                 m_oObj = other.m_oObj;
     270             :             }
     271             :             return *this;
     272             :         }
     273             : 
     274       57543 :         ~ConstIterator() = default;
     275             : 
     276      104101 :         CPLJSONObject &operator*() const
     277             :         {
     278      104101 :             m_oObj = m_oSelf[m_nIdx];
     279      104101 :             return m_oObj;
     280             :         }
     281             : 
     282       96984 :         ConstIterator &operator++()
     283             :         {
     284       96984 :             m_nIdx++;
     285       96984 :             return *this;
     286             :         }
     287             : 
     288             :         bool operator==(const ConstIterator &it) const
     289             :         {
     290             :             return m_nIdx == it.m_nIdx;
     291             :         }
     292             : 
     293      124817 :         bool operator!=(const ConstIterator &it) const
     294             :         {
     295      124817 :             return m_nIdx != it.m_nIdx;
     296             :         }
     297             :     };
     298             : 
     299             :     /*! @endcond */
     300             :   public:
     301             :     int Size() const;
     302             : 
     303             :     //! Return the size of the array
     304          41 :     inline size_t size() const
     305             :     {
     306          41 :         return static_cast<size_t>(Size());
     307             :     }
     308             : 
     309             :     void AddNull();
     310             :     void Add(const CPLJSONObject &oValue);
     311             :     void Add(const std::string &osValue);
     312             :     void Add(const char *pszValue);
     313             :     void Add(double dfValue);
     314             :     void Add(int nValue);
     315             :     void Add(GInt64 nValue);
     316             :     void Add(uint64_t nValue);
     317             :     void Add(bool bValue);
     318             : 
     319             :     CPLJSONObject operator[](int nIndex);
     320             :     const CPLJSONObject operator[](int nIndex) const;
     321             : 
     322             :     CPLJSONObject operator[](size_t nIndex);
     323             :     const CPLJSONObject operator[](size_t nIndex) const;
     324             : 
     325             :     /** Iterator to first element */
     326       27489 :     ConstIterator begin() const
     327             :     {
     328       27489 :         return ConstIterator(*this, true);
     329             :     }
     330             : 
     331             :     /** Iterator to after last element */
     332       27833 :     ConstIterator end() const
     333             :     {
     334       27833 :         return ConstIterator(*this, false);
     335             :     }
     336             : };
     337             : 
     338             : /**
     339             :  * @brief The CPLJSONDocument class Wrapper class around json-c library
     340             :  */
     341             : class CPL_DLL CPLJSONDocument
     342             : {
     343             :   public:
     344             :     /*! @cond Doxygen_Suppress */
     345             :     CPLJSONDocument();
     346             :     ~CPLJSONDocument();
     347             :     CPLJSONDocument(const CPLJSONDocument &other);
     348             :     CPLJSONDocument &operator=(const CPLJSONDocument &other);
     349             :     CPLJSONDocument(CPLJSONDocument &&other);
     350             :     CPLJSONDocument &operator=(CPLJSONDocument &&other);
     351             :     /*! @endcond */
     352             : 
     353             :     bool Save(const std::string &osPath) const;
     354             :     std::string SaveAsString() const;
     355             : 
     356             :     CPLJSONObject GetRoot();
     357             :     const CPLJSONObject GetRoot() const;
     358             :     void SetRoot(const CPLJSONObject &oRoot);
     359             :     bool Load(const std::string &osPath);
     360             :     bool LoadMemory(const std::string &osStr);
     361             :     bool LoadMemory(const GByte *pabyData, int nLength = -1);
     362             :     bool LoadChunks(const std::string &osPath, size_t nChunkSize = 16384,
     363             :                     GDALProgressFunc pfnProgress = nullptr,
     364             :                     void *pProgressArg = nullptr);
     365             :     bool LoadUrl(const std::string &osUrl, const char *const *papszOptions,
     366             :                  GDALProgressFunc pfnProgress = nullptr,
     367             :                  void *pProgressArg = nullptr);
     368             : 
     369             :   private:
     370             :     mutable JSONObjectH m_poRootJsonObject;
     371             : };
     372             : 
     373             : /*! @cond Doxygen_Suppress */
     374             : template <class T>
     375         289 : inline CPLJSONObject &CPLJSONObject::operator=(std::initializer_list<T> list)
     376             : {
     377         289 :     return operator=(CPLJSONArray::Build(list));
     378             : }
     379             : 
     380             : /*! @endcond */
     381             : 
     382             : CPLStringList CPLParseKeyValueJson(const char *pszJson);
     383             : 
     384             : #endif  // CPL_JSON_H_INCLUDED

Generated by: LCOV version 1.14