All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
writer.h
1 // Copyright (C) 2011 Milo Yip
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef RAPIDJSON_WRITER_H_
22 #define RAPIDJSON_WRITER_H_
23 
24 #include "rapidjson.h"
25 #include "internal/stack.h"
26 #include "internal/strfunc.h"
27 #include "internal/dtoa.h"
28 #include "internal/itoa.h"
29 #include "stringbuffer.h"
30 #include <new> // placement new
31 
32 #ifdef _MSC_VER
33 RAPIDJSON_DIAG_PUSH
34 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
35 #endif
36 
37 namespace rapidjson {
38 
39 //! JSON writer
40 /*! Writer implements the concept Handler.
41  It generates JSON text by events to an output os.
42 
43  User may programmatically calls the functions of a writer to generate JSON text.
44 
45  On the other side, a writer can also be passed to objects that generates events,
46 
47  for example Reader::Parse() and Document::Accept().
48 
49  \tparam OutputStream Type of output stream.
50  \tparam SourceEncoding Encoding of source string.
51  \tparam TargetEncoding Encoding of output stream.
52  \tparam Allocator Type of allocator for allocating memory of stack.
53  \note implements Handler concept
54 */
55 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
56 class Writer {
57 public:
58  typedef typename SourceEncoding::Ch Ch;
59 
60  //! Constructor
61  /*! \param os Output stream.
62  \param allocator User supplied allocator. If it is null, it will create a private one.
63  \param levelDepth Initial capacity of stack.
64  */
65  Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
66  os_(&os), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
67 
68  Writer(Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
69  os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
70 
71  //! Reset the writer with a new stream.
72  /*!
73  This function reset the writer with a new stream and default settings,
74  in order to make a Writer object reusable for output multiple JSONs.
75 
76  \param os New output stream.
77  \code
78  Writer<OutputStream> writer(os1);
79  writer.StartObject();
80  // ...
81  writer.EndObject();
82 
83  writer.Reset(os2);
84  writer.StartObject();
85  // ...
86  writer.EndObject();
87  \endcode
88  */
89  void Reset(OutputStream& os) {
90  os_ = &os;
91  hasRoot_ = false;
92  level_stack_.Clear();
93  }
94 
95  //! Checks whether the output is a complete JSON.
96  /*!
97  A complete JSON has a complete root object or array.
98  */
99  bool IsComplete() const {
100  return hasRoot_ && level_stack_.Empty();
101  }
102 
103  /*!@name Implementation of Handler
104  \see Handler
105  */
106  //@{
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 
115  //! Writes the given \c double value to the stream
116  /*!
117  \param d The value to be written.
118  \return Whether it is succeed.
119  */
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;
124  Prefix(kStringType);
125  return WriteString(str, length);
126  }
127 
128  bool StartObject() {
129  Prefix(kObjectType);
130  new (level_stack_.template Push<Level>()) Level(false);
131  return WriteStartObject();
132  }
133 
134  bool EndObject(SizeType memberCount = 0) {
135  (void)memberCount;
136  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
137  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
138  level_stack_.template Pop<Level>(1);
139  bool ret = WriteEndObject();
140  if (level_stack_.Empty()) // end of json text
141  os_->Flush();
142  return ret;
143  }
144 
145  bool StartArray() {
146  Prefix(kArrayType);
147  new (level_stack_.template Push<Level>()) Level(true);
148  return WriteStartArray();
149  }
150 
151  bool EndArray(SizeType elementCount = 0) {
152  (void)elementCount;
153  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
154  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
155  level_stack_.template Pop<Level>(1);
156  bool ret = WriteEndArray();
157  if (level_stack_.Empty()) // end of json text
158  os_->Flush();
159  return ret;
160  }
161  //@}
162 
163  /*! @name Convenience extensions */
164  //@{
165 
166  //! Simpler but slower overload.
167  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
168 
169  //@}
170 
171 protected:
172  //! Information for each nested level
173  struct Level {
174  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
175  size_t valueCount; //!< number of values in this level
176  bool inArray; //!< true if in array, otherwise in object
177  };
178 
179  static const size_t kDefaultLevelDepth = 32;
180 
181  bool WriteNull() {
182  os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
183  }
184 
185  bool WriteBool(bool b) {
186  if (b) {
187  os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
188  }
189  else {
190  os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
191  }
192  return true;
193  }
194 
195  bool WriteInt(int i) {
196  char buffer[11];
197  const char* end = internal::i32toa(i, buffer);
198  for (const char* p = buffer; p != end; ++p)
199  os_->Put(*p);
200  return true;
201  }
202 
203  bool WriteUint(unsigned u) {
204  char buffer[10];
205  const char* end = internal::u32toa(u, buffer);
206  for (const char* p = buffer; p != end; ++p)
207  os_->Put(*p);
208  return true;
209  }
210 
211  bool WriteInt64(int64_t i64) {
212  char buffer[21];
213  const char* end = internal::i64toa(i64, buffer);
214  for (const char* p = buffer; p != end; ++p)
215  os_->Put(*p);
216  return true;
217  }
218 
219  bool WriteUint64(uint64_t u64) {
220  char buffer[20];
221  char* end = internal::u64toa(u64, buffer);
222  for (char* p = buffer; p != end; ++p)
223  os_->Put(*p);
224  return true;
225  }
226 
227  bool WriteDouble(double d) {
228  char buffer[25];
229  char* end = internal::dtoa(d, buffer);
230  for (char* p = buffer; p != end; ++p)
231  os_->Put(*p);
232  return true;
233  }
234 
235  bool WriteString(const Ch* str, SizeType length) {
236  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
237  static const char escape[256] = {
238 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
239  //0 1 2 3 4 5 6 7 8 9 A B C D E F
240  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
241  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
242  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
243  Z16, Z16, // 30~4F
244  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
245  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
246 #undef Z16
247  };
248 
249  os_->Put('\"');
250  GenericStringStream<SourceEncoding> is(str);
251  while (is.Tell() < length) {
252  const Ch c = is.Peek();
253  if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
254  // Unicode escaping
255  unsigned codepoint;
256  if (!SourceEncoding::Decode(is, &codepoint))
257  return false;
258  os_->Put('\\');
259  os_->Put('u');
260  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
261  os_->Put(hexDigits[(codepoint >> 12) & 15]);
262  os_->Put(hexDigits[(codepoint >> 8) & 15]);
263  os_->Put(hexDigits[(codepoint >> 4) & 15]);
264  os_->Put(hexDigits[(codepoint ) & 15]);
265  }
266  else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
267  // Surrogate pair
268  unsigned s = codepoint - 0x010000;
269  unsigned lead = (s >> 10) + 0xD800;
270  unsigned trail = (s & 0x3FF) + 0xDC00;
271  os_->Put(hexDigits[(lead >> 12) & 15]);
272  os_->Put(hexDigits[(lead >> 8) & 15]);
273  os_->Put(hexDigits[(lead >> 4) & 15]);
274  os_->Put(hexDigits[(lead ) & 15]);
275  os_->Put('\\');
276  os_->Put('u');
277  os_->Put(hexDigits[(trail >> 12) & 15]);
278  os_->Put(hexDigits[(trail >> 8) & 15]);
279  os_->Put(hexDigits[(trail >> 4) & 15]);
280  os_->Put(hexDigits[(trail ) & 15]);
281  }
282  else
283  return false; // invalid code point
284  }
285  else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
286  is.Take();
287  os_->Put('\\');
288  os_->Put(escape[(unsigned char)c]);
289  if (escape[(unsigned char)c] == 'u') {
290  os_->Put('0');
291  os_->Put('0');
292  os_->Put(hexDigits[(unsigned char)c >> 4]);
293  os_->Put(hexDigits[(unsigned char)c & 0xF]);
294  }
295  }
296  else
298  }
299  os_->Put('\"');
300  return true;
301  }
302 
303  bool WriteStartObject() { os_->Put('{'); return true; }
304  bool WriteEndObject() { os_->Put('}'); return true; }
305  bool WriteStartArray() { os_->Put('['); return true; }
306  bool WriteEndArray() { os_->Put(']'); return true; }
307 
308  void Prefix(Type type) {
309  (void)type;
310  if (level_stack_.GetSize() != 0) { // this value is not at root
311  Level* level = level_stack_.template Top<Level>();
312  if (level->valueCount > 0) {
313  if (level->inArray)
314  os_->Put(','); // add comma if it is not the first element in array
315  else // in object
316  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
317  }
318  if (!level->inArray && level->valueCount % 2 == 0)
319  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
320  level->valueCount++;
321  }
322  else {
323  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
324  hasRoot_ = true;
325  }
326  }
327 
328  OutputStream* os_;
329  internal::Stack<Allocator> level_stack_;
330  bool hasRoot_;
331 
332 private:
333  // Prohibit copy constructor & assignment operator.
334  Writer(const Writer&);
335  Writer& operator=(const Writer&);
336 };
337 
338 // Full specialization for StringStream to prevent memory copying
339 
340 template<>
341 inline bool Writer<StringBuffer>::WriteInt(int i) {
342  char *buffer = os_->Push(11);
343  const char* end = internal::i32toa(i, buffer);
344  os_->Pop(11 - (end - buffer));
345  return true;
346 }
347 
348 template<>
349 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
350  char *buffer = os_->Push(10);
351  const char* end = internal::u32toa(u, buffer);
352  os_->Pop(10 - (end - buffer));
353  return true;
354 }
355 
356 template<>
357 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
358  char *buffer = os_->Push(21);
359  const char* end = internal::i64toa(i64, buffer);
360  os_->Pop(21 - (end - buffer));
361  return true;
362 }
363 
364 template<>
365 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
366  char *buffer = os_->Push(20);
367  const char* end = internal::u64toa(u, buffer);
368  os_->Pop(20 - (end - buffer));
369  return true;
370 }
371 
372 template<>
373 inline bool Writer<StringBuffer>::WriteDouble(double d) {
374  char *buffer = os_->Push(25);
375  char* end = internal::dtoa(d, buffer);
376  os_->Pop(25 - (end - buffer));
377  return true;
378 }
379 
380 } // namespace rapidjson
381 
382 #ifdef _MSC_VER
383 RAPIDJSON_DIAG_POP
384 #endif
385 
386 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:423
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:99
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:162
false
Definition: rapidjson.h:422
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:120
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:89
bool inArray
true if in array, otherwise in object
Definition: writer.h:176
Information for each nested level.
Definition: writer.h:173
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:175
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:167
Type
Type of JSON value.
Definition: rapidjson.h:420
object
Definition: rapidjson.h:424
array
Definition: rapidjson.h:425
JSON writer.
Definition: writer.h:56
null
Definition: rapidjson.h:421
size_t valueCount
number of values in this level
Definition: writer.h:175
string
Definition: rapidjson.h:426
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:594
number
Definition: rapidjson.h:427
Writer(OutputStream &os, Allocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:65