1 | // Tencent is pleased to support the open source community by making RapidJSON available. |
2 | // |
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
4 | // |
5 | // Licensed under the MIT License (the "License"); you may not use this file except |
6 | // in compliance with the License. You may obtain a copy of the License at |
7 | // |
8 | // http://opensource.org/licenses/MIT |
9 | // |
10 | // Unless required by applicable law or agreed to in writing, software distributed |
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the |
13 | // specific language governing permissions and limitations under the License. |
14 | |
15 | #include "rapidjson.h" |
16 | |
17 | #ifndef RAPIDJSON_STREAM_H_ |
18 | #define RAPIDJSON_STREAM_H_ |
19 | |
20 | #include "encodings.h" |
21 | |
22 | RAPIDJSON_NAMESPACE_BEGIN |
23 | |
24 | /////////////////////////////////////////////////////////////////////////////// |
25 | // Stream |
26 | |
27 | /*! \class rapidjson::Stream |
28 | \brief Concept for reading and writing characters. |
29 | |
30 | For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). |
31 | |
32 | For write-only stream, only need to implement Put() and Flush(). |
33 | |
34 | \code |
35 | concept Stream { |
36 | typename Ch; //!< Character type of the stream. |
37 | |
38 | //! Read the current character from stream without moving the read cursor. |
39 | Ch Peek() const; |
40 | |
41 | //! Read the current character from stream and moving the read cursor to next character. |
42 | Ch Take(); |
43 | |
44 | //! Get the current read cursor. |
45 | //! \return Number of characters read from start. |
46 | size_t Tell(); |
47 | |
48 | //! Begin writing operation at the current read pointer. |
49 | //! \return The begin writer pointer. |
50 | Ch* PutBegin(); |
51 | |
52 | //! Write a character. |
53 | void Put(Ch c); |
54 | |
55 | //! Flush the buffer. |
56 | void Flush(); |
57 | |
58 | //! End the writing operation. |
59 | //! \param begin The begin write pointer returned by PutBegin(). |
60 | //! \return Number of characters written. |
61 | size_t PutEnd(Ch* begin); |
62 | } |
63 | \endcode |
64 | */ |
65 | |
66 | //! Provides additional information for stream. |
67 | /*! |
68 | By using traits pattern, this type provides a default configuration for stream. |
69 | For custom stream, this type can be specialized for other configuration. |
70 | See TEST(Reader, CustomStringStream) in readertest.cpp for example. |
71 | */ |
72 | template<typename Stream> |
73 | struct StreamTraits { |
74 | //! Whether to make local copy of stream for optimization during parsing. |
75 | /*! |
76 | By default, for safety, streams do not use local copy optimization. |
77 | Stream that can be copied fast should specialize this, like StreamTraits<StringStream>. |
78 | */ |
79 | enum { copyOptimization = 0 }; |
80 | }; |
81 | |
82 | //! Reserve n characters for writing to a stream. |
83 | template<typename Stream> |
84 | inline void PutReserve(Stream& stream, size_t count) { |
85 | (void)stream; |
86 | (void)count; |
87 | } |
88 | |
89 | //! Write character to a stream, presuming buffer is reserved. |
90 | template<typename Stream> |
91 | inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { |
92 | stream.Put(c); |
93 | } |
94 | |
95 | //! Put N copies of a character to a stream. |
96 | template<typename Stream, typename Ch> |
97 | inline void PutN(Stream& stream, Ch c, size_t n) { |
98 | PutReserve(stream, n); |
99 | for (size_t i = 0; i < n; i++) |
100 | PutUnsafe(stream, c); |
101 | } |
102 | |
103 | /////////////////////////////////////////////////////////////////////////////// |
104 | // StringStream |
105 | |
106 | //! Read-only string stream. |
107 | /*! \note implements Stream concept |
108 | */ |
109 | template <typename Encoding> |
110 | struct GenericStringStream { |
111 | typedef typename Encoding::Ch Ch; |
112 | |
113 | GenericStringStream(const Ch *src) : src_(src), head_(src) {} |
114 | |
115 | Ch Peek() const { return *src_; } |
116 | Ch Take() { return *src_++; } |
117 | size_t Tell() const { return static_cast<size_t>(src_ - head_); } |
118 | |
119 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } |
120 | void Put(Ch) { RAPIDJSON_ASSERT(false); } |
121 | void Flush() { RAPIDJSON_ASSERT(false); } |
122 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } |
123 | |
124 | const Ch* src_; //!< Current read position. |
125 | const Ch* head_; //!< Original head of the string. |
126 | }; |
127 | |
128 | template <typename Encoding> |
129 | struct StreamTraits<GenericStringStream<Encoding> > { |
130 | enum { copyOptimization = 1 }; |
131 | }; |
132 | |
133 | //! String stream with UTF8 encoding. |
134 | typedef GenericStringStream<UTF8<> > StringStream; |
135 | |
136 | /////////////////////////////////////////////////////////////////////////////// |
137 | // InsituStringStream |
138 | |
139 | //! A read-write string stream. |
140 | /*! This string stream is particularly designed for in-situ parsing. |
141 | \note implements Stream concept |
142 | */ |
143 | template <typename Encoding> |
144 | struct GenericInsituStringStream { |
145 | typedef typename Encoding::Ch Ch; |
146 | |
147 | GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} |
148 | |
149 | // Read |
150 | Ch Peek() { return *src_; } |
151 | Ch Take() { return *src_++; } |
152 | size_t Tell() { return static_cast<size_t>(src_ - head_); } |
153 | |
154 | // Write |
155 | void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } |
156 | |
157 | Ch* PutBegin() { return dst_ = src_; } |
158 | size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); } |
159 | void Flush() {} |
160 | |
161 | Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } |
162 | void Pop(size_t count) { dst_ -= count; } |
163 | |
164 | Ch* src_; |
165 | Ch* dst_; |
166 | Ch* head_; |
167 | }; |
168 | |
169 | template <typename Encoding> |
170 | struct StreamTraits<GenericInsituStringStream<Encoding> > { |
171 | enum { copyOptimization = 1 }; |
172 | }; |
173 | |
174 | //! Insitu string stream with UTF8 encoding. |
175 | typedef GenericInsituStringStream<UTF8<> > InsituStringStream; |
176 | |
177 | RAPIDJSON_NAMESPACE_END |
178 | |
179 | #endif // RAPIDJSON_STREAM_H_ |
180 | |