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