Merge pull request #537 from madewokherd/ccwmarshal
[mono.git] / mcs / class / corlib / System.IO / UnmanagedMemoryAccessor.cs
1 //
2 // System.IO.UnmanagedMemoryAccessor.cs
3 //
4 // Author:
5 //  Zoltan Varga (vargaz@gmail.com)
6 //  Marek Safar (marek.safar@gmail.com)
7 //
8 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 #if NET_4_0
31
32 using System;
33 using System.Runtime.InteropServices;
34 using System.Security.Permissions;
35
36 namespace System.IO
37 {
38         [MonoTODO ("Offset is ignored")]
39         public class UnmanagedMemoryAccessor : IDisposable {
40                 SafeBuffer buffer;
41 #pragma warning disable 414
42                 long offset;
43 #pragma warning restore
44                 long capacity;
45                 bool canwrite, canread;
46
47                 protected UnmanagedMemoryAccessor ()
48                 {
49                 }
50
51                 public UnmanagedMemoryAccessor (SafeBuffer buffer, long offset, long capacity)
52                 {
53                         Initialize (buffer, offset, capacity, FileAccess.ReadWrite);
54                 }
55
56                 public UnmanagedMemoryAccessor (SafeBuffer buffer, long offset, long capacity, FileAccess access)
57                 {
58                         Initialize (buffer, offset, capacity, access);
59                 }
60
61                 [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
62                 protected void Initialize(SafeBuffer buffer, long offset, long capacity, FileAccess access)
63                 {
64                         if (buffer == null)
65                                 throw new ArgumentNullException ("buffer");
66                         if (offset < 0)
67                                 throw new ArgumentOutOfRangeException ("offset");
68                         if (capacity < 0)
69                                 throw new ArgumentOutOfRangeException ("capacity");
70
71                         if (access == FileAccess.Read || access == FileAccess.ReadWrite)
72                                 canread = true;
73                         if (access == FileAccess.Write || access == FileAccess.ReadWrite)
74                                 canwrite = true;
75
76                         if (this.buffer != null)
77                                 Dispose (true);
78                                          
79                         this.buffer = buffer;
80                         this.offset = offset;
81                         this.capacity = capacity;
82                 }
83                 
84                 public void Dispose ()
85                 {
86                         Dispose (true);
87                         GC.SuppressFinalize (this);
88                 }
89
90                 protected virtual void Dispose (bool disposing)
91                 {
92                         if (buffer != null){
93                                 if (disposing){
94                                         buffer.Dispose ();
95                                 }
96                         }
97                         buffer = null;
98                 }
99
100                 public byte ReadByte (long position) 
101                 {
102                         if (!canread)
103                                 throw new NotSupportedException ();
104                         if (buffer == null)
105                                 throw new ObjectDisposedException ("buffer");
106                         if (position < 0)
107                                 throw new ArgumentOutOfRangeException ();
108                         
109                         return buffer.Read<byte> ((ulong) position);
110                 }
111
112                 public bool ReadBoolean (long position) 
113                 {
114                         if (!canread)
115                                 throw new NotSupportedException ();
116                         if (buffer == null)
117                                 throw new ObjectDisposedException ("buffer");
118                         if (position < 0)
119                                 throw new ArgumentOutOfRangeException ();
120                         
121                         return buffer.Read<bool> ((ulong) position);
122                 }
123
124                 public char ReadChar (long position) 
125                 {
126                         if (!canread)
127                                 throw new NotSupportedException ();
128                         if (buffer == null)
129                                 throw new ObjectDisposedException ("buffer");
130                         if (position < 0)
131                                 throw new ArgumentOutOfRangeException ();
132                         
133                         return buffer.Read<char> ((ulong) position);
134                 }
135                 
136                 public decimal ReadDecimal (long position) 
137                 {
138                         if (!canread)
139                                 throw new NotSupportedException ();
140                         if (buffer == null)
141                                 throw new ObjectDisposedException ("buffer");
142                         if (position < 0)
143                                 throw new ArgumentOutOfRangeException ();
144                         
145                         return buffer.Read<decimal> ((ulong) position);
146                 }
147                 
148                 public double ReadDouble (long position) 
149                 {
150                         if (!canread)
151                                 throw new NotSupportedException ();
152                         if (buffer == null)
153                                 throw new ObjectDisposedException ("buffer");
154                         if (position < 0)
155                                 throw new ArgumentOutOfRangeException ();
156                         
157                         return buffer.Read<double> ((ulong) position);
158                 }
159
160                 public short ReadInt16 (long position) 
161                 {
162                         if (!canread)
163                                 throw new NotSupportedException ();
164                         if (buffer == null)
165                                 throw new ObjectDisposedException ("buffer");
166                         if (position < 0)
167                                 throw new ArgumentOutOfRangeException ();
168                         
169                         return buffer.Read<short> ((ulong) position);
170                 }
171                 
172                 public int ReadInt32 (long position) 
173                 {
174                         if (!canread)
175                                 throw new NotSupportedException ();
176                         if (buffer == null)
177                                 throw new ObjectDisposedException ("buffer");
178                         if (position < 0)
179                                 throw new ArgumentOutOfRangeException ();
180                         
181                         return buffer.Read<int> ((ulong) position);
182                 }
183                 
184                 public long ReadInt64 (long position) 
185                 {
186                         if (!canread)
187                                 throw new NotSupportedException ();
188                         if (buffer == null)
189                                 throw new ObjectDisposedException ("buffer");
190                         if (position < 0)
191                                 throw new ArgumentOutOfRangeException ();
192                         
193                         return buffer.Read<long> ((ulong) position);
194                 }
195                 
196                 [CLSCompliant (false)]
197                 public sbyte ReadSByte (long position) 
198                 {
199                         if (!canread)
200                                 throw new NotSupportedException ();
201                         if (buffer == null)
202                                 throw new ObjectDisposedException ("buffer");
203                         if (position < 0)
204                                 throw new ArgumentOutOfRangeException ();
205                         
206                         return buffer.Read<sbyte> ((ulong) position);
207                 }
208                 
209                 public float ReadSingle (long position) 
210                 {
211                         if (!canread)
212                                 throw new NotSupportedException ();
213                         if (buffer == null)
214                                 throw new ObjectDisposedException ("buffer");
215                         if (position < 0)
216                                 throw new ArgumentOutOfRangeException ();
217                         
218                         return buffer.Read<float> ((ulong) position);
219                 }
220                 
221                 [CLSCompliant (false)]
222                 public ushort ReadUInt16 (long position) 
223                 {
224                         if (!canread)
225                                 throw new NotSupportedException ();
226                         if (buffer == null)
227                                 throw new ObjectDisposedException ("buffer");
228                         if (position < 0)
229                                 throw new ArgumentOutOfRangeException ();
230                         
231                         return buffer.Read<ushort> ((ulong) position);
232                 }
233
234                 [CLSCompliant (false)]
235                 public uint ReadUInt32 (long position) 
236                 {
237                         if (!canread)
238                                 throw new NotSupportedException ();
239                         if (buffer == null)
240                                 throw new ObjectDisposedException ("buffer");
241                         if (position < 0)
242                                 throw new ArgumentOutOfRangeException ();
243                         
244                         return buffer.Read<uint> ((ulong) position);
245                 }
246
247                 [CLSCompliant (false)]
248                 public ulong ReadUInt64 (long position) 
249                 {
250                         if (!canread)
251                                 throw new NotSupportedException ();
252                         if (buffer == null)
253                                 throw new ObjectDisposedException ("buffer");
254                         if (position < 0)
255                                 throw new ArgumentOutOfRangeException ();
256                         
257                         return buffer.Read<ulong> ((ulong) position);
258                 }
259
260                 public void Read<T> (long position, out T structure) where T : struct
261                 {
262                         if (!canread)
263                                 throw new NotSupportedException ();
264                         if (buffer == null)
265                                 throw new ObjectDisposedException ("buffer");
266                         if (position < 0)
267                                 throw new ArgumentOutOfRangeException ();
268                         
269                         structure = buffer.Read<T> ((ulong) position);
270                 }
271
272                 public int ReadArray<T> (long position, T [] array, int offset, int count) where T : struct
273                 {
274                         if (position < 0)
275                                 throw new ArgumentOutOfRangeException ();
276                         
277                         long left = capacity - position;
278                         var slots = Math.Min (count, (int)(left / Marshal.SizeOf (typeof (T))));
279
280                         buffer.ReadArray ((ulong) position, array, offset, slots);
281                         return slots;
282                 }
283                 
284                 public void Write (long position, bool value) 
285                 {
286                         if (!canwrite)
287                                 throw new NotSupportedException ();
288                         if (buffer == null)
289                                 throw new ObjectDisposedException ("buffer");
290                         if (position < 0)
291                                 throw new ArgumentOutOfRangeException ();
292                         
293                         buffer.Write ((ulong)position, value);
294                 }
295
296                 public void Write (long position, byte value) 
297                 {
298                         if (!canwrite)
299                                 throw new NotSupportedException ();
300                         if (buffer == null)
301                                 throw new ObjectDisposedException ("buffer");
302                         if (position < 0)
303                                 throw new ArgumentOutOfRangeException ();
304                         
305                         buffer.Write ((ulong)position, value);
306                 }
307
308                 public void Write (long position, char value) 
309                 {
310                         if (!canwrite)
311                                 throw new NotSupportedException ();
312                         if (buffer == null)
313                                 throw new ObjectDisposedException ("buffer");
314                         if (position < 0)
315                                 throw new ArgumentOutOfRangeException ();
316                         
317                         buffer.Write ((ulong)position, value);
318                 }
319
320                 public void Write (long position, decimal value) 
321                 {
322                         if (!canwrite)
323                                 throw new NotSupportedException ();
324                         if (buffer == null)
325                                 throw new ObjectDisposedException ("buffer");
326                         if (position < 0)
327                                 throw new ArgumentOutOfRangeException ();
328                         
329                         buffer.Write ((ulong)position, value);
330                 }
331                 
332                 public void Write (long position, double value) 
333                 {
334                         if (!canwrite)
335                                 throw new NotSupportedException ();
336                         if (buffer == null)
337                                 throw new ObjectDisposedException ("buffer");
338                         if (position < 0)
339                                 throw new ArgumentOutOfRangeException ();
340                         
341                         buffer.Write ((ulong)position, value);
342                 }
343
344                 public void Write (long position, short value) 
345                 {
346                         if (!canwrite)
347                                 throw new NotSupportedException ();
348                         if (buffer == null)
349                                 throw new ObjectDisposedException ("buffer");
350                         if (position < 0)
351                                 throw new ArgumentOutOfRangeException ();
352                         
353                         buffer.Write ((ulong)position, value);
354                 }
355
356                 public void Write (long position, int value) 
357                 {
358                         if (!canwrite)
359                                 throw new NotSupportedException ();
360                         if (buffer == null)
361                                 throw new ObjectDisposedException ("buffer");
362                         if (position < 0)
363                                 throw new ArgumentOutOfRangeException ();
364                         
365                         buffer.Write ((ulong)position, value);
366                 }
367
368                 public void Write (long position, long value) 
369                 {
370                         if (!canwrite)
371                                 throw new NotSupportedException ();
372                         if (buffer == null)
373                                 throw new ObjectDisposedException ("buffer");
374                         if (position < 0)
375                                 throw new ArgumentOutOfRangeException ();
376                         
377                         buffer.Write ((ulong)position, value);
378                 }
379
380                 [CLSCompliant (false)]
381                 public void Write (long position, sbyte value) 
382                 {
383                         if (!canwrite)
384                                 throw new NotSupportedException ();
385                         if (buffer == null)
386                                 throw new ObjectDisposedException ("buffer");
387                         if (position < 0)
388                                 throw new ArgumentOutOfRangeException ();
389                         
390                         buffer.Write ((ulong)position, value);
391                 }
392
393                 public void Write (long position, float value) 
394                 {
395                         if (!canwrite)
396                                 throw new NotSupportedException ();
397                         if (buffer == null)
398                                 throw new ObjectDisposedException ("buffer");
399                         if (position < 0)
400                                 throw new ArgumentOutOfRangeException ();
401                         
402                         buffer.Write ((ulong)position, value);
403                 }
404
405                 [CLSCompliant (false)]
406                 public void Write (long position, ushort value) 
407                 {
408                         if (!canwrite)
409                                 throw new NotSupportedException ();
410                         if (buffer == null)
411                                 throw new ObjectDisposedException ("buffer");
412                         if (position < 0)
413                                 throw new ArgumentOutOfRangeException ();
414                         
415                         buffer.Write ((ulong)position, value);
416                 }
417
418                 [CLSCompliant (false)]
419                 public void Write (long position, uint value) 
420                 {
421                         if (!canwrite)
422                                 throw new NotSupportedException ();
423                         if (buffer == null)
424                                 throw new ObjectDisposedException ("buffer");
425                         if (position < 0)
426                                 throw new ArgumentOutOfRangeException ();
427                         
428                         buffer.Write ((ulong)position, value);
429                 }
430
431                 [CLSCompliant (false)]
432                 public void Write (long position, ulong value) 
433                 {
434                         if (!canwrite)
435                                 throw new NotSupportedException ();
436                         if (buffer == null)
437                                 throw new ObjectDisposedException ("buffer");
438                         if (position < 0)
439                                 throw new ArgumentOutOfRangeException ();
440                         
441                         buffer.Write ((ulong)position, value);
442                 }
443
444                 public void Write<T> (long position, ref T structure) where T : struct
445                 {
446                         if (!canwrite)
447                                 throw new NotSupportedException ();
448                         if (buffer == null)
449                                 throw new ObjectDisposedException ("buffer");
450                         if (position < 0)
451                                 throw new ArgumentOutOfRangeException ();
452                         
453                         buffer.Write<T> ((ulong)position, structure);
454                 }
455
456                 public void WriteArray<T> (long position, T [] array, int offset, int count) where T : struct 
457                 {
458                         buffer.WriteArray ((ulong)position, array, offset, count);
459                 }
460         
461                 public bool CanRead {
462                         get { return canread; }
463                 }
464
465                 public bool CanWrite {
466                         get { return canwrite; }
467                 }
468
469                 public long Capacity {
470                         get { return capacity; }
471                 }
472                 
473                 protected bool IsOpen {
474                         get { return buffer != null; }
475                 }
476         }
477 }
478
479 #endif