Merge pull request #2274 from esdrubal/udpclientreceive
[mono.git] / mcs / class / corlib / ReferenceSources / Buffer.cs
1 namespace System
2 {
3         partial class Buffer
4         {
5                 public static int ByteLength (Array array)
6                 {
7                         // note: the other methods in this class also use ByteLength to test for
8                         // null and non-primitive arguments as a side-effect.
9
10                         if (array == null)
11                                 throw new ArgumentNullException ("array");
12
13                         int length = _ByteLength (array);
14                         if (length < 0)
15                                 throw new ArgumentException (Locale.GetText ("Object must be an array of primitives."));
16
17                         return length;
18                 }
19
20                 public static byte GetByte (Array array, int index)
21                 {
22                         if (index < 0 || index >= ByteLength (array))
23                                 throw new ArgumentOutOfRangeException ("index");
24
25                         return _GetByte (array, index);
26                 }
27
28                 public static void SetByte (Array array, int index, byte value)
29                 {
30                         if (index < 0 || index >= ByteLength (array))
31                                 throw new ArgumentOutOfRangeException ("index");
32
33                         _SetByte (array, index, value);
34                 }
35
36                 public static void BlockCopy (Array src, int srcOffset, Array dst, int dstOffset, int count)
37                 {
38                         if (src == null)
39                                 throw new ArgumentNullException ("src");
40
41                         if (dst == null)
42                                 throw new ArgumentNullException ("dst");
43
44                         if (srcOffset < 0)
45                                 throw new ArgumentOutOfRangeException ("srcOffset", Locale.GetText(
46                                         "Non-negative number required."));
47
48                         if (dstOffset < 0)
49                                 throw new ArgumentOutOfRangeException ("dstOffset", Locale.GetText (
50                                         "Non-negative number required."));
51
52                         if (count < 0)
53                                 throw new ArgumentOutOfRangeException ("count", Locale.GetText (
54                                         "Non-negative number required."));
55
56                         // We do the checks in unmanaged code for performance reasons
57                         bool res = InternalBlockCopy (src, srcOffset, dst, dstOffset, count);
58                         if (!res) {
59                                 // watch for integer overflow
60                                 if ((srcOffset > ByteLength (src) - count) || (dstOffset > ByteLength (dst) - count))
61                                         throw new ArgumentException (Locale.GetText (
62                                                 "Offset and length were out of bounds for the array or count is greater than " + 
63                                                 "the number of elements from index to the end of the source collection."));
64                         }
65                 }
66
67                 [CLSCompliantAttribute (false)]
68                 public static unsafe void MemoryCopy (void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy)
69                 {
70                         if (sourceBytesToCopy > destinationSizeInBytes) {
71                                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceBytesToCopy);
72                         }
73
74                         var src = (byte*)source;
75                         var dst = (byte*)destination;
76                         while (sourceBytesToCopy > int.MaxValue) {
77                                 Memcpy (dst, src, int.MaxValue);
78                                 sourceBytesToCopy -= int.MaxValue;
79                                 src += int.MaxValue;
80                                 dst += int.MaxValue;
81                         }
82
83                         memcpy1 (dst, src, (int) sourceBytesToCopy);
84                 }
85
86                 [CLSCompliantAttribute (false)]
87                 public static unsafe void MemoryCopy (void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy)
88                 {
89                         if (sourceBytesToCopy > destinationSizeInBytes) {
90                                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceBytesToCopy);
91                         }
92
93                         var src = (byte*)source;
94                         var dst = (byte*)destination;
95                         while (sourceBytesToCopy > int.MaxValue) {
96                                 Memcpy (dst, src, int.MaxValue);
97                                 sourceBytesToCopy -= int.MaxValue;
98                                 src += int.MaxValue;
99                                 dst += int.MaxValue;
100                         }
101
102                         Memcpy (dst, src, (int) sourceBytesToCopy);
103                 }
104
105                 internal static unsafe void memcpy4 (byte *dest, byte *src, int size) {
106                         /*while (size >= 32) {
107                                 // using long is better than int and slower than double
108                                 // FIXME: enable this only on correct alignment or on platforms
109                                 // that can tolerate unaligned reads/writes of doubles
110                                 ((double*)dest) [0] = ((double*)src) [0];
111                                 ((double*)dest) [1] = ((double*)src) [1];
112                                 ((double*)dest) [2] = ((double*)src) [2];
113                                 ((double*)dest) [3] = ((double*)src) [3];
114                                 dest += 32;
115                                 src += 32;
116                                 size -= 32;
117                         }*/
118                         while (size >= 16) {
119                                 ((int*)dest) [0] = ((int*)src) [0];
120                                 ((int*)dest) [1] = ((int*)src) [1];
121                                 ((int*)dest) [2] = ((int*)src) [2];
122                                 ((int*)dest) [3] = ((int*)src) [3];
123                                 dest += 16;
124                                 src += 16;
125                                 size -= 16;
126                         }
127                         while (size >= 4) {
128                                 ((int*)dest) [0] = ((int*)src) [0];
129                                 dest += 4;
130                                 src += 4;
131                                 size -= 4;
132                         }
133                         while (size > 0) {
134                                 ((byte*)dest) [0] = ((byte*)src) [0];
135                                 dest += 1;
136                                 src += 1;
137                                 --size;
138                         }
139                 }
140                 internal static unsafe void memcpy2 (byte *dest, byte *src, int size) {
141                         while (size >= 8) {
142                                 ((short*)dest) [0] = ((short*)src) [0];
143                                 ((short*)dest) [1] = ((short*)src) [1];
144                                 ((short*)dest) [2] = ((short*)src) [2];
145                                 ((short*)dest) [3] = ((short*)src) [3];
146                                 dest += 8;
147                                 src += 8;
148                                 size -= 8;
149                         }
150                         while (size >= 2) {
151                                 ((short*)dest) [0] = ((short*)src) [0];
152                                 dest += 2;
153                                 src += 2;
154                                 size -= 2;
155                         }
156                         if (size > 0)
157                                 ((byte*)dest) [0] = ((byte*)src) [0];
158                 }
159                 static unsafe void memcpy1 (byte *dest, byte *src, int size) {
160                         while (size >= 8) {
161                                 ((byte*)dest) [0] = ((byte*)src) [0];
162                                 ((byte*)dest) [1] = ((byte*)src) [1];
163                                 ((byte*)dest) [2] = ((byte*)src) [2];
164                                 ((byte*)dest) [3] = ((byte*)src) [3];
165                                 ((byte*)dest) [4] = ((byte*)src) [4];
166                                 ((byte*)dest) [5] = ((byte*)src) [5];
167                                 ((byte*)dest) [6] = ((byte*)src) [6];
168                                 ((byte*)dest) [7] = ((byte*)src) [7];
169                                 dest += 8;
170                                 src += 8;
171                                 size -= 8;
172                         }
173                         while (size >= 2) {
174                                 ((byte*)dest) [0] = ((byte*)src) [0];
175                                 ((byte*)dest) [1] = ((byte*)src) [1];
176                                 dest += 2;
177                                 src += 2;
178                                 size -= 2;
179                         }
180                         if (size > 0)
181                                 ((byte*)dest) [0] = ((byte*)src) [0];
182                 }
183
184                 internal static unsafe void Memcpy (byte *dest, byte *src, int size) {
185                         // FIXME: if pointers are not aligned, try to align them
186                         // so a faster routine can be used. Handle the case where
187                         // the pointers can't be reduced to have the same alignment
188                         // (just ignore the issue on x86?)
189                         if ((((int)dest | (int)src) & 3) != 0) {
190                                 if (((int)dest & 1) != 0 && ((int)src & 1) != 0 && size >= 1) {
191                                         dest [0] = src [0];
192                                         ++dest;
193                                         ++src;
194                                         --size;
195                                 }
196                                 if (((int)dest & 2) != 0 && ((int)src & 2) != 0 && size >= 2) {
197                                         ((short*)dest) [0] = ((short*)src) [0];
198                                         dest += 2;
199                                         src += 2;
200                                         size -= 2;
201                                 }
202                                 if ((((int)dest | (int)src) & 1) != 0) {
203                                         memcpy1 (dest, src, size);
204                                         return;
205                                 }
206                                 if ((((int)dest | (int)src) & 2) != 0) {
207                                         memcpy2 (dest, src, size);
208                                         return;
209                                 }
210                         }
211                         memcpy4 (dest, src, size);
212                 }
213         }
214 }