1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 */ 9 #pragma once 10 11 #include <tools/toolsdllapi.h> 12 #include <rtl/ustring.hxx> 13 14 namespace rtl 15 { 16 class OStringBuffer; 17 } 18 19 /** Simple JSON encoder designed specifically for LibreOfficeKit purposes. 20 * 21 * (1) Minimal allocations/re-allocations/copying 22 * (2) Small/simple JSON documents 23 * (3) ascii property names 24 */ 25 namespace tools 26 { 27 class ScopedJsonWriterNode; 28 class ScopedJsonWriterArray; 29 class ScopedJsonWriterStruct; 30 31 class TOOLS_DLLPUBLIC JsonWriter 32 { 33 friend class ScopedJsonWriterNode; 34 friend class ScopedJsonWriterArray; 35 friend class ScopedJsonWriterStruct; 36 37 int mSpaceAllocated; 38 char* mpBuffer; 39 int mStartNodeCount; 40 char* mPos; 41 bool mbFirstFieldInNode; 42 43 public: 44 JsonWriter(); 45 ~JsonWriter(); 46 47 [[nodiscard]] ScopedJsonWriterNode startNode(const char*); 48 [[nodiscard]] ScopedJsonWriterArray startArray(const char*); 49 [[nodiscard]] ScopedJsonWriterStruct startStruct(); 50 51 void put(const char* pPropName, const OUString& rPropValue); 52 void put(const char* pPropName, const OString& rPropValue); 53 void put(const char* pPropName, const char* pPropVal); put(const char * pPropName,const std::string & rPropValue)54 void put(const char* pPropName, const std::string& rPropValue) 55 { 56 put(pPropName, rPropValue.data()); 57 } 58 put(const char * pPropName,sal_uInt16 nPropVal)59 void put(const char* pPropName, sal_uInt16 nPropVal) { put(pPropName, sal_Int64(nPropVal)); } put(const char * pPropName,sal_Int16 nPropVal)60 void put(const char* pPropName, sal_Int16 nPropVal) { put(pPropName, sal_Int64(nPropVal)); } put(const char * pPropName,sal_Int32 nPropVal)61 void put(const char* pPropName, sal_Int32 nPropVal) { put(pPropName, sal_Int64(nPropVal)); } put(const char * pPropName,sal_uInt32 nPropVal)62 void put(const char* pPropName, sal_uInt32 nPropVal) { put(pPropName, sal_Int64(nPropVal)); } 63 void put(const char* pPropName, sal_Int64); 64 void put(const char* pPropName, bool); 65 void put(const char* pPropName, double); 66 67 void putSimpleValue(const OUString& rPropValue); 68 69 /// This assumes that this data belongs at this point in the stream, and is valid, and properly encoded 70 void putRaw(const rtl::OStringBuffer&); 71 72 /** Hands ownership of the underlying storage buffer to the caller, 73 * after this no more document modifications may be written. */ 74 char* extractData(); 75 OString extractAsOString(); 76 std::string extractAsStdString(); 77 78 /** returns true if the current JSON data matches the string */ 79 bool isDataEquals(const std::string&) const; 80 81 private: 82 void endNode(); 83 void endArray(); 84 void endStruct(); 85 void addCommaBeforeField(); 86 void reallocBuffer(int noMoreBytesRequired); 87 void writeEscapedOUString(const OUString& rPropVal); 88 89 // this part inline to speed up the fast path ensureSpace(int noMoreBytesRequired)90 inline void ensureSpace(int noMoreBytesRequired) 91 { 92 assert(mpBuffer && "already extracted data"); 93 int currentUsed = mPos - mpBuffer; 94 if (currentUsed + noMoreBytesRequired >= mSpaceAllocated) 95 reallocBuffer(noMoreBytesRequired); 96 } 97 }; 98 99 /** 100 * Auto-closes the node. 101 */ 102 class ScopedJsonWriterNode 103 { 104 friend class JsonWriter; 105 106 JsonWriter& mrWriter; 107 ScopedJsonWriterNode(JsonWriter & rWriter)108 ScopedJsonWriterNode(JsonWriter& rWriter) 109 : mrWriter(rWriter) 110 { 111 } 112 113 public: ~ScopedJsonWriterNode()114 ~ScopedJsonWriterNode() { mrWriter.endNode(); } 115 }; 116 117 /** 118 * Auto-closes the node. 119 */ 120 class ScopedJsonWriterArray 121 { 122 friend class JsonWriter; 123 124 JsonWriter& mrWriter; 125 ScopedJsonWriterArray(JsonWriter & rWriter)126 ScopedJsonWriterArray(JsonWriter& rWriter) 127 : mrWriter(rWriter) 128 { 129 } 130 131 public: ~ScopedJsonWriterArray()132 ~ScopedJsonWriterArray() { mrWriter.endArray(); } 133 }; 134 135 /** 136 * Auto-closes the node. 137 */ 138 class ScopedJsonWriterStruct 139 { 140 friend class JsonWriter; 141 142 JsonWriter& mrWriter; 143 ScopedJsonWriterStruct(JsonWriter & rWriter)144 ScopedJsonWriterStruct(JsonWriter& rWriter) 145 : mrWriter(rWriter) 146 { 147 } 148 149 public: ~ScopedJsonWriterStruct()150 ~ScopedJsonWriterStruct() { mrWriter.endStruct(); } 151 }; 152 }; 153 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ 154