|
17 | 17 |
|
18 | 18 | #include "stream.h"
|
19 | 19 | #include <iosfwd>
|
20 |
| -#include <cstring> |
21 | 20 |
|
22 | 21 | #ifdef __clang__
|
23 | 22 | RAPIDJSON_DIAG_PUSH
|
@@ -50,76 +49,70 @@ class BasicIStreamWrapper {
|
50 | 49 | public:
|
51 | 50 | typedef typename StreamType::char_type Ch;
|
52 | 51 |
|
53 |
| - BasicIStreamWrapper(StreamType& stream) : stream_(stream), buffer_(peekBuffer_), size_(sizeof(peekBuffer_) / sizeof(Ch)), pos_(), len_(), count_() {} |
54 |
| - |
55 |
| - BasicIStreamWrapper(StreamType& stream, Ch *buffer, size_t size) : stream_(stream), buffer_(buffer), size_(size), pos_(), len_(), count_() { |
56 |
| - RAPIDJSON_ASSERT(buffer_ != 0 && static_cast<std::streamsize>(size_) > 0); |
57 |
| - if (RAPIDJSON_UNLIKELY(size_ < sizeof(peekBuffer_) / sizeof(Ch))) { |
58 |
| - size_ = sizeof(peekBuffer_) / sizeof(Ch); |
59 |
| - buffer_ = peekBuffer_; |
60 |
| - } |
61 |
| - } |
62 |
| - |
63 |
| - Ch Peek() const { |
64 |
| - if (RAPIDJSON_UNLIKELY(pos_ == len_) && !Read()) |
65 |
| - return static_cast<Ch>('\0'); |
66 |
| - return buffer_[pos_]; |
| 52 | + //! Constructor. |
| 53 | + /*! |
| 54 | + \param stream stream opened for read. |
| 55 | + */ |
| 56 | + BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { |
| 57 | + Read(); |
67 | 58 | }
|
68 | 59 |
|
69 |
| - Ch Take() { |
70 |
| - if (RAPIDJSON_UNLIKELY(pos_ == len_) && !Read()) |
71 |
| - return static_cast<Ch>('\0'); |
72 |
| - return buffer_[pos_++]; |
| 60 | + //! Constructor. |
| 61 | + /*! |
| 62 | + \param stream stream opened for read. |
| 63 | + \param buffer user-supplied buffer. |
| 64 | + \param bufferSize size of buffer in bytes. Must >=4 bytes. |
| 65 | + */ |
| 66 | + BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { |
| 67 | + RAPIDJSON_ASSERT(bufferSize >= 4); |
| 68 | + Read(); |
73 | 69 | }
|
74 | 70 |
|
75 |
| - // tellg() may return -1 when failed. So we count by ourself. |
76 |
| - size_t Tell() const { return count_ + pos_; } |
| 71 | + Ch Peek() const { return *current_; } |
| 72 | + Ch Take() { Ch c = *current_; Read(); return c; } |
| 73 | + size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } |
77 | 74 |
|
78 | 75 | // Not implemented
|
79 |
| - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } |
80 | 76 | void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
81 |
| - void Flush() { RAPIDJSON_ASSERT(false); } |
| 77 | + void Flush() { RAPIDJSON_ASSERT(false); } |
| 78 | + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } |
82 | 79 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
83 | 80 |
|
84 | 81 | // For encoding detection only.
|
85 | 82 | const Ch* Peek4() const {
|
86 |
| - RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. |
87 |
| - if (len_ - pos_ < 4) { |
88 |
| - if (pos_) { |
89 |
| - len_ -= pos_; |
90 |
| - std::memmove(buffer_, buffer_ + pos_, len_); |
91 |
| - count_ += pos_; |
92 |
| - pos_ = 0; |
93 |
| - } |
94 |
| - if (!stream_.read(buffer_ + len_, static_cast<std::streamsize>(size_ - len_))) { |
95 |
| - len_ += static_cast<size_t>(stream_.gcount()); |
96 |
| - if (len_ < 4) |
97 |
| - return 0; |
98 |
| - } |
99 |
| - else |
100 |
| - len_ = size_; |
101 |
| - } |
102 |
| - return &buffer_[pos_]; |
| 83 | + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; |
103 | 84 | }
|
104 | 85 |
|
105 | 86 | private:
|
| 87 | + BasicIStreamWrapper(); |
106 | 88 | BasicIStreamWrapper(const BasicIStreamWrapper&);
|
107 | 89 | BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
|
108 | 90 |
|
109 |
| - size_t Read() const { |
110 |
| - count_ += pos_; |
111 |
| - pos_ = 0; |
112 |
| - if (!stream_.read(buffer_, static_cast<std::streamsize>(size_))) |
113 |
| - len_ = static_cast<size_t>(stream_.gcount()); |
114 |
| - else |
115 |
| - len_ = size_; |
116 |
| - return len_; |
| 91 | + void Read() { |
| 92 | + if (current_ < bufferLast_) |
| 93 | + ++current_; |
| 94 | + else if (!eof_) { |
| 95 | + count_ += readCount_; |
| 96 | + readCount_ = bufferSize_; |
| 97 | + bufferLast_ = buffer_ + readCount_ - 1; |
| 98 | + current_ = buffer_; |
| 99 | + |
| 100 | + if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) { |
| 101 | + readCount_ = static_cast<size_t>(stream_.gcount()); |
| 102 | + *(bufferLast_ = buffer_ + readCount_) = '\0'; |
| 103 | + eof_ = true; |
| 104 | + } |
| 105 | + } |
117 | 106 | }
|
118 | 107 |
|
119 |
| - StreamType& stream_; |
| 108 | + StreamType &stream_; |
120 | 109 | Ch peekBuffer_[4], *buffer_;
|
121 |
| - size_t size_; |
122 |
| - mutable size_t pos_, len_, count_; |
| 110 | + size_t bufferSize_; |
| 111 | + Ch *bufferLast_; |
| 112 | + Ch *current_; |
| 113 | + size_t readCount_; |
| 114 | + size_t count_; //!< Number of characters read |
| 115 | + bool eof_; |
123 | 116 | };
|
124 | 117 |
|
125 | 118 | typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
|
|
0 commit comments