1// Tencent is pleased to support the open source community by making RapidJSON available. 2// 3// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4// 5// Licensed under the MIT License (the "License"); you may not use this file except 6// in compliance with the License. You may obtain a copy of the License at 7// 8// http://opensource.org/licenses/MIT 9// 10// Unless required by applicable law or agreed to in writing, software distributed 11// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12// CONDITIONS OF ANY KIND, either express or implied. See the License for the 13// specific language governing permissions and limitations under the License. 14 15#ifndef RAPIDJSON_WRITER_H_ 16#define RAPIDJSON_WRITER_H_ 17 18#include "rapidjson.h" 19#include "internal/stack.h" 20#include "internal/strfunc.h" 21#include "internal/dtoa.h" 22#include "internal/itoa.h" 23#include "stringbuffer.h" 24#include <new> // placement new 25 26#if RAPIDJSON_HAS_STDSTRING 27#include <string> 28#endif 29 30#ifdef _MSC_VER 31RAPIDJSON_DIAG_PUSH 32RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant 33#endif 34 35RAPIDJSON_NAMESPACE_BEGIN 36 37//! JSON writer 38/*! Writer implements the concept Handler. 39 It generates JSON text by events to an output os. 40 41 User may programmatically calls the functions of a writer to generate JSON text. 42 43 On the other side, a writer can also be passed to objects that generates events, 44 45 for example Reader::Parse() and Document::Accept(). 46 47 \tparam OutputStream Type of output stream. 48 \tparam SourceEncoding Encoding of source string. 49 \tparam TargetEncoding Encoding of output stream. 50 \tparam StackAllocator Type of allocator for allocating memory of stack. 51 \note implements Handler concept 52*/ 53template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> 54class Writer { 55public: 56 typedef typename SourceEncoding::Ch Ch; 57 58 //! Constructor 59 /*! \param os Output stream. 60 \param stackAllocator User supplied allocator. If it is null, it will create a private one. 61 \param levelDepth Initial capacity of stack. 62 */ 63 explicit 64 Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 65 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} 66 67 explicit 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#if RAPIDJSON_HAS_STDSTRING 129 bool String(const std::basic_string<Ch>& str) { 130 return String(str.data(), SizeType(str.size())); 131 } 132#endif 133 134 bool StartObject() { 135 Prefix(kObjectType); 136 new (level_stack_.template Push<Level>()) Level(false); 137 return WriteStartObject(); 138 } 139 140 bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } 141 142 bool EndObject(SizeType memberCount = 0) { 143 (void)memberCount; 144 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); 145 RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); 146 level_stack_.template Pop<Level>(1); 147 bool ret = WriteEndObject(); 148 if (level_stack_.Empty()) // end of json text 149 os_->Flush(); 150 return ret; 151 } 152 153 bool StartArray() { 154 Prefix(kArrayType); 155 new (level_stack_.template Push<Level>()) Level(true); 156 return WriteStartArray(); 157 } 158 159 bool EndArray(SizeType elementCount = 0) { 160 (void)elementCount; 161 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); 162 RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); 163 level_stack_.template Pop<Level>(1); 164 bool ret = WriteEndArray(); 165 if (level_stack_.Empty()) // end of json text 166 os_->Flush(); 167 return ret; 168 } 169 //@} 170 171 /*! @name Convenience extensions */ 172 //@{ 173 174 //! Simpler but slower overload. 175 bool String(const Ch* str) { return String(str, internal::StrLen(str)); } 176 bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } 177 178 //@} 179 180protected: 181 //! Information for each nested level 182 struct Level { 183 explicit Level(bool inArray_) : valueCount(0), inArray(inArray_) {} 184 size_t valueCount; //!< number of values in this level 185 bool inArray; //!< true if in array, otherwise in object 186 }; 187 188 static const size_t kDefaultLevelDepth = 32; 189 190 bool WriteNull() { 191 os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; 192 } 193 194 bool WriteBool(bool b) { 195 if (b) { 196 os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); 197 } 198 else { 199 os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); 200 } 201 return true; 202 } 203 204 bool WriteInt(int i) { 205 char buffer[11]; 206 const char* end = internal::i32toa(i, buffer); 207 for (const char* p = buffer; p != end; ++p) 208 os_->Put(*p); 209 return true; 210 } 211 212 bool WriteUint(unsigned u) { 213 char buffer[10]; 214 const char* end = internal::u32toa(u, buffer); 215 for (const char* p = buffer; p != end; ++p) 216 os_->Put(*p); 217 return true; 218 } 219 220 bool WriteInt64(int64_t i64) { 221 char buffer[21]; 222 const char* end = internal::i64toa(i64, buffer); 223 for (const char* p = buffer; p != end; ++p) 224 os_->Put(*p); 225 return true; 226 } 227 228 bool WriteUint64(uint64_t u64) { 229 char buffer[20]; 230 char* end = internal::u64toa(u64, buffer); 231 for (char* p = buffer; p != end; ++p) 232 os_->Put(*p); 233 return true; 234 } 235 236 bool WriteDouble(double d) { 237 char buffer[25]; 238 char* end = internal::dtoa(d, buffer); 239 for (char* p = buffer; p != end; ++p) 240 os_->Put(*p); 241 return true; 242 } 243 244 bool WriteString(const Ch* str, SizeType length) { 245 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 246 static const char escape[256] = { 247#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 248 //0 1 2 3 4 5 6 7 8 9 A B C D E F 249 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 250 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 251 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 252 Z16, Z16, // 30~4F 253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 254 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF 255#undef Z16 256 }; 257 258 os_->Put('\"'); 259 GenericStringStream<SourceEncoding> is(str); 260 while (is.Tell() < length) { 261 const Ch c = is.Peek(); 262 if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { 263 // Unicode escaping 264 unsigned codepoint; 265 if (!SourceEncoding::Decode(is, &codepoint)) 266 return false; 267 os_->Put('\\'); 268 os_->Put('u'); 269 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { 270 os_->Put(hexDigits[(codepoint >> 12) & 15]); 271 os_->Put(hexDigits[(codepoint >> 8) & 15]); 272 os_->Put(hexDigits[(codepoint >> 4) & 15]); 273 os_->Put(hexDigits[(codepoint ) & 15]); 274 } 275 else { 276 RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); 277 // Surrogate pair 278 unsigned s = codepoint - 0x010000; 279 unsigned lead = (s >> 10) + 0xD800; 280 unsigned trail = (s & 0x3FF) + 0xDC00; 281 os_->Put(hexDigits[(lead >> 12) & 15]); 282 os_->Put(hexDigits[(lead >> 8) & 15]); 283 os_->Put(hexDigits[(lead >> 4) & 15]); 284 os_->Put(hexDigits[(lead ) & 15]); 285 os_->Put('\\'); 286 os_->Put('u'); 287 os_->Put(hexDigits[(trail >> 12) & 15]); 288 os_->Put(hexDigits[(trail >> 8) & 15]); 289 os_->Put(hexDigits[(trail >> 4) & 15]); 290 os_->Put(hexDigits[(trail ) & 15]); 291 } 292 } 293 else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { 294 is.Take(); 295 os_->Put('\\'); 296 os_->Put(escape[(unsigned char)c]); 297 if (escape[(unsigned char)c] == 'u') { 298 os_->Put('0'); 299 os_->Put('0'); 300 os_->Put(hexDigits[(unsigned char)c >> 4]); 301 os_->Put(hexDigits[(unsigned char)c & 0xF]); 302 } 303 } 304 else 305 if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_)) 306 return false; 307 } 308 os_->Put('\"'); 309 return true; 310 } 311 312 bool WriteStartObject() { os_->Put('{'); return true; } 313 bool WriteEndObject() { os_->Put('}'); return true; } 314 bool WriteStartArray() { os_->Put('['); return true; } 315 bool WriteEndArray() { os_->Put(']'); return true; } 316 317 void Prefix(Type type) { 318 (void)type; 319 if (level_stack_.GetSize() != 0) { // this value is not at root 320 Level* level = level_stack_.template Top<Level>(); 321 if (level->valueCount > 0) { 322 if (level->inArray) 323 os_->Put(','); // add comma if it is not the first element in array 324 else // in object 325 os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); 326 } 327 if (!level->inArray && level->valueCount % 2 == 0) 328 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name 329 level->valueCount++; 330 } 331 else { 332 RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. 333 hasRoot_ = true; 334 } 335 } 336 337 OutputStream* os_; 338 internal::Stack<StackAllocator> level_stack_; 339 bool hasRoot_; 340 341private: 342 // Prohibit copy constructor & assignment operator. 343 Writer(const Writer&); 344 Writer& operator=(const Writer&); 345}; 346 347// Full specialization for StringStream to prevent memory copying 348 349template<> 350inline bool Writer<StringBuffer>::WriteInt(int i) { 351 char *buffer = os_->Push(11); 352 const char* end = internal::i32toa(i, buffer); 353 os_->Pop(static_cast<size_t>(11 - (end - buffer))); 354 return true; 355} 356 357template<> 358inline bool Writer<StringBuffer>::WriteUint(unsigned u) { 359 char *buffer = os_->Push(10); 360 const char* end = internal::u32toa(u, buffer); 361 os_->Pop(static_cast<size_t>(10 - (end - buffer))); 362 return true; 363} 364 365template<> 366inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { 367 char *buffer = os_->Push(21); 368 const char* end = internal::i64toa(i64, buffer); 369 os_->Pop(static_cast<size_t>(21 - (end - buffer))); 370 return true; 371} 372 373template<> 374inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { 375 char *buffer = os_->Push(20); 376 const char* end = internal::u64toa(u, buffer); 377 os_->Pop(static_cast<size_t>(20 - (end - buffer))); 378 return true; 379} 380 381template<> 382inline bool Writer<StringBuffer>::WriteDouble(double d) { 383 char *buffer = os_->Push(25); 384 char* end = internal::dtoa(d, buffer); 385 os_->Pop(static_cast<size_t>(25 - (end - buffer))); 386 return true; 387} 388 389RAPIDJSON_NAMESPACE_END 390 391#ifdef _MSC_VER 392RAPIDJSON_DIAG_POP 393#endif 394 395#endif // RAPIDJSON_RAPIDJSON_H_ 396