Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / io / unmanagedmemoryaccessor.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** Class:  UnmanagedMemoryAccessor
9 ** 
10 ** <OWNER>[....]</OWNER>
11 **
12 ** Purpose: Provides a fast, AV free, cross-language way of 
13 **          accessing unmanaged memory in a random fashion.
14 **
15 ** Date:  February 7, 2007
16 **
17 ===========================================================*/
18
19 using System;
20 using System.Runtime.InteropServices;
21 using System.Runtime.CompilerServices;
22 using System.Runtime.ConstrainedExecution;
23 using System.Runtime.Versioning;
24 using System.Security.Permissions;
25 using Microsoft.Win32.SafeHandles;
26 using System.Diagnostics.Contracts;
27
28 namespace System.IO {
29
30     /// Perf notes: ReadXXX, WriteXXX (for basic types) acquire and release the 
31     /// SafeBuffer pointer rather than relying on generic Read(T) from SafeBuffer because
32     /// this gives better throughput; benchmarks showed about 12-15% better.
33     public class UnmanagedMemoryAccessor : IDisposable {
34
35         [System.Security.SecurityCritical] // auto-generated
36         private SafeBuffer _buffer;
37         private Int64 _offset;
38         [ContractPublicPropertyName("Capacity")]
39         private Int64 _capacity;
40         private FileAccess _access;
41         private bool _isOpen;
42         private bool _canRead;
43         private bool _canWrite;
44
45         protected UnmanagedMemoryAccessor() {
46             _isOpen = false;
47         }
48
49         #region SafeBuffer ctors and initializers
50         // <SecurityKernel Critical="True" Ring="1">
51         // <ReferencesCritical Name="Method: Initialize(SafeBuffer, Int64, Int64, FileAccess):Void" Ring="1" />
52         // </SecurityKernel>
53         [System.Security.SecuritySafeCritical]
54         public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity) {
55             Initialize(buffer, offset, capacity, FileAccess.Read);
56         }
57
58         [System.Security.SecuritySafeCritical]  // auto-generated
59         public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access) {
60             Initialize(buffer, offset, capacity, access);
61         }
62
63         [System.Security.SecuritySafeCritical]  // auto-generated
64         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
65         protected void Initialize(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access) {
66             if (buffer == null) {
67                 throw new ArgumentNullException("buffer");
68             }
69             if (offset < 0) {
70                 throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
71             }
72             if (capacity < 0) {
73                 throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
74             }
75             if (buffer.ByteLength < (UInt64)(offset + capacity)) {
76                 throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndCapacityOutOfBounds"));
77             }
78             if (access < FileAccess.Read || access > FileAccess.ReadWrite) {
79                 throw new ArgumentOutOfRangeException("access");
80             }
81             Contract.EndContractBlock();
82
83             if (_isOpen) {
84                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice"));
85             }
86
87             unsafe {
88                 byte* pointer = null;
89                 RuntimeHelpers.PrepareConstrainedRegions();
90                 try {
91                     buffer.AcquirePointer(ref pointer);
92                     if (((byte*)((Int64)pointer + offset + capacity)) < pointer) {
93                         throw new ArgumentException(Environment.GetResourceString("Argument_UnmanagedMemAccessorWrapAround"));
94                     }
95                 }
96                 finally {
97                     if (pointer != null) {
98                         buffer.ReleasePointer();
99                     }
100                 }
101             }
102
103             _offset = offset;
104             _buffer = buffer;
105             _capacity = capacity;
106             _access = access;
107             _isOpen = true;
108             _canRead = (_access & FileAccess.Read) != 0;
109             _canWrite = (_access & FileAccess.Write) != 0;
110         }
111
112         #endregion
113
114         public Int64 Capacity {
115             get { 
116                 return _capacity; 
117             }
118         }
119
120         public bool CanRead {
121             get { 
122                 return _isOpen && _canRead; 
123             }
124         }
125
126         public bool CanWrite {
127             get { 
128                 return _isOpen && _canWrite; 
129             }
130         }
131
132         protected virtual void Dispose(bool disposing) {
133             _isOpen = false;
134         }
135
136         public void Dispose() {
137             Dispose(true);
138             GC.SuppressFinalize(this);
139         }
140
141         protected bool IsOpen {
142             get { return _isOpen; }
143         }
144
145         public bool ReadBoolean(Int64 position) {
146             int sizeOfType = sizeof(bool);
147             EnsureSafeToRead(position, sizeOfType);
148
149             byte b = InternalReadByte(position);
150             return b != 0;
151         }
152
153         public byte ReadByte(Int64 position) {
154             int sizeOfType = sizeof(byte);
155             EnsureSafeToRead(position, sizeOfType);
156
157             return InternalReadByte(position);
158         }
159
160         [System.Security.SecuritySafeCritical]  // auto-generated
161         public char ReadChar(Int64 position) {
162             int sizeOfType = sizeof(char);
163             EnsureSafeToRead(position, sizeOfType);
164          
165             char result;
166
167             unsafe {
168                 byte* pointer = null;
169                 RuntimeHelpers.PrepareConstrainedRegions();
170                 try {
171                     _buffer.AcquirePointer(ref pointer);
172                     pointer += (_offset + position);
173                     
174 #if ALIGN_ACCESS
175                     // check if pointer is aligned
176                     if (((int)pointer & (sizeOfType - 1)) == 0) {
177 #endif
178                         result = *((char*)(pointer));
179 #if ALIGN_ACCESS
180                     }
181                     else {
182                         result = (char)( *pointer | *(pointer + 1) << 8 ) ;
183                     }
184 #endif
185                 }
186                 finally {
187                     if (pointer != null) {
188                         _buffer.ReleasePointer();
189                     }
190                 }
191             }
192
193             return result;
194         }
195
196         // See comment above.
197         [System.Security.SecuritySafeCritical]
198         public Int16 ReadInt16(Int64 position) {
199             int sizeOfType = sizeof(Int16);
200             EnsureSafeToRead(position, sizeOfType);
201
202             Int16 result;
203
204             unsafe {
205                 byte* pointer = null;
206                 RuntimeHelpers.PrepareConstrainedRegions();
207                 try {
208                     _buffer.AcquirePointer(ref pointer);
209                     pointer += (_offset + position);
210
211 #if ALIGN_ACCESS
212                     // check if pointer is aligned
213                     if (((int)pointer & (sizeOfType - 1)) == 0) {
214 #endif
215                         result = *((Int16*)(pointer));
216 #if ALIGN_ACCESS
217                     }
218                     else {
219                         result = (Int16)( *pointer | *(pointer + 1) << 8 );
220                     }
221 #endif
222                 }
223                 finally {
224                     if (pointer != null) {
225                         _buffer.ReleasePointer();
226                     }
227                 }
228             }
229
230             return result;
231         }
232
233
234         [System.Security.SecuritySafeCritical]  // auto-generated
235         public Int32 ReadInt32(Int64 position) {
236             int sizeOfType = sizeof(Int32);
237             EnsureSafeToRead(position, sizeOfType);
238
239             Int32 result;
240             unsafe {
241                 byte* pointer = null;
242                 RuntimeHelpers.PrepareConstrainedRegions();
243                 try {
244                     _buffer.AcquirePointer(ref pointer);
245                     pointer += (_offset + position);
246
247 #if ALIGN_ACCESS
248                     // check if pointer is aligned
249                     if (((int)pointer & (sizeOfType - 1)) == 0) {
250 #endif
251                         result = *((Int32*)(pointer));
252 #if ALIGN_ACCESS
253                     }
254                     else {
255                         result = (Int32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
256                     }
257 #endif
258                 }
259                 finally {
260                     if (pointer != null) {
261                         _buffer.ReleasePointer();
262                     }
263                 }
264             }
265
266             return result;
267         }
268
269         [System.Security.SecuritySafeCritical]  // auto-generated
270         public Int64 ReadInt64(Int64 position) {
271             int sizeOfType = sizeof(Int64);
272             EnsureSafeToRead(position, sizeOfType);
273
274             Int64 result;
275             unsafe {
276                 byte* pointer = null;
277                 RuntimeHelpers.PrepareConstrainedRegions();
278                 try {
279                     _buffer.AcquirePointer(ref pointer);
280                     pointer += (_offset + position);
281
282 #if ALIGN_ACCESS
283                     // check if pointer is aligned
284                     if (((int)pointer & (sizeOfType - 1)) == 0) {
285 #endif
286                         result = *((Int64*)(pointer));
287 #if ALIGN_ACCESS
288                     }
289                     else {
290                         int lo = *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24;
291                         int hi = *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24;
292                         result = (Int64)(((Int64)hi << 32) | (UInt32)lo);
293                     }
294 #endif
295                     }
296                 finally {
297                     if (pointer != null) {
298                         _buffer.ReleasePointer();
299                     }
300                 }
301             }
302
303             return result;
304         }
305
306         [System.Security.SecuritySafeCritical]  // auto-generated
307         public Decimal ReadDecimal(Int64 position) {
308             int sizeOfType = sizeof(Decimal);
309             EnsureSafeToRead(position, sizeOfType);
310
311             int[] decimalArray = new int[4];
312             ReadArray<int>(position, decimalArray, 0, decimalArray.Length);
313
314             return new Decimal(decimalArray);
315         }
316
317         [System.Security.SecuritySafeCritical]  // auto-generated
318         public Single ReadSingle(Int64 position) {
319             int sizeOfType = sizeof(Single);
320             EnsureSafeToRead(position, sizeOfType);
321
322             Single result;
323             unsafe {
324                 byte* pointer = null;
325                 RuntimeHelpers.PrepareConstrainedRegions();
326                 try {
327                     _buffer.AcquirePointer(ref pointer);
328                     pointer += (_offset + position);
329
330 #if ALIGN_ACCESS
331                     // check if pointer is aligned
332                     if (((int)pointer & (sizeOfType - 1)) == 0) {
333 #endif
334                     result = *((Single*)(pointer));
335 #if ALIGN_ACCESS
336                     }
337                     else {
338                     UInt32 tempResult = (UInt32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
339                     result = *((float*)&tempResult);
340                     }
341 #endif
342                 }
343                 finally {
344                     if (pointer != null) {
345                         _buffer.ReleasePointer();
346                     }
347                 }
348             }
349
350             return result;
351         }
352
353         [System.Security.SecuritySafeCritical]  // auto-generated
354         public Double ReadDouble(Int64 position) {
355             int sizeOfType = sizeof(Double);
356             EnsureSafeToRead(position, sizeOfType);
357
358             Double result;
359             unsafe {
360                 byte* pointer = null;
361                 RuntimeHelpers.PrepareConstrainedRegions();
362                 try {
363                     _buffer.AcquirePointer(ref pointer);
364                     pointer += (_offset + position);
365
366 #if ALIGN_ACCESS
367                     // check if pointer is aligned
368                     if (((int)pointer & (sizeOfType - 1)) == 0) {
369 #endif
370                     result = *((Double*)(pointer));
371 #if ALIGN_ACCESS
372                     }
373                     else {
374
375                     UInt32 lo = (UInt32)( *pointer | *(pointer + 1) << 8  | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
376                     UInt32 hi = (UInt32)( *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24 );
377                     UInt64 tempResult = ((UInt64)hi) << 32 | lo;
378                     result = *((double*)&tempResult);
379
380                     }
381 #endif
382                 }
383                 finally {
384                     if (pointer != null) {
385                         _buffer.ReleasePointer();
386                     }
387                 }
388             }
389
390             return result;
391         }
392
393         [System.Security.SecuritySafeCritical]  // auto-generated
394         [CLSCompliant(false)]
395         public SByte ReadSByte(Int64 position) {
396             int sizeOfType = sizeof(SByte);
397             EnsureSafeToRead(position, sizeOfType);
398
399             SByte result;
400             unsafe {
401                 byte* pointer = null;
402                 RuntimeHelpers.PrepareConstrainedRegions();
403                 try {
404                     _buffer.AcquirePointer(ref pointer);
405                     pointer += (_offset + position);
406                     result = *((SByte*)pointer);
407                 }
408                 finally {
409                     if (pointer != null) {
410                         _buffer.ReleasePointer();
411                     }
412                 }
413             }
414
415             return result;
416         }
417         
418         [System.Security.SecuritySafeCritical]  // auto-generated
419         [CLSCompliant(false)]
420         public UInt16 ReadUInt16(Int64 position) {
421             int sizeOfType = sizeof(UInt16);
422             EnsureSafeToRead(position, sizeOfType);
423
424             UInt16 result;
425             unsafe {
426                 byte* pointer = null;
427                 RuntimeHelpers.PrepareConstrainedRegions();
428                 try {
429                     _buffer.AcquirePointer(ref pointer);
430                     pointer += (_offset + position);
431
432 #if ALIGN_ACCESS
433                     // check if pointer is aligned
434                     if (((int)pointer & (sizeOfType - 1)) == 0) {
435 #endif
436                     result = *((UInt16*)(pointer));
437 #if ALIGN_ACCESS
438                     }
439                     else {
440                         result = (UInt16)( *pointer | *(pointer + 1) << 8 );
441                     }
442 #endif
443
444                 }
445                 finally {
446                     if (pointer != null) {
447                         _buffer.ReleasePointer();
448                     }
449                 }
450             }
451
452             return result;
453         }
454         
455         [System.Security.SecuritySafeCritical]  // auto-generated
456         [CLSCompliant(false)]
457         public UInt32 ReadUInt32(Int64 position) {
458             int sizeOfType = sizeof(UInt32);
459             EnsureSafeToRead(position, sizeOfType);
460
461             UInt32 result;
462             unsafe {
463                 byte* pointer = null;
464                 RuntimeHelpers.PrepareConstrainedRegions();
465                 try {
466                     _buffer.AcquirePointer(ref pointer);
467                     pointer += (_offset + position);
468
469 #if ALIGN_ACCESS
470                     // check if pointer is aligned
471                     if (((int)pointer & (sizeOfType - 1)) == 0) {
472 #endif
473                     result = *((UInt32*)(pointer));
474 #if ALIGN_ACCESS
475                     }
476                     else {
477                         result = (UInt32)( *pointer | *(pointer + 1) << 8  | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
478                     }
479 #endif
480
481                 }
482                 finally {
483                     if (pointer != null) {
484                         _buffer.ReleasePointer();
485                     }
486                 }
487             }
488
489             return result;
490         }
491
492         [System.Security.SecuritySafeCritical]  // auto-generated
493         [CLSCompliant(false)]
494         public UInt64 ReadUInt64(Int64 position) {
495             int sizeOfType = sizeof(UInt64);
496             EnsureSafeToRead(position, sizeOfType);
497
498             UInt64 result;
499             unsafe {
500                 byte* pointer = null;
501                 RuntimeHelpers.PrepareConstrainedRegions();
502                 try {
503                     _buffer.AcquirePointer(ref pointer);
504                     pointer += (_offset + position);
505
506 #if ALIGN_ACCESS
507                     // check if pointer is aligned
508                     if (((int)pointer & (sizeOfType - 1)) == 0) {
509 #endif
510                     result = *((UInt64*)(pointer));
511 #if ALIGN_ACCESS
512                     }
513                     else {
514                         UInt32 lo = (UInt32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
515                         UInt32 hi = (UInt32)( *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24 );
516                         result = (UInt64)(((UInt64)hi << 32) | lo );
517                     }
518 #endif
519
520                 }
521                 finally {
522                     if (pointer != null) {
523                         _buffer.ReleasePointer();
524                     }
525                 }
526             }
527
528             return result;
529         }
530
531         // Reads a struct of type T from unmanaged memory, into the reference pointed to by ref value.  
532         // Note: this method is not safe, since it overwrites the contents of a structure, it can be 
533         // used to modify the private members of a struct.  Furthermore, using this with a struct that
534         // contains reference members will most likely cause the runtime to AV.  Note, that despite 
535         // various checks made by the C++ code used by Marshal.PtrToStructure, Marshal.PtrToStructure
536         // will still overwrite privates and will also crash the runtime when used with structs 
537         // containing reference members.  For this reason, I am sticking an UnmanagedCode requirement
538         // on this method to match Marshal.PtrToStructure.
539
540         // Alos note that this method is most performant when used with medium to large sized structs
541         // (larger than 8 bytes -- though this is number is JIT and architecture dependent).   As 
542         // such, it is best to use the ReadXXX methods for small standard types such as ints, longs, 
543         // bools, etc.
544
545         [System.Security.SecurityCritical]  // auto-generated_required
546         public void Read<T>(Int64 position, out T structure) where T : struct {
547             if (position < 0) {
548                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
549             }
550             Contract.EndContractBlock();
551
552             if (!_isOpen) {
553                 throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
554             }
555             if (!CanRead) {
556                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading"));
557             }
558
559             UInt32 sizeOfT = Marshal.SizeOfType(typeof(T));
560             if (position > _capacity - sizeOfT) { 
561                 if (position >= _capacity) {
562                     throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
563                 }
564                 else {
565                     throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead", typeof(T).FullName), "position");
566                 }
567             }
568
569             structure = _buffer.Read<T>((UInt64)(_offset + position));
570         }
571
572         // Reads 'count' structs of type T from unmanaged memory, into 'array' starting at 'offset'.  
573         // Note: this method is not safe, since it overwrites the contents of structures, it can 
574         // be used to modify the private members of a struct.  Furthermore, using this with a 
575         // struct that contains reference members will most likely cause the runtime to AV. This
576         // is consistent with Marshal.PtrToStructure.
577
578         [System.Security.SecurityCritical]  // auto-generated_required
579         public int ReadArray<T>(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct {
580             if (array == null) {
581                 throw new ArgumentNullException("array", "Buffer cannot be null.");
582             }
583             if (offset < 0) {
584                 throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
585             }
586             if (count < 0) {
587                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
588             }
589             if (array.Length - offset < count) {
590                 throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndLengthOutOfBounds"));
591             }
592             Contract.EndContractBlock();
593             if (!CanRead) {
594                 if (!_isOpen) {
595                     throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
596                 }
597                 else {
598                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading"));
599                 }
600             }
601             if (position < 0) {
602                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
603             }
604
605             UInt32 sizeOfT = Marshal.AlignedSizeOf<T>();
606
607             // only check position and ask for fewer Ts if count is too big
608             if (position >= _capacity) {
609                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
610             }
611
612             int n = count;
613             long spaceLeft = _capacity - position;
614             if (spaceLeft < 0) {
615                 n = 0;
616             }
617             else {
618                 ulong spaceNeeded = (ulong)(sizeOfT * count);
619                 if ((ulong)spaceLeft < spaceNeeded) {
620                     n = (int)(spaceLeft / sizeOfT);
621                 }
622             }
623
624             _buffer.ReadArray<T>((UInt64)(_offset + position), array, offset, n);
625
626             return n;
627         }
628
629         // ************** Write Methods ****************/
630
631         // The following 13 WriteXXX methods write a value of type XXX into unmanaged memory at 'positon'. 
632         // The bounds of the unmanaged memory are checked against to ensure that there is enough 
633         // space after 'position' to write a value of type XXX.  XXX can be a bool, byte, char, decimal, 
634         // double, short, int, long, sbyte, float, ushort, uint, or ulong. 
635
636
637         public void Write(Int64 position, bool value) {
638             int sizeOfType = sizeof(bool);
639             EnsureSafeToWrite(position, sizeOfType);
640
641             byte b = (byte)(value ? 1 : 0);
642             InternalWrite(position, b);
643         }
644
645         public void Write(Int64 position, byte value) {
646             int sizeOfType = sizeof(byte);
647             EnsureSafeToWrite(position, sizeOfType);
648
649             InternalWrite(position, value);
650         }
651
652         [System.Security.SecuritySafeCritical]  // auto-generated
653         public void Write(Int64 position, char value) {
654             int sizeOfType = sizeof(char);
655             EnsureSafeToWrite(position, sizeOfType);
656
657             unsafe {
658                 byte* pointer = null;
659                 RuntimeHelpers.PrepareConstrainedRegions();
660                 try {
661                     _buffer.AcquirePointer(ref pointer);
662                     pointer += (_offset + position);
663
664 #if ALIGN_ACCESS
665                     // check if pointer is aligned
666                     if (((int)pointer & (sizeOfType - 1)) == 0) {
667 #endif
668                         *((char*)pointer) = value;
669 #if ALIGN_ACCESS
670                     }
671                     else {
672                         *(pointer) = (byte)value;
673                         *(pointer+1) = (byte)(value >> 8);
674                     }
675 #endif
676                 }
677                 finally {
678                     if (pointer != null) {
679                         _buffer.ReleasePointer();
680                     }
681                 }
682             }
683
684         }
685
686
687         [System.Security.SecuritySafeCritical]  // auto-generated
688         public void Write(Int64 position, Int16 value) {
689             int sizeOfType = sizeof(Int16);
690             EnsureSafeToWrite(position, sizeOfType);
691
692             unsafe {
693                 byte* pointer = null;
694                 RuntimeHelpers.PrepareConstrainedRegions();
695                 try {
696                     _buffer.AcquirePointer(ref pointer);
697                     pointer += (_offset + position);
698
699 #if ALIGN_ACCESS
700                     // check if pointer is aligned
701                     if (((int)pointer & (sizeOfType - 1)) == 0) {
702 #endif
703                         *((Int16*)pointer) = value;
704 #if ALIGN_ACCESS
705                     }
706                     else {
707                         *(pointer) = (byte)value;
708                         *(pointer + 1) = (byte)(value >> 8);
709                     }
710 #endif
711                 }
712                 finally {
713                     if (pointer != null) {
714                         _buffer.ReleasePointer();
715                     }
716                 }
717             }
718         }
719
720
721         [System.Security.SecuritySafeCritical]  // auto-generated
722         public void Write(Int64 position, Int32 value) {
723             int sizeOfType = sizeof(Int32);
724             EnsureSafeToWrite(position, sizeOfType);
725
726             unsafe {
727                 byte* pointer = null;
728                 RuntimeHelpers.PrepareConstrainedRegions();
729                 try {
730                     _buffer.AcquirePointer(ref pointer);
731                     pointer += (_offset + position);
732
733 #if ALIGN_ACCESS
734                     // check if pointer is aligned
735                     if (((int)pointer & (sizeOfType - 1)) == 0) {
736 #endif
737                         *((Int32*)pointer) = value;
738 #if ALIGN_ACCESS
739                     }
740                     else {
741                         *(pointer) = (byte)value;
742                         *(pointer + 1) = (byte)(value >> 8);
743                         *(pointer + 2) = (byte)(value >> 16);
744                         *(pointer + 3) = (byte)(value >> 24);
745                     }
746 #endif
747                 }
748                 finally {
749                     if (pointer != null) {
750                         _buffer.ReleasePointer();
751                     }
752                 }
753             }
754         }
755
756         [System.Security.SecuritySafeCritical]  // auto-generated
757         public void Write(Int64 position, Int64 value) {
758             int sizeOfType = sizeof(Int64);
759             EnsureSafeToWrite(position, sizeOfType);
760
761             unsafe {
762                 byte* pointer = null;
763                 RuntimeHelpers.PrepareConstrainedRegions();
764                 try {
765                     _buffer.AcquirePointer(ref pointer);
766                     pointer += (_offset + position);
767 #if ALIGN_ACCESS
768                     // check if pointer is aligned
769                     if (((int)pointer & (sizeOfType - 1)) == 0) {
770 #endif
771                         *((Int64*)pointer) = value;
772 #if ALIGN_ACCESS
773                     }
774                     else {
775                         *(pointer) = (byte)value;
776                         *(pointer + 1) = (byte)(value >> 8);
777                         *(pointer + 2) = (byte)(value >> 16);
778                         *(pointer + 3) = (byte)(value >> 24);
779                         *(pointer + 4) = (byte)(value >> 32);
780                         *(pointer + 5) = (byte)(value >> 40);
781                         *(pointer + 6) = (byte)(value >> 48);
782                         *(pointer + 7) = (byte)(value >> 56);
783                     }
784 #endif
785                 }
786                 finally {
787                     if (pointer != null) {
788                         _buffer.ReleasePointer();
789                     }
790                 }
791             }
792         }
793
794         [System.Security.SecuritySafeCritical]  // auto-generated
795         public void Write(Int64 position, Decimal value) {
796             int sizeOfType = sizeof(Decimal);
797             EnsureSafeToWrite(position, sizeOfType);
798
799             byte[] decimalArray = new byte[16];
800             Decimal.GetBytes(value, decimalArray);
801
802             int[] bits = new int[4];
803             int flags = ((int)decimalArray[12]) | ((int)decimalArray[13] << 8) | ((int)decimalArray[14] << 16) | ((int)decimalArray[15] << 24);
804             int lo = ((int)decimalArray[0]) | ((int)decimalArray[1] << 8) | ((int)decimalArray[2] << 16) | ((int)decimalArray[3] << 24);
805             int mid = ((int)decimalArray[4]) | ((int)decimalArray[5] << 8) | ((int)decimalArray[6] << 16) | ((int)decimalArray[7] << 24);
806             int hi = ((int)decimalArray[8]) | ((int)decimalArray[9] << 8) | ((int)decimalArray[10] << 16) | ((int)decimalArray[11] << 24);
807             bits[0] = lo;
808             bits[1] = mid;
809             bits[2] = hi;
810             bits[3] = flags;
811
812             WriteArray<int>(position, bits, 0, bits.Length);
813         }
814
815         [System.Security.SecuritySafeCritical]  // auto-generated
816         public void Write(Int64 position, Single value) {
817             int sizeOfType = sizeof(Single);
818             EnsureSafeToWrite(position, sizeOfType);
819
820             unsafe {
821                 byte* pointer = null;
822                 RuntimeHelpers.PrepareConstrainedRegions();
823                 try {
824                     _buffer.AcquirePointer(ref pointer);
825                     pointer += (_offset + position);
826 #if ALIGN_ACCESS
827                     // check if pointer is aligned
828                     if (((int)pointer & (sizeOfType - 1)) == 0) {
829 #endif
830                     *((Single*)pointer) = value;
831 #if ALIGN_ACCESS
832                     }
833                     else {
834                     UInt32 tmpValue = *(UInt32*)&value;
835                     *(pointer) = (byte)tmpValue;
836                     *(pointer + 1) = (byte)(tmpValue >> 8);
837                     *(pointer + 2) = (byte)(tmpValue >> 16);
838                     *(pointer + 3) = (byte)(tmpValue >> 24);
839
840                     }
841 #endif
842                 }
843                 finally {
844                     if (pointer != null) {
845                         _buffer.ReleasePointer();
846                     }
847                 }
848             }
849         }
850
851         [System.Security.SecuritySafeCritical]  // auto-generated
852         public void Write(Int64 position, Double value) {
853             int sizeOfType = sizeof(Double);
854             EnsureSafeToWrite(position, sizeOfType);
855
856             unsafe {
857                 byte* pointer = null;
858                 RuntimeHelpers.PrepareConstrainedRegions();
859                 try {
860                     _buffer.AcquirePointer(ref pointer);
861                     pointer += (_offset + position);
862 #if ALIGN_ACCESS
863                     // check if pointer is aligned
864                     if (((int)pointer & (sizeOfType - 1)) == 0) {
865 #endif
866                     *((Double*)pointer) = value;
867 #if ALIGN_ACCESS
868                     }
869                     else {
870                     UInt64 tmpValue = *(UInt64 *)&value;
871                     *(pointer) = (byte) tmpValue;
872                     *(pointer + 1) = (byte) (tmpValue >> 8);
873                     *(pointer + 2) = (byte) (tmpValue >> 16);
874                     *(pointer + 3) = (byte) (tmpValue >> 24);
875                     *(pointer + 4) = (byte) (tmpValue >> 32);
876                     *(pointer + 5) = (byte) (tmpValue >> 40);
877                     *(pointer + 6) = (byte) (tmpValue >> 48);
878                     *(pointer + 7) = (byte) (tmpValue >> 56);
879
880                     }
881 #endif
882                 }
883                 finally {
884                     if (pointer != null) {
885                         _buffer.ReleasePointer();
886                     }
887                 }
888             }
889         }
890
891         [System.Security.SecuritySafeCritical]  // auto-generated
892         [CLSCompliant(false)]
893         public void Write(Int64 position, SByte value) {
894             int sizeOfType = sizeof(SByte);
895             EnsureSafeToWrite(position, sizeOfType);
896
897             unsafe {
898                 byte* pointer = null;
899                 RuntimeHelpers.PrepareConstrainedRegions();
900                 try {
901                     _buffer.AcquirePointer(ref pointer);
902                     pointer += (_offset + position);
903                     *((SByte*)pointer) = value;
904                 }
905                 finally {
906                     if (pointer != null) {
907                         _buffer.ReleasePointer();
908                     }
909                 }
910             }
911         }
912
913         [System.Security.SecuritySafeCritical]  // auto-generated
914         [CLSCompliant(false)]
915         public void Write(Int64 position, UInt16 value) {
916             int sizeOfType = sizeof(UInt16);
917             EnsureSafeToWrite(position, sizeOfType);
918
919             unsafe {
920                 byte* pointer = null;
921                 RuntimeHelpers.PrepareConstrainedRegions();
922                 try {
923                     _buffer.AcquirePointer(ref pointer);
924                     pointer += (_offset + position);
925
926 #if ALIGN_ACCESS
927                     // check if pointer is aligned
928                     if (((int)pointer & (sizeOfType - 1)) == 0) {
929 #endif
930                     *((UInt16*)pointer) = value;
931 #if ALIGN_ACCESS
932                     }
933                     else {
934                         *(pointer) = (byte)value;
935                         *(pointer + 1) = (byte)(value >> 8);
936                     }
937 #endif
938                 }
939                 finally {
940                     if (pointer != null) {
941                         _buffer.ReleasePointer();
942                     }
943                 }
944             }
945         }
946
947         [System.Security.SecuritySafeCritical]  // auto-generated
948         [CLSCompliant(false)]
949         public void Write(Int64 position, UInt32 value) {
950             int sizeOfType = sizeof(UInt32);
951             EnsureSafeToWrite(position, sizeOfType);
952
953             unsafe {
954                 byte* pointer = null;
955                 RuntimeHelpers.PrepareConstrainedRegions();
956                 try {
957                     _buffer.AcquirePointer(ref pointer);
958                     pointer += (_offset + position);
959
960 #if ALIGN_ACCESS
961                     // check if pointer is aligned
962                     if (((int)pointer & (sizeOfType - 1)) == 0) {
963 #endif
964                     *((UInt32*)pointer) = value;
965 #if ALIGN_ACCESS
966                     }
967                     else {
968                         *(pointer) = (byte)value;
969                         *(pointer + 1) = (byte)(value >> 8);
970                         *(pointer + 2) = (byte)(value >> 16);
971                         *(pointer + 3) = (byte)(value >> 24);
972                     }
973 #endif
974
975                 }
976                 finally {
977                     if (pointer != null) {
978                         _buffer.ReleasePointer();
979                     }
980                 }
981             }
982         }
983
984         [System.Security.SecuritySafeCritical]  // auto-generated
985         [CLSCompliant(false)]
986         public void Write(Int64 position, UInt64 value) {
987             int sizeOfType = sizeof(UInt64);
988             EnsureSafeToWrite(position, sizeOfType);
989
990             unsafe {
991                 byte* pointer = null;
992                 RuntimeHelpers.PrepareConstrainedRegions();
993                 try {
994                     _buffer.AcquirePointer(ref pointer);
995                     pointer += (_offset + position);
996 #if ALIGN_ACCESS
997                     // check if pointer is aligned
998                     if (((int)pointer & (sizeOfType - 1)) == 0) {
999 #endif
1000                     *((UInt64*)pointer) = value;
1001 #if ALIGN_ACCESS
1002                     }
1003                     else {
1004                         *(pointer) = (byte)value;
1005                         *(pointer + 1) = (byte)(value >> 8);
1006                         *(pointer + 2) = (byte)(value >> 16);
1007                         *(pointer + 3) = (byte)(value >> 24);
1008                         *(pointer + 4) = (byte)(value >> 32);
1009                         *(pointer + 5) = (byte)(value >> 40);
1010                         *(pointer + 6) = (byte)(value >> 48);
1011                         *(pointer + 7) = (byte)(value >> 56);
1012                     }
1013 #endif
1014
1015                 }
1016                 finally {
1017                     if (pointer != null) {
1018                         _buffer.ReleasePointer();
1019                     }
1020                 }
1021             }
1022         }
1023
1024         // Writes the struct pointed to by ref value into unmanaged memory.  Note that this method
1025         // is most performant when used with medium to large sized structs (larger than 8 bytes 
1026         // though this is number is JIT and architecture dependent).   As such, it is best to use 
1027         // the WriteX methods for small standard types such as ints, longs, bools, etc.
1028
1029         [System.Security.SecurityCritical]  // auto-generated_required
1030         public void Write<T>(Int64 position, ref T structure) where T : struct {
1031             if (position < 0) {
1032                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1033             }
1034             Contract.EndContractBlock();
1035
1036             if (!_isOpen) {
1037                 throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
1038             }
1039             if (!CanWrite) {
1040                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing"));
1041             }
1042
1043             UInt32 sizeOfT = Marshal.SizeOfType(typeof(T));
1044             if (position > _capacity - sizeOfT) {
1045                 if (position >= _capacity) {
1046                     throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
1047                 }
1048                 else {
1049                     throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", typeof(T).FullName), "position");
1050                 }
1051             }
1052
1053             _buffer.Write<T>((UInt64)(_offset + position), structure);
1054         }
1055
1056         // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory. 
1057
1058
1059         [System.Security.SecurityCritical]  // auto-generated_required
1060         public void WriteArray<T>(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct {
1061             if (array == null) {
1062                 throw new ArgumentNullException("array", "Buffer cannot be null.");
1063             }
1064             if (offset < 0) {
1065                 throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1066             }
1067             if (count < 0) {
1068                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1069             }
1070             if (array.Length - offset < count) {
1071                 throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndLengthOutOfBounds"));
1072             }
1073             if (position < 0) {
1074                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1075             }
1076             if (position >= Capacity) {
1077                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
1078             }
1079             Contract.EndContractBlock();
1080
1081             if (!_isOpen) {
1082                 throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
1083             }
1084             if (!CanWrite) {
1085                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing"));
1086             }
1087
1088             _buffer.WriteArray<T>((UInt64)(_offset + position), array, offset, count);
1089         }
1090
1091         [System.Security.SecuritySafeCritical]  // auto-generated
1092         private byte InternalReadByte(Int64 position) {
1093             Contract.Assert(CanRead, "UMA not readable");
1094             Contract.Assert(position >= 0, "position less than 0");
1095             Contract.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
1096
1097             byte result;
1098             unsafe {
1099                 byte* pointer = null;
1100                 RuntimeHelpers.PrepareConstrainedRegions();
1101                 try {
1102                     _buffer.AcquirePointer(ref pointer);
1103                     result = *((byte*)(pointer + _offset + position));
1104                 }
1105                 finally {
1106                     if (pointer != null) {
1107                         _buffer.ReleasePointer();
1108                     }
1109                 }
1110             }
1111             return result;
1112         }
1113
1114         [System.Security.SecuritySafeCritical]  // auto-generated
1115         private void InternalWrite(Int64 position, byte value) {
1116             Contract.Assert(CanWrite, "UMA not writeable");
1117             Contract.Assert(position >= 0, "position less than 0");
1118             Contract.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
1119
1120             unsafe {
1121                 byte* pointer = null;
1122                 RuntimeHelpers.PrepareConstrainedRegions();
1123                 try {
1124                     _buffer.AcquirePointer(ref pointer);
1125                     *((byte*)(pointer + _offset + position)) = value;
1126                 }
1127                 finally {
1128                     if (pointer != null) {
1129                         _buffer.ReleasePointer();
1130                     }
1131                 }
1132             }
1133         }
1134
1135         private void EnsureSafeToRead(Int64 position, int sizeOfType) {
1136             if (!_isOpen) {
1137                 throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
1138             }
1139             if (!CanRead) {
1140                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading"));
1141             }
1142             if (position < 0) {
1143                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1144             }
1145             Contract.EndContractBlock();
1146             if (position > _capacity - sizeOfType) {
1147                 if (position >= _capacity) {
1148                     throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
1149                 }
1150                 else {
1151                     throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead"), "position");
1152                 }
1153             }
1154         }
1155
1156         private void EnsureSafeToWrite(Int64 position, int sizeOfType) {
1157             if (!_isOpen) {
1158                 throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
1159             }
1160             if (!CanWrite) {
1161                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing"));
1162             }
1163             if (position < 0) {
1164                 throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1165             }
1166             Contract.EndContractBlock();
1167             if (position > _capacity - sizeOfType) {
1168                 if (position >= _capacity) {
1169                     throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
1170                 }
1171                 else {
1172                     throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", "Byte"), "position");
1173                 }
1174             }
1175         }
1176
1177     }
1178 }