writer.h
1 #ifndef RAPIDJSON_WRITER_H_
2 #define RAPIDJSON_WRITER_H_
3 
4 #include "rapidjson.h"
5 #include "internal/stack.h"
6 #include "internal/strfunc.h"
7 #include "internal/itoa.h"
8 #include "stringbuffer.h"
9 #include <cstdio> // snprintf() or _sprintf_s()
10 #include <new> // placement new
11 
12 #ifdef _MSC_VER
13 RAPIDJSON_DIAG_PUSH
14 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
15 #endif
16 
17 namespace rapidjson {
18 
19 //! JSON writer
20 /*! Writer implements the concept Handler.
21  It generates JSON text by events to an output os.
22 
23  User may programmatically calls the functions of a writer to generate JSON text.
24 
25  On the other side, a writer can also be passed to objects that generates events,
26 
27  for example Reader::Parse() and Document::Accept().
28 
29  \tparam OutputStream Type of output stream.
30  \tparam SourceEncoding Encoding of source string.
31  \tparam TargetEncoding Encoding of output stream.
32  \tparam Allocator Type of allocator for allocating memory of stack.
33  \note implements Handler concept
34 */
35 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
36 class Writer {
37 public:
38  typedef typename SourceEncoding::Ch Ch;
39 
40  //! Constructor
41  /*! \param os Output stream.
42  \param allocator User supplied allocator. If it is null, it will create a private one.
43  \param levelDepth Initial capacity of stack.
44  */
45  Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
46  os_(&os), level_stack_(allocator, levelDepth * sizeof(Level)),
47  doublePrecision_(kDefaultDoublePrecision), hasRoot_(false) {}
48 
49  Writer(Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
50  os_(0), level_stack_(allocator, levelDepth * sizeof(Level)),
51  doublePrecision_(kDefaultDoublePrecision), hasRoot_(false) {}
52 
53  //! Reset the writer with a new stream.
54  /*!
55  This function reset the writer with a new stream and default settings,
56  in order to make a Writer object reusable for output multiple JSONs.
57 
58  \param os New output stream.
59  \code
60  Writer<OutputStream> writer(os1);
61  writer.StartObject();
62  // ...
63  writer.EndObject();
64 
65  writer.Reset(os2);
66  writer.StartObject();
67  // ...
68  writer.EndObject();
69  \endcode
70  */
71  void Reset(OutputStream& os) {
72  os_ = &os;
73  doublePrecision_ = kDefaultDoublePrecision;
74  hasRoot_ = false;
75  level_stack_.Clear();
76  }
77 
78  //! Checks whether the output is a complete JSON.
79  /*!
80  A complete JSON has a complete root object or array.
81  */
82  bool IsComplete() const {
83  return hasRoot_ && level_stack_.Empty();
84  }
85 
86  //! Set the number of significant digits for \c double values
87  /*! When writing a \c double value to the \c OutputStream, the number
88  of significant digits is limited to 6 by default.
89  \param p maximum number of significant digits (default: 6)
90  \return The Writer itself for fluent API.
91  */
92  Writer& SetDoublePrecision(int p = kDefaultDoublePrecision) {
93  if (p < 0) p = kDefaultDoublePrecision; // negative precision is ignored
94  doublePrecision_ = p;
95  return *this;
96  }
97 
98  //! \see SetDoublePrecision()
99  int GetDoublePrecision() const { return doublePrecision_; }
100 
101  /*!@name Implementation of Handler
102  \see Handler
103  */
104  //@{
105 
106  bool Null() { Prefix(kNullType); return WriteNull(); }
107  bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
108  bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
109  bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
110  bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
111  bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
112 
113  //! Writes the given \c double value to the stream
114  /*!
115  The number of significant digits (the precision) to be written
116  can be set by \ref SetDoublePrecision() for the Writer:
117  \code
118  Writer<...> writer(...);
119  writer.SetDoublePrecision(12).Double(M_PI);
120  \endcode
121  \param d The value to be written.
122  \return Whether it is succeed.
123  */
124  bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
125 
126  bool String(const Ch* str, SizeType length, bool copy = false) {
127  (void)copy;
128  Prefix(kStringType);
129  return WriteString(str, length);
130  }
131 
132  bool StartObject() {
133  Prefix(kObjectType);
134  new (level_stack_.template Push<Level>()) Level(false);
135  return WriteStartObject();
136  }
137 
138  bool EndObject(SizeType memberCount = 0) {
139  (void)memberCount;
140  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
141  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
142  level_stack_.template Pop<Level>(1);
143  bool ret = WriteEndObject();
144  if (level_stack_.Empty()) // end of json text
145  os_->Flush();
146  return ret;
147  }
148 
149  bool StartArray() {
150  Prefix(kArrayType);
151  new (level_stack_.template Push<Level>()) Level(true);
152  return WriteStartArray();
153  }
154 
155  bool EndArray(SizeType elementCount = 0) {
156  (void)elementCount;
157  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
158  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
159  level_stack_.template Pop<Level>(1);
160  bool ret = WriteEndArray();
161  if (level_stack_.Empty()) // end of json text
162  os_->Flush();
163  return ret;
164  }
165  //@}
166 
167  /*! @name Convenience extensions */
168  //@{
169 
170  //! Writes the given \c double value to the stream (explicit precision)
171  /*!
172  The currently set double precision is ignored in favor of the explicitly
173  given precision for this value.
174  \see Double(), SetDoublePrecision(), GetDoublePrecision()
175  \param d The value to be written
176  \param precision The number of significant digits for this value
177  \return Whether it is succeeded.
178  */
179  bool Double(double d, int precision) {
180  int oldPrecision = GetDoublePrecision();
181  SetDoublePrecision(precision);
182  bool ret = Double(d);
183  SetDoublePrecision(oldPrecision);
184  return ret;
185  }
186 
187  //! Simpler but slower overload.
188  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
189 
190  //@}
191 
192 protected:
193  //! Information for each nested level
194  struct Level {
195  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
196  size_t valueCount; //!< number of values in this level
197  bool inArray; //!< true if in array, otherwise in object
198  };
199 
200  static const size_t kDefaultLevelDepth = 32;
201 
202  bool WriteNull() {
203  os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
204  }
205 
206  bool WriteBool(bool b) {
207  if (b) {
208  os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
209  }
210  else {
211  os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
212  }
213  return true;
214  }
215 
216  bool WriteInt(int i) {
217  char buffer[11];
218  const char* end = internal::i32toa(i, buffer);
219  for (const char* p = buffer; p != end; ++p)
220  os_->Put(*p);
221  return true;
222  }
223 
224  bool WriteUint(unsigned u) {
225  char buffer[10];
226  const char* end = internal::u32toa(u, buffer);
227  for (const char* p = buffer; p != end; ++p)
228  os_->Put(*p);
229  return true;
230  }
231 
232  bool WriteInt64(int64_t i64) {
233  char buffer[21];
234  const char* end = internal::i64toa(i64, buffer);
235  for (const char* p = buffer; p != end; ++p)
236  os_->Put(*p);
237  return true;
238  }
239 
240  bool WriteUint64(uint64_t u64) {
241  char buffer[20];
242  const char* end = internal::u64toa(u64, buffer);
243  for (const char* p = buffer; p != end; ++p)
244  os_->Put(*p);
245  return true;
246  }
247 
248 #ifdef _MSC_VER
249 #define RAPIDJSON_SNPRINTF sprintf_s
250 #else
251 #define RAPIDJSON_SNPRINTF snprintf
252 #endif
253 
254  //! \todo Optimization with custom double-to-string converter.
255  bool WriteDouble(double d) {
256  char buffer[100];
257  int ret = RAPIDJSON_SNPRINTF(buffer, sizeof(buffer), "%.*g", doublePrecision_, d);
258  RAPIDJSON_ASSERT(ret >= 1);
259  for (int i = 0; i < ret; i++)
260  os_->Put(buffer[i]);
261  return true;
262  }
263 #undef RAPIDJSON_SNPRINTF
264 
265  bool WriteString(const Ch* str, SizeType length) {
266  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
267  static const char escape[256] = {
268 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
269  //0 1 2 3 4 5 6 7 8 9 A B C D E F
270  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
271  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
272  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
273  Z16, Z16, // 30~4F
274  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
275  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
276 #undef Z16
277  };
278 
279  os_->Put('\"');
280  GenericStringStream<SourceEncoding> is(str);
281  while (is.Tell() < length) {
282  const Ch c = is.Peek();
283  if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
284  // Unicode escaping
285  unsigned codepoint;
286  if (!SourceEncoding::Decode(is, &codepoint))
287  return false;
288  os_->Put('\\');
289  os_->Put('u');
290  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
291  os_->Put(hexDigits[(codepoint >> 12) & 15]);
292  os_->Put(hexDigits[(codepoint >> 8) & 15]);
293  os_->Put(hexDigits[(codepoint >> 4) & 15]);
294  os_->Put(hexDigits[(codepoint ) & 15]);
295  }
296  else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
297  // Surrogate pair
298  unsigned s = codepoint - 0x010000;
299  unsigned lead = (s >> 10) + 0xD800;
300  unsigned trail = (s & 0x3FF) + 0xDC00;
301  os_->Put(hexDigits[(lead >> 12) & 15]);
302  os_->Put(hexDigits[(lead >> 8) & 15]);
303  os_->Put(hexDigits[(lead >> 4) & 15]);
304  os_->Put(hexDigits[(lead ) & 15]);
305  os_->Put('\\');
306  os_->Put('u');
307  os_->Put(hexDigits[(trail >> 12) & 15]);
308  os_->Put(hexDigits[(trail >> 8) & 15]);
309  os_->Put(hexDigits[(trail >> 4) & 15]);
310  os_->Put(hexDigits[(trail ) & 15]);
311  }
312  else
313  return false; // invalid code point
314  }
315  else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
316  is.Take();
317  os_->Put('\\');
318  os_->Put(escape[(unsigned char)c]);
319  if (escape[(unsigned char)c] == 'u') {
320  os_->Put('0');
321  os_->Put('0');
322  os_->Put(hexDigits[(unsigned char)c >> 4]);
323  os_->Put(hexDigits[(unsigned char)c & 0xF]);
324  }
325  }
326  else
328  }
329  os_->Put('\"');
330  return true;
331  }
332 
333  bool WriteStartObject() { os_->Put('{'); return true; }
334  bool WriteEndObject() { os_->Put('}'); return true; }
335  bool WriteStartArray() { os_->Put('['); return true; }
336  bool WriteEndArray() { os_->Put(']'); return true; }
337 
338  void Prefix(Type type) {
339  (void)type;
340  if (level_stack_.GetSize() != 0) { // this value is not at root
341  Level* level = level_stack_.template Top<Level>();
342  if (level->valueCount > 0) {
343  if (level->inArray)
344  os_->Put(','); // add comma if it is not the first element in array
345  else // in object
346  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
347  }
348  if (!level->inArray && level->valueCount % 2 == 0)
349  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
350  level->valueCount++;
351  }
352  else {
353  RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
354  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
355  hasRoot_ = true;
356  }
357  }
358 
359  OutputStream* os_;
360  internal::Stack<Allocator> level_stack_;
361  int doublePrecision_;
362  bool hasRoot_;
363 
364  static const int kDefaultDoublePrecision = 6;
365 
366 private:
367  // Prohibit copy constructor & assignment operator.
368  Writer(const Writer&);
369  Writer& operator=(const Writer&);
370 };
371 
372 // Full specialization for StringStream to prevent memory copying
373 
374 template<>
375 inline bool Writer<StringBuffer>::WriteInt(int i) {
376  char *buffer = os_->Push(11);
377  const char* end = internal::i32toa(i, buffer);
378  os_->Pop(11 - (end - buffer));
379  return true;
380 }
381 
382 template<>
383 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
384  char *buffer = os_->Push(10);
385  const char* end = internal::u32toa(u, buffer);
386  os_->Pop(10 - (end - buffer));
387  return true;
388 }
389 
390 template<>
391 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
392  char *buffer = os_->Push(21);
393  const char* end = internal::i64toa(i64, buffer);
394  os_->Pop(21 - (end - buffer));
395  return true;
396 }
397 
398 template<>
399 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
400  char *buffer = os_->Push(20);
401  const char* end = internal::u64toa(u, buffer);
402  os_->Pop(20 - (end - buffer));
403  return true;
404 }
405 
406 } // namespace rapidjson
407 
408 #ifdef _MSC_VER
409 RAPIDJSON_DIAG_POP
410 #endif
411 
412 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:394
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:82
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:133
false
Definition: rapidjson.h:393
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:124
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:71
bool inArray
true if in array, otherwise in object
Definition: writer.h:197
Information for each nested level.
Definition: writer.h:194
Writer & SetDoublePrecision(int p=kDefaultDoublePrecision)
Set the number of significant digits for double values.
Definition: writer.h:92
bool Double(double d, int precision)
Writes the given double value to the stream (explicit precision)
Definition: writer.h:179
int GetDoublePrecision() const
Definition: writer.h:99
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:146
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:188
Type
Type of JSON value.
Definition: rapidjson.h:391
object
Definition: rapidjson.h:395
array
Definition: rapidjson.h:396
JSON writer.
Definition: writer.h:36
main RapidJSON namespace
Definition: allocators.h:6
null
Definition: rapidjson.h:392
bool WriteDouble(double d)
Definition: writer.h:255
size_t valueCount
number of values in this level
Definition: writer.h:196
string
Definition: rapidjson.h:397
common definitions and configuration
Concept for allocating, resizing and freeing memory block.
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream &is, OutputStream &os)
Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the outp...
Definition: encodings.h:574
number
Definition: rapidjson.h:398
Writer(OutputStream &os, Allocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:45