| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
1 |
// Tencent is pleased to support the open source community by making RapidJSON available. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
2 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
3 |
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
4 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
5 |
// Licensed under the MIT License (the "License"); you may not use this file except |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
6 |
// in compliance with the License. You may obtain a copy of the License at |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
7 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
8 |
// http://opensource.org/licenses/MIT |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
9 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
10 |
// Unless required by applicable law or agreed to in writing, software distributed |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
11 |
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
12 |
// CONDITIONS OF ANY KIND, either express or implied. See the License for the |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
13 |
// specific language governing permissions and limitations under the License. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
14 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
15 |
#ifndef CEREAL_RAPIDJSON_WRITER_H_ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
16 |
#define CEREAL_RAPIDJSON_WRITER_H_ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
17 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
18 |
#include "stream.h" |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
19 |
#include "internal/stack.h" |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
20 |
#include "internal/strfunc.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
21 |
#include "internal/dtoa.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
22 |
#include "internal/itoa.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
23 |
#include "stringbuffer.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
24 |
#include <new> // placement new |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
25 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
26 |
#if defined(CEREAL_RAPIDJSON_SIMD) && defined(_MSC_VER) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
27 |
#include <intrin.h> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
28 |
#pragma intrinsic(_BitScanForward) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
29 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
30 |
#ifdef CEREAL_RAPIDJSON_SSE42 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
31 |
#include <nmmintrin.h> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
32 |
#elif defined(CEREAL_RAPIDJSON_SSE2) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
33 |
#include <emmintrin.h> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
34 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
35 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
36 |
#ifdef _MSC_VER |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
37 |
CEREAL_RAPIDJSON_DIAG_PUSH |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
38 |
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
39 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
40 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
41 |
#ifdef __clang__ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
42 |
CEREAL_RAPIDJSON_DIAG_PUSH |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
43 |
CEREAL_RAPIDJSON_DIAG_OFF(padded) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
44 |
CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
45 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
46 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
47 |
CEREAL_RAPIDJSON_NAMESPACE_BEGIN |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
48 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
49 |
/////////////////////////////////////////////////////////////////////////////// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
50 |
// WriteFlag |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
51 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
52 |
/*! \def CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
53 |
\ingroup CEREAL_RAPIDJSON_CONFIG |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
54 |
\brief User-defined kWriteDefaultFlags definition. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
55 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
56 |
User can define this as any \c WriteFlag combinations. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
57 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
58 |
#ifndef CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
59 |
#define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
60 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
61 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
62 |
//! Combination of writeFlags |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
63 |
enum WriteFlag { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
64 |
kWriteNoFlags = 0, //!< No flags are set. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
65 |
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
66 |
kWriteNanAndInfFlag = 2, //!< Allow writing of Inf, -Inf and NaN. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
67 |
kWriteDefaultFlags = CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
68 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
69 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
70 |
//! JSON writer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
71 |
/*! Writer implements the concept Handler. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
72 |
It generates JSON text by events to an output os. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
73 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
74 |
User may programmatically calls the functions of a writer to generate JSON text. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
75 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
76 |
On the other side, a writer can also be passed to objects that generates events, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
77 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
78 |
for example Reader::Parse() and Document::Accept(). |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
79 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
80 |
\tparam OutputStream Type of output stream. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
81 |
\tparam SourceEncoding Encoding of source string. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
82 |
\tparam TargetEncoding Encoding of output stream. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
83 |
\tparam StackAllocator Type of allocator for allocating memory of stack. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
84 |
\note implements Handler concept |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
85 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
86 |
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
87 |
class Writer { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
88 |
public: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
89 |
typedef typename SourceEncoding::Ch Ch; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
90 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
91 |
static const int kDefaultMaxDecimalPlaces = 324; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
92 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
93 |
//! Constructor |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
94 |
/*! \param os Output stream. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
95 |
\param stackAllocator User supplied allocator. If it is null, it will create a private one. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
96 |
\param levelDepth Initial capacity of stack. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
97 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
98 |
explicit |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
99 |
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
100 |
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
101 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
102 |
explicit |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
103 |
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
104 |
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
105 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
106 |
//! Reset the writer with a new stream. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
107 |
/*! |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
108 |
This function reset the writer with a new stream and default settings, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
109 |
in order to make a Writer object reusable for output multiple JSONs. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
110 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
111 |
\param os New output stream. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
112 |
\code |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
113 |
Writer<OutputStream> writer(os1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
114 |
writer.StartObject(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
115 |
// ... |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
116 |
writer.EndObject(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
117 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
118 |
writer.Reset(os2); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
119 |
writer.StartObject(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
120 |
// ... |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
121 |
writer.EndObject(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
122 |
\endcode |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
123 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
124 |
void Reset(OutputStream& os) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
125 |
os_ = &os; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
126 |
hasRoot_ = false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
127 |
level_stack_.Clear(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
128 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
129 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
130 |
//! Checks whether the output is a complete JSON. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
131 |
/*! |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
132 |
A complete JSON has a complete root object or array. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
133 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
134 |
bool IsComplete() const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
135 |
return hasRoot_ && level_stack_.Empty(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
136 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
137 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
138 |
int GetMaxDecimalPlaces() const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
139 |
return maxDecimalPlaces_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
140 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
141 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
142 |
//! Sets the maximum number of decimal places for double output. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
143 |
/*! |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
144 |
This setting truncates the output with specified number of decimal places. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
145 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
146 |
For example, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
147 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
148 |
\code |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
149 |
writer.SetMaxDecimalPlaces(3); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
150 |
writer.StartArray(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
151 |
writer.Double(0.12345); // "0.123" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
152 |
writer.Double(0.0001); // "0.0" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
153 |
writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
154 |
writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
155 |
writer.EndArray(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
156 |
\endcode |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
157 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
158 |
The default setting does not truncate any decimal places. You can restore to this setting by calling |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
159 |
\code |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
160 |
writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
161 |
\endcode |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
162 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
163 |
void SetMaxDecimalPlaces(int maxDecimalPlaces) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
164 |
maxDecimalPlaces_ = maxDecimalPlaces; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
165 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
166 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
167 |
/*!@name Implementation of Handler |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
168 |
\see Handler |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
169 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
170 |
//@{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
171 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
172 |
bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
173 |
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
174 |
bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
175 |
bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
176 |
bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
177 |
bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
178 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
179 |
//! Writes the given \c double value to the stream |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
180 |
/*! |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
181 |
\param d The value to be written. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
182 |
\return Whether it is succeed. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
183 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
184 |
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
185 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
186 |
bool RawNumber(const Ch* str, SizeType length, bool copy = false) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
187 |
(void)copy; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
188 |
Prefix(kNumberType); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
189 |
return EndValue(WriteString(str, length)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
190 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
191 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
192 |
bool String(const Ch* str, SizeType length, bool copy = false) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
193 |
(void)copy; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
194 |
Prefix(kStringType); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
195 |
return EndValue(WriteString(str, length)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
196 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
197 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
198 |
#if CEREAL_RAPIDJSON_HAS_STDSTRING |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
199 |
bool String(const std::basic_string<Ch>& str) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
200 |
return String(str.data(), SizeType(str.size())); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
201 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
202 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
203 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
204 |
bool StartObject() { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
205 |
Prefix(kObjectType); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
206 |
new (level_stack_.template Push<Level>()) Level(false); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
207 |
return WriteStartObject(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
208 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
209 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
210 |
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
211 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
212 |
bool EndObject(SizeType memberCount = 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
213 |
(void)memberCount; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
214 |
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
215 |
CEREAL_RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
216 |
level_stack_.template Pop<Level>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
217 |
return EndValue(WriteEndObject()); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
218 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
219 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
220 |
bool StartArray() { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
221 |
Prefix(kArrayType); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
222 |
new (level_stack_.template Push<Level>()) Level(true); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
223 |
return WriteStartArray(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
224 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
225 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
226 |
bool EndArray(SizeType elementCount = 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
227 |
(void)elementCount; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
228 |
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
229 |
CEREAL_RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
230 |
level_stack_.template Pop<Level>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
231 |
return EndValue(WriteEndArray()); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
232 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
233 |
//@} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
234 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
235 |
/*! @name Convenience extensions */ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
236 |
//@{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
237 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
238 |
//! Simpler but slower overload. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
239 |
bool String(const Ch* str) { return String(str, internal::StrLen(str)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
240 |
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
241 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
242 |
//@} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
243 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
244 |
//! Write a raw JSON value. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
245 |
/*! |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
246 |
For user to write a stringified JSON as a value. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
247 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
248 |
\param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
249 |
\param length Length of the json. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
250 |
\param type Type of the root of json. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
251 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
252 |
bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
253 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
254 |
protected: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
255 |
//! Information for each nested level |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
256 |
struct Level { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
257 |
Level(bool inArray_) : valueCount(0), inArray(inArray_) {} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
258 |
size_t valueCount; //!< number of values in this level |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
259 |
bool inArray; //!< true if in array, otherwise in object |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
260 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
261 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
262 |
static const size_t kDefaultLevelDepth = 32; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
263 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
264 |
bool WriteNull() { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
265 |
PutReserve(*os_, 4); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
266 |
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
267 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
268 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
269 |
bool WriteBool(bool b) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
270 |
if (b) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
271 |
PutReserve(*os_, 4); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
272 |
PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
273 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
274 |
else { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
275 |
PutReserve(*os_, 5); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
276 |
PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
277 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
278 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
279 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
280 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
281 |
bool WriteInt(int i) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
282 |
char buffer[11]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
283 |
const char* end = internal::i32toa(i, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
284 |
PutReserve(*os_, static_cast<size_t>(end - buffer)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
285 |
for (const char* p = buffer; p != end; ++p) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
286 |
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
287 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
288 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
289 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
290 |
bool WriteUint(unsigned u) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
291 |
char buffer[10]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
292 |
const char* end = internal::u32toa(u, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
293 |
PutReserve(*os_, static_cast<size_t>(end - buffer)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
294 |
for (const char* p = buffer; p != end; ++p) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
295 |
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
296 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
297 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
298 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
299 |
bool WriteInt64(int64_t i64) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
300 |
char buffer[21]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
301 |
const char* end = internal::i64toa(i64, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
302 |
PutReserve(*os_, static_cast<size_t>(end - buffer)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
303 |
for (const char* p = buffer; p != end; ++p) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
304 |
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
305 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
306 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
307 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
308 |
bool WriteUint64(uint64_t u64) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
309 |
char buffer[20]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
310 |
char* end = internal::u64toa(u64, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
311 |
PutReserve(*os_, static_cast<size_t>(end - buffer)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
312 |
for (char* p = buffer; p != end; ++p) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
313 |
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
314 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
315 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
316 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
317 |
bool WriteDouble(double d) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
318 |
if (internal::Double(d).IsNanOrInf()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
319 |
if (!(writeFlags & kWriteNanAndInfFlag)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
320 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
321 |
if (internal::Double(d).IsNan()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
322 |
PutReserve(*os_, 3); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
323 |
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
324 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
325 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
326 |
if (internal::Double(d).Sign()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
327 |
PutReserve(*os_, 9); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
328 |
PutUnsafe(*os_, '-'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
329 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
330 |
else |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
331 |
PutReserve(*os_, 8); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
332 |
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
333 |
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
334 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
335 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
336 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
337 |
char buffer[25]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
338 |
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
339 |
PutReserve(*os_, static_cast<size_t>(end - buffer)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
340 |
for (char* p = buffer; p != end; ++p) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
341 |
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
342 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
343 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
344 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
345 |
bool WriteString(const Ch* str, SizeType length) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
346 |
static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
347 |
static const char escape[256] = { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
348 |
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
349 |
//0 1 2 3 4 5 6 7 8 9 A B C D E F |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
350 |
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
351 |
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
352 |
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
353 |
Z16, Z16, // 30~4F |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
354 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
355 |
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
356 |
#undef Z16 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
357 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
358 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
359 |
if (TargetEncoding::supportUnicode) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
360 |
PutReserve(*os_, 2 + length * 6); // "\uxxxx..." |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
361 |
else |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
362 |
PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
363 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
364 |
PutUnsafe(*os_, '\"'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
365 |
GenericStringStream<SourceEncoding> is(str); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
366 |
while (ScanWriteUnescapedString(is, length)) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
367 |
const Ch c = is.Peek(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
368 |
if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
369 |
// Unicode escaping |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
370 |
unsigned codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
371 |
if (CEREAL_RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
372 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
373 |
PutUnsafe(*os_, '\\'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
374 |
PutUnsafe(*os_, 'u'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
375 |
if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
376 |
PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
377 |
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
378 |
PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
379 |
PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
380 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
381 |
else { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
382 |
CEREAL_RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
383 |
// Surrogate pair |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
384 |
unsigned s = codepoint - 0x010000; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
385 |
unsigned lead = (s >> 10) + 0xD800; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
386 |
unsigned trail = (s & 0x3FF) + 0xDC00; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
387 |
PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
388 |
PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
389 |
PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
390 |
PutUnsafe(*os_, hexDigits[(lead ) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
391 |
PutUnsafe(*os_, '\\'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
392 |
PutUnsafe(*os_, 'u'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
393 |
PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
394 |
PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
395 |
PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
396 |
PutUnsafe(*os_, hexDigits[(trail ) & 15]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
397 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
398 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
399 |
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && CEREAL_RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
400 |
is.Take(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
401 |
PutUnsafe(*os_, '\\'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
402 |
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)])); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
403 |
if (escape[static_cast<unsigned char>(c)] == 'u') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
404 |
PutUnsafe(*os_, '0'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
405 |
PutUnsafe(*os_, '0'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
406 |
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
407 |
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
408 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
409 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
410 |
else if (CEREAL_RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
411 |
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
412 |
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
413 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
414 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
415 |
PutUnsafe(*os_, '\"'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
416 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
417 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
418 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
419 |
bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
420 |
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
421 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
422 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
423 |
bool WriteStartObject() { os_->Put('{'); return true; } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
424 |
bool WriteEndObject() { os_->Put('}'); return true; } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
425 |
bool WriteStartArray() { os_->Put('['); return true; } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
426 |
bool WriteEndArray() { os_->Put(']'); return true; } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
427 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
428 |
bool WriteRawValue(const Ch* json, size_t length) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
429 |
PutReserve(*os_, length); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
430 |
for (size_t i = 0; i < length; i++) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
431 |
CEREAL_RAPIDJSON_ASSERT(json[i] != '\0'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
432 |
PutUnsafe(*os_, json[i]); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
433 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
434 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
435 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
436 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
437 |
void Prefix(Type type) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
438 |
(void)type; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
439 |
if (CEREAL_RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
440 |
Level* level = level_stack_.template Top<Level>(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
441 |
if (level->valueCount > 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
442 |
if (level->inArray) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
443 |
os_->Put(','); // add comma if it is not the first element in array |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
444 |
else // in object |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
445 |
os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
446 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
447 |
if (!level->inArray && level->valueCount % 2 == 0) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
448 |
CEREAL_RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
449 |
level->valueCount++; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
450 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
451 |
else { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
452 |
CEREAL_RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
453 |
hasRoot_ = true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
454 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
455 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
456 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
457 |
// Flush the value if it is the top level one. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
458 |
bool EndValue(bool ret) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
459 |
if (CEREAL_RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
460 |
os_->Flush(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
461 |
return ret; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
462 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
463 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
464 |
OutputStream* os_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
465 |
internal::Stack<StackAllocator> level_stack_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
466 |
int maxDecimalPlaces_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
467 |
bool hasRoot_; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
468 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
469 |
private: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
470 |
// Prohibit copy constructor & assignment operator. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
471 |
Writer(const Writer&); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
472 |
Writer& operator=(const Writer&); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
473 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
474 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
475 |
// Full specialization for StringStream to prevent memory copying |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
476 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
477 |
template<> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
478 |
inline bool Writer<StringBuffer>::WriteInt(int i) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
479 |
char *buffer = os_->Push(11); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
480 |
const char* end = internal::i32toa(i, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
481 |
os_->Pop(static_cast<size_t>(11 - (end - buffer))); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
482 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
483 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
484 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
485 |
template<> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
486 |
inline bool Writer<StringBuffer>::WriteUint(unsigned u) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
487 |
char *buffer = os_->Push(10); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
488 |
const char* end = internal::u32toa(u, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
489 |
os_->Pop(static_cast<size_t>(10 - (end - buffer))); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
490 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
491 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
492 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
493 |
template<> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
494 |
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
495 |
char *buffer = os_->Push(21); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
496 |
const char* end = internal::i64toa(i64, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
497 |
os_->Pop(static_cast<size_t>(21 - (end - buffer))); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
498 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
499 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
500 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
501 |
template<> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
502 |
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
503 |
char *buffer = os_->Push(20); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
504 |
const char* end = internal::u64toa(u, buffer); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
505 |
os_->Pop(static_cast<size_t>(20 - (end - buffer))); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
506 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
507 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
508 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
509 |
template<> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
510 |
inline bool Writer<StringBuffer>::WriteDouble(double d) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
511 |
if (internal::Double(d).IsNanOrInf()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
512 |
// Note: This code path can only be reached if (CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
513 |
if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
514 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
515 |
if (internal::Double(d).IsNan()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
516 |
PutReserve(*os_, 3); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
517 |
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
518 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
519 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
520 |
if (internal::Double(d).Sign()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
521 |
PutReserve(*os_, 9); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
522 |
PutUnsafe(*os_, '-'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
523 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
524 |
else |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
525 |
PutReserve(*os_, 8); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
526 |
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
527 |
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
528 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
529 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
530 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
531 |
char *buffer = os_->Push(25); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
532 |
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
533 |
os_->Pop(static_cast<size_t>(25 - (end - buffer))); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
534 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
535 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
536 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
537 |
#if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
538 |
template<> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
539 |
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
540 |
if (length < 16) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
541 |
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
542 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
543 |
if (!CEREAL_RAPIDJSON_LIKELY(is.Tell() < length)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
544 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
545 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
546 |
const char* p = is.src_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
547 |
const char* end = is.head_ + length; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
548 |
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
549 |
const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
550 |
if (nextAligned > end) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
551 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
552 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
553 |
while (p != nextAligned) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
554 |
if (*p < 0x20 || *p == '\"' || *p == '\\') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
555 |
is.src_ = p; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
556 |
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
557 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
558 |
else |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
559 |
os_->PutUnsafe(*p++); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
560 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
561 |
// The rest of string using SIMD |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
562 |
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
563 |
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
564 |
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
565 |
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
566 |
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
567 |
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
568 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
569 |
for (; p != endAligned; p += 16) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
570 |
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
571 |
const __m128i t1 = _mm_cmpeq_epi8(s, dq); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
572 |
const __m128i t2 = _mm_cmpeq_epi8(s, bs); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
573 |
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
574 |
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
575 |
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
576 |
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
577 |
SizeType len; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
578 |
#ifdef _MSC_VER // Find the index of first escaped |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
579 |
unsigned long offset; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
580 |
_BitScanForward(&offset, r); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
581 |
len = offset; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
582 |
#else |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
583 |
len = static_cast<SizeType>(__builtin_ffs(r) - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
584 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
585 |
char* q = reinterpret_cast<char*>(os_->PushUnsafe(len)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
586 |
for (size_t i = 0; i < len; i++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
587 |
q[i] = p[i]; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
588 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
589 |
p += len; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
590 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
591 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
592 |
_mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
593 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
594 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
595 |
is.src_ = p; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
596 |
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
597 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
598 |
#endif // defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
599 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
600 |
CEREAL_RAPIDJSON_NAMESPACE_END |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
601 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
602 |
#ifdef _MSC_VER |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
603 |
CEREAL_RAPIDJSON_DIAG_POP |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
604 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
605 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
606 |
#ifdef __clang__ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
607 |
CEREAL_RAPIDJSON_DIAG_POP |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
608 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
609 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
610 |
#endif // CEREAL_RAPIDJSON_CEREAL_RAPIDJSON_H_ |
|
|
1970-01-01 00:00 |
611 |
|