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 : #include "cpl_port.h" 24 : 25 : class CPL_DLL CPLJSonStreamingWriter 26 : { 27 : public: 28 : typedef void (*SerializationFuncType)(const char *pszTxt, void *pUserData); 29 : 30 : private: 31 : CPLJSonStreamingWriter(const CPLJSonStreamingWriter &) = delete; 32 : CPLJSonStreamingWriter &operator=(const CPLJSonStreamingWriter &) = delete; 33 : 34 : std::string m_osStr{}; 35 : SerializationFuncType m_pfnSerializationFunc = nullptr; 36 : void *m_pUserData = nullptr; 37 : bool m_bPretty = true; 38 : std::string m_osIndent = std::string(" "); 39 : std::string m_osIndentAcc{}; 40 : int m_nLevel = 0; 41 : bool m_bNewLineEnabled = true; 42 : 43 : struct State 44 : { 45 : bool bIsObj = false; 46 : bool bFirstChild = true; 47 : 48 531 : explicit State(bool bIsObjIn) : bIsObj(bIsObjIn) 49 : { 50 531 : } 51 : }; 52 : 53 : std::vector<State> m_states{}; 54 : bool m_bWaitForValue = false; 55 : 56 : void Print(const std::string &text); 57 : void IncIndent(); 58 : void DecIndent(); 59 : static std::string FormatString(const std::string &str); 60 : void EmitCommaIfNeeded(); 61 : 62 : public: 63 : CPLJSonStreamingWriter(SerializationFuncType pfnSerializationFunc, 64 : void *pUserData); 65 : ~CPLJSonStreamingWriter(); 66 : 67 24 : void SetPrettyFormatting(bool bPretty) 68 : { 69 24 : m_bPretty = bPretty; 70 24 : } 71 : 72 : void SetIndentationSize(int nSpaces); 73 : 74 : // cppcheck-suppress functionStatic 75 47 : const std::string &GetString() const 76 : { 77 47 : return m_osStr; 78 : } 79 : 80 : void Add(const std::string &str); 81 : void Add(const char *pszStr); 82 : void Add(bool bVal); 83 : 84 82 : void Add(int nVal) 85 : { 86 82 : Add(static_cast<std::int64_t>(nVal)); 87 82 : } 88 : 89 29 : void Add(unsigned int nVal) 90 : { 91 29 : Add(static_cast<std::int64_t>(nVal)); 92 29 : } 93 : 94 : void Add(std::int64_t nVal); 95 : void Add(std::uint64_t nVal); 96 : void Add(float fVal, int nPrecision = 9); 97 : void Add(double dfVal, int nPrecision = 18); 98 : void AddNull(); 99 : 100 : void StartObj(); 101 : void EndObj(); 102 : void AddObjKey(const std::string &key); 103 : 104 : struct CPL_DLL ObjectContext 105 : { 106 : CPLJSonStreamingWriter &m_serializer; 107 : 108 : ObjectContext(const ObjectContext &) = delete; 109 : ObjectContext(ObjectContext &&) = default; 110 : 111 307 : explicit inline ObjectContext(CPLJSonStreamingWriter &serializer) 112 307 : : m_serializer(serializer) 113 : { 114 307 : m_serializer.StartObj(); 115 307 : } 116 : 117 307 : ~ObjectContext() 118 307 : { 119 307 : m_serializer.EndObj(); 120 307 : } 121 : }; 122 : 123 307 : inline ObjectContext MakeObjectContext() 124 : { 125 307 : return ObjectContext(*this); 126 : } 127 : 128 : void StartArray(); 129 : void EndArray(); 130 : 131 : struct CPL_DLL ArrayContext 132 : { 133 : CPLJSonStreamingWriter &m_serializer; 134 : bool m_bForceSingleLine; 135 : bool m_bNewLineEnabledBackup; 136 : 137 : ArrayContext(const ArrayContext &) = delete; 138 : ArrayContext(ArrayContext &&) = default; 139 : 140 224 : inline explicit ArrayContext(CPLJSonStreamingWriter &serializer, 141 : bool bForceSingleLine = false) 142 224 : : m_serializer(serializer), m_bForceSingleLine(bForceSingleLine), 143 224 : m_bNewLineEnabledBackup(serializer.GetNewLine()) 144 : { 145 224 : if (m_bForceSingleLine) 146 16 : serializer.SetNewline(false); 147 224 : m_serializer.StartArray(); 148 224 : } 149 : 150 224 : ~ArrayContext() 151 224 : { 152 224 : m_serializer.EndArray(); 153 224 : if (m_bForceSingleLine) 154 16 : m_serializer.SetNewline(m_bNewLineEnabledBackup); 155 224 : } 156 : }; 157 : 158 224 : inline ArrayContext MakeArrayContext(bool bForceSingleLine = false) 159 : { 160 224 : return ArrayContext(*this, bForceSingleLine); 161 : } 162 : 163 224 : bool GetNewLine() const 164 : { 165 224 : return m_bNewLineEnabled; 166 : } 167 : 168 113 : void SetNewline(bool bEnabled) 169 : { 170 113 : m_bNewLineEnabled = bEnabled; 171 113 : } 172 : }; 173 : 174 : #endif // __cplusplus 175 : 176 : /*! @endcond */ 177 : 178 : #endif // CPL_JSON_STREAMING_WRITER_H