Fix null sessions in HttpContextWrapper.Session
[mono.git] / mcs / class / corlib / System.IO / TextReader.cs
1 //
2 // System.IO.TextReader
3 //
4 // Authors:
5 //   Marcin Szczepanski (marcins@zipworld.com.au)
6 //   Miguel de Icaza (miguel@gnome.org)
7 //   Marek Safar (marek.safar@gmail.com)
8
9 //
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Copyright 2011 Xamarin Inc.
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Runtime.InteropServices;
35 #if NET_4_5
36 using System.Threading.Tasks;
37 #endif
38
39 namespace System.IO {
40
41         [Serializable]
42         [ComVisible (true)]
43 #if NET_2_1
44         public abstract class TextReader : IDisposable {
45 #else
46         public abstract class TextReader : MarshalByRefObject, IDisposable {
47 #endif
48
49                 sealed class NullTextReader : TextReader
50                 {
51                         public override string ReadLine ()
52                         {
53                                 return null;
54                         }
55
56                         public override string ReadToEnd ()
57                         {
58                                 return String.Empty;
59                         }
60                 }
61
62                 public static readonly TextReader Null = new NullTextReader ();
63
64                 protected TextReader()
65                 {
66                 }
67                 
68                 public virtual void Close()
69                 { 
70                         Dispose(true);
71                 }
72
73                 public void Dispose ()
74                 {
75                         Dispose(true);
76                 }
77
78                 protected virtual void Dispose (bool disposing)
79                 {
80                         if (disposing){
81                                 // If we are explicitly disposed, we can avoid finalization.
82                                 GC.SuppressFinalize (this);
83                         }
84                         return;
85                 }
86                 
87                 public virtual int Peek()
88                 {
89                         return -1;
90                 }
91                 
92                 public virtual int Read()
93                 {
94                         return -1;
95                 }
96                 
97                 public virtual int Read ([In, Out] char[] buffer, int index, int count)
98                 {
99                         int c, i;
100                         
101                         for (i = 0; i < count; i++) {
102                                 if ((c = Read ()) == -1)
103                                         return i;
104                                 buffer [index + i] = (char)c;
105                         }
106                         
107                         return i;
108                 }
109                 
110                 public virtual int ReadBlock ([In, Out] char [] buffer, int index, int count)
111                 {
112                         int total_read_count = 0;
113                         int current_read_count = 0;
114
115                         do {
116                                 current_read_count = Read (buffer, index, count);
117                                 index += current_read_count;
118                                 total_read_count += current_read_count;
119                                 count -= current_read_count;
120                         } while (current_read_count != 0 && count > 0);
121
122                         return total_read_count;
123                 }
124
125                 public virtual string ReadLine ()
126                 { 
127                         var result = new System.Text.StringBuilder ();
128                         int c;
129
130                         while ((c = Read ()) != -1){
131                                 // check simple character line ending
132                                 if (c == '\n')
133                                         break;
134                                 if (c == '\r') {
135                                         if (Peek () == '\n') 
136                                                 Read ();
137                                         break;
138                                 }
139                                 result.Append ((char) c);
140                         }
141                         if (c == -1 && result.Length == 0)
142                                 return null;
143                         
144                         return result.ToString ();
145                 }
146
147                 public virtual string ReadToEnd ()
148                 { 
149                         var result = new System.Text.StringBuilder ();
150                         int c;
151                         while ((c = Read ()) != -1)
152                                 result.Append ((char) c);
153                         return result.ToString ();
154                 }
155
156                 public static TextReader Synchronized (TextReader reader)
157                 {
158                         if (reader == null)
159                                 throw new ArgumentNullException ("reader is null");
160                         if (reader is SynchronizedReader)
161                                 return reader;
162
163                         return new SynchronizedReader (reader);
164                 }
165
166 #if NET_4_5
167                 //
168                 // Use tuple to pack the arguments because it's faster than
169                 // setting up anonymous method container with an instance delegate
170                 //
171                 public virtual Task<int> ReadAsync (char[] buffer, int index, int count)
172                 {
173                         return Task.Factory.StartNew (l => {
174                                 var t = (Tuple<TextReader, char[], int, int>) l;
175                                 return t.Item1.Read (t.Item2, t.Item3, t.Item4);
176                         }, Tuple.Create (this, buffer, index, count));
177                 }
178
179                 public virtual Task<int> ReadBlockAsync (char[] buffer, int index, int count)
180                 {
181                         return Task.Factory.StartNew (l => {
182                                 var t = (Tuple<TextReader, char[], int, int>) l;
183                                 return t.Item1.ReadBlock (t.Item2, t.Item3, t.Item4);
184                         }, Tuple.Create (this, buffer, index, count));
185                 }
186
187                 public virtual Task<string> ReadLineAsync ()
188                 {
189                         return Task.Factory.StartNew (l => ((TextReader) l).ReadLine (), this);
190                 }
191
192                 public virtual Task<string> ReadToEndAsync ()
193                 {
194                         return Task.Factory.StartNew (l => ((TextReader) l).ReadToEnd (), this);
195                 }
196 #endif
197         }
198
199         //
200         // Synchronized Reader implementation, used internally.
201         //
202         [Serializable]
203         sealed class SynchronizedReader : TextReader
204         {
205                 readonly TextReader reader;
206                 
207                 public SynchronizedReader (TextReader reader)
208                 {
209                         this.reader = reader;
210                 }
211
212                 public override void Close ()
213                 {
214                         lock (this){
215                                 reader.Close ();
216                         }
217                 }
218
219                 public override int Peek ()
220                 {
221                         lock (this){
222                                 return reader.Peek ();
223                         }
224                 }
225
226                 public override int ReadBlock (char [] buffer, int index, int count)
227                 {
228                         lock (this){
229                                 return reader.ReadBlock (buffer, index, count);
230                         }
231                 }
232
233                 public override string ReadLine ()
234                 {
235                         lock (this){
236                                 return reader.ReadLine ();
237                         }
238                 }
239
240                 public override string ReadToEnd ()
241                 {
242                         lock (this){
243                                 return reader.ReadToEnd ();
244                         }
245                 }
246
247                 public override int Read ()
248                 {
249                         lock (this){
250                                 return reader.Read ();
251                         }
252                 }
253
254                 public override int Read (char [] buffer, int index, int count)
255                 {
256                         lock (this){
257                                 return reader.Read (buffer, index, count);
258                         }
259                 }
260
261 #if NET_4_5
262                 public override Task<int> ReadAsync (char[] buffer, int index, int count)
263                 {
264                         lock (this) {
265                                 return reader.ReadAsync (buffer, index, count);
266                         }
267                 }
268
269                 public override Task<int> ReadBlockAsync (char[] buffer, int index, int count)
270                 {
271                         lock (this) {
272                                 return reader.ReadBlockAsync (buffer, index, count);
273                         }
274                 }
275
276                 public override Task<string> ReadLineAsync ()
277                 {
278                         lock (this) {
279                                 return reader.ReadLineAsync ();
280                         }
281                 }
282
283                 public override Task<string> ReadToEndAsync ()
284                 {
285                         lock (this) {
286                                 return reader.ReadToEndAsync ();
287                         }
288                 }
289 #endif
290         }
291 }