Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / mscorlib / system / io / textreader.cs
blob2a026f203f42710fc72154492f555a640ab4ea36
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 ** Class: TextReader
9 **
10 ** <OWNER>Microsoft</OWNER>
13 ** Purpose: Abstract base class for all Text-only Readers.
14 ** Subclasses will include StreamReader & StringReader.
17 ===========================================================*/
19 using System;
20 using System.Text;
21 using System.Runtime.InteropServices;
22 using System.Runtime.CompilerServices;
23 using System.Reflection;
24 using System.Security.Permissions;
25 using System.Diagnostics.CodeAnalysis;
26 using System.Diagnostics.Contracts;
27 #if FEATURE_ASYNC_IO
28 using System.Threading;
29 using System.Threading.Tasks;
30 #endif
32 namespace System.IO {
33 // This abstract base class represents a reader that can read a sequential
34 // stream of characters. This is not intended for reading bytes -
35 // there are methods on the Stream class to read bytes.
36 // A subclass must minimally implement the Peek() and Read() methods.
38 // This class is intended for character input, not bytes.
39 // There are methods on the Stream class for reading bytes.
40 [Serializable]
41 [ComVisible(true)]
42 #if FEATURE_REMOTING || MONO
43 public abstract class TextReader : MarshalByRefObject, IDisposable {
44 #else // FEATURE_REMOTING
45 public abstract class TextReader : IDisposable {
46 #endif // FEATURE_REMOTING
48 #if FEATURE_ASYNC_IO
49 [NonSerialized]
50 private static Func<object, string> _ReadLineDelegate = state => ((TextReader)state).ReadLine();
52 [NonSerialized]
53 private static Func<object, int> _ReadDelegate = state =>
55 Tuple<TextReader, char[], int, int> tuple = (Tuple<TextReader, char[], int, int>)state;
56 return tuple.Item1.Read(tuple.Item2, tuple.Item3, tuple.Item4);
58 #endif //FEATURE_ASYNC_IO
60 public static readonly TextReader Null = new NullTextReader();
62 protected TextReader() {}
64 // Closes this TextReader and releases any system resources associated with the
65 // TextReader. Following a call to Close, any operations on the TextReader
66 // may raise exceptions.
67 //
68 // This default method is empty, but descendant classes can override the
69 // method to provide the appropriate functionality.
70 public virtual void Close()
72 Dispose(true);
73 GC.SuppressFinalize(this);
76 public void Dispose()
78 Dispose(true);
79 GC.SuppressFinalize(this);
82 protected virtual void Dispose(bool disposing)
86 // Returns the next available character without actually reading it from
87 // the input stream. The current position of the TextReader is not changed by
88 // this operation. The returned value is -1 if no further characters are
89 // available.
90 //
91 // This default method simply returns -1.
93 [Pure]
94 public virtual int Peek()
96 Contract.Ensures(Contract.Result<int>() >= -1);
98 return -1;
101 // Reads the next character from the input stream. The returned value is
102 // -1 if no further characters are available.
104 // This default method simply returns -1.
106 public virtual int Read()
108 Contract.Ensures(Contract.Result<int>() >= -1);
109 return -1;
112 // Reads a block of characters. This method will read up to
113 // count characters from this TextReader into the
114 // buffer character array starting at position
115 // index. Returns the actual number of characters read.
117 public virtual int Read([In, Out] char[] buffer, int index, int count)
119 if (buffer==null)
120 throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
121 if (index < 0)
122 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
123 if (count < 0)
124 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
125 if (buffer.Length - index < count)
126 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
127 Contract.Ensures(Contract.Result<int>() >= 0);
128 Contract.Ensures(Contract.Result<int>() <= Contract.OldValue(count));
129 Contract.EndContractBlock();
131 int n = 0;
132 do {
133 int ch = Read();
134 if (ch == -1) break;
135 buffer[index + n++] = (char)ch;
136 } while (n < count);
137 return n;
140 // Reads all characters from the current position to the end of the
141 // TextReader, and returns them as one string.
142 public virtual String ReadToEnd()
144 Contract.Ensures(Contract.Result<String>() != null);
146 char[] chars = new char[4096];
147 int len;
148 StringBuilder sb = new StringBuilder(4096);
149 while((len=Read(chars, 0, chars.Length)) != 0)
151 sb.Append(chars, 0, len);
153 return sb.ToString();
156 // Blocking version of read. Returns only when count
157 // characters have been read or the end of the file was reached.
159 public virtual int ReadBlock([In, Out] char[] buffer, int index, int count)
161 Contract.Ensures(Contract.Result<int>() >= 0);
162 Contract.Ensures(Contract.Result<int>() <= count);
164 int i, n = 0;
165 do {
166 n += (i = Read(buffer, index + n, count - n));
167 } while (i > 0 && n < count);
168 return n;
171 // Reads a line. A line is defined as a sequence of characters followed by
172 // a carriage return ('\r'), a line feed ('\n'), or a carriage return
173 // immediately followed by a line feed. The resulting string does not
174 // contain the terminating carriage return and/or line feed. The returned
175 // value is null if the end of the input stream has been reached.
177 public virtual String ReadLine()
179 StringBuilder sb = new StringBuilder();
180 while (true) {
181 int ch = Read();
182 if (ch == -1) break;
183 if (ch == '\r' || ch == '\n')
185 if (ch == '\r' && Peek() == '\n') Read();
186 return sb.ToString();
188 sb.Append((char)ch);
190 if (sb.Length > 0) return sb.ToString();
191 return null;
194 #if FEATURE_ASYNC_IO
195 #region Task based Async APIs
196 [HostProtection(ExternalThreading=true)]
197 [ComVisible(false)]
198 public virtual Task<String> ReadLineAsync()
200 return Task<String>.Factory.StartNew(_ReadLineDelegate, this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
203 [HostProtection(ExternalThreading=true)]
204 [ComVisible(false)]
205 public async virtual Task<String> ReadToEndAsync()
207 char[] chars = new char[4096];
208 int len;
209 StringBuilder sb = new StringBuilder(4096);
210 while((len = await ReadAsyncInternal(chars, 0, chars.Length).ConfigureAwait(false)) != 0)
212 sb.Append(chars, 0, len);
214 return sb.ToString();
217 [HostProtection(ExternalThreading=true)]
218 [ComVisible(false)]
219 public virtual Task<int> ReadAsync(char[] buffer, int index, int count)
221 if (buffer==null)
222 throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
223 if (index < 0 || count < 0)
224 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
225 if (buffer.Length - index < count)
226 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
227 Contract.EndContractBlock();
229 return ReadAsyncInternal(buffer, index, count);
232 internal virtual Task<int> ReadAsyncInternal(char[] buffer, int index, int count)
234 Contract.Requires(buffer != null);
235 Contract.Requires(index >= 0);
236 Contract.Requires(count >= 0);
237 Contract.Requires(buffer.Length - index >= count);
239 Tuple<TextReader, char[], int, int> tuple = new Tuple<TextReader, char[], int, int>(this, buffer, index, count);
240 return Task<int>.Factory.StartNew(_ReadDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
243 [HostProtection(ExternalThreading=true)]
244 [ComVisible(false)]
245 public virtual Task<int> ReadBlockAsync(char[] buffer, int index, int count)
247 if (buffer==null)
248 throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
249 if (index < 0 || count < 0)
250 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
251 if (buffer.Length - index < count)
252 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
254 Contract.EndContractBlock();
256 return ReadBlockAsyncInternal(buffer, index, count);
259 [HostProtection(ExternalThreading=true)]
260 private async Task<int> ReadBlockAsyncInternal(char[] buffer, int index, int count)
262 Contract.Requires(buffer != null);
263 Contract.Requires(index >= 0);
264 Contract.Requires(count >= 0);
265 Contract.Requires(buffer.Length - index >= count);
267 int i, n = 0;
270 i = await ReadAsyncInternal(buffer, index + n, count - n).ConfigureAwait(false);
271 n += i;
272 } while (i > 0 && n < count);
274 return n;
276 #endregion
277 #endif //FEATURE_ASYNC_IO
279 [HostProtection(Synchronization=true)]
280 public static TextReader Synchronized(TextReader reader)
282 if (reader==null)
283 throw new ArgumentNullException("reader");
284 Contract.Ensures(Contract.Result<TextReader>() != null);
285 Contract.EndContractBlock();
287 if (reader is SyncTextReader)
288 return reader;
290 return new SyncTextReader(reader);
293 [Serializable]
294 private sealed class NullTextReader : TextReader
296 public NullTextReader(){}
298 [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
299 public override int Read(char[] buffer, int index, int count)
301 return 0;
304 public override String ReadLine()
306 return null;
310 [Serializable]
311 internal sealed class SyncTextReader : TextReader
313 internal TextReader _in;
315 internal SyncTextReader(TextReader t)
317 _in = t;
320 [MethodImplAttribute(MethodImplOptions.Synchronized)]
321 public override void Close()
323 // So that any overriden Close() gets run
324 _in.Close();
327 [MethodImplAttribute(MethodImplOptions.Synchronized)]
328 protected override void Dispose(bool disposing)
330 // Explicitly pick up a potentially methodimpl'ed Dispose
331 if (disposing)
332 ((IDisposable)_in).Dispose();
335 [MethodImplAttribute(MethodImplOptions.Synchronized)]
336 public override int Peek()
338 return _in.Peek();
341 [MethodImplAttribute(MethodImplOptions.Synchronized)]
342 public override int Read()
344 return _in.Read();
347 [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
348 [MethodImplAttribute(MethodImplOptions.Synchronized)]
349 public override int Read([In, Out] char[] buffer, int index, int count)
351 return _in.Read(buffer, index, count);
354 [MethodImplAttribute(MethodImplOptions.Synchronized)]
355 public override int ReadBlock([In, Out] char[] buffer, int index, int count)
357 return _in.ReadBlock(buffer, index, count);
360 [MethodImplAttribute(MethodImplOptions.Synchronized)]
361 public override String ReadLine()
363 return _in.ReadLine();
366 [MethodImplAttribute(MethodImplOptions.Synchronized)]
367 public override String ReadToEnd()
369 return _in.ReadToEnd();
371 #if FEATURE_ASYNC_IO
374 // On SyncTextReader all APIs should run synchronously, even the async ones.
377 [ComVisible(false)]
378 [MethodImplAttribute(MethodImplOptions.Synchronized)]
379 public override Task<String> ReadLineAsync()
381 return Task.FromResult(ReadLine());
384 [ComVisible(false)]
385 [MethodImplAttribute(MethodImplOptions.Synchronized)]
386 public override Task<String> ReadToEndAsync()
388 return Task.FromResult(ReadToEnd());
391 [ComVisible(false)]
392 [MethodImplAttribute(MethodImplOptions.Synchronized)]
393 public override Task<int> ReadBlockAsync(char[] buffer, int index, int count)
395 if (buffer==null)
396 throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
397 if (index < 0 || count < 0)
398 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
399 if (buffer.Length - index < count)
400 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
402 Contract.EndContractBlock();
404 return Task.FromResult(ReadBlock(buffer, index, count));
407 [ComVisible(false)]
408 [MethodImplAttribute(MethodImplOptions.Synchronized)]
409 public override Task<int> ReadAsync(char[] buffer, int index, int count)
411 if (buffer==null)
412 throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
413 if (index < 0 || count < 0)
414 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
415 if (buffer.Length - index < count)
416 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
417 Contract.EndContractBlock();
419 return Task.FromResult(Read(buffer, index, count));
421 #endif //FEATURE_ASYNC_IO