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

Generated by: LCOV version 1.14