Pass cancellation token to CopyAsync read block
[mono.git] / mcs / class / corlib / System.IO / StringReader.cs
1 //
2 // System.IO.StringReader
3 //
4 // Authors:
5 //   Marcin Szczepanski (marcins@zipworld.com.au)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 // Copyright 2011 Xamarin Inc.
10 //
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Globalization;
34 using System.Runtime.InteropServices;
35 #if NET_4_5
36 using System.Threading.Tasks;
37 #endif
38
39 namespace System.IO {
40         [Serializable]
41         [ComVisible (true)]
42         public class StringReader : TextReader {
43
44                 string source;
45                 int nextChar;
46                 int sourceLength;
47                 static char[] cr_lf;
48
49                 public StringReader (string s)
50                 {
51                         if (s == null) 
52                                 throw new ArgumentNullException ("s");
53
54                         this.source = s;
55                         nextChar = 0;
56                         sourceLength = s.Length;
57                 }
58
59                 public override void Close ()
60                 {
61                         Dispose (true);
62                 }
63
64                 protected override void Dispose (bool disposing)
65                 {
66                         source = null;
67                         base.Dispose (disposing);
68                 }
69
70                 public override int Peek ()
71                 {
72                         if (source == null)
73                                 ObjectDisposedException ();
74
75                         if (nextChar >= sourceLength) 
76                                 return -1;
77                         return (int)source [nextChar];
78                 }
79
80                 public override int Read ()
81                 {
82                         if (source == null)
83                                 ObjectDisposedException ();
84
85                         if (nextChar >= sourceLength)
86                                 return -1;
87                         return (int)source [nextChar++];
88                 }
89
90                 // The method will read up to count characters from the StringReader
91                 // into the buffer character array starting at position index. Returns
92                 // the actual number of characters read, or zero if the end of the string
93                 // has been reached and no characters are read.
94
95                 public override int Read ([In, Out] char[] buffer, int index, int count)
96                 {
97                         if (source == null)
98                                 ObjectDisposedException ();
99
100                         if (buffer == null)
101                                 throw new ArgumentNullException ("buffer");
102                         if (buffer.Length - index < count)
103                                 throw new ArgumentException ();
104                         if (index < 0 || count < 0)
105                                 throw new ArgumentOutOfRangeException ();
106
107                         int charsToRead;
108
109                         // reordered to avoir possible integer overflow
110                         if (nextChar > sourceLength - count)
111                                 charsToRead = sourceLength - nextChar;
112                         else
113                                 charsToRead = count;
114                         
115                         source.CopyTo (nextChar, buffer, index, charsToRead);
116
117                         nextChar += charsToRead;
118
119                         return charsToRead;
120                 }
121
122                 public override string ReadLine ()
123                 {
124                         // Reads until next \r or \n or \r\n, otherwise return null
125
126                         if (source == null)
127                                 ObjectDisposedException ();
128
129                         if (nextChar >= source.Length)
130                                 return null;
131
132                         if (cr_lf == null)
133                                 cr_lf = new char [] { '\n', '\r' };
134                         
135                         int readto = source.IndexOfAny (cr_lf, nextChar);
136                         
137                         if (readto == -1)
138                                 return ReadToEnd ();
139
140                         bool consecutive = source[readto] == '\r'
141                                 && readto + 1 < source.Length
142                                 && source[readto + 1] == '\n';
143
144                         string nextLine = source.Substring (nextChar, readto - nextChar);
145                         nextChar = readto + ((consecutive) ? 2 : 1);
146                         return nextLine;
147                 }
148
149                 public override string ReadToEnd ()
150                 {
151                         if (source == null)
152                                 ObjectDisposedException ();
153                         string toEnd = source.Substring (nextChar, sourceLength - nextChar);
154                         nextChar = sourceLength;
155                         return toEnd;
156                 }
157
158 #if NET_4_5
159                 //
160                 // All async methods return finished task with a result as it's faster
161                 // than setting up async call
162                 //
163                 public override Task<int> ReadAsync (char[] buffer, int index, int count)
164                 {
165                         return Task.FromResult (Read (buffer, index, count));
166                 }
167
168                 public override Task<int> ReadBlockAsync (char[] buffer, int index, int count)
169                 {
170                         return Task.FromResult (ReadBlock (buffer, index, count));
171                 }
172
173                 public override Task<string> ReadLineAsync ()
174                 {
175                         return Task.FromResult (ReadLine ());
176                 }
177
178                 public override Task<string> ReadToEndAsync ()
179                 {
180                         return Task.FromResult (ReadToEnd ());
181                 }
182 #endif
183
184                 static void ObjectDisposedException ()
185                 {
186                         throw new ObjectDisposedException ("StringReader", 
187                                                            Locale.GetText ("Cannot read from a closed StringReader"));
188                 }
189         }
190 }