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 RAPIDJSON_NAMESPACE_BEGIN
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 stackAllocator User supplied allocator. If it is null, it will create a private one.
63 \param levelDepth Initial capacity of stack.
64 */
65 explicit
66 Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
67 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
68
69 explicit
70 Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
71 os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
72
73 //! Reset the writer with a new stream.
74 /*!
75 This function reset the writer with a new stream and default settings,
76 in order to make a Writer object reusable for output multiple JSONs.
77
78 \param os New output stream.
79 \code
80 Writer<OutputStream> writer(os1);
81 writer.StartObject();
82 // ...
83 writer.EndObject();
84
85 writer.Reset(os2);
86 writer.StartObject();
87 // ...
88 writer.EndObject();
89 \endcode
90 */
Reset(OutputStream & os)91 void Reset(OutputStream& os) {
92 os_ = &os;
93 hasRoot_ = false;
94 level_stack_.Clear();
95 }
96
97 //! Checks whether the output is a complete JSON.
98 /*!
99 A complete JSON has a complete root object or array.
100 */
IsComplete()101 bool IsComplete() const {
102 return hasRoot_ && level_stack_.Empty();
103 }
104
105 /*!@name Implementation of Handler
106 \see Handler
107 */
108 //@{
109
Null()110 bool Null() { Prefix(kNullType); return WriteNull(); }
Bool(bool b)111 bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
Int(int i)112 bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
Uint(unsigned u)113 bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
Int64(int64_t i64)114 bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
Uint64(uint64_t u64)115 bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
116
117 //! Writes the given \c double value to the stream
118 /*!
119 \param d The value to be written.
120 \return Whether it is succeed.
121 */
Double(double d)122 bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
123
124 bool String(const Ch* str, SizeType length, bool copy = false) {
125 (void)copy;
126 Prefix(kStringType);
127 return WriteString(str, length);
128 }
129
StartObject()130 bool StartObject() {
131 Prefix(kObjectType);
132 new (level_stack_.template Push<Level>()) Level(false);
133 return WriteStartObject();
134 }
135
136 bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
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
StartArray()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 //! Simpler but slower overload.
String(const Ch * str)171 bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
Key(const Ch * str)172 bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
173
174 //@}
175
176 protected:
177 //! Information for each nested level
178 struct Level {
LevelLevel179 Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
180 size_t valueCount; //!< number of values in this level
181 bool inArray; //!< true if in array, otherwise in object
182 };
183
184 static const size_t kDefaultLevelDepth = 32;
185
WriteNull()186 bool WriteNull() {
187 os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
188 }
189
WriteBool(bool b)190 bool WriteBool(bool b) {
191 if (b) {
192 os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
193 }
194 else {
195 os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
196 }
197 return true;
198 }
199
WriteInt(int i)200 bool WriteInt(int i) {
201 char buffer[11];
202 const char* end = internal::i32toa(i, buffer);
203 for (const char* p = buffer; p != end; ++p)
204 os_->Put(*p);
205 return true;
206 }
207
WriteUint(unsigned u)208 bool WriteUint(unsigned u) {
209 char buffer[10];
210 const char* end = internal::u32toa(u, buffer);
211 for (const char* p = buffer; p != end; ++p)
212 os_->Put(*p);
213 return true;
214 }
215
WriteInt64(int64_t i64)216 bool WriteInt64(int64_t i64) {
217 char buffer[21];
218 const char* end = internal::i64toa(i64, buffer);
219 for (const char* p = buffer; p != end; ++p)
220 os_->Put(*p);
221 return true;
222 }
223
WriteUint64(uint64_t u64)224 bool WriteUint64(uint64_t u64) {
225 char buffer[20];
226 char* end = internal::u64toa(u64, buffer);
227 for (char* p = buffer; p != end; ++p)
228 os_->Put(*p);
229 return true;
230 }
231
WriteDouble(double d)232 bool WriteDouble(double d) {
233 char buffer[25];
234 char* end = internal::dtoa(d, buffer);
235 for (char* p = buffer; p != end; ++p)
236 os_->Put(*p);
237 return true;
238 }
239
WriteString(const Ch * str,SizeType length)240 bool WriteString(const Ch* str, SizeType length) {
241 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
242 static const char escape[256] = {
243 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
244 //0 1 2 3 4 5 6 7 8 9 A B C D E F
245 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
246 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
247 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
248 Z16, Z16, // 30~4F
249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
250 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
251 #undef Z16
252 };
253
254 os_->Put('\"');
255 GenericStringStream<SourceEncoding> is(str);
256 while (is.Tell() < length) {
257 const Ch c = is.Peek();
258 if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
259 // Unicode escaping
260 unsigned codepoint;
261 if (!SourceEncoding::Decode(is, &codepoint))
262 return false;
263 os_->Put('\\');
264 os_->Put('u');
265 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
266 os_->Put(hexDigits[(codepoint >> 12) & 15]);
267 os_->Put(hexDigits[(codepoint >> 8) & 15]);
268 os_->Put(hexDigits[(codepoint >> 4) & 15]);
269 os_->Put(hexDigits[(codepoint ) & 15]);
270 }
271 else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
272 // Surrogate pair
273 unsigned s = codepoint - 0x010000;
274 unsigned lead = (s >> 10) + 0xD800;
275 unsigned trail = (s & 0x3FF) + 0xDC00;
276 os_->Put(hexDigits[(lead >> 12) & 15]);
277 os_->Put(hexDigits[(lead >> 8) & 15]);
278 os_->Put(hexDigits[(lead >> 4) & 15]);
279 os_->Put(hexDigits[(lead ) & 15]);
280 os_->Put('\\');
281 os_->Put('u');
282 os_->Put(hexDigits[(trail >> 12) & 15]);
283 os_->Put(hexDigits[(trail >> 8) & 15]);
284 os_->Put(hexDigits[(trail >> 4) & 15]);
285 os_->Put(hexDigits[(trail ) & 15]);
286 }
287 else
288 return false; // invalid code point
289 }
290 else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
291 is.Take();
292 os_->Put('\\');
293 os_->Put(escape[(unsigned char)c]);
294 if (escape[(unsigned char)c] == 'u') {
295 os_->Put('0');
296 os_->Put('0');
297 os_->Put(hexDigits[(unsigned char)c >> 4]);
298 os_->Put(hexDigits[(unsigned char)c & 0xF]);
299 }
300 }
301 else
302 Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_);
303 }
304 os_->Put('\"');
305 return true;
306 }
307
WriteStartObject()308 bool WriteStartObject() { os_->Put('{'); return true; }
WriteEndObject()309 bool WriteEndObject() { os_->Put('}'); return true; }
WriteStartArray()310 bool WriteStartArray() { os_->Put('['); return true; }
WriteEndArray()311 bool WriteEndArray() { os_->Put(']'); return true; }
312
Prefix(Type type)313 void Prefix(Type type) {
314 (void)type;
315 if (level_stack_.GetSize() != 0) { // this value is not at root
316 Level* level = level_stack_.template Top<Level>();
317 if (level->valueCount > 0) {
318 if (level->inArray)
319 os_->Put(','); // add comma if it is not the first element in array
320 else // in object
321 os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
322 }
323 if (!level->inArray && level->valueCount % 2 == 0)
324 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
325 level->valueCount++;
326 }
327 else {
328 RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
329 hasRoot_ = true;
330 }
331 }
332
333 OutputStream* os_;
334 internal::Stack<StackAllocator> level_stack_;
335 bool hasRoot_;
336
337 private:
338 // Prohibit copy constructor & assignment operator.
339 Writer(const Writer&);
340 Writer& operator=(const Writer&);
341 };
342
343 // Full specialization for StringStream to prevent memory copying
344
345 template<>
WriteInt(int i)346 inline bool Writer<StringBuffer>::WriteInt(int i) {
347 char *buffer = os_->Push(11);
348 const char* end = internal::i32toa(i, buffer);
349 os_->Pop(11 - (end - buffer));
350 return true;
351 }
352
353 template<>
WriteUint(unsigned u)354 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
355 char *buffer = os_->Push(10);
356 const char* end = internal::u32toa(u, buffer);
357 os_->Pop(10 - (end - buffer));
358 return true;
359 }
360
361 template<>
WriteInt64(int64_t i64)362 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
363 char *buffer = os_->Push(21);
364 const char* end = internal::i64toa(i64, buffer);
365 os_->Pop(21 - (end - buffer));
366 return true;
367 }
368
369 template<>
WriteUint64(uint64_t u)370 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
371 char *buffer = os_->Push(20);
372 const char* end = internal::u64toa(u, buffer);
373 os_->Pop(20 - (end - buffer));
374 return true;
375 }
376
377 template<>
WriteDouble(double d)378 inline bool Writer<StringBuffer>::WriteDouble(double d) {
379 char *buffer = os_->Push(25);
380 char* end = internal::dtoa(d, buffer);
381 os_->Pop(25 - (end - buffer));
382 return true;
383 }
384
385 RAPIDJSON_NAMESPACE_END
386
387 #ifdef _MSC_VER
388 RAPIDJSON_DIAG_POP
389 #endif
390
391 #endif // RAPIDJSON_RAPIDJSON_H_
392