@@ -48,57 +48,71 @@ template <typename StreamType>
48
48
class BasicIStreamWrapper {
49
49
public:
50
50
typedef typename StreamType::char_type Ch;
51
- BasicIStreamWrapper (StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
52
51
53
- Ch Peek () const {
54
- typename StreamType::int_type c = stream_.peek ();
55
- return RAPIDJSON_LIKELY (c != StreamType::traits_type::eof ()) ? static_cast <Ch>(c) : static_cast <Ch>(' \0 ' );
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 ();
56
58
}
57
59
58
- Ch Take () {
59
- typename StreamType::int_type c = stream_.get ();
60
- if (RAPIDJSON_LIKELY (c != StreamType::traits_type::eof ())) {
61
- count_++;
62
- return static_cast <Ch>(c);
63
- }
64
- else
65
- return ' \0 ' ;
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 ();
66
69
}
67
70
68
- // tellg() may return -1 when failed. So we count by ourself.
69
- size_t Tell () const { return count_; }
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_); }
70
74
71
- Ch* PutBegin () { RAPIDJSON_ASSERT ( false ); return 0 ; }
75
+ // Not implemented
72
76
void Put (Ch) { RAPIDJSON_ASSERT (false ); }
73
- void Flush () { RAPIDJSON_ASSERT (false ); }
77
+ void Flush () { RAPIDJSON_ASSERT (false ); }
78
+ Ch* PutBegin () { RAPIDJSON_ASSERT (false ); return 0 ; }
74
79
size_t PutEnd (Ch*) { RAPIDJSON_ASSERT (false ); return 0 ; }
75
80
76
81
// For encoding detection only.
77
82
const Ch* Peek4 () const {
78
- RAPIDJSON_ASSERT (sizeof (Ch) == 1 ); // Only usable for byte stream.
79
- int i;
80
- bool hasError = false ;
81
- for (i = 0 ; i < 4 ; ++i) {
82
- typename StreamType::int_type c = stream_.get ();
83
- if (c == StreamType::traits_type::eof ()) {
84
- hasError = true ;
85
- stream_.clear ();
86
- break ;
87
- }
88
- peekBuffer_[i] = static_cast <Ch>(c);
89
- }
90
- for (--i; i >= 0 ; --i)
91
- stream_.putback (peekBuffer_[i]);
92
- return !hasError ? peekBuffer_ : 0 ;
83
+ return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0 ;
93
84
}
94
85
95
86
private:
87
+ BasicIStreamWrapper ();
96
88
BasicIStreamWrapper (const BasicIStreamWrapper&);
97
89
BasicIStreamWrapper& operator =(const BasicIStreamWrapper&);
98
90
99
- StreamType& stream_;
100
- size_t count_; // !< Number of characters read. Note:
101
- mutable Ch peekBuffer_[4 ];
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
+ }
106
+ }
107
+
108
+ StreamType &stream_;
109
+ Ch peekBuffer_[4 ], *buffer_;
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_;
102
116
};
103
117
104
118
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
0 commit comments