2 // System.BitConverter.cs
5 // Matt Kimball (matt@kimball.net)
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 public static readonly bool IsLittleEndian = AmILittleEndian ();
40 static unsafe bool AmILittleEndian ()
42 // binary representations of 1.0:
43 // big endian: 3f f0 00 00 00 00 00 00
44 // little endian: 00 00 00 00 00 00 f0 3f
50 public unsafe static long DoubleToInt64Bits (double value)
52 return *(long *) &value;
55 public unsafe static double Int64BitsToDouble (long value)
57 return *(double *) &value;
60 unsafe static byte[] GetBytes (byte *ptr, int count)
62 byte [] ret = new byte [count];
64 for (int i = 0; i < count; i++) {
71 unsafe public static byte[] GetBytes (bool value)
73 return GetBytes ((byte *) &value, 1);
76 unsafe public static byte[] GetBytes (char value)
78 return GetBytes ((byte *) &value, 2);
81 unsafe public static byte[] GetBytes (short value)
83 return GetBytes ((byte *) &value, 2);
86 unsafe public static byte[] GetBytes (int value)
88 return GetBytes ((byte *) &value, 4);
91 unsafe public static byte[] GetBytes (long value)
93 return GetBytes ((byte *) &value, 8);
96 [CLSCompliant (false)]
97 unsafe public static byte[] GetBytes (ushort value)
99 return GetBytes ((byte *) &value, 2);
102 [CLSCompliant (false)]
103 unsafe public static byte[] GetBytes (uint value)
105 return GetBytes ((byte *) &value, 4);
108 [CLSCompliant (false)]
109 unsafe public static byte[] GetBytes (ulong value)
111 return GetBytes ((byte *) &value, 8);
114 unsafe public static byte[] GetBytes (float value)
116 return GetBytes ((byte *) &value, 4);
119 unsafe public static byte[] GetBytes (double value)
121 return GetBytes ((byte *) &value, 8);
124 unsafe static void PutBytes (byte *dst, byte[] src, int start_index, int count)
127 throw new ArgumentNullException ("value");
129 if (start_index < 0 || (start_index > src.Length - 1))
130 throw new ArgumentOutOfRangeException ("startIndex", "Index was"
131 + " out of range. Must be non-negative and less than the"
132 + " size of the collection.");
134 // avoid integer overflow (with large pos/neg start_index values)
135 if (src.Length - count < start_index)
136 throw new ArgumentException ("Destination array is not long"
137 + " enough to copy all the items in the collection."
138 + " Check array index and length.");
140 for (int i = 0; i < count; i++)
141 dst[i] = src[i + start_index];
144 unsafe public static bool ToBoolean (byte[] value, int startIndex)
147 throw new ArgumentNullException ("value");
149 if (startIndex < 0 || (startIndex > value.Length - 1))
150 throw new ArgumentOutOfRangeException ("startIndex", "Index was"
151 + " out of range. Must be non-negative and less than the"
152 + " size of the collection.");
154 if (value [startIndex] != 0)
160 unsafe public static char ToChar (byte[] value, int startIndex)
164 PutBytes ((byte *) &ret, value, startIndex, 2);
169 unsafe public static short ToInt16 (byte[] value, int startIndex)
173 PutBytes ((byte *) &ret, value, startIndex, 2);
178 unsafe public static int ToInt32 (byte[] value, int startIndex)
182 PutBytes ((byte *) &ret, value, startIndex, 4);
187 unsafe public static long ToInt64 (byte[] value, int startIndex)
191 PutBytes ((byte *) &ret, value, startIndex, 8);
196 [CLSCompliant (false)]
197 unsafe public static ushort ToUInt16 (byte[] value, int startIndex)
201 PutBytes ((byte *) &ret, value, startIndex, 2);
206 [CLSCompliant (false)]
207 unsafe public static uint ToUInt32 (byte[] value, int startIndex)
211 PutBytes ((byte *) &ret, value, startIndex, 4);
216 [CLSCompliant (false)]
217 unsafe public static ulong ToUInt64 (byte[] value, int startIndex)
221 PutBytes ((byte *) &ret, value, startIndex, 8);
226 unsafe public static float ToSingle (byte[] value, int startIndex)
230 PutBytes ((byte *) &ret, value, startIndex, 4);
235 unsafe public static double ToDouble (byte[] value, int startIndex)
239 PutBytes ((byte *) &ret, value, startIndex, 8);
244 public static string ToString (byte[] value)
247 throw new ArgumentNullException ("value");
249 return ToString (value, 0, value.Length);
252 public static string ToString (byte[] value, int startIndex)
255 throw new ArgumentNullException ("value");
257 return ToString (value, startIndex, value.Length - startIndex);
260 public static string ToString (byte[] value, int startIndex, int length)
263 throw new ArgumentNullException ("byteArray");
265 // The 4th and last clause (start_index >= value.Length)
266 // was added as a small fix to a very obscure bug.
267 // It makes a small difference when start_index is
268 // outside the range and length==0.
269 if (startIndex < 0 || startIndex >= value.Length) {
270 // special (but valid) case (e.g. new byte [0])
271 if ((startIndex == 0) && (value.Length == 0))
273 throw new ArgumentOutOfRangeException ("startIndex", "Index was"
274 + " out of range. Must be non-negative and less than the"
275 + " size of the collection.");
279 throw new ArgumentOutOfRangeException ("length",
280 "Value must be positive.");
282 // note: re-ordered to avoid possible integer overflow
283 if (startIndex > value.Length - length)
284 throw new ArgumentException ("startIndex + length > value.Length");
289 StringBuilder builder = new StringBuilder(length * 3 - 1);
290 int end = startIndex + length;
292 for (int i = startIndex; i < end; i++) {
296 char high = (char)((value[i] >> 4) & 0x0f);
297 char low = (char)(value[i] & 0x0f);
312 builder.Append(high);
316 return builder.ToString ();