All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 StackAllocator 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 StackAllocator = CrtAllocator>
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, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
66  os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
67 
68  Writer(StackAllocator* 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 Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
135 
136  bool EndObject(SizeType memberCount = 0) {
137  (void)memberCount;
138  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
139  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
140  level_stack_.template Pop<Level>(1);
141  bool ret = WriteEndObject();
142  if (level_stack_.Empty()) // end of json text
143  os_->Flush();
144  return ret;
145  }
146 
147  bool StartArray() {
148  Prefix(kArrayType);
149  new (level_stack_.template Push<Level>()) Level(true);
150  return WriteStartArray();
151  }
152 
153  bool EndArray(SizeType elementCount = 0) {
154  (void)elementCount;
155  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
156  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
157  level_stack_.template Pop<Level>(1);
158  bool ret = WriteEndArray();
159  if (level_stack_.Empty()) // end of json text
160  os_->Flush();
161  return ret;
162  }
163  //@}
164 
165  /*! @name Convenience extensions */
166  //@{
167 
168  //! Simpler but slower overload.
169  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
170  bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
171 
172  //@}
173 
174 protected:
175  //! Information for each nested level
176  struct Level {
177  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
178  size_t valueCount; //!< number of values in this level
179  bool inArray; //!< true if in array, otherwise in object
180  };
181 
182  static const size_t kDefaultLevelDepth = 32;
183 
184  bool WriteNull() {
185  os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
186  }
187 
188  bool WriteBool(bool b) {
189  if (b) {
190  os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
191  }
192  else {
193  os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
194  }
195  return true;
196  }
197 
198  bool WriteInt(int i) {
199  char buffer[11];
200  const char* end = internal::i32toa(i, buffer);
201  for (const char* p = buffer; p != end; ++p)
202  os_->Put(*p);
203  return true;
204  }
205 
206  bool WriteUint(unsigned u) {
207  char buffer[10];
208  const char* end = internal::u32toa(u, buffer);
209  for (const char* p = buffer; p != end; ++p)
210  os_->Put(*p);
211  return true;
212  }
213 
214  bool WriteInt64(int64_t i64) {
215  char buffer[21];
216  const char* end = internal::i64toa(i64, buffer);
217  for (const char* p = buffer; p != end; ++p)
218  os_->Put(*p);
219  return true;
220  }
221 
222  bool WriteUint64(uint64_t u64) {
223  char buffer[20];
224  char* end = internal::u64toa(u64, buffer);
225  for (char* p = buffer; p != end; ++p)
226  os_->Put(*p);
227  return true;
228  }
229 
230  bool WriteDouble(double d) {
231  char buffer[25];
232  char* end = internal::dtoa(d, buffer);
233  for (char* p = buffer; p != end; ++p)
234  os_->Put(*p);
235  return true;
236  }
237 
238  bool WriteString(const Ch* str, SizeType length) {
239  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
240  static const char escape[256] = {
241 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
242  //0 1 2 3 4 5 6 7 8 9 A B C D E F
243  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
244  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
245  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
246  Z16, Z16, // 30~4F
247  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
248  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
249 #undef Z16
250  };
251 
252  os_->Put('\"');
253  GenericStringStream<SourceEncoding> is(str);
254  while (is.Tell() < length) {
255  const Ch c = is.Peek();
256  if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
257  // Unicode escaping
258  unsigned codepoint;
259  if (!SourceEncoding::Decode(is, &codepoint))
260  return false;
261  os_->Put('\\');
262  os_->Put('u');
263  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
264  os_->Put(hexDigits[(codepoint >> 12) & 15]);
265  os_->Put(hexDigits[(codepoint >> 8) & 15]);
266  os_->Put(hexDigits[(codepoint >> 4) & 15]);
267  os_->Put(hexDigits[(codepoint ) & 15]);
268  }
269  else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
270  // Surrogate pair
271  unsigned s = codepoint - 0x010000;
272  unsigned lead = (s >> 10) + 0xD800;
273  unsigned trail = (s & 0x3FF) + 0xDC00;
274  os_->Put(hexDigits[(lead >> 12) & 15]);
275  os_->Put(hexDigits[(lead >> 8) & 15]);
276  os_->Put(hexDigits[(lead >> 4) & 15]);
277  os_->Put(hexDigits[(lead ) & 15]);
278  os_->Put('\\');
279  os_->Put('u');
280  os_->Put(hexDigits[(trail >> 12) & 15]);
281  os_->Put(hexDigits[(trail >> 8) & 15]);
282  os_->Put(hexDigits[(trail >> 4) & 15]);
283  os_->Put(hexDigits[(trail ) & 15]);
284  }
285  else
286  return false; // invalid code point
287  }
288  else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
289  is.Take();
290  os_->Put('\\');
291  os_->Put(escape[(unsigned char)c]);
292  if (escape[(unsigned char)c] == 'u') {
293  os_->Put('0');
294  os_->Put('0');
295  os_->Put(hexDigits[(unsigned char)c >> 4]);
296  os_->Put(hexDigits[(unsigned char)c & 0xF]);
297  }
298  }
299  else
301  }
302  os_->Put('\"');
303  return true;
304  }
305 
306  bool WriteStartObject() { os_->Put('{'); return true; }
307  bool WriteEndObject() { os_->Put('}'); return true; }
308  bool WriteStartArray() { os_->Put('['); return true; }
309  bool WriteEndArray() { os_->Put(']'); return true; }
310 
311  void Prefix(Type type) {
312  (void)type;
313  if (level_stack_.GetSize() != 0) { // this value is not at root
314  Level* level = level_stack_.template Top<Level>();
315  if (level->valueCount > 0) {
316  if (level->inArray)
317  os_->Put(','); // add comma if it is not the first element in array
318  else // in object
319  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
320  }
321  if (!level->inArray && level->valueCount % 2 == 0)
322  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
323  level->valueCount++;
324  }
325  else {
326  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
327  hasRoot_ = true;
328  }
329  }
330 
331  OutputStream* os_;
332  internal::Stack<StackAllocator> level_stack_;
333  bool hasRoot_;
334 
335 private:
336  // Prohibit copy constructor & assignment operator.
337  Writer(const Writer&);
338  Writer& operator=(const Writer&);
339 };
340 
341 // Full specialization for StringStream to prevent memory copying
342 
343 template<>
344 inline bool Writer<StringBuffer>::WriteInt(int i) {
345  char *buffer = os_->Push(11);
346  const char* end = internal::i32toa(i, buffer);
347  os_->Pop(11 - (end - buffer));
348  return true;
349 }
350 
351 template<>
352 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
353  char *buffer = os_->Push(10);
354  const char* end = internal::u32toa(u, buffer);
355  os_->Pop(10 - (end - buffer));
356  return true;
357 }
358 
359 template<>
360 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
361  char *buffer = os_->Push(21);
362  const char* end = internal::i64toa(i64, buffer);
363  os_->Pop(21 - (end - buffer));
364  return true;
365 }
366 
367 template<>
368 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
369  char *buffer = os_->Push(20);
370  const char* end = internal::u64toa(u, buffer);
371  os_->Pop(20 - (end - buffer));
372  return true;
373 }
374 
375 template<>
376 inline bool Writer<StringBuffer>::WriteDouble(double d) {
377  char *buffer = os_->Push(25);
378  char* end = internal::dtoa(d, buffer);
379  os_->Pop(25 - (end - buffer));
380  return true;
381 }
382 
383 } // namespace rapidjson
384 
385 #ifdef _MSC_VER
386 RAPIDJSON_DIAG_POP
387 #endif
388 
389 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:570
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:120
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:247
false
Definition: rapidjson.h:569
bool inArray
true if in array, otherwise in object
Definition: writer.h:179
Information for each nested level.
Definition: writer.h:176
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:169
Type
Type of JSON value.
Definition: rapidjson.h:567
object
Definition: rapidjson.h:571
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:65
size_t valueCount
number of values in this level
Definition: writer.h:178
array
Definition: rapidjson.h:572
JSON writer.
Definition: writer.h:56
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:99
null
Definition: rapidjson.h:568
string
Definition: rapidjson.h:573
common definitions and configuration
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
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:89
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:269
number
Definition: rapidjson.h:574