2009-08-20 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System / System.Collections.Specialized / BitVector32.cs
1 //
2 // System.Collections.Specialized.BitVector32.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Lawrence Pit (loz@cable.a2000.nl)
7 //   Andrew Birkett (adb@tardis.ed.ac.uk)
8 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
9 //
10 // (C) Ximian, Inc.  http://www.ximian.com
11 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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.Text;
34
35 namespace System.Collections.Specialized {
36         
37         public struct BitVector32 {
38                 int bits;
39
40                 public struct Section {
41                         private short mask;
42                         private short offset;
43                         
44                         internal Section (short mask, short offset) {
45                                 this.mask = mask;
46                                 this.offset = offset;
47                         }
48                         
49                         public short Mask {
50                                 get { return mask; }
51                         }
52                         
53                         public short Offset {
54                                 get { return offset; }
55                         }
56 #if NET_2_0
57                         public static bool operator == (Section v1, Section v2)
58                         {
59                                 return v1.mask == v2.mask &&
60                                        v1.offset == v2.offset;
61                         }
62
63                         public static bool operator != (Section v1, Section v2)
64                         {
65                                 return v1.mask != v2.mask ||
66                                        v1.offset != v2.offset;
67                         }
68
69                         public bool Equals (Section obj)
70                         {
71                                 return this.mask == obj.mask &&
72                                        this.offset == obj.offset;
73                         }
74 #endif
75                         public override bool Equals (object o) 
76                         {
77                                 if (! (o is Section))
78                                         return false;
79
80                                 Section section = (Section) o;
81                                 return this.mask == section.mask &&
82                                        this.offset == section.offset;
83                         }                       
84
85                         public override int GetHashCode ()
86                         {
87                                 return mask << offset; 
88                         }
89                         
90                         public override string ToString ()
91                         {
92                                 return ToString (this); 
93                         }
94
95                         public static string ToString (Section value)
96                         {
97                                 StringBuilder b = new StringBuilder ();
98                                 b.Append ("Section{0x");
99                                 b.Append (Convert.ToString(value.Mask,16));
100                                 b.Append (", 0x");
101                                 b.Append (Convert.ToString(value.Offset,16));
102                                 b.Append ("}");
103
104                                 return b.ToString ();
105                         }
106                 }
107                 
108                 // Constructors
109                 
110                 public BitVector32 (BitVector32 source)
111                 {
112                         bits = source.bits;
113                 }
114
115                 public BitVector32 (int init)
116                 {
117                         bits = init;
118                 }
119                 
120                 // Properties
121                 
122                 public int Data {
123                         get { return bits; }
124                 }
125                 
126                 public int this [BitVector32.Section section] {
127                         get {
128                                 return ((bits >> section.Offset) & section.Mask);
129                         }
130
131                         set {
132                                 if (value < 0)
133                                         throw new ArgumentException ("Section can't hold negative values");
134                                 if (value > section.Mask)
135                                         throw new ArgumentException ("Value too large to fit in section");
136                                 bits &= ~(section.Mask << section.Offset);
137                                 bits |= (value << section.Offset);
138                         }
139                 }
140                 
141                 public bool this [int mask] {
142                         get {
143 #if NET_2_0
144                                 return (bits & mask) == mask;
145 #else
146                                 long tmp = (uint)bits;
147                                 return (tmp & (long)mask) == (long)mask;
148 #endif
149                         }
150                         
151                         set { 
152                                 if (value)
153                                         bits |= mask;
154                                 else
155                                         bits &= ~mask;
156                         }
157                 }
158                 
159                 // Methods
160                 
161                 public static int CreateMask ()
162                 {
163                         return 1;
164                 }
165
166                 public static int CreateMask (int prev)
167                 {
168                         if (prev == 0)
169                                 return 1;
170                         if (prev == Int32.MinValue) 
171                                 throw new InvalidOperationException ("all bits set");
172                         return prev << 1;
173                 }
174
175                 public static Section CreateSection (short maxValue)
176                 {
177                         return CreateSection (maxValue, new Section (0, 0));
178                 }
179                 
180                 public static Section CreateSection (short maxValue, BitVector32.Section previous)
181                 {
182                         if (maxValue < 1)
183                                 throw new ArgumentException ("maxValue");
184                         
185                         int bit = HighestSetBit(maxValue);
186                         int mask = (1 << bit) - 1;
187                         int offset = previous.Offset + HighestSetBit (previous.Mask);
188
189                         if (offset + bit > 32) {
190                                 throw new ArgumentException ("Sections cannot exceed 32 bits in total");
191                         }
192
193                         return new Section ((short) mask, (short) offset);
194                 }
195                 
196                 public override bool Equals (object o)
197                 {
198                         return (o is BitVector32) && bits == ((BitVector32) o).bits;
199                 }
200
201                 public override int GetHashCode ()
202                 {
203                         return bits.GetHashCode ();
204                 }
205                 
206                 public override string ToString () 
207                 {
208                         return ToString (this);
209                 }
210                 
211                 public static string ToString (BitVector32 value)
212                 {
213                         StringBuilder b = new StringBuilder ();
214                         b.Append ("BitVector32{");
215                         long mask = (long) 0x80000000;
216                         while (mask > 0) {
217                                 b.Append (((value.bits & mask) == 0) ? '0' : '1');
218                                 mask >>= 1;
219                         }
220                         b.Append ('}');
221                         return b.ToString ();
222                 }
223
224                 // Private utilities
225                 private static int HighestSetBit (int i) 
226                 {
227                         int count = 0;
228                         while(i >> count != 0)
229                                 count++;
230                         return count;
231                 }
232         }
233 }