载入中...
搜索中...
未找到
writer.h
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.
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 "stream.h"
19#include "internal/clzll.h"
20#include "internal/meta.h"
21#include "internal/stack.h"
22#include "internal/strfunc.h"
23#include "internal/dtoa.h"
24#include "internal/itoa.h"
25#include "stringbuffer.h"
26#include <new> // placement new
27
28#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
29#include <intrin.h>
30#pragma intrinsic(_BitScanForward)
31#endif
32#ifdef RAPIDJSON_SSE42
33#include <nmmintrin.h>
34#elif defined(RAPIDJSON_SSE2)
35#include <emmintrin.h>
36#elif defined(RAPIDJSON_NEON)
37#include <arm_neon.h>
38#endif
39
40#ifdef __clang__
41RAPIDJSON_DIAG_PUSH
42RAPIDJSON_DIAG_OFF(padded)
43RAPIDJSON_DIAG_OFF(unreachable-code)
44RAPIDJSON_DIAG_OFF(c++98-compat)
45#elif defined(_MSC_VER)
46RAPIDJSON_DIAG_PUSH
47RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
48#endif
49
50RAPIDJSON_NAMESPACE_BEGIN
51
52///////////////////////////////////////////////////////////////////////////////
53// WriteFlag
54
55/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
56 \ingroup RAPIDJSON_CONFIG
57 \brief User-defined kWriteDefaultFlags definition.
58
59 User can define this as any \c WriteFlag combinations.
60*/
61#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
62#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
63#endif
64
65//! Combination of writeFlags
67 kWriteNoFlags = 0, //!< No flags are set.
68 kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
69 kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
70 kWriteNanAndInfNullFlag = 4, //!< Allow writing of Infinity, -Infinity and NaN as null.
71 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
72};
73
74//! JSON writer
75/*! Writer implements the concept Handler.
76 It generates JSON text by events to an output os.
77
78 User may programmatically calls the functions of a writer to generate JSON text.
79
80 On the other side, a writer can also be passed to objects that generates events,
81
82 for example Reader::Parse() and Document::Accept().
83
84 \tparam OutputStream Type of output stream.
85 \tparam SourceEncoding Encoding of source string.
86 \tparam TargetEncoding Encoding of output stream.
87 \tparam StackAllocator Type of allocator for allocating memory of stack.
88 \note implements Handler concept
89*/
90template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
91class Writer {
92public:
93 typedef typename SourceEncoding::Ch Ch;
94
95 static const int kDefaultMaxDecimalPlaces = 324;
96
97 //! Constructor
98 /*! \param os Output stream.
99 \param stackAllocator User supplied allocator. If it is null, it will create a private one.
100 \param levelDepth Initial capacity of stack.
101 */
102 explicit
103 Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
104 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
105
106 explicit
107 Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
108 os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
109
110#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
111 Writer(Writer&& rhs) :
112 os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
113 rhs.os_ = 0;
114 }
115#endif
116
117 //! Reset the writer with a new stream.
118 /*!
119 This function reset the writer with a new stream and default settings,
120 in order to make a Writer object reusable for output multiple JSONs.
121
122 \param os New output stream.
123 \code
124 Writer<OutputStream> writer(os1);
125 writer.StartObject();
126 // ...
127 writer.EndObject();
128
129 writer.Reset(os2);
130 writer.StartObject();
131 // ...
132 writer.EndObject();
133 \endcode
134 */
135 void Reset(OutputStream& os) {
136 os_ = &os;
137 hasRoot_ = false;
138 level_stack_.Clear();
139 }
140
141 //! Checks whether the output is a complete JSON.
142 /*!
143 A complete JSON has a complete root object or array.
144 */
145 bool IsComplete() const {
146 return hasRoot_ && level_stack_.Empty();
147 }
148
149 int GetMaxDecimalPlaces() const {
150 return maxDecimalPlaces_;
151 }
152
153 //! Sets the maximum number of decimal places for double output.
154 /*!
155 This setting truncates the output with specified number of decimal places.
156
157 For example,
158
159 \code
160 writer.SetMaxDecimalPlaces(3);
161 writer.StartArray();
162 writer.Double(0.12345); // "0.123"
163 writer.Double(0.0001); // "0.0"
164 writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
165 writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
166 writer.EndArray();
167 \endcode
168
169 The default setting does not truncate any decimal places. You can restore to this setting by calling
170 \code
171 writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
172 \endcode
173 */
174 void SetMaxDecimalPlaces(int maxDecimalPlaces) {
175 maxDecimalPlaces_ = maxDecimalPlaces;
176 }
177
178 /*!@name Implementation of Handler
179 \see Handler
180 */
181 //@{
182
183 bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
184 bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
185 bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
186 bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
187 bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
188 bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
189
190 //! Writes the given \c double value to the stream
191 /*!
192 \param d The value to be written.
193 \return Whether it is succeed.
194 */
195 bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
196
197 bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
198 RAPIDJSON_ASSERT(str != 0);
199 (void)copy;
200 Prefix(kNumberType);
201 return EndValue(WriteString(str, length));
202 }
203
204 bool String(const Ch* str, SizeType length, bool copy = false) {
205 RAPIDJSON_ASSERT(str != 0);
206 (void)copy;
207 Prefix(kStringType);
208 return EndValue(WriteString(str, length));
209 }
210
211#if RAPIDJSON_HAS_STDSTRING
212 bool String(const std::basic_string<Ch>& str) {
213 return String(str.data(), SizeType(str.size()));
214 }
215#endif
216
217 bool StartObject() {
218 Prefix(kObjectType);
219 new (level_stack_.template Push<Level>()) Level(false);
220 return WriteStartObject();
221 }
222
223 bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
224
225#if RAPIDJSON_HAS_STDSTRING
226 bool Key(const std::basic_string<Ch>& str)
227 {
228 return Key(str.data(), SizeType(str.size()));
229 }
230#endif
231
232 bool EndObject(SizeType memberCount = 0) {
233 (void)memberCount;
234 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
235 RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
236 RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
237 level_stack_.template Pop<Level>(1);
238 return EndValue(WriteEndObject());
239 }
240
241 bool StartArray() {
242 Prefix(kArrayType);
243 new (level_stack_.template Push<Level>()) Level(true);
244 return WriteStartArray();
245 }
246
247 bool EndArray(SizeType elementCount = 0) {
248 (void)elementCount;
249 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
250 RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
251 level_stack_.template Pop<Level>(1);
252 return EndValue(WriteEndArray());
253 }
254 //@}
255
256 /*! @name Convenience extensions */
257 //@{
258
259 //! Simpler but slower overload.
260 bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
261 bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
262
263 //@}
264
265 //! Write a raw JSON value.
266 /*!
267 For user to write a stringified JSON as a value.
268
269 \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
270 \param length Length of the json.
271 \param type Type of the root of json.
272 */
273 bool RawValue(const Ch* json, size_t length, Type type) {
274 RAPIDJSON_ASSERT(json != 0);
275 Prefix(type);
276 return EndValue(WriteRawValue(json, length));
277 }
278
279 //! Flush the output stream.
280 /*!
281 Allows the user to flush the output stream immediately.
282 */
283 void Flush() {
284 os_->Flush();
285 }
286
287 static const size_t kDefaultLevelDepth = 32;
288
289protected:
290 //! Information for each nested level
291 struct Level {
292 Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
293 size_t valueCount; //!< number of values in this level
294 bool inArray; //!< true if in array, otherwise in object
295 };
296
297 bool WriteNull() {
298 PutReserve(*os_, 4);
299 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
300 }
301
302 bool WriteBool(bool b) {
303 if (b) {
304 PutReserve(*os_, 4);
305 PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
306 }
307 else {
308 PutReserve(*os_, 5);
309 PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
310 }
311 return true;
312 }
313
314 bool WriteInt(int i) {
315 char buffer[11];
316 const char* end = internal::i32toa(i, buffer);
317 PutReserve(*os_, static_cast<size_t>(end - buffer));
318 for (const char* p = buffer; p != end; ++p)
319 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
320 return true;
321 }
322
323 bool WriteUint(unsigned u) {
324 char buffer[10];
325 const char* end = internal::u32toa(u, buffer);
326 PutReserve(*os_, static_cast<size_t>(end - buffer));
327 for (const char* p = buffer; p != end; ++p)
328 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
329 return true;
330 }
331
332 bool WriteInt64(int64_t i64) {
333 char buffer[21];
334 const char* end = internal::i64toa(i64, buffer);
335 PutReserve(*os_, static_cast<size_t>(end - buffer));
336 for (const char* p = buffer; p != end; ++p)
337 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
338 return true;
339 }
340
341 bool WriteUint64(uint64_t u64) {
342 char buffer[20];
343 char* end = internal::u64toa(u64, buffer);
344 PutReserve(*os_, static_cast<size_t>(end - buffer));
345 for (char* p = buffer; p != end; ++p)
346 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
347 return true;
348 }
349
350 bool WriteDouble(double d) {
351 if (internal::Double(d).IsNanOrInf()) {
352 if (!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag))
353 return false;
354 if (writeFlags & kWriteNanAndInfNullFlag) {
355 PutReserve(*os_, 4);
356 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
357 return true;
358 }
359 if (internal::Double(d).IsNan()) {
360 PutReserve(*os_, 3);
361 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
362 return true;
363 }
364 if (internal::Double(d).Sign()) {
365 PutReserve(*os_, 9);
366 PutUnsafe(*os_, '-');
367 }
368 else
369 PutReserve(*os_, 8);
370 PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
371 PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
372 return true;
373 }
374
375 char buffer[25];
376 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
377 PutReserve(*os_, static_cast<size_t>(end - buffer));
378 for (char* p = buffer; p != end; ++p)
379 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
380 return true;
381 }
382
383 bool WriteString(const Ch* str, SizeType length) {
384 static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
385 static const char escape[256] = {
386#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
387 //0 1 2 3 4 5 6 7 8 9 A B C D E F
388 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
389 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
390 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
391 Z16, Z16, // 30~4F
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
393 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
394#undef Z16
395 };
396
397 if (TargetEncoding::supportUnicode)
398 PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
399 else
400 PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
401
402 PutUnsafe(*os_, '\"');
403 GenericStringStream<SourceEncoding> is(str);
404 while (ScanWriteUnescapedString(is, length)) {
405 const Ch c = is.Peek();
406 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
407 // Unicode escaping
408 unsigned codepoint;
409 if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
410 return false;
411 PutUnsafe(*os_, '\\');
412 PutUnsafe(*os_, 'u');
413 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
414 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
415 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
416 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
417 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
418 }
419 else {
420 RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
421 // Surrogate pair
422 unsigned s = codepoint - 0x010000;
423 unsigned lead = (s >> 10) + 0xD800;
424 unsigned trail = (s & 0x3FF) + 0xDC00;
425 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
426 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
427 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
428 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
429 PutUnsafe(*os_, '\\');
430 PutUnsafe(*os_, 'u');
431 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
432 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
433 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
434 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
435 }
436 }
437 else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
438 is.Take();
439 PutUnsafe(*os_, '\\');
440 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
441 if (escape[static_cast<unsigned char>(c)] == 'u') {
442 PutUnsafe(*os_, '0');
443 PutUnsafe(*os_, '0');
444 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
445 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
446 }
447 }
448 else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
449 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
450 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
451 return false;
452 }
453 PutUnsafe(*os_, '\"');
454 return true;
455 }
456
457 bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
458 return RAPIDJSON_LIKELY(is.Tell() < length);
459 }
460
461 bool WriteStartObject() { os_->Put('{'); return true; }
462 bool WriteEndObject() { os_->Put('}'); return true; }
463 bool WriteStartArray() { os_->Put('['); return true; }
464 bool WriteEndArray() { os_->Put(']'); return true; }
465
466 bool WriteRawValue(const Ch* json, size_t length) {
467 PutReserve(*os_, length);
468 GenericStringStream<SourceEncoding> is(json);
469 while (RAPIDJSON_LIKELY(is.Tell() < length)) {
470 RAPIDJSON_ASSERT(is.Peek() != '\0');
471 if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
472 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
473 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
474 return false;
475 }
476 return true;
477 }
478
479 void Prefix(Type type) {
480 (void)type;
481 if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
482 Level* level = level_stack_.template Top<Level>();
483 if (level->valueCount > 0) {
484 if (level->inArray)
485 os_->Put(','); // add comma if it is not the first element in array
486 else // in object
487 os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
488 }
489 if (!level->inArray && level->valueCount % 2 == 0)
490 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
491 level->valueCount++;
492 }
493 else {
494 RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
495 hasRoot_ = true;
496 }
497 }
498
499 // Flush the value if it is the top level one.
500 bool EndValue(bool ret) {
501 if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
502 Flush();
503 return ret;
504 }
505
506 OutputStream* os_;
507 internal::Stack<StackAllocator> level_stack_;
508 int maxDecimalPlaces_;
509 bool hasRoot_;
510
511private:
512 // Prohibit copy constructor & assignment operator.
513 Writer(const Writer&);
514 Writer& operator=(const Writer&);
515};
516
517// Full specialization for StringStream to prevent memory copying
518
519template<>
520inline bool Writer<StringBuffer>::WriteInt(int i) {
521 char *buffer = os_->Push(11);
522 const char* end = internal::i32toa(i, buffer);
523 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
524 return true;
525}
526
527template<>
528inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
529 char *buffer = os_->Push(10);
530 const char* end = internal::u32toa(u, buffer);
531 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
532 return true;
533}
534
535template<>
536inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
537 char *buffer = os_->Push(21);
538 const char* end = internal::i64toa(i64, buffer);
539 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
540 return true;
541}
542
543template<>
544inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
545 char *buffer = os_->Push(20);
546 const char* end = internal::u64toa(u, buffer);
547 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
548 return true;
549}
550
551template<>
552inline bool Writer<StringBuffer>::WriteDouble(double d) {
553 if (internal::Double(d).IsNanOrInf()) {
554 // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
555 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
556 return false;
557 if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) {
558 PutReserve(*os_, 4);
559 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
560 return true;
561 }
562 if (internal::Double(d).IsNan()) {
563 PutReserve(*os_, 3);
564 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
565 return true;
566 }
567 if (internal::Double(d).Sign()) {
568 PutReserve(*os_, 9);
569 PutUnsafe(*os_, '-');
570 }
571 else
572 PutReserve(*os_, 8);
573 PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
574 PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
575 return true;
576 }
577
578 char *buffer = os_->Push(25);
579 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
580 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
581 return true;
582}
583
584#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
585template<>
586inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
587 if (length < 16)
588 return RAPIDJSON_LIKELY(is.Tell() < length);
589
590 if (!RAPIDJSON_LIKELY(is.Tell() < length))
591 return false;
592
593 const char* p = is.src_;
594 const char* end = is.head_ + length;
595 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
596 const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
597 if (nextAligned > end)
598 return true;
599
600 while (p != nextAligned)
601 if (*p < 0x20 || *p == '\"' || *p == '\\') {
602 is.src_ = p;
603 return RAPIDJSON_LIKELY(is.Tell() < length);
604 }
605 else
606 os_->PutUnsafe(*p++);
607
608 // The rest of string using SIMD
609 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
610 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
611 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
612 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
613 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
614 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
615
616 for (; p != endAligned; p += 16) {
617 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
618 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
619 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
620 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
621 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
622 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
623 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
624 SizeType len;
625#ifdef _MSC_VER // Find the index of first escaped
626 unsigned long offset;
627 _BitScanForward(&offset, r);
628 len = offset;
629#else
630 len = static_cast<SizeType>(__builtin_ffs(r) - 1);
631#endif
632 char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
633 for (size_t i = 0; i < len; i++)
634 q[i] = p[i];
635
636 p += len;
637 break;
638 }
639 _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
640 }
641
642 is.src_ = p;
643 return RAPIDJSON_LIKELY(is.Tell() < length);
644}
645#elif defined(RAPIDJSON_NEON)
646template<>
647inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
648 if (length < 16)
649 return RAPIDJSON_LIKELY(is.Tell() < length);
650
651 if (!RAPIDJSON_LIKELY(is.Tell() < length))
652 return false;
653
654 const char* p = is.src_;
655 const char* end = is.head_ + length;
656 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
657 const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
658 if (nextAligned > end)
659 return true;
660
661 while (p != nextAligned)
662 if (*p < 0x20 || *p == '\"' || *p == '\\') {
663 is.src_ = p;
664 return RAPIDJSON_LIKELY(is.Tell() < length);
665 }
666 else
667 os_->PutUnsafe(*p++);
668
669 // The rest of string using SIMD
670 const uint8x16_t s0 = vmovq_n_u8('"');
671 const uint8x16_t s1 = vmovq_n_u8('\\');
672 const uint8x16_t s2 = vmovq_n_u8('\b');
673 const uint8x16_t s3 = vmovq_n_u8(32);
674
675 for (; p != endAligned; p += 16) {
676 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
677 uint8x16_t x = vceqq_u8(s, s0);
678 x = vorrq_u8(x, vceqq_u8(s, s1));
679 x = vorrq_u8(x, vceqq_u8(s, s2));
680 x = vorrq_u8(x, vcltq_u8(s, s3));
681
682 x = vrev64q_u8(x); // Rev in 64
683 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
684 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
685
686 SizeType len = 0;
687 bool escaped = false;
688 if (low == 0) {
689 if (high != 0) {
690 uint32_t lz = internal::clzll(high);
691 len = 8 + (lz >> 3);
692 escaped = true;
693 }
694 } else {
695 uint32_t lz = internal::clzll(low);
696 len = lz >> 3;
697 escaped = true;
698 }
699 if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
700 char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
701 for (size_t i = 0; i < len; i++)
702 q[i] = p[i];
703
704 p += len;
705 break;
706 }
707 vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
708 }
709
710 is.src_ = p;
711 return RAPIDJSON_LIKELY(is.Tell() < length);
712}
713#endif // RAPIDJSON_NEON
714
715RAPIDJSON_NAMESPACE_END
716
717#if defined(_MSC_VER) || defined(__clang__)
718RAPIDJSON_DIAG_POP
719#endif
720
721#endif // RAPIDJSON_RAPIDJSON_H_
JSON writer
定义 writer.h:91
bool IsComplete() const
Checks whether the output is a complete JSON.
定义 writer.h:145
void Flush()
Flush the output stream.
定义 writer.h:283
bool String(const Ch *const &str)
Simpler but slower overload.
定义 writer.h:260
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
定义 writer.h:273
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor
定义 writer.h:103
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
定义 writer.h:174
void Reset(OutputStream &os)
Reset the writer with a new stream.
定义 writer.h:135
bool Double(double d)
Writes the given double value to the stream
定义 writer.h:195
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
User-defined kWriteDefaultFlags definition.
定义 writer.h:62
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
定义 rapidjson.h:494
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
定义 rapidjson.h:507
#define RAPIDJSON_ASSERT(x)
Assertion.
定义 rapidjson.h:437
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
定义 stream.h:91
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
定义 rapidjson.h:415
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
定义 stream.h:84
WriteFlag
Combination of writeFlags
定义 writer.h:66
@ kWriteNanAndInfFlag
Allow writing of Infinity, -Infinity and NaN.
定义 writer.h:69
@ kWriteNanAndInfNullFlag
Allow writing of Infinity, -Infinity and NaN as null.
定义 writer.h:70
@ kWriteDefaultFlags
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
定义 writer.h:71
@ kWriteValidateEncodingFlag
Validate encoding of JSON strings.
定义 writer.h:68
@ kWriteNoFlags
No flags are set.
定义 writer.h:67
Type
Type of JSON value
定义 rapidjson.h:729
@ kNumberType
number
定义 rapidjson.h:736
Information for each nested level
定义 writer.h:291
bool inArray
true if in array, otherwise in object
定义 writer.h:294
size_t valueCount
number of values in this level
定义 writer.h:293