2002-06-27 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / class / corlib / System / BitConverter.cs
1 //
2 // System.BitConverter
3 //
4 // Author:
5 //   Matt Kimball (matt@kimball.net)
6 //
7
8 using System;
9
10 namespace System {
11         public sealed class BitConverter {
12
13                 private BitConverter () {}
14
15                 static bool AmILittleEndian()
16                 {
17                         byte[] one = GetBytes((int)1);
18                         return (one[0] == 1);
19                 }
20
21                 public static readonly bool IsLittleEndian = AmILittleEndian ();
22
23                 public static long DoubleToInt64Bits(double value)
24                 {
25                         return ToInt64(GetBytes(value), 0);
26                 }
27
28                 public static double Int64BitsToDouble(long value)
29                 {
30                         return ToDouble(GetBytes(value), 0);
31                 }
32
33                 unsafe static byte[] GetBytes(byte *ptr, int count)
34                 {
35                         byte[] ret = new byte[count];
36
37                         for (int i = 0; i < count; i++) {
38                                 ret[i] = ptr[i];
39                         }
40
41                         return ret;
42                 }
43
44                 unsafe public static byte[] GetBytes(bool value)
45                 {
46                         return GetBytes((byte *)&value, 1);
47                 }
48
49                 unsafe public static byte[] GetBytes(char value)
50                 {
51                         return GetBytes((byte *)&value, 2);
52                 }
53
54                 unsafe public static byte[] GetBytes(short value)
55                 {
56                         return GetBytes((byte *)&value, 2);
57                 }
58
59                 unsafe public static byte[] GetBytes(int value)
60                 {
61                         return GetBytes((byte *)&value, 4);
62                 }
63
64                 unsafe public static byte[] GetBytes(long value)
65                 {
66                         return GetBytes((byte *)&value, 8);
67                 }
68
69                 [CLSCompliant(false)]
70                 unsafe public static byte[] GetBytes(ushort value)
71                 {
72                         return GetBytes((byte *)&value, 2);
73                 }
74
75                 [CLSCompliant(false)]
76                 unsafe public static byte[] GetBytes(uint value)
77                 {
78                         return GetBytes((byte *)&value, 4);
79                 }
80
81                 [CLSCompliant(false)]
82                 unsafe public static byte[] GetBytes(ulong value)
83                 {
84                         return GetBytes((byte *)&value, 8);
85                 }
86
87                 unsafe public static byte[] GetBytes(float value)
88                 {
89                         return GetBytes((byte *)&value, 4);
90                 }
91
92                 unsafe public static byte[] GetBytes(double value)
93                 {
94                         return GetBytes((byte *)&value, 8);
95                 }
96
97                 unsafe static void PutBytes(byte *dst, byte[] src, int start_index, int count)
98                 {
99                         if (src == null) {
100                                 throw new ArgumentNullException();
101                         }
102
103                         if (src.Length < start_index + count) {
104                                 // LAMESPEC:
105                                 // the docs say it should be ArgumentOutOfRangeException, but
106                                 // the mscorlib throws an ArgumentException.
107                                 throw new ArgumentException();
108                         }
109
110                         for (int i = 0; i < count; i++) {
111                                 dst[i] = src[i + start_index];
112                         }
113                 }
114
115                 unsafe public static bool ToBoolean(byte[] value, int start_index)
116                 {
117                         bool ret;
118
119                         PutBytes((byte *)&ret, value, start_index, 1);
120
121                         return ret;
122                 }
123
124                 unsafe public static char ToChar(byte[] value, int start_index)
125                 {
126                         char ret;
127
128                         PutBytes((byte *)&ret, value, start_index, 2);
129
130                         return ret;
131                 }
132
133                 unsafe public static short ToInt16(byte[] value, int start_index)
134                 {
135                         short ret;
136
137                         PutBytes((byte *)&ret, value, start_index, 2);
138
139                         return ret;
140                 }
141
142                 unsafe public static int ToInt32(byte[] value, int start_index)
143                 {
144                         int ret;
145
146                         PutBytes((byte *)&ret, value, start_index, 4);
147
148                         return ret;
149                 }
150
151                 unsafe public static long ToInt64(byte[] value, int start_index)
152                 {
153                         long ret;
154
155                         PutBytes((byte *)&ret, value, start_index, 8);
156
157                         return ret;
158                 }
159
160                 [CLSCompliant(false)]
161                 unsafe public static ushort ToUInt16(byte[] value, int start_index)
162                 {
163                         ushort ret;
164
165                         PutBytes((byte *)&ret, value, start_index, 2);
166
167                         return ret;
168                 }
169
170                 [CLSCompliant(false)]
171                 unsafe public static uint ToUInt32(byte[] value, int start_index)
172                 {
173                         uint ret;
174
175                         PutBytes((byte *)&ret, value, start_index, 4);
176
177                         return ret;
178                 }
179
180                 [CLSCompliant(false)]
181                 unsafe public static ulong ToUInt64(byte[] value, int start_index)
182                 {
183                         ulong ret;
184
185                         PutBytes((byte *)&ret, value, start_index, 8);
186
187                         return ret;
188                 }
189
190                 unsafe public static float ToSingle(byte[] value, int start_index)
191                 {
192                         float ret;
193
194                         PutBytes((byte *)&ret, value, start_index, 4);
195
196                         return ret;
197                 }
198
199                 unsafe public static double ToDouble(byte[] value, int start_index)
200                 {
201                         double ret;
202
203                         PutBytes((byte *)&ret, value, start_index, 8);
204
205                         return ret;
206                 }
207
208                 public static string ToString(byte[] value)
209                 {
210                         if (value == null) {
211                                 throw new ArgumentNullException();
212                         }
213
214                         return ToString(value, 0, value.Length);
215                 }
216
217                 public static string ToString(byte[] value, int start_index)
218                 {
219                         if (value == null)
220                                 throw new ArgumentNullException("value");
221                         if (start_index < 0 || start_index > value.Length - 1) 
222                                 throw new ArgumentOutOfRangeException("start_index");
223
224                         return ToString(value, start_index, value.Length - start_index);
225                 }
226
227                 public static string ToString(byte[] value, int start_index, int length)
228                 {
229                         if (value == null) {
230                                 throw new ArgumentNullException();
231                         }
232
233                         // The 4th and last clause (start_index >= value.Length)
234                         // was added as a small fix to a very obscure bug.
235                         // It makes a small difference when start_index is
236                         // outside the range and length==0. 
237                         if (start_index < 0 || length < 0 || start_index + length > value.Length || start_index >= value.Length) {
238                                 throw new ArgumentOutOfRangeException();
239                         }
240                         string ret = "";
241                         int end = start_index + length;
242
243                         for (int i = start_index; i < end; i++) {
244                                 if (i > start_index)
245                                         ret = ret + '-';
246                                 
247                                 char high = (char)((value[i] >> 4) & 0x0f);
248                                 char low = (char)(value[i] & 0x0f);
249
250                                 if (high < 10) 
251                                         high += '0';
252                                 else {
253                                         high -= (char) 10;
254                                         high += 'A';
255                                 }
256
257                                 if (low < 10)
258                                         low += '0';
259                                 else {
260                                         low -= (char) 10;
261                                         low += 'A';
262                                 }
263
264                                 ret = ret + high + low;
265                         }
266
267                         return ret;
268                 }
269         }
270 }