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