Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: CPL - Common Portability Library 4 : * Purpose: JSon streaming writer 5 : * Author: Even Rouault, even.rouault at spatialys.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #ifndef CPL_JSON_STREAMING_WRITER_H 14 : #define CPL_JSON_STREAMING_WRITER_H 15 : 16 : /*! @cond Doxygen_Suppress */ 17 : 18 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) 19 : 20 : #include <cstdint> 21 : #include <vector> 22 : #include <string> 23 : 24 : #include "cpl_float.h" 25 : #include "cpl_port.h" 26 : 27 : class CPL_DLL CPLJSonStreamingWriter 28 : { 29 : public: 30 : typedef void (*SerializationFuncType)(const char *pszTxt, void *pUserData); 31 : 32 : private: 33 : CPLJSonStreamingWriter(const CPLJSonStreamingWriter &) = delete; 34 : CPLJSonStreamingWriter &operator=(const CPLJSonStreamingWriter &) = delete; 35 : 36 : std::string m_osStr{}; 37 : SerializationFuncType m_pfnSerializationFunc = nullptr; 38 : void *m_pUserData = nullptr; 39 : bool m_bPretty = true; 40 : std::string m_osIndent = std::string(" "); 41 : std::string m_osIndentAcc{}; 42 : int m_nLevel = 0; 43 : bool m_bNewLineEnabled = true; 44 : std::string m_osTmpForSerialize{}; 45 : std::string m_osTmpForFormatString{}; 46 : 47 : struct State 48 : { 49 : bool bIsObj = false; 50 : bool bFirstChild = true; 51 : 52 1086 : explicit State(bool bIsObjIn) : bIsObj(bIsObjIn) 53 : { 54 1086 : } 55 : }; 56 : 57 : std::vector<State> m_states{}; 58 : bool m_bWaitForValue = false; 59 : 60 : void IncIndent(); 61 : void DecIndent(); 62 : const std::string &FormatString(const std::string_view &str); 63 : void EmitCommaIfNeeded(); 64 : 65 : void Serialize(const char *pszStr, size_t nLength); 66 : 67 : protected: 68 : virtual void Serialize(const std::string_view &str); 69 : 70 : public: 71 : CPLJSonStreamingWriter(SerializationFuncType pfnSerializationFunc, 72 : void *pUserData); 73 : virtual ~CPLJSonStreamingWriter(); 74 : 75 : void clear(); 76 : 77 103 : void SetPrettyFormatting(bool bPretty) 78 : { 79 103 : m_bPretty = bPretty; 80 103 : } 81 : 82 : void SetIndentationSize(int nSpaces); 83 : 84 : // cppcheck-suppress functionStatic 85 149 : const std::string &GetString() const 86 : { 87 149 : return m_osStr; 88 : } 89 : 90 : void Add(const char *pszStr); 91 : void Add(const std::string &str); 92 : void Add(const std::string_view &str); 93 : void Add(bool bVal); 94 : 95 : void AddSerializedValue(const std::string_view &str); 96 : 97 128 : void Add(int nVal) 98 : { 99 128 : Add(static_cast<std::int64_t>(nVal)); 100 128 : } 101 : 102 29 : void Add(unsigned int nVal) 103 : { 104 29 : Add(static_cast<std::int64_t>(nVal)); 105 29 : } 106 : 107 : void Add(std::int64_t nVal); 108 : void Add(std::uint64_t nVal); 109 : void Add(GFloat16 hfVal, int nPrecision = 5); 110 : void Add(float fVal, int nPrecision = 9); 111 : void Add(double dfVal, int nPrecision = 17); 112 : void AddNull(); 113 : 114 : void StartObj(); 115 : void EndObj(); 116 : void AddObjKey(const std::string_view &key); 117 : 118 : struct CPL_DLL ObjectContext 119 : { 120 : CPLJSonStreamingWriter &m_serializer; 121 : 122 : ObjectContext(const ObjectContext &) = delete; 123 : ObjectContext(ObjectContext &&) = default; 124 : 125 480 : explicit inline ObjectContext(CPLJSonStreamingWriter &serializer) 126 480 : : m_serializer(serializer) 127 : { 128 480 : m_serializer.StartObj(); 129 480 : } 130 : 131 480 : ~ObjectContext() 132 480 : { 133 480 : m_serializer.EndObj(); 134 480 : } 135 : }; 136 : 137 480 : inline ObjectContext MakeObjectContext() 138 : { 139 480 : return ObjectContext(*this); 140 : } 141 : 142 : void StartArray(); 143 : void EndArray(); 144 : 145 : struct CPL_DLL ArrayContext 146 : { 147 : CPLJSonStreamingWriter &m_serializer; 148 : bool m_bForceSingleLine; 149 : bool m_bNewLineEnabledBackup; 150 : 151 : ArrayContext(const ArrayContext &) = delete; 152 : ArrayContext(ArrayContext &&) = default; 153 : 154 361 : inline explicit ArrayContext(CPLJSonStreamingWriter &serializer, 155 : bool bForceSingleLine = false) 156 361 : : m_serializer(serializer), m_bForceSingleLine(bForceSingleLine), 157 361 : m_bNewLineEnabledBackup(serializer.GetNewLine()) 158 : { 159 361 : if (m_bForceSingleLine) 160 22 : serializer.SetNewline(false); 161 361 : m_serializer.StartArray(); 162 361 : } 163 : 164 361 : ~ArrayContext() 165 361 : { 166 361 : m_serializer.EndArray(); 167 361 : if (m_bForceSingleLine) 168 22 : m_serializer.SetNewline(m_bNewLineEnabledBackup); 169 361 : } 170 : }; 171 : 172 361 : inline ArrayContext MakeArrayContext(bool bForceSingleLine = false) 173 : { 174 361 : return ArrayContext(*this, bForceSingleLine); 175 : } 176 : 177 361 : bool GetNewLine() const 178 : { 179 361 : return m_bNewLineEnabled; 180 : } 181 : 182 140 : void SetNewline(bool bEnabled) 183 : { 184 140 : m_bNewLineEnabled = bEnabled; 185 140 : } 186 : }; 187 : 188 : #endif // __cplusplus 189 : 190 : /*! @endcond */ 191 : 192 : #endif // CPL_JSON_STREAMING_WRITER_H