GDevelop Core
Core library for developing platforms and tools compatible with GDevelop.
prettywriter.h
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_PRETTYWRITER_H_
16 #define RAPIDJSON_PRETTYWRITER_H_
17 
18 #include "writer.h"
19 
20 #ifdef __GNUC__
21 RAPIDJSON_DIAG_PUSH
22 RAPIDJSON_DIAG_OFF(effc++)
23 #endif
24 
26 
28 
30 enum PrettyFormatOptions {
31  kFormatDefault = 0,
32  kFormatSingleLineArray = 1
33 };
34 
36 
42 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
43 class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
44 public:
46  typedef typename Base::Ch Ch;
47 
49 
53  explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
54  Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
55 
56 
57  explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
58  Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
59 
61 
65  PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
66  RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
67  indentChar_ = indentChar;
68  indentCharCount_ = indentCharCount;
69  return *this;
70  }
71 
73 
75  PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
76  formatOptions_ = options;
77  return *this;
78  }
79 
84 
85  bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
86  bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
87  bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
88  bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
89  bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
90  bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
91  bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
92 
93  bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
94  (void)copy;
95  PrettyPrefix(kNumberType);
96  return Base::WriteString(str, length);
97  }
98 
99  bool String(const Ch* str, SizeType length, bool copy = false) {
100  (void)copy;
101  PrettyPrefix(kStringType);
102  return Base::WriteString(str, length);
103  }
104 
105 #if RAPIDJSON_HAS_STDSTRING
106  bool String(const std::basic_string<Ch>& str) {
107  return String(str.data(), SizeType(str.size()));
108  }
109 #endif
110 
111  bool StartObject() {
112  PrettyPrefix(kObjectType);
113  new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
114  return Base::WriteStartObject();
115  }
116 
117  bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
118 
119 #if RAPIDJSON_HAS_STDSTRING
120  bool Key(const std::basic_string<Ch>& str) {
121  return Key(str.data(), SizeType(str.size()));
122  }
123 #endif
124 
125  bool EndObject(SizeType memberCount = 0) {
126  (void)memberCount;
127  RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
128  RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
129  bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
130 
131  if (!empty) {
132  Base::os_->Put('\n');
133  WriteIndent();
134  }
135  bool ret = Base::WriteEndObject();
136  (void)ret;
137  RAPIDJSON_ASSERT(ret == true);
138  if (Base::level_stack_.Empty()) // end of json text
139  Base::os_->Flush();
140  return true;
141  }
142 
143  bool StartArray() {
144  PrettyPrefix(kArrayType);
145  new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
146  return Base::WriteStartArray();
147  }
148 
149  bool EndArray(SizeType memberCount = 0) {
150  (void)memberCount;
151  RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
152  RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
153  bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
154 
155  if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
156  Base::os_->Put('\n');
157  WriteIndent();
158  }
159  bool ret = Base::WriteEndArray();
160  (void)ret;
161  RAPIDJSON_ASSERT(ret == true);
162  if (Base::level_stack_.Empty()) // end of json text
163  Base::os_->Flush();
164  return true;
165  }
166 
168 
171 
173  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
174  bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
175 
177 
179 
187  bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
188 
189 protected:
190  void PrettyPrefix(Type type) {
191  (void)type;
192  if (Base::level_stack_.GetSize() != 0) { // this value is not at root
193  typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
194 
195  if (level->inArray) {
196  if (level->valueCount > 0) {
197  Base::os_->Put(','); // add comma if it is not the first element in array
198  if (formatOptions_ & kFormatSingleLineArray)
199  Base::os_->Put(' ');
200  }
201 
202  if (!(formatOptions_ & kFormatSingleLineArray)) {
203  Base::os_->Put('\n');
204  WriteIndent();
205  }
206  }
207  else { // in object
208  if (level->valueCount > 0) {
209  if (level->valueCount % 2 == 0) {
210  Base::os_->Put(',');
211  Base::os_->Put('\n');
212  }
213  else {
214  Base::os_->Put(':');
215  Base::os_->Put(' ');
216  }
217  }
218  else
219  Base::os_->Put('\n');
220 
221  if (level->valueCount % 2 == 0)
222  WriteIndent();
223  }
224  if (!level->inArray && level->valueCount % 2 == 0)
225  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
226  level->valueCount++;
227  }
228  else {
229  RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
230  Base::hasRoot_ = true;
231  }
232  }
233 
234  void WriteIndent() {
235  size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
236  PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
237  }
238 
239  Ch indentChar_;
240  unsigned indentCharCount_;
241  PrettyFormatOptions formatOptions_;
242 
243 private:
244  // Prohibit copy constructor & assignment operator.
245  PrettyWriter(const PrettyWriter&);
246  PrettyWriter& operator=(const PrettyWriter&);
247 };
248 
250 
251 #ifdef __GNUC__
252 RAPIDJSON_DIAG_POP
253 #endif
254 
255 #endif // RAPIDJSON_RAPIDJSON_H_
Writer with indentation and spacing.
Definition: prettywriter.h:43
PrettyWriter & SetFormatOptions(PrettyFormatOptions options)
Set pretty writer formatting options.
Definition: prettywriter.h:75
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: prettywriter.h:187
bool String(const Ch *str)
Simpler but slower overload.
Definition: prettywriter.h:173
PrettyWriter(OutputStream &os, StackAllocator *allocator=0, size_t levelDepth=Base::kDefaultLevelDepth)
Constructor.
Definition: prettywriter.h:53
PrettyWriter & SetIndent(Ch indentChar, unsigned indentCharCount)
Set custom indentation.
Definition: prettywriter.h:65
JSON writer.
Definition: writer.h:87
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
Type
Type of JSON value.
Definition: rapidjson.h:603
@ kFalseType
false
Definition: rapidjson.h:605
@ kObjectType
object
Definition: rapidjson.h:607
@ kTrueType
true
Definition: rapidjson.h:606
@ kStringType
string
Definition: rapidjson.h:609
@ kNullType
null
Definition: rapidjson.h:604
@ kArrayType
array
Definition: rapidjson.h:608
@ kNumberType
number
Definition: rapidjson.h:610
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380