prettywriter.h
Engine/source/persistence/rapidjson/prettywriter.h
Classes:
class
Writer with indentation and spacing.
Public Enumerations
enum
PrettyFormatOptions { kFormatDefault = 0 kFormatSingleLineArray = 1 }
Combination of PrettyWriter format flags.
Detailed Description
Public Enumerations
PrettyFormatOptions
Enumerator
- kFormatDefault = 0
Default pretty formatting.
- kFormatSingleLineArray = 1
Format arrays on a single line.
Combination of PrettyWriter format flags.
1 2// Tencent is pleased to support the open source community by making RapidJSON available. 3// 4// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 5// 6// Licensed under the MIT License (the "License"); you may not use this file except 7// in compliance with the License. You may obtain a copy of the License at 8// 9// http://opensource.org/licenses/MIT 10// 11// Unless required by applicable law or agreed to in writing, software distributed 12// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 13// CONDITIONS OF ANY KIND, either express or implied. See the License for the 14// specific language governing permissions and limitations under the License. 15 16#ifndef RAPIDJSON_PRETTYWRITER_H_ 17#define RAPIDJSON_PRETTYWRITER_H_ 18 19#include "writer.h" 20 21#ifdef __GNUC__ 22RAPIDJSON_DIAG_PUSH 23RAPIDJSON_DIAG_OFF(effc++) 24#endif 25 26#if defined(__clang__) 27RAPIDJSON_DIAG_PUSH 28RAPIDJSON_DIAG_OFF(c++98-compat) 29#endif 30 31RAPIDJSON_NAMESPACE_BEGIN 32 33//! Combination of PrettyWriter format flags. 34/*! \see PrettyWriter::SetFormatOptions 35 */ 36enum PrettyFormatOptions { 37 kFormatDefault = 0, //!< Default pretty formatting. 38 kFormatSingleLineArray = 1 //!< Format arrays on a single line. 39}; 40 41//! Writer with indentation and spacing. 42/*! 43 \tparam OutputStream Type of output os. 44 \tparam SourceEncoding Encoding of source string. 45 \tparam TargetEncoding Encoding of output stream. 46 \tparam StackAllocator Type of allocator for allocating memory of stack. 47*/ 48template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> 49class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { 50public: 51 typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base; 52 typedef typename Base::Ch Ch; 53 54 //! Constructor 55 /*! \param os Output stream. 56 \param allocator User supplied allocator. If it is null, it will create a private one. 57 \param levelDepth Initial capacity of stack. 58 */ 59 explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 60 Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} 61 62 63 explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 64 Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} 65 66#if RAPIDJSON_HAS_CXX11_RVALUE_REFS 67 PrettyWriter(PrettyWriter&& rhs) : 68 Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} 69#endif 70 71 //! Set custom indentation. 72 /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). 73 \param indentCharCount Number of indent characters for each indentation level. 74 \note The default indentation is 4 spaces. 75 */ 76 PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { 77 RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); 78 indentChar_ = indentChar; 79 indentCharCount_ = indentCharCount; 80 return *this; 81 } 82 83 //! Set pretty writer formatting options. 84 /*! \param options Formatting options. 85 */ 86 PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { 87 formatOptions_ = options; 88 return *this; 89 } 90 91 /*! @name Implementation of Handler 92 \see Handler 93 */ 94 //@{ 95 96 bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } 97 bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } 98 bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } 99 bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); } 100 bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); } 101 bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } 102 bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } 103 104 bool RawNumber(const Ch* str, SizeType length, bool copy = false) { 105 RAPIDJSON_ASSERT(str != 0); 106 (void)copy; 107 PrettyPrefix(kNumberType); 108 return Base::EndValue(Base::WriteString(str, length)); 109 } 110 111 bool String(const Ch* str, SizeType length, bool copy = false) { 112 RAPIDJSON_ASSERT(str != 0); 113 (void)copy; 114 PrettyPrefix(kStringType); 115 return Base::EndValue(Base::WriteString(str, length)); 116 } 117 118#if RAPIDJSON_HAS_STDSTRING 119 bool String(const std::basic_string<Ch>& str) { 120 return String(str.data(), SizeType(str.size())); 121 } 122#endif 123 124 bool StartObject() { 125 PrettyPrefix(kObjectType); 126 new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); 127 return Base::WriteStartObject(); 128 } 129 130 bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } 131 132#if RAPIDJSON_HAS_STDSTRING 133 bool Key(const std::basic_string<Ch>& str) { 134 return Key(str.data(), SizeType(str.size())); 135 } 136#endif 137 138 bool EndObject(SizeType memberCount = 0) { 139 (void)memberCount; 140 RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object 141 RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object 142 RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value 143 144 bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; 145 146 if (!empty) { 147 Base::os_->Put('\n'); 148 WriteIndent(); 149 } 150 bool ret = Base::EndValue(Base::WriteEndObject()); 151 (void)ret; 152 RAPIDJSON_ASSERT(ret == true); 153 if (Base::level_stack_.Empty()) // end of json text 154 Base::Flush(); 155 return true; 156 } 157 158 bool StartArray() { 159 PrettyPrefix(kArrayType); 160 new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); 161 return Base::WriteStartArray(); 162 } 163 164 bool EndArray(SizeType memberCount = 0) { 165 (void)memberCount; 166 RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); 167 RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); 168 bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; 169 170 if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { 171 Base::os_->Put('\n'); 172 WriteIndent(); 173 } 174 bool ret = Base::EndValue(Base::WriteEndArray()); 175 (void)ret; 176 RAPIDJSON_ASSERT(ret == true); 177 if (Base::level_stack_.Empty()) // end of json text 178 Base::Flush(); 179 return true; 180 } 181 182 //@} 183 184 /*! @name Convenience extensions */ 185 //@{ 186 187 //! Simpler but slower overload. 188 bool String(const Ch* str) { return String(str, internal::StrLen(str)); } 189 bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } 190 191 //@} 192 193 //! Write a raw JSON value. 194 /*! 195 For user to write a stringified JSON as a value. 196 197 \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. 198 \param length Length of the json. 199 \param type Type of the root of json. 200 \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. 201 */ 202 bool RawValue(const Ch* json, size_t length, Type type) { 203 RAPIDJSON_ASSERT(json != 0); 204 PrettyPrefix(type); 205 return Base::EndValue(Base::WriteRawValue(json, length)); 206 } 207 208protected: 209 void PrettyPrefix(Type type) { 210 (void)type; 211 if (Base::level_stack_.GetSize() != 0) { // this value is not at root 212 typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>(); 213 214 if (level->inArray) { 215 if (level->valueCount > 0) { 216 Base::os_->Put(','); // add comma if it is not the first element in array 217 if (formatOptions_ & kFormatSingleLineArray) 218 Base::os_->Put(' '); 219 } 220 221 if (!(formatOptions_ & kFormatSingleLineArray)) { 222 Base::os_->Put('\n'); 223 WriteIndent(); 224 } 225 } 226 else { // in object 227 if (level->valueCount > 0) { 228 if (level->valueCount % 2 == 0) { 229 Base::os_->Put(','); 230 Base::os_->Put('\n'); 231 } 232 else { 233 Base::os_->Put(':'); 234 Base::os_->Put(' '); 235 } 236 } 237 else 238 Base::os_->Put('\n'); 239 240 if (level->valueCount % 2 == 0) 241 WriteIndent(); 242 } 243 if (!level->inArray && level->valueCount % 2 == 0) 244 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name 245 level->valueCount++; 246 } 247 else { 248 RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. 249 Base::hasRoot_ = true; 250 } 251 } 252 253 void WriteIndent() { 254 size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; 255 PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count); 256 } 257 258 Ch indentChar_; 259 unsigned indentCharCount_; 260 PrettyFormatOptions formatOptions_; 261 262private: 263 // Prohibit copy constructor & assignment operator. 264 PrettyWriter(const PrettyWriter&); 265 PrettyWriter& operator=(const PrettyWriter&); 266}; 267 268RAPIDJSON_NAMESPACE_END 269 270#if defined(__clang__) 271RAPIDJSON_DIAG_POP 272#endif 273 274#ifdef __GNUC__ 275RAPIDJSON_DIAG_POP 276#endif 277 278#endif // RAPIDJSON_RAPIDJSON_H_ 279