]>
Commit | Line | Data |
---|---|---|
31f18b77 FG |
1 | // Tencent is pleased to support the open source community by making RapidJSON available. |
2 | // | |
1e59de90 | 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. |
31f18b77 FG |
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_ISTREAMWRAPPER_H_ | |
16 | #define RAPIDJSON_ISTREAMWRAPPER_H_ | |
17 | ||
18 | #include "stream.h" | |
19 | #include <iosfwd> | |
1e59de90 | 20 | #include <ios> |
31f18b77 FG |
21 | |
22 | #ifdef __clang__ | |
23 | RAPIDJSON_DIAG_PUSH | |
24 | RAPIDJSON_DIAG_OFF(padded) | |
1e59de90 | 25 | #elif defined(_MSC_VER) |
31f18b77 FG |
26 | RAPIDJSON_DIAG_PUSH |
27 | RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized | |
28 | #endif | |
29 | ||
30 | RAPIDJSON_NAMESPACE_BEGIN | |
31 | ||
32 | //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. | |
33 | /*! | |
34 | The classes can be wrapped including but not limited to: | |
35 | ||
36 | - \c std::istringstream | |
37 | - \c std::stringstream | |
38 | - \c std::wistringstream | |
39 | - \c std::wstringstream | |
40 | - \c std::ifstream | |
41 | - \c std::fstream | |
42 | - \c std::wifstream | |
43 | - \c std::wfstream | |
44 | ||
45 | \tparam StreamType Class derived from \c std::basic_istream. | |
46 | */ | |
47 | ||
48 | template <typename StreamType> | |
49 | class BasicIStreamWrapper { | |
50 | public: | |
51 | typedef typename StreamType::char_type Ch; | |
31f18b77 | 52 | |
1e59de90 TL |
53 | //! Constructor. |
54 | /*! | |
55 | \param stream stream opened for read. | |
56 | */ | |
57 | BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { | |
58 | Read(); | |
31f18b77 FG |
59 | } |
60 | ||
1e59de90 TL |
61 | //! Constructor. |
62 | /*! | |
63 | \param stream stream opened for read. | |
64 | \param buffer user-supplied buffer. | |
65 | \param bufferSize size of buffer in bytes. Must >=4 bytes. | |
66 | */ | |
67 | BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { | |
68 | RAPIDJSON_ASSERT(bufferSize >= 4); | |
69 | Read(); | |
31f18b77 FG |
70 | } |
71 | ||
1e59de90 TL |
72 | Ch Peek() const { return *current_; } |
73 | Ch Take() { Ch c = *current_; Read(); return c; } | |
74 | size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } | |
31f18b77 | 75 | |
1e59de90 | 76 | // Not implemented |
31f18b77 | 77 | void Put(Ch) { RAPIDJSON_ASSERT(false); } |
1e59de90 TL |
78 | void Flush() { RAPIDJSON_ASSERT(false); } |
79 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | |
31f18b77 FG |
80 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } |
81 | ||
82 | // For encoding detection only. | |
83 | const Ch* Peek4() const { | |
1e59de90 | 84 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; |
31f18b77 FG |
85 | } |
86 | ||
87 | private: | |
1e59de90 | 88 | BasicIStreamWrapper(); |
31f18b77 FG |
89 | BasicIStreamWrapper(const BasicIStreamWrapper&); |
90 | BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); | |
91 | ||
1e59de90 TL |
92 | void Read() { |
93 | if (current_ < bufferLast_) | |
94 | ++current_; | |
95 | else if (!eof_) { | |
96 | count_ += readCount_; | |
97 | readCount_ = bufferSize_; | |
98 | bufferLast_ = buffer_ + readCount_ - 1; | |
99 | current_ = buffer_; | |
100 | ||
101 | if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) { | |
102 | readCount_ = static_cast<size_t>(stream_.gcount()); | |
103 | *(bufferLast_ = buffer_ + readCount_) = '\0'; | |
104 | eof_ = true; | |
105 | } | |
106 | } | |
107 | } | |
108 | ||
109 | StreamType &stream_; | |
110 | Ch peekBuffer_[4], *buffer_; | |
111 | size_t bufferSize_; | |
112 | Ch *bufferLast_; | |
113 | Ch *current_; | |
114 | size_t readCount_; | |
115 | size_t count_; //!< Number of characters read | |
116 | bool eof_; | |
31f18b77 FG |
117 | }; |
118 | ||
119 | typedef BasicIStreamWrapper<std::istream> IStreamWrapper; | |
120 | typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper; | |
121 | ||
122 | #if defined(__clang__) || defined(_MSC_VER) | |
123 | RAPIDJSON_DIAG_POP | |
124 | #endif | |
125 | ||
126 | RAPIDJSON_NAMESPACE_END | |
127 | ||
128 | #endif // RAPIDJSON_ISTREAMWRAPPER_H_ |