Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / corlib / System / ArraySegment.cs
1 //
2 // ArraySegment.cs
3 //
4 // Authors:
5 //  Ben Maurer (bmaurer@ximian.com)
6 //  Jensen Somers <jensen.somers@gmail.com>
7 //  Marek Safar (marek.safar@gmail.com)
8 //
9 // Copyright (C) 2004 Novell
10 // Copyright (C) 2012 Xamarin, Inc (http://www.xamarin.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections;
33 using System.Collections.Generic;
34
35 namespace System
36 {
37         [Serializable]
38         public struct ArraySegment<T>
39 #if NET_4_5
40                 : IList<T>, IReadOnlyList<T>
41 #endif
42         {
43                 T [] array;
44                 readonly int offset, count;
45                 
46                 public ArraySegment (T [] array, int offset, int count)
47                 {
48                         if (array == null)
49                                 throw new ArgumentNullException ("array");
50                         
51                         if (offset < 0)
52                                 throw new ArgumentOutOfRangeException ("offset", "Non-negative number required.");
53
54                         if (count < 0)
55                                 throw new ArgumentOutOfRangeException ("count", "Non-negative number required.");
56
57                         if (offset > array.Length)
58                                 throw new ArgumentException ("out of bounds");
59
60                         // now offset is valid, or just beyond the end.
61                         // Check count -- do it this way to avoid overflow on 'offset + count'
62                         if (array.Length - offset < count)
63                                 throw new ArgumentException ("out of bounds", "offset");
64                         
65                         this.array = array;
66                         this.offset = offset;
67                         this.count = count;
68                 }
69                 
70                 public ArraySegment (T [] array)
71                 {
72                         if (array == null)
73                                 throw new ArgumentNullException ("array");
74                         
75                         this.array = array;
76                         this.offset = 0;
77                         this.count = array.Length;
78                 }
79                 
80                 public T [] Array {
81                         get { return array; }
82                 }
83                 
84                 public int Offset {
85                         get { return offset; }
86                 }
87                 
88                 public int Count {
89                         get { return count; }
90                 }
91                 
92                 public override bool Equals (Object obj)
93                 {
94                         if (obj is ArraySegment<T>) {
95                                 return this.Equals((ArraySegment<T>) obj);
96                         }
97                         return false;
98                 }
99                 
100                 public bool Equals (ArraySegment<T> obj)
101                 {
102                         if ((this.array == obj.Array) && (this.offset == obj.Offset) && (this.count == obj.Count))
103                                 return true;
104                         return false;
105                 }
106                 
107                 public override int GetHashCode ()
108                 {
109                         return ((this.array.GetHashCode() ^ this.offset) ^ this.count);
110                 }
111                 
112                 public static bool operator ==(ArraySegment<T> a, ArraySegment<T> b)
113                 {
114                         return a.Equals(b);
115                 }
116                 
117                 public static bool operator !=(ArraySegment<T> a, ArraySegment<T> b)
118                 {
119                         return !(a.Equals(b));
120                 }
121
122 #if NET_4_5
123                 bool ICollection<T>.IsReadOnly {
124                         get {
125                                 return true;
126                         }
127                 }
128
129                 T IReadOnlyList<T>.this[int index] {
130                         get {
131                                 return ((IList<T>) this)[index];
132                         }
133                 }
134
135                 T IList<T>.this[int index] {
136                         get {
137                                 if (index < 0 || count < index)
138                                         throw new ArgumentOutOfRangeException ("index");
139
140                                 return array[offset + index];
141                         }
142                         set {
143                                 if (index < 0 || count < index)
144                                         throw new ArgumentOutOfRangeException ("index");
145
146                                 array[offset + index] = value;
147                         }
148                 }
149
150                 void ICollection<T>.Add (T item)
151                 {
152                         throw new NotSupportedException ();
153                 }
154
155                 void ICollection<T>.Clear ()
156                 {
157                         throw new NotSupportedException ();
158                 }
159                 
160                 bool ICollection<T>.Remove (T item)
161                 {
162                         throw new NotSupportedException ();
163                 }
164                 
165                 void IList<T>.Insert (int index, T item)
166                 {
167                         throw new NotSupportedException ();
168                 }
169
170                 void IList<T>.RemoveAt (int index)
171                 {
172                         throw new NotSupportedException ();
173                 }
174
175                 bool ICollection<T>.Contains (T item)
176                 {
177                         return System.Array.IndexOf (array, item, offset, count) >= 0;
178                 }
179
180                 void ICollection<T>.CopyTo (T[] array, int arrayIndex)
181                 {
182                         System.Array.Copy (this.array, offset, array, arrayIndex, count);
183                 }
184
185                 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
186                 {
187                         for (int i = 0; i < count; ++i)
188                                 yield return array[offset + i];
189                 }
190
191                 IEnumerator IEnumerable.GetEnumerator ()
192                 {
193                         return ((IEnumerable<T>) this).GetEnumerator ();
194                 }
195
196                 int IList<T>.IndexOf (T item)
197                 {
198                         var res = System.Array.IndexOf (array, item, offset, count);
199                         return res < 0 ? -1 : res - offset;
200                 }
201
202 #endif
203         }
204 }