writer.h Source File

writer.h Source File#

Composable Kernel: writer.h Source File
writer.h
Go to the documentation of this file.
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
51
53// WriteFlag
54
61#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
62#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
63#endif
64
76
78
93template <typename OutputStream,
94 typename SourceEncoding = UTF8<>,
95 typename TargetEncoding = UTF8<>,
96 typename StackAllocator = CrtAllocator,
97 unsigned writeFlags = kWriteDefaultFlags>
98class Writer
99{
100 public:
101 typedef typename SourceEncoding::Ch Ch;
102
103 static const int kDefaultMaxDecimalPlaces = 324;
104
106
110 explicit Writer(OutputStream& os,
111 StackAllocator* stackAllocator = 0,
112 size_t levelDepth = kDefaultLevelDepth)
113 : os_(&os),
114 level_stack_(stackAllocator, levelDepth * sizeof(Level)),
116 hasRoot_(false)
117 {
118 }
119
120 explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth)
121 : os_(0),
122 level_stack_(allocator, levelDepth * sizeof(Level)),
124 hasRoot_(false)
125 {
126 }
127
128#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
129 Writer(Writer&& rhs)
130 : os_(rhs.os_),
131 level_stack_(std::move(rhs.level_stack_)),
133 hasRoot_(rhs.hasRoot_)
134 {
135 rhs.os_ = 0;
136 }
137#endif
138
140
157 void Reset(OutputStream& os)
158 {
159 os_ = &os;
160 hasRoot_ = false;
161 level_stack_.Clear();
162 }
163
165
168 bool IsComplete() const { return hasRoot_ && level_stack_.Empty(); }
169
171
173
190 void SetMaxDecimalPlaces(int maxDecimalPlaces) { maxDecimalPlaces_ = maxDecimalPlaces; }
191
196
197 bool Null()
198 {
200 return EndValue(WriteNull());
201 }
202 bool Bool(bool b)
203 {
205 return EndValue(WriteBool(b));
206 }
207 bool Int(int i)
208 {
210 return EndValue(WriteInt(i));
211 }
212 bool Uint(unsigned u)
213 {
215 return EndValue(WriteUint(u));
216 }
217 bool Int64(int64_t i64)
218 {
220 return EndValue(WriteInt64(i64));
221 }
222 bool Uint64(uint64_t u64)
223 {
225 return EndValue(WriteUint64(u64));
226 }
227
229
233 bool Double(double d)
234 {
236 return EndValue(WriteDouble(d));
237 }
238
239 bool RawNumber(const Ch* str, SizeType length, bool copy = false)
240 {
241 RAPIDJSON_ASSERT(str != 0);
242 (void)copy;
244 return EndValue(WriteString(str, length));
245 }
246
247 bool String(const Ch* str, SizeType length, bool copy = false)
248 {
249 RAPIDJSON_ASSERT(str != 0);
250 (void)copy;
252 return EndValue(WriteString(str, length));
253 }
254
255#if RAPIDJSON_HAS_STDSTRING
256 bool String(const std::basic_string<Ch>& str)
257 {
258 return String(str.data(), SizeType(str.size()));
259 }
260#endif
261
263 {
265 new(level_stack_.template Push<Level>()) Level(false);
266 return WriteStartObject();
267 }
268
269 bool Key(const Ch* str, SizeType length, bool copy = false)
270 {
271 return String(str, length, copy);
272 }
273
274#if RAPIDJSON_HAS_STDSTRING
275 bool Key(const std::basic_string<Ch>& str) { return Key(str.data(), SizeType(str.size())); }
276#endif
277
278 bool EndObject(SizeType memberCount = 0)
279 {
280 (void)memberCount;
281 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
283 !level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
284 RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount %
285 2); // Object has a Key without a Value
286 level_stack_.template Pop<Level>(1);
287 return EndValue(WriteEndObject());
288 }
289
291 {
293 new(level_stack_.template Push<Level>()) Level(true);
294 return WriteStartArray();
295 }
296
297 bool EndArray(SizeType elementCount = 0)
298 {
299 (void)elementCount;
300 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
301 RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
302 level_stack_.template Pop<Level>(1);
303 return EndValue(WriteEndArray());
304 }
305
306
309
311 bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
312 bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
313
315
317
323 bool RawValue(const Ch* json, size_t length, Type type)
324 {
325 RAPIDJSON_ASSERT(json != 0);
326 Prefix(type);
327 return EndValue(WriteRawValue(json, length));
328 }
329
331
334 void Flush() { os_->Flush(); }
335
336 static const size_t kDefaultLevelDepth = 32;
337
338 protected:
340 struct Level
341 {
342 Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
343 size_t valueCount;
344 bool inArray;
345 };
346
348 {
349 PutReserve(*os_, 4);
350 PutUnsafe(*os_, 'n');
351 PutUnsafe(*os_, 'u');
352 PutUnsafe(*os_, 'l');
353 PutUnsafe(*os_, 'l');
354 return true;
355 }
356
357 bool WriteBool(bool b)
358 {
359 if(b)
360 {
361 PutReserve(*os_, 4);
362 PutUnsafe(*os_, 't');
363 PutUnsafe(*os_, 'r');
364 PutUnsafe(*os_, 'u');
365 PutUnsafe(*os_, 'e');
366 }
367 else
368 {
369 PutReserve(*os_, 5);
370 PutUnsafe(*os_, 'f');
371 PutUnsafe(*os_, 'a');
372 PutUnsafe(*os_, 'l');
373 PutUnsafe(*os_, 's');
374 PutUnsafe(*os_, 'e');
375 }
376 return true;
377 }
378
379 bool WriteInt(int i)
380 {
381 char buffer[11];
382 const char* end = internal::i32toa(i, buffer);
383 PutReserve(*os_, static_cast<size_t>(end - buffer));
384 for(const char* p = buffer; p != end; ++p)
385 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
386 return true;
387 }
388
389 bool WriteUint(unsigned u)
390 {
391 char buffer[10];
392 const char* end = internal::u32toa(u, buffer);
393 PutReserve(*os_, static_cast<size_t>(end - buffer));
394 for(const char* p = buffer; p != end; ++p)
395 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
396 return true;
397 }
398
400 {
401 char buffer[21];
402 const char* end = internal::i64toa(i64, buffer);
403 PutReserve(*os_, static_cast<size_t>(end - buffer));
404 for(const char* p = buffer; p != end; ++p)
405 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
406 return true;
407 }
408
410 {
411 char buffer[20];
412 char* end = internal::u64toa(u64, buffer);
413 PutReserve(*os_, static_cast<size_t>(end - buffer));
414 for(char* p = buffer; p != end; ++p)
415 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
416 return true;
417 }
418
419 bool WriteDouble(double d)
420 {
421 if(internal::Double(d).IsNanOrInf())
422 {
423 if(!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag))
424 return false;
425 if(writeFlags & kWriteNanAndInfNullFlag)
426 {
427 PutReserve(*os_, 4);
428 PutUnsafe(*os_, 'n');
429 PutUnsafe(*os_, 'u');
430 PutUnsafe(*os_, 'l');
431 PutUnsafe(*os_, 'l');
432 return true;
433 }
434 if(internal::Double(d).IsNan())
435 {
436 PutReserve(*os_, 3);
437 PutUnsafe(*os_, 'N');
438 PutUnsafe(*os_, 'a');
439 PutUnsafe(*os_, 'N');
440 return true;
441 }
442 if(internal::Double(d).Sign())
443 {
444 PutReserve(*os_, 9);
445 PutUnsafe(*os_, '-');
446 }
447 else
448 PutReserve(*os_, 8);
449 PutUnsafe(*os_, 'I');
450 PutUnsafe(*os_, 'n');
451 PutUnsafe(*os_, 'f');
452 PutUnsafe(*os_, 'i');
453 PutUnsafe(*os_, 'n');
454 PutUnsafe(*os_, 'i');
455 PutUnsafe(*os_, 't');
456 PutUnsafe(*os_, 'y');
457 return true;
458 }
459
460 char buffer[25];
461 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
462 PutReserve(*os_, static_cast<size_t>(end - buffer));
463 for(char* p = buffer; p != end; ++p)
464 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
465 return true;
466 }
467
468 bool WriteString(const Ch* str, SizeType length)
469 {
470 static const typename OutputStream::Ch hexDigits[16] = {
471 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
472 static const char escape[256] = {
473#define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
474 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
475 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
476 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
477 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
478 Z16, Z16, // 30~4F
479 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50
480 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
481#undef Z16
482 };
483
484 if(TargetEncoding::supportUnicode)
485 PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
486 else
487 PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
488
489 PutUnsafe(*os_, '\"');
491 while(ScanWriteUnescapedString(is, length))
492 {
493 const Ch c = is.Peek();
494 if(!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80)
495 {
496 // Unicode escaping
497 unsigned codepoint;
498 if(RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
499 return false;
500 PutUnsafe(*os_, '\\');
501 PutUnsafe(*os_, 'u');
502 if(codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF))
503 {
504 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
505 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
506 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
507 PutUnsafe(*os_, hexDigits[(codepoint) & 15]);
508 }
509 else
510 {
511 RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
512 // Surrogate pair
513 unsigned s = codepoint - 0x010000;
514 unsigned lead = (s >> 10) + 0xD800;
515 unsigned trail = (s & 0x3FF) + 0xDC00;
516 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
517 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
518 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
519 PutUnsafe(*os_, hexDigits[(lead) & 15]);
520 PutUnsafe(*os_, '\\');
521 PutUnsafe(*os_, 'u');
522 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
523 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
524 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
525 PutUnsafe(*os_, hexDigits[(trail) & 15]);
526 }
527 }
528 else if((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
529 RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))
530 {
531 is.Take();
532 PutUnsafe(*os_, '\\');
533 PutUnsafe(
534 *os_,
535 static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
536 if(escape[static_cast<unsigned char>(c)] == 'u')
537 {
538 PutUnsafe(*os_, '0');
539 PutUnsafe(*os_, '0');
540 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
541 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
542 }
543 }
544 else if(RAPIDJSON_UNLIKELY(
545 !(writeFlags & kWriteValidateEncodingFlag
548 *os_))))
549 return false;
550 }
551 PutUnsafe(*os_, '\"');
552 return true;
553 }
554
556 {
557 return RAPIDJSON_LIKELY(is.Tell() < length);
558 }
559
561 {
562 os_->Put('{');
563 return true;
564 }
566 {
567 os_->Put('}');
568 return true;
569 }
571 {
572 os_->Put('[');
573 return true;
574 }
576 {
577 os_->Put(']');
578 return true;
579 }
580
581 bool WriteRawValue(const Ch* json, size_t length)
582 {
583 PutReserve(*os_, length);
585 while(RAPIDJSON_LIKELY(is.Tell() < length))
586 {
587 RAPIDJSON_ASSERT(is.Peek() != '\0');
589 !(writeFlags & kWriteValidateEncodingFlag
592 return false;
593 }
594 return true;
595 }
596
597 void Prefix(Type type)
598 {
599 (void)type;
600 if(RAPIDJSON_LIKELY(level_stack_.GetSize() != 0))
601 { // this value is not at root
602 Level* level = level_stack_.template Top<Level>();
603 if(level->valueCount > 0)
604 {
605 if(level->inArray)
606 os_->Put(','); // add comma if it is not the first element in array
607 else // in object
608 os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
609 }
610 if(!level->inArray && level->valueCount % 2 == 0)
612 type == kStringType); // if it's in object, then even number should be a name
613 level->valueCount++;
614 }
615 else
616 {
617 RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
618 hasRoot_ = true;
619 }
620 }
621
622 // Flush the value if it is the top level one.
623 bool EndValue(bool ret)
624 {
625 if(RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
626 Flush();
627 return ret;
628 }
629
630 OutputStream* os_;
634
635 private:
636 // Prohibit copy constructor & assignment operator.
637 Writer(const Writer&);
638 Writer& operator=(const Writer&);
639};
640
641// Full specialization for StringStream to prevent memory copying
642
643template <>
645{
646 char* buffer = os_->Push(11);
647 const char* end = internal::i32toa(i, buffer);
648 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
649 return true;
650}
651
652template <>
653inline bool Writer<StringBuffer>::WriteUint(unsigned u)
654{
655 char* buffer = os_->Push(10);
656 const char* end = internal::u32toa(u, buffer);
657 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
658 return true;
659}
660
661template <>
663{
664 char* buffer = os_->Push(21);
665 const char* end = internal::i64toa(i64, buffer);
666 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
667 return true;
668}
669
670template <>
672{
673 char* buffer = os_->Push(20);
674 const char* end = internal::u64toa(u, buffer);
675 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
676 return true;
677}
678
679template <>
681{
682 if(internal::Double(d).IsNanOrInf())
683 {
684 // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS &
685 // kWriteNanAndInfFlag).
687 return false;
689 {
690 PutReserve(*os_, 4);
691 PutUnsafe(*os_, 'n');
692 PutUnsafe(*os_, 'u');
693 PutUnsafe(*os_, 'l');
694 PutUnsafe(*os_, 'l');
695 return true;
696 }
697 if(internal::Double(d).IsNan())
698 {
699 PutReserve(*os_, 3);
700 PutUnsafe(*os_, 'N');
701 PutUnsafe(*os_, 'a');
702 PutUnsafe(*os_, 'N');
703 return true;
704 }
705 if(internal::Double(d).Sign())
706 {
707 PutReserve(*os_, 9);
708 PutUnsafe(*os_, '-');
709 }
710 else
711 PutReserve(*os_, 8);
712 PutUnsafe(*os_, 'I');
713 PutUnsafe(*os_, 'n');
714 PutUnsafe(*os_, 'f');
715 PutUnsafe(*os_, 'i');
716 PutUnsafe(*os_, 'n');
717 PutUnsafe(*os_, 'i');
718 PutUnsafe(*os_, 't');
719 PutUnsafe(*os_, 'y');
720 return true;
721 }
722
723 char* buffer = os_->Push(25);
724 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
725 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
726 return true;
727}
728
729#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
730template <>
732{
733 if(length < 16)
734 return RAPIDJSON_LIKELY(is.Tell() < length);
735
736 if(!RAPIDJSON_LIKELY(is.Tell() < length))
737 return false;
738
739 const char* p = is.src_;
740 const char* end = is.head_ + length;
741 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) &
742 static_cast<size_t>(~15));
743 const char* endAligned =
744 reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
745 if(nextAligned > end)
746 return true;
747
748 while(p != nextAligned)
749 if(*p < 0x20 || *p == '\"' || *p == '\\')
750 {
751 is.src_ = p;
752 return RAPIDJSON_LIKELY(is.Tell() < length);
753 }
754 else
755 os_->PutUnsafe(*p++);
756
757 // The rest of string using SIMD
758 static const char dquote[16] = {'\"',
759 '\"',
760 '\"',
761 '\"',
762 '\"',
763 '\"',
764 '\"',
765 '\"',
766 '\"',
767 '\"',
768 '\"',
769 '\"',
770 '\"',
771 '\"',
772 '\"',
773 '\"'};
774 static const char bslash[16] = {'\\',
775 '\\',
776 '\\',
777 '\\',
778 '\\',
779 '\\',
780 '\\',
781 '\\',
782 '\\',
783 '\\',
784 '\\',
785 '\\',
786 '\\',
787 '\\',
788 '\\',
789 '\\'};
790 static const char space[16] = {0x1F,
791 0x1F,
792 0x1F,
793 0x1F,
794 0x1F,
795 0x1F,
796 0x1F,
797 0x1F,
798 0x1F,
799 0x1F,
800 0x1F,
801 0x1F,
802 0x1F,
803 0x1F,
804 0x1F,
805 0x1F};
806 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
807 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
808 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
809
810 for(; p != endAligned; p += 16)
811 {
812 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
813 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
814 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
815 const __m128i t3 =
816 _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
817 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
818 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
819 if(RAPIDJSON_UNLIKELY(r != 0))
820 { // some of characters is escaped
821 SizeType len;
822#ifdef _MSC_VER // Find the index of first escaped
823 unsigned long offset;
824 _BitScanForward(&offset, r);
825 len = offset;
826#else
827 len = static_cast<SizeType>(__builtin_ffs(r) - 1);
828#endif
829 char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
830 for(size_t i = 0; i < len; i++)
831 q[i] = p[i];
832
833 p += len;
834 break;
835 }
836 _mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s);
837 }
838
839 is.src_ = p;
840 return RAPIDJSON_LIKELY(is.Tell() < length);
841}
842#elif defined(RAPIDJSON_NEON)
843template <>
845{
846 if(length < 16)
847 return RAPIDJSON_LIKELY(is.Tell() < length);
848
849 if(!RAPIDJSON_LIKELY(is.Tell() < length))
850 return false;
851
852 const char* p = is.src_;
853 const char* end = is.head_ + length;
854 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) &
855 static_cast<size_t>(~15));
856 const char* endAligned =
857 reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
858 if(nextAligned > end)
859 return true;
860
861 while(p != nextAligned)
862 if(*p < 0x20 || *p == '\"' || *p == '\\')
863 {
864 is.src_ = p;
865 return RAPIDJSON_LIKELY(is.Tell() < length);
866 }
867 else
868 os_->PutUnsafe(*p++);
869
870 // The rest of string using SIMD
871 const uint8x16_t s0 = vmovq_n_u8('"');
872 const uint8x16_t s1 = vmovq_n_u8('\\');
873 const uint8x16_t s2 = vmovq_n_u8('\b');
874 const uint8x16_t s3 = vmovq_n_u8(32);
875
876 for(; p != endAligned; p += 16)
877 {
878 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
879 uint8x16_t x = vceqq_u8(s, s0);
880 x = vorrq_u8(x, vceqq_u8(s, s1));
881 x = vorrq_u8(x, vceqq_u8(s, s2));
882 x = vorrq_u8(x, vcltq_u8(s, s3));
883
884 x = vrev64q_u8(x); // Rev in 64
885 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
886 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
887
888 SizeType len = 0;
889 bool escaped = false;
890 if(low == 0)
891 {
892 if(high != 0)
893 {
894 uint32_t lz = internal::clzll(high);
895 len = 8 + (lz >> 3);
896 escaped = true;
897 }
898 }
899 else
900 {
901 uint32_t lz = internal::clzll(low);
902 len = lz >> 3;
903 escaped = true;
904 }
905 if(RAPIDJSON_UNLIKELY(escaped))
906 { // some of characters is escaped
907 char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
908 for(size_t i = 0; i < len; i++)
909 q[i] = p[i];
910
911 p += len;
912 break;
913 }
914 vst1q_u8(reinterpret_cast<uint8_t*>(os_->PushUnsafe(16)), s);
915 }
916
917 is.src_ = p;
918 return RAPIDJSON_LIKELY(is.Tell() < length);
919}
920#endif // RAPIDJSON_NEON
921
923
924#if defined(_MSC_VER) || defined(__clang__)
925RAPIDJSON_DIAG_POP
926#endif
927
928#endif // RAPIDJSON_RAPIDJSON_H_
C-runtime library allocator.
Definition allocators.h:83
JSON writer.
Definition writer.h:99
bool EndObject(SizeType memberCount=0)
Writes the given double value to the stream.
Definition writer.h:278
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition writer.h:168
bool Key(const Ch *str, SizeType length, bool copy=false)
Writes the given double value to the stream.
Definition writer.h:269
void Prefix(Type type)
Simpler but slower overload.
Definition writer.h:597
bool Double(double d)
Writes the given double value to the stream.
Definition writer.h:233
bool WriteUint(unsigned u)
Simpler but slower overload.
Definition writer.h:389
bool String(const Ch *const &str)
Simpler but slower overload.
Definition writer.h:311
bool WriteInt(int i)
Simpler but slower overload.
Definition writer.h:379
bool StartArray()
Writes the given double value to the stream.
Definition writer.h:290
bool WriteStartArray()
Simpler but slower overload.
Definition writer.h:570
bool Int64(int64_t i64)
Writes the given double value to the stream.
Definition writer.h:217
bool WriteBool(bool b)
Simpler but slower overload.
Definition writer.h:357
bool WriteNull()
Simpler but slower overload.
Definition writer.h:347
bool Uint64(uint64_t u64)
Writes the given double value to the stream.
Definition writer.h:222
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition writer.h:190
bool Uint(unsigned u)
Writes the given double value to the stream.
Definition writer.h:212
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Definition writer.h:120
bool WriteEndObject()
Simpler but slower overload.
Definition writer.h:565
bool WriteStartObject()
Simpler but slower overload.
Definition writer.h:560
bool String(const Ch *str, SizeType length, bool copy=false)
Writes the given double value to the stream.
Definition writer.h:247
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition writer.h:157
void Flush()
Flush the output stream.
Definition writer.h:334
bool WriteRawValue(const Ch *json, size_t length)
Simpler but slower overload.
Definition writer.h:581
bool ScanWriteUnescapedString(GenericStringStream< SourceEncoding > &is, size_t length)
Simpler but slower overload.
Definition writer.h:555
internal::Stack< StackAllocator > level_stack_
Definition writer.h:631
bool WriteInt64(int64_t i64)
Simpler but slower overload.
Definition writer.h:399
bool WriteEndArray()
Simpler but slower overload.
Definition writer.h:575
bool Key(const Ch *const &str)
Simpler but slower overload.
Definition writer.h:312
bool EndArray(SizeType elementCount=0)
Writes the given double value to the stream.
Definition writer.h:297
bool WriteString(const Ch *str, SizeType length)
Simpler but slower overload.
Definition writer.h:468
bool WriteUint64(uint64_t u64)
Simpler but slower overload.
Definition writer.h:409
int GetMaxDecimalPlaces() const
Definition writer.h:170
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
Writes the given double value to the stream.
Definition writer.h:239
bool Int(int i)
Writes the given double value to the stream.
Definition writer.h:207
bool Bool(bool b)
Writes the given double value to the stream.
Definition writer.h:202
bool EndValue(bool ret)
Simpler but slower overload.
Definition writer.h:623
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition writer.h:323
bool WriteDouble(double d)
Simpler but slower overload.
Definition writer.h:419
bool StartObject()
Writes the given double value to the stream.
Definition writer.h:262
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition writer.h:110
bool Null()
Writes the given double value to the stream.
Definition writer.h:197
Definition ieee754.h:24
A type-unsafe stack for storing different types of data.
Definition stack.h:38
__device__ void copy(const SrcTensorType &src_tensor, DstTensorType &dst_tensor)
Perform optimized copy between two tensors partitions (threadwise copy). Tensors must have the same s...
Definition copy.hpp:36
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition stream.h:96
GenericStringStream< UTF8< char > > StringStream
Definition fwd.h:58
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition rapidjson.h:518
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition rapidjson.h:531
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:451
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition rapidjson.h:121
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition rapidjson.h:124
@ offset
Definition coordinate_transform.hpp:26
typename vector_type< uint8_t, 16 >::type uint8x16_t
Definition dtype_vector.hpp:2253
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
Definition dtoa.h:296
char * u64toa(uint64_t value, char *buffer)
Definition itoa.h:135
char * i64toa(int64_t value, char *buffer)
Definition itoa.h:312
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition strfunc.h:32
char * u32toa(uint32_t value, char *buffer)
Definition itoa.h:41
char * i32toa(int32_t value, char *buffer)
Definition itoa.h:122
uint32_t clzll(uint64_t x)
Definition clzll.h:32
STL namespace.
Type
Type of JSON value.
Definition rapidjson.h:760
@ kFalseType
false
Definition rapidjson.h:762
@ kObjectType
object
Definition rapidjson.h:764
@ kTrueType
true
Definition rapidjson.h:763
@ kStringType
string
Definition rapidjson.h:766
@ kNullType
null
Definition rapidjson.h:761
@ kArrayType
array
Definition rapidjson.h:765
@ kNumberType
number
Definition rapidjson.h:767
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.).
Definition rapidjson.h:429
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition stream.h:88
Read-only string stream.
Definition stream.h:163
Ch Peek() const
Definition stream.h:168
Ch Take()
Definition stream.h:169
const Ch * head_
Original head of the string.
Definition stream.h:186
size_t Tell() const
Definition stream.h:170
const Ch * src_
Current read position.
Definition stream.h:185
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream &is, OutputStream &os)
Definition encodings.h:837
static RAPIDJSON_FORCEINLINE bool Validate(InputStream &is, OutputStream &os)
Validate one Unicode codepoint from an encoded stream.
Definition encodings.h:848
UTF-8 encoding.
Definition encodings.h:98
Level(bool inArray_)
Definition writer.h:342
size_t valueCount
number of values in this level
Definition writer.h:343
bool inArray
true if in array, otherwise in object
Definition writer.h:344
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
Definition writer.h:62
WriteFlag
Combination of writeFlags.
Definition writer.h:67
@ kWriteNanAndInfFlag
Allow writing of Infinity, -Infinity and NaN.
Definition writer.h:70
@ kWriteValidateEncodingFlag
Validate encoding of JSON strings.
Definition writer.h:69
@ kWriteNanAndInfNullFlag
Allow writing of Infinity, -Infinity and NaN as null.
Definition writer.h:71
@ kWriteDefaultFlags
Definition writer.h:72
@ kWriteNoFlags
No flags are set.
Definition writer.h:68
#define Z16