NGL  6.5
The NCCA Graphics Library
writer.h
Go to the documentation of this file.
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_WRITER_H_
16 #define RAPIDJSON_WRITER_H_
17 
18 #include "rapidjson.h"
19 #include "internal/stack.h"
20 #include "internal/strfunc.h"
21 #include "internal/dtoa.h"
22 #include "internal/itoa.h"
23 #include "stringbuffer.h"
24 #include <new> // placement new
25 
26 #if RAPIDJSON_HAS_STDSTRING
27 #include <string>
28 #endif
29 
30 #ifdef _MSC_VER
31 RAPIDJSON_DIAG_PUSH
32 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
33 #endif
34 
36 
38 
53 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
54 class Writer {
55 public:
56  typedef typename SourceEncoding::Ch Ch;
57 
59 
63  explicit
64  Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
65  os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
66 
67  explicit
68  Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
69  os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
70 
72 
89  void Reset(OutputStream& os) {
90  os_ = &os;
91  hasRoot_ = false;
93  }
94 
96 
99  bool IsComplete() const {
100  return hasRoot_ && level_stack_.Empty();
101  }
102 
107 
108  bool Null() { Prefix(kNullType); return WriteNull(); }
109  bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
110  bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
111  bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
112  bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
113  bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
114 
116 
120  bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
121 
122  bool String(const Ch* str, SizeType length, bool copy = false) {
123  (void)copy;
125  return WriteString(str, length);
126  }
127 
128 #if RAPIDJSON_HAS_STDSTRING
129  bool String(const std::basic_string<Ch>& str) {
130  return String(str.data(), SizeType(str.size()));
131  }
132 #endif
133 
134  bool StartObject() {
136  new (level_stack_.template Push<Level>()) Level(false);
137  return WriteStartObject();
138  }
139 
140  bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
141 
142  bool EndObject(SizeType memberCount = 0) {
143  (void)memberCount;
145  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
146  level_stack_.template Pop<Level>(1);
147  bool ret = WriteEndObject();
148  if (level_stack_.Empty()) // end of json text
149  os_->Flush();
150  return ret;
151  }
152 
153  bool StartArray() {
155  new (level_stack_.template Push<Level>()) Level(true);
156  return WriteStartArray();
157  }
158 
159  bool EndArray(SizeType elementCount = 0) {
160  (void)elementCount;
162  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
163  level_stack_.template Pop<Level>(1);
164  bool ret = WriteEndArray();
165  if (level_stack_.Empty()) // end of json text
166  os_->Flush();
167  return ret;
168  }
170 
173 
175  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
176  bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
177 
179 
180 protected:
182  struct Level {
183  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
184  size_t valueCount;
185  bool inArray;
186  };
187 
188  static const size_t kDefaultLevelDepth = 32;
189 
190  bool WriteNull() {
191  os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
192  }
193 
194  bool WriteBool(bool b) {
195  if (b) {
196  os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
197  }
198  else {
199  os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
200  }
201  return true;
202  }
203 
204  bool WriteInt(int i) {
205  char buffer[11];
206  const char* end = internal::i32toa(i, buffer);
207  for (const char* p = buffer; p != end; ++p)
208  os_->Put(*p);
209  return true;
210  }
211 
212  bool WriteUint(unsigned u) {
213  char buffer[10];
214  const char* end = internal::u32toa(u, buffer);
215  for (const char* p = buffer; p != end; ++p)
216  os_->Put(*p);
217  return true;
218  }
219 
220  bool WriteInt64(int64_t i64) {
221  char buffer[21];
222  const char* end = internal::i64toa(i64, buffer);
223  for (const char* p = buffer; p != end; ++p)
224  os_->Put(*p);
225  return true;
226  }
227 
228  bool WriteUint64(uint64_t u64) {
229  char buffer[20];
230  char* end = internal::u64toa(u64, buffer);
231  for (char* p = buffer; p != end; ++p)
232  os_->Put(*p);
233  return true;
234  }
235 
236  bool WriteDouble(double d) {
237  char buffer[25];
238  char* end = internal::dtoa(d, buffer);
239  for (char* p = buffer; p != end; ++p)
240  os_->Put(*p);
241  return true;
242  }
243 
244  bool WriteString(const Ch* str, SizeType length) {
245  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
246  static const char escape[256] = {
247 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
248  //0 1 2 3 4 5 6 7 8 9 A B C D E F
249  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
250  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
251  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
252  Z16, Z16, // 30~4F
253  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
254  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
255 #undef Z16
256  };
257 
258  os_->Put('\"');
260  while (is.Tell() < length) {
261  const Ch c = is.Peek();
262  if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
263  // Unicode escaping
264  unsigned codepoint;
265  if (!SourceEncoding::Decode(is, &codepoint))
266  return false;
267  os_->Put('\\');
268  os_->Put('u');
269  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
270  os_->Put(hexDigits[(codepoint >> 12) & 15]);
271  os_->Put(hexDigits[(codepoint >> 8) & 15]);
272  os_->Put(hexDigits[(codepoint >> 4) & 15]);
273  os_->Put(hexDigits[(codepoint ) & 15]);
274  }
275  else {
276  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
277  // Surrogate pair
278  unsigned s = codepoint - 0x010000;
279  unsigned lead = (s >> 10) + 0xD800;
280  unsigned trail = (s & 0x3FF) + 0xDC00;
281  os_->Put(hexDigits[(lead >> 12) & 15]);
282  os_->Put(hexDigits[(lead >> 8) & 15]);
283  os_->Put(hexDigits[(lead >> 4) & 15]);
284  os_->Put(hexDigits[(lead ) & 15]);
285  os_->Put('\\');
286  os_->Put('u');
287  os_->Put(hexDigits[(trail >> 12) & 15]);
288  os_->Put(hexDigits[(trail >> 8) & 15]);
289  os_->Put(hexDigits[(trail >> 4) & 15]);
290  os_->Put(hexDigits[(trail ) & 15]);
291  }
292  }
293  else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
294  is.Take();
295  os_->Put('\\');
296  os_->Put(escape[(unsigned char)c]);
297  if (escape[(unsigned char)c] == 'u') {
298  os_->Put('0');
299  os_->Put('0');
300  os_->Put(hexDigits[(unsigned char)c >> 4]);
301  os_->Put(hexDigits[(unsigned char)c & 0xF]);
302  }
303  }
304  else
306  return false;
307  }
308  os_->Put('\"');
309  return true;
310  }
311 
312  bool WriteStartObject() { os_->Put('{'); return true; }
313  bool WriteEndObject() { os_->Put('}'); return true; }
314  bool WriteStartArray() { os_->Put('['); return true; }
315  bool WriteEndArray() { os_->Put(']'); return true; }
316 
317  void Prefix(Type type) {
318  (void)type;
319  if (level_stack_.GetSize() != 0) { // this value is not at root
320  Level* level = level_stack_.template Top<Level>();
321  if (level->valueCount > 0) {
322  if (level->inArray)
323  os_->Put(','); // add comma if it is not the first element in array
324  else // in object
325  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
326  }
327  if (!level->inArray && level->valueCount % 2 == 0)
328  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
329  level->valueCount++;
330  }
331  else {
332  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
333  hasRoot_ = true;
334  }
335  }
336 
337  OutputStream* os_;
339  bool hasRoot_;
340 
341 private:
342  // Prohibit copy constructor & assignment operator.
343  Writer(const Writer&);
344  Writer& operator=(const Writer&);
345 };
346 
347 // Full specialization for StringStream to prevent memory copying
348 
349 template<>
350 inline bool Writer<StringBuffer>::WriteInt(int i) {
351  char *buffer = os_->Push(11);
352  const char* end = internal::i32toa(i, buffer);
353  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
354  return true;
355 }
356 
357 template<>
358 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
359  char *buffer = os_->Push(10);
360  const char* end = internal::u32toa(u, buffer);
361  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
362  return true;
363 }
364 
365 template<>
367  char *buffer = os_->Push(21);
368  const char* end = internal::i64toa(i64, buffer);
369  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
370  return true;
371 }
372 
373 template<>
375  char *buffer = os_->Push(20);
376  const char* end = internal::u64toa(u, buffer);
377  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
378  return true;
379 }
380 
381 template<>
382 inline bool Writer<StringBuffer>::WriteDouble(double d) {
383  char *buffer = os_->Push(25);
384  char* end = internal::dtoa(d, buffer);
385  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
386  return true;
387 }
388 
390 
391 #ifdef _MSC_VER
392 RAPIDJSON_DIAG_POP
393 #endif
394 
395 #endif // RAPIDJSON_RAPIDJSON_H_
void Prefix(Type type)
Definition: writer.h:317
bool Key(const Ch *str)
Definition: writer.h:176
bool Bool(bool b)
Definition: writer.h:109
internal::Stack< StackAllocator > level_stack_
Definition: writer.h:338
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:123
Writer & operator=(const Writer &)
bool StartArray()
Definition: writer.h:153
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:322
GLint level
Definition: glew.h:1255
bool WriteInt(int i)
Definition: writer.h:204
object
Definition: rapidjson.h:646
bool WriteEndArray()
Definition: writer.h:315
bool WriteInt64(int64_t i64)
Definition: writer.h:220
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1256
bool Int64(int64_t i64)
Definition: writer.h:112
array
Definition: rapidjson.h:647
const GLfloat * c
Definition: glew.h:16629
bool WriteStartObject()
Definition: writer.h:312
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:89
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:122
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:120
bool Null()
Definition: writer.h:108
false
Definition: rapidjson.h:644
bool WriteString(const Ch *str, SizeType length)
Definition: writer.h:244
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
JSON writer.
Definition: writer.h:54
typedef void(GLAPIENTRY *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target
bool WriteStartArray()
Definition: writer.h:314
static const size_t kDefaultLevelDepth
Definition: writer.h:188
GLuint GLsizei GLsizei * length
Definition: glew.h:1828
bool WriteBool(bool b)
Definition: writer.h:194
GLdouble GLdouble GLdouble b
Definition: glew.h:9162
void Clear()
Definition: stack.h:94
size_t GetSize() const
Definition: stack.h:146
Encoding conversion.
Definition: encodings.h:586
GLuint GLuint end
Definition: glew.h:1256
string
Definition: rapidjson.h:648
bool Empty() const
Definition: stack.h:145
bool WriteUint64(uint64_t u64)
Definition: writer.h:228
size_t valueCount
number of values in this level
Definition: writer.h:184
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:64
Read-only string stream.
Definition: rapidjson.h:571
bool EndArray(SizeType elementCount=0)
Definition: writer.h:159
unsigned __int64 uint64_t
Definition: stdint.h:136
GLfloat GLfloat p
Definition: glew.h:16654
number
Definition: rapidjson.h:649
size_t Tell() const
Definition: rapidjson.h:578
GLuint buffer
Definition: glew.h:1683
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
bool WriteUint(unsigned u)
Definition: writer.h:212
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
bool Uint64(uint64_t u64)
Definition: writer.h:113
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:175
Ch Peek() const
Definition: rapidjson.h:576
char * dtoa(double value, char *buffer)
Definition: dtoa.h:189
bool WriteNull()
Definition: writer.h:190
#define Z16
Information for each nested level.
Definition: writer.h:182
bool hasRoot_
Definition: writer.h:339
Level(bool inArray_)
Definition: writer.h:183
bool EndObject(SizeType memberCount=0)
Definition: writer.h:142
common definitions and configuration
SourceEncoding::Ch Ch
Definition: writer.h:56
signed __int64 int64_t
Definition: stdint.h:135
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Definition: writer.h:68
bool StartObject()
Definition: writer.h:134
bool WriteDouble(double d)
Definition: writer.h:236
true
Definition: rapidjson.h:645
bool WriteEndObject()
Definition: writer.h:313
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:30
bool Uint(unsigned u)
Definition: writer.h:111
OutputStream * os_
Definition: writer.h:337
Type
Type of JSON value.
Definition: rapidjson.h:642
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:99
char * i64toa(int64_t value, char *buffer)
Definition: itoa.h:291
bool Int(int i)
Definition: writer.h:110
GLdouble s
Definition: glew.h:1393
bool inArray
true if in array, otherwise in object
Definition: writer.h:185
char * i32toa(int32_t value, char *buffer)
Definition: itoa.h:113
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:344
null
Definition: rapidjson.h:643
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:140