1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
#include "stdafx.h"
#include "BufferedReader.h"
//Creates a buffering character-input stream that uses a default-sized input buffer.
//Parameters:
//in - A Reader
BufferedReader::BufferedReader( Reader *in ) : reader( in ), readMark( 0 ), bufferedMark( 0 ), eofReached( false )
{
bufferSize = 64;
buffer = new wchar_t[bufferSize];
memset( buffer,0,sizeof(wchar_t)*bufferSize);
bufferMore();
}
BufferedReader::~BufferedReader()
{
delete[] buffer;
}
void BufferedReader::bufferMore()
{
// Don't buffer more unless we are going to read at least twice as much as what is already left
if( bufferedMark - readMark > (BUFFER_MORE_AMOUNT / 2) )
return;
if( bufferSize < (bufferedMark + BUFFER_MORE_AMOUNT) )
{
// Enlarge the buffer
wchar_t *temp = new wchar_t[bufferSize * 2];
memset( temp,0,sizeof(wchar_t)*bufferSize*2);
std::copy( buffer, buffer+bufferSize, temp );
delete[] buffer;
buffer = temp;
bufferSize = bufferSize * 2;
}
int value = 0;
unsigned int newCharsBuffered = 0;
while( newCharsBuffered < BUFFER_MORE_AMOUNT && (value = reader->read() ) != -1 )
{
buffer[bufferedMark++] = value;
newCharsBuffered++;
}
}
//Closes the stream and releases any system resources associated with it. Once the stream has been closed,
//further read(), ready(), mark(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.
void BufferedReader::close()
{
reader->close();
}
//Reads a single character.
//Returns:
//The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached
int BufferedReader::read()
{
// We should have buffered at least as much as we have read
assert( bufferedMark >= readMark );
if( bufferedMark == readMark )
{
int value = reader->read();
if( value == -1 )
return -1;
buffer[bufferedMark++] = value;
bufferMore();
}
return buffer[readMark++];
}
//Reads characters into a portion of an array.
//This method implements the general contract of the corresponding read method of the Reader class.
//As an additional convenience, it attempts to read as many characters as possible by repeatedly invoking the read method
//of the underlying stream. This iterated read continues until one of the following conditions becomes true:
//
//The specified number of characters have been read,
//The read method of the underlying stream returns -1, indicating end-of-file, or
//The ready method of the underlying stream returns false, indicating that further input requests would block.
//If the first read on the underlying stream returns -1 to indicate end-of-file then this method returns -1.
//Otherwise this method returns the number of characters actually read.
//Subclasses of this class are encouraged, but not required, to attempt to read as many characters as possible in the same fashion.
//
//Ordinarily this method takes characters from this stream's character buffer, filling it from the underlying stream as necessary.
//If, however, the buffer is empty, the mark is not valid, and the requested length is at least as large as the buffer,
//then this method will read characters directly from the underlying stream into the given array.
//Thus redundant BufferedReaders will not copy data unnecessarily.
//
//Parameters:
//cbuf - Destination buffer
//off - Offset at which to start storing characters
//len - Maximum number of characters to read
//Returns:
//The number of characters read, or -1 if the end of the stream has been reached
int BufferedReader::read(wchar_t cbuf[], unsigned int off, unsigned int len)
{
if( bufferSize < (bufferedMark + len) )
{
// Enlarge the buffer
wchar_t *temp = new wchar_t[bufferSize * 2];
memset( temp,0,sizeof(wchar_t)*bufferSize*2);
std::copy( buffer, buffer+bufferSize, temp );
delete[] buffer;
buffer = temp;
bufferSize = bufferSize * 2;
}
unsigned int charsRead = 0;
while( charsRead < len && readMark <= bufferedMark )
{
cbuf[off + charsRead] = buffer[ readMark++ ];
charsRead++;
}
int value = 0;
while( charsRead < len && (value = reader->read() ) != -1 )
{
buffer[bufferedMark++] = value;
cbuf[off+charsRead] = value;
charsRead++;
readMark++;
}
bufferMore();
return charsRead;
}
//Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'),
//or a carriage return followed immediately by a linefeed.
//Returns:
//A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
wstring BufferedReader::readLine()
{
wstring output = L"";
bool newLineCharFound = false;
while( readMark < bufferedMark )
{
wchar_t value = buffer[readMark++];
if( !newLineCharFound )
{
if( ( value == '\n') || ( value == '\r') )
{
newLineCharFound = true;
}
else
{
output.push_back(value);
}
}
else
{
if( ( value != '\n') && ( value != '\r') )
{
readMark--; // Move back the read mark on char so we get this char again next time
break;
}
}
// This will only actually read more from the stream if we have less than half of the amount that
// will be added left to read
bufferMore();
}
return output;
}
|