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 : * Permission is hereby granted, free of charge, to any person obtaining a 11 : * copy of this software and associated documentation files (the "Software"), 12 : * to deal in the Software without restriction, including without limitation 13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 : * and/or sell copies of the Software, and to permit persons to whom the 15 : * Software is furnished to do so, subject to the following conditions: 16 : * 17 : * The above copyright notice and this permission notice shall be included 18 : * in all copies or substantial portions of the Software. 19 : * 20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 : * DEALINGS IN THE SOFTWARE. 27 : ****************************************************************************/ 28 : 29 : #ifndef CPL_JSON_STREAMING_WRITER_H 30 : #define CPL_JSON_STREAMING_WRITER_H 31 : 32 : /*! @cond Doxygen_Suppress */ 33 : 34 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) 35 : 36 : #include <cstdint> 37 : #include <vector> 38 : #include <string> 39 : #include "cpl_port.h" 40 : 41 : class CPL_DLL CPLJSonStreamingWriter 42 : { 43 : public: 44 : typedef void (*SerializationFuncType)(const char *pszTxt, void *pUserData); 45 : 46 : private: 47 : CPLJSonStreamingWriter(const CPLJSonStreamingWriter &) = delete; 48 : CPLJSonStreamingWriter &operator=(const CPLJSonStreamingWriter &) = delete; 49 : 50 : std::string m_osStr{}; 51 : SerializationFuncType m_pfnSerializationFunc = nullptr; 52 : void *m_pUserData = nullptr; 53 : bool m_bPretty = true; 54 : std::string m_osIndent = std::string(" "); 55 : std::string m_osIndentAcc{}; 56 : int m_nLevel = 0; 57 : bool m_bNewLineEnabled = true; 58 : 59 : struct State 60 : { 61 : bool bIsObj = false; 62 : bool bFirstChild = true; 63 : 64 531 : explicit State(bool bIsObjIn) : bIsObj(bIsObjIn) 65 : { 66 531 : } 67 : }; 68 : 69 : std::vector<State> m_states{}; 70 : bool m_bWaitForValue = false; 71 : 72 : void Print(const std::string &text); 73 : void IncIndent(); 74 : void DecIndent(); 75 : static std::string FormatString(const std::string &str); 76 : void EmitCommaIfNeeded(); 77 : 78 : public: 79 : CPLJSonStreamingWriter(SerializationFuncType pfnSerializationFunc, 80 : void *pUserData); 81 : ~CPLJSonStreamingWriter(); 82 : 83 24 : void SetPrettyFormatting(bool bPretty) 84 : { 85 24 : m_bPretty = bPretty; 86 24 : } 87 : 88 : void SetIndentationSize(int nSpaces); 89 : 90 : // cppcheck-suppress functionStatic 91 47 : const std::string &GetString() const 92 : { 93 47 : return m_osStr; 94 : } 95 : 96 : void Add(const std::string &str); 97 : void Add(const char *pszStr); 98 : void Add(bool bVal); 99 : 100 82 : void Add(int nVal) 101 : { 102 82 : Add(static_cast<std::int64_t>(nVal)); 103 82 : } 104 : 105 29 : void Add(unsigned int nVal) 106 : { 107 29 : Add(static_cast<std::int64_t>(nVal)); 108 29 : } 109 : 110 : void Add(std::int64_t nVal); 111 : void Add(std::uint64_t nVal); 112 : void Add(float fVal, int nPrecision = 9); 113 : void Add(double dfVal, int nPrecision = 18); 114 : void AddNull(); 115 : 116 : void StartObj(); 117 : void EndObj(); 118 : void AddObjKey(const std::string &key); 119 : 120 : struct CPL_DLL ObjectContext 121 : { 122 : CPLJSonStreamingWriter &m_serializer; 123 : 124 : ObjectContext(const ObjectContext &) = delete; 125 : ObjectContext(ObjectContext &&) = default; 126 : 127 307 : explicit inline ObjectContext(CPLJSonStreamingWriter &serializer) 128 307 : : m_serializer(serializer) 129 : { 130 307 : m_serializer.StartObj(); 131 307 : } 132 : 133 307 : ~ObjectContext() 134 307 : { 135 307 : m_serializer.EndObj(); 136 307 : } 137 : }; 138 : 139 307 : inline ObjectContext MakeObjectContext() 140 : { 141 307 : return ObjectContext(*this); 142 : } 143 : 144 : void StartArray(); 145 : void EndArray(); 146 : 147 : struct CPL_DLL ArrayContext 148 : { 149 : CPLJSonStreamingWriter &m_serializer; 150 : bool m_bForceSingleLine; 151 : bool m_bNewLineEnabledBackup; 152 : 153 : ArrayContext(const ArrayContext &) = delete; 154 : ArrayContext(ArrayContext &&) = default; 155 : 156 224 : inline explicit ArrayContext(CPLJSonStreamingWriter &serializer, 157 : bool bForceSingleLine = false) 158 224 : : m_serializer(serializer), m_bForceSingleLine(bForceSingleLine), 159 224 : m_bNewLineEnabledBackup(serializer.GetNewLine()) 160 : { 161 224 : if (m_bForceSingleLine) 162 16 : serializer.SetNewline(false); 163 224 : m_serializer.StartArray(); 164 224 : } 165 : 166 224 : ~ArrayContext() 167 224 : { 168 224 : m_serializer.EndArray(); 169 224 : if (m_bForceSingleLine) 170 16 : m_serializer.SetNewline(m_bNewLineEnabledBackup); 171 224 : } 172 : }; 173 : 174 224 : inline ArrayContext MakeArrayContext(bool bForceSingleLine = false) 175 : { 176 224 : return ArrayContext(*this, bForceSingleLine); 177 : } 178 : 179 224 : bool GetNewLine() const 180 : { 181 224 : return m_bNewLineEnabled; 182 : } 183 : 184 113 : void SetNewline(bool bEnabled) 185 : { 186 113 : m_bNewLineEnabled = bEnabled; 187 113 : } 188 : }; 189 : 190 : #endif // __cplusplus 191 : 192 : /*! @endcond */ 193 : 194 : #endif // CPL_JSON_STREAMING_WRITER_H