[runtime] Move pending_exception from InternalThread to Thread to avoid crashing...
[mono.git] / mcs / class / corlib / Mono / DataConverter.cs
1 //
2 // Authors:
3 //   Miguel de Icaza (miguel@novell.com)
4 //
5 // See the following url for documentation:
6 //     http://www.mono-project.com/Mono_DataConvert
7 //
8 // Compilation Options:
9 //     MONO_DATACONVERTER_PUBLIC:
10 //         Makes the class public instead of the default internal.
11 //
12 //     MONO_DATACONVERTER_STATIC_METHODS:     
13 //         Exposes the public static methods.
14 //
15 // TODO:
16 //   Support for "DoubleWordsAreSwapped" for ARM devices
17 //
18 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
19 //
20 // Permission is hereby granted, free of charge, to any person obtaining
21 // a copy of this software and associated documentation files (the
22 // "Software"), to deal in the Software without restriction, including
23 // without limitation the rights to use, copy, modify, merge, publish,
24 // distribute, sublicense, and/or sell copies of the Software, and to
25 // permit persons to whom the Software is furnished to do so, subject to
26 // the following conditions:
27 // 
28 // The above copyright notice and this permission notice shall be
29 // included in all copies or substantial portions of the Software.
30 // 
31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 //
39 using System;
40 using System.Collections;
41 using System.Text;
42 using System.Collections.Generic;
43
44 #pragma warning disable 3021
45
46 namespace Mono {
47
48 #if MONO_DATACONVERTER_PUBLIC
49         public
50 #endif
51         unsafe abstract class DataConverter {
52
53 // Disables the warning: CLS compliance checking will not be performed on
54 //  `XXXX' because it is not visible from outside this assembly
55 #pragma warning disable  3019
56                 static readonly DataConverter SwapConv = new SwapConverter ();
57                 static readonly DataConverter CopyConv = new CopyConverter ();
58
59                 public static readonly bool IsLittleEndian = BitConverter.IsLittleEndian;
60                         
61                 public abstract double GetDouble (byte [] data, int index);
62                 public abstract float  GetFloat  (byte [] data, int index);
63                 public abstract long   GetInt64  (byte [] data, int index);
64                 public abstract int    GetInt32  (byte [] data, int index);
65
66                 public abstract short  GetInt16  (byte [] data, int index);
67
68                 [CLSCompliant (false)]
69                 public abstract uint   GetUInt32 (byte [] data, int index);
70                 [CLSCompliant (false)]
71                 public abstract ushort GetUInt16 (byte [] data, int index);
72                 [CLSCompliant (false)]
73                 public abstract ulong  GetUInt64 (byte [] data, int index);
74                 
75                 public abstract void PutBytes (byte [] dest, int destIdx, double value);
76                 public abstract void PutBytes (byte [] dest, int destIdx, float value);
77                 public abstract void PutBytes (byte [] dest, int destIdx, int value);
78                 public abstract void PutBytes (byte [] dest, int destIdx, long value);
79                 public abstract void PutBytes (byte [] dest, int destIdx, short value);
80
81                 [CLSCompliant (false)]
82                 public abstract void PutBytes (byte [] dest, int destIdx, ushort value);
83                 [CLSCompliant (false)]
84                 public abstract void PutBytes (byte [] dest, int destIdx, uint value);
85                 [CLSCompliant (false)]
86                 public abstract void PutBytes (byte [] dest, int destIdx, ulong value);
87
88                 public byte[] GetBytes (double value)
89                 {
90                         byte [] ret = new byte [8];
91                         PutBytes (ret, 0, value);
92                         return ret;
93                 }
94                 
95                 public byte[] GetBytes (float value)
96                 {
97                         byte [] ret = new byte [4];
98                         PutBytes (ret, 0, value);
99                         return ret;
100                 }
101                 
102                 public byte[] GetBytes (int value)
103                 {
104                         byte [] ret = new byte [4];
105                         PutBytes (ret, 0, value);
106                         return ret;
107                 }
108                 
109                 public byte[] GetBytes (long value)
110                 {
111                         byte [] ret = new byte [8];
112                         PutBytes (ret, 0, value);
113                         return ret;
114                 }
115                 
116                 public byte[] GetBytes (short value)
117                 {
118                         byte [] ret = new byte [2];
119                         PutBytes (ret, 0, value);
120                         return ret;
121                 }
122
123                 [CLSCompliant (false)]
124                 public byte[] GetBytes (ushort value)
125                 {
126                         byte [] ret = new byte [2];
127                         PutBytes (ret, 0, value);
128                         return ret;
129                 }
130                 
131                 [CLSCompliant (false)]
132                 public byte[] GetBytes (uint value)
133                 {
134                         byte [] ret = new byte [4];
135                         PutBytes (ret, 0, value);
136                         return ret;
137                 }
138                 
139                 [CLSCompliant (false)]
140                 public byte[] GetBytes (ulong value)
141                 {
142                         byte [] ret = new byte [8];
143                         PutBytes (ret, 0, value);
144                         return ret;
145                 }
146                 
147                 static public DataConverter LittleEndian {
148                         get {
149                                 return BitConverter.IsLittleEndian ? CopyConv : SwapConv;
150                         }
151                 }
152
153                 static public DataConverter BigEndian {
154                         get {
155                                 return BitConverter.IsLittleEndian ? SwapConv : CopyConv;
156                         }
157                 }
158
159                 static public DataConverter Native {
160                         get {
161                                 return CopyConv;
162                         }
163                 }
164
165                 static int Align (int current, int align)
166                 {
167                         return ((current + align - 1) / align) * align;
168                 }
169                         
170                 class PackContext {
171                         // Buffer
172                         public byte [] buffer;
173                         int next;
174
175                         public string description;
176                         public int i; // position in the description
177                         public DataConverter conv;
178                         public int repeat;
179                         
180                         //
181                         // if align == -1, auto align to the size of the byte array
182                         // if align == 0, do not do alignment
183                         // Any other values aligns to that particular size
184                         //
185                         public int align;
186
187                         public void Add (byte [] group)
188                         {
189                                 //Console.WriteLine ("Adding {0} bytes to {1} (next={2}", group.Length,
190                                 // buffer == null ? "null" : buffer.Length.ToString (), next);
191                                 
192                                 if (buffer == null){
193                                         buffer = group;
194                                         next = group.Length;
195                                         return;
196                                 }
197                                 if (align != 0){
198                                         if (align == -1)
199                                                 next = Align (next, group.Length);
200                                         else
201                                                 next = Align (next, align);
202                                         align = 0;
203                                 }
204
205                                 if (next + group.Length > buffer.Length){
206                                         byte [] nb = new byte [System.Math.Max (next, 16) * 2 + group.Length];
207                                         Array.Copy (buffer, nb, buffer.Length);
208                                         Array.Copy (group, 0, nb, next, group.Length);
209                                         next = next + group.Length;
210                                         buffer = nb;
211                                 } else {
212                                         Array.Copy (group, 0, buffer, next, group.Length);
213                                         next += group.Length;
214                                 }
215                         }
216
217                         public byte [] Get ()
218                         {
219                                 if (buffer == null)
220                                         return new byte [0];
221                                 
222                                 if (buffer.Length != next){
223                                         byte [] b = new byte [next];
224                                         Array.Copy (buffer, b, next);
225                                         return b;
226                                 }
227                                 return buffer;
228                         }
229                 }
230
231                 //
232                 // Format includes:
233                 // Control:
234                 //   ^    Switch to big endian encoding
235                 //   _    Switch to little endian encoding
236                 //   %    Switch to host (native) encoding
237                 //   !    aligns the next data type to its natural boundary (for strings this is 4).
238                 //
239                 // Types:
240                 //   s    Int16
241                 //   S    UInt16
242                 //   i    Int32
243                 //   I    UInt32
244                 //   l    Int64
245                 //   L    UInt64
246                 //   f    float
247                 //   d    double
248                 //   b    byte
249                 //   c    1-byte signed character
250                 //   C    1-byte unsigned character
251                 //   z8   string encoded as UTF8 with 1-byte null terminator
252                 //   z6   string encoded as UTF16 with 2-byte null terminator
253                 //   z7   string encoded as UTF7 with 1-byte null terminator
254                 //   zb   string encoded as BigEndianUnicode with 2-byte null terminator
255                 //   z3   string encoded as UTF32 with 4-byte null terminator
256                 //   z4   string encoded as UTF32 big endian with 4-byte null terminator
257                 //   $8   string encoded as UTF8
258                 //   $6   string encoded as UTF16
259                 //   $7   string encoded as UTF7
260                 //   $b   string encoded as BigEndianUnicode
261                 //   $3   string encoded as UTF32
262                 //   $4   string encoded as UTF-32 big endian encoding
263                 //   x    null byte
264                 //
265                 // Repeats, these are prefixes:
266                 //   N    a number between 1 and 9, indicates a repeat count (process N items
267                 //        with the following datatype
268                 //   [N]  For numbers larger than 9, use brackets, for example [20]
269                 //   *    Repeat the next data type until the arguments are exhausted
270                 //
271                 static public byte [] Pack (string description, params object [] args)
272                 {
273                         int argn = 0;
274                         PackContext b = new PackContext ();
275                         b.conv = CopyConv;
276                         b.description = description;
277
278                         for (b.i = 0; b.i < description.Length; ){
279                                 object oarg;
280
281                                 if (argn < args.Length)
282                                         oarg = args [argn];
283                                 else {
284                                         if (b.repeat != 0)
285                                                 break;
286                                         
287                                         oarg = null;
288                                 }
289
290                                 int save = b.i;
291                                 
292                                 if (PackOne (b, oarg)){
293                                         argn++;
294                                         if (b.repeat > 0){
295                                                 if (--b.repeat > 0)
296                                                         b.i = save;
297                                                 else
298                                                         b.i++;
299                                         } else
300                                                 b.i++;
301                                 } else
302                                         b.i++;
303                         }
304                         return b.Get ();
305                 }
306
307                 static public byte [] PackEnumerable (string description, IEnumerable args)
308                 {
309                         PackContext b = new PackContext ();
310                         b.conv = CopyConv;
311                         b.description = description;
312                         
313                         IEnumerator enumerator = args.GetEnumerator ();
314                         bool ok = enumerator.MoveNext ();
315
316                         for (b.i = 0; b.i < description.Length; ){
317                                 object oarg;
318
319                                 if (ok)
320                                         oarg = enumerator.Current;
321                                 else {
322                                         if (b.repeat != 0)
323                                                 break;
324                                         oarg = null;
325                                 }
326                                                 
327                                 int save = b.i;
328                                 
329                                 if (PackOne (b, oarg)){
330                                         ok = enumerator.MoveNext ();
331                                         if (b.repeat > 0){
332                                                 if (--b.repeat > 0)
333                                                         b.i = save;
334                                                 else
335                                                         b.i++;
336                                         } else
337                                                 b.i++;
338                                 } else
339                                         b.i++;
340                         }
341                         return b.Get ();
342                 }
343                         
344                 //
345                 // Packs one datum `oarg' into the buffer `b', using the string format
346                 // in `description' at position `i'
347                 //
348                 // Returns: true if we must pick the next object from the list
349                 //
350                 static bool PackOne (PackContext b, object oarg)
351                 {
352                         int n;
353                         
354                         switch (b.description [b.i]){
355                         case '^':
356                                 b.conv = BigEndian;
357                                 return false;
358                         case '_':
359                                 b.conv = LittleEndian;
360                                 return false;
361                         case '%':
362                                 b.conv = Native;
363                                 return false;
364
365                         case '!':
366                                 b.align = -1;
367                                 return false;
368                                 
369                         case 'x':
370                                 b.Add (new byte [] { 0 });
371                                 return false;
372                                 
373                                 // Type Conversions
374                         case 'i':
375                                 b.Add (b.conv.GetBytes (Convert.ToInt32 (oarg)));
376                                 break;
377                                 
378                         case 'I':
379                                 b.Add (b.conv.GetBytes (Convert.ToUInt32 (oarg)));
380                                 break;
381                                 
382                         case 's':
383                                 b.Add (b.conv.GetBytes (Convert.ToInt16 (oarg)));
384                                 break;
385                                 
386                         case 'S':
387                                 b.Add (b.conv.GetBytes (Convert.ToUInt16 (oarg)));
388                                 break;
389                                 
390                         case 'l':
391                                 b.Add (b.conv.GetBytes (Convert.ToInt64 (oarg)));
392                                 break;
393                                 
394                         case 'L':
395                                 b.Add (b.conv.GetBytes (Convert.ToUInt64 (oarg)));
396                                 break;
397                                 
398                         case 'f':
399                                 b.Add (b.conv.GetBytes (Convert.ToSingle (oarg)));
400                                 break;
401                                 
402                         case 'd':
403                                 b.Add (b.conv.GetBytes (Convert.ToDouble (oarg)));
404                                 break;
405                                 
406                         case 'b':
407                                 b.Add (new byte [] { Convert.ToByte (oarg) });
408                                 break;
409
410                         case 'c':
411                                 b.Add (new byte [] { (byte) (Convert.ToSByte (oarg)) });
412                                 break;
413
414                         case 'C':
415                                 b.Add (new byte [] { Convert.ToByte (oarg) });
416                                 break;
417
418                                 // Repeat acount;
419                         case '1': case '2': case '3': case '4': case '5':
420                         case '6': case '7': case '8': case '9':
421                                 b.repeat = ((short) b.description [b.i]) - ((short) '0');
422                                 return false;
423
424                         case '*':
425                                 b.repeat = Int32.MaxValue;
426                                 return false;
427                                 
428                         case '[':
429                                 int count = -1, j;
430                                 
431                                 for (j = b.i+1; j < b.description.Length; j++){
432                                         if (b.description [j] == ']')
433                                                 break;
434                                         n = ((short) b.description [j]) - ((short) '0');
435                                         if (n >= 0 && n <= 9){
436                                                 if (count == -1)
437                                                         count = n;
438                                                 else
439                                                         count = count * 10 + n;
440                                         }
441                                 }
442                                 if (count == -1)
443                                         throw new ArgumentException ("invalid size specification");
444                                 b.i = j;
445                                 b.repeat = count;
446                                 return false;
447                                 
448                         case '$': case 'z':
449                                 bool add_null = b.description [b.i] == 'z';
450                                 b.i++;
451                                 if (b.i >= b.description.Length)
452                                         throw new ArgumentException ("$ description needs a type specified", "description");
453                                 char d = b.description [b.i];
454                                 Encoding e;
455                                 
456                                 switch (d){
457                                 case '8':
458                                         e = Encoding.UTF8;
459                                         n = 1;
460                                         break;
461                                 case '6':
462                                         e = Encoding.Unicode;
463                                         n = 2;
464                                         break;
465                                 case '7':
466 #if PCL
467                                         e = Encoding.GetEncoding ("utf-7");
468 #else
469                                         e = Encoding.UTF7;
470 #endif
471                                         n = 1;
472                                         break;
473                                 case 'b':
474                                         e = Encoding.BigEndianUnicode;
475                                         n = 2;
476                                         break;
477                                 case '3':
478 #if PCL
479                                         e = Encoding.GetEncoding ("utf-32");
480 #else
481                                         e = Encoding.GetEncoding (12000);
482 #endif
483                                         n = 4;
484                                         break;
485                                 case '4':
486 #if PCL
487                                         e = Encoding.GetEncoding ("utf-32BE");
488 #else
489                                         e = Encoding.GetEncoding (12001);
490 #endif
491                                         n = 4;
492                                         break;
493                                         
494                                 default:
495                                         throw new ArgumentException ("Invalid format for $ specifier", "description");
496                                 }
497                                 if (b.align == -1)
498                                         b.align = 4;
499                                 b.Add (e.GetBytes (Convert.ToString (oarg)));
500                                 if (add_null)
501                                         b.Add (new byte [n]);
502                                 break;
503                         default:
504                                 throw new ArgumentException (String.Format ("invalid format specified `{0}'",
505                                                                             b.description [b.i]));
506                         }
507                         return true;
508                 }
509
510                 static bool Prepare (byte [] buffer, ref int idx, int size, ref bool align)
511                 {
512                         if (align){
513                                 idx = Align (idx, size);
514                                 align = false;
515                         }
516                         if (idx + size > buffer.Length){
517                                 idx = buffer.Length;
518                                 return false;
519                         }
520                         return true;
521                 }
522                 
523                 static public IList Unpack (string description, byte [] buffer, int startIndex)
524                 {
525                         DataConverter conv = CopyConv;
526                         var result = new List<object> ();
527                         int idx = startIndex;
528                         bool align = false;
529                         int repeat = 0, n;
530                         
531                         for (int i = 0; i < description.Length && idx < buffer.Length; ){
532                                 int save = i;
533                                 
534                                 switch (description [i]){
535                                 case '^':
536                                         conv = BigEndian;
537                                         break;
538                                 case '_':
539                                         conv = LittleEndian;
540                                         break;
541                                 case '%':
542                                         conv = Native;
543                                         break;
544                                 case 'x':
545                                         idx++;
546                                         break;
547
548                                 case '!':
549                                         align = true;
550                                         break;
551
552                                         // Type Conversions
553                                 case 'i':
554                                         if (Prepare (buffer, ref idx, 4, ref align)){
555                                                 result.Add (conv.GetInt32 (buffer, idx));
556                                                 idx += 4;
557                                         } 
558                                         break;
559                                 
560                                 case 'I':
561                                         if (Prepare (buffer, ref idx, 4, ref align)){
562                                                 result.Add (conv.GetUInt32 (buffer, idx));
563                                                 idx += 4;
564                                         }
565                                         break;
566                                 
567                                 case 's':
568                                         if (Prepare (buffer, ref idx, 2, ref align)){
569                                                 result.Add (conv.GetInt16 (buffer, idx));
570                                                 idx += 2;
571                                         }
572                                         break;
573                                 
574                                 case 'S':
575                                         if (Prepare (buffer, ref idx, 2, ref align)){
576                                                 result.Add (conv.GetUInt16 (buffer, idx));
577                                                 idx += 2;
578                                         }
579                                         break;
580                                 
581                                 case 'l':
582                                         if (Prepare (buffer, ref idx, 8, ref align)){
583                                                 result.Add (conv.GetInt64 (buffer, idx));
584                                                 idx += 8;
585                                         }
586                                         break;
587                                 
588                                 case 'L':
589                                         if (Prepare (buffer, ref idx, 8, ref align)){
590                                                 result.Add (conv.GetUInt64 (buffer, idx));
591                                                 idx += 8;
592                                         }
593                                         break;
594                                 
595                                 case 'f':
596                                         if (Prepare (buffer, ref idx, 4, ref align)){
597                                                 result.Add (conv.GetFloat (buffer, idx));
598                                                 idx += 4;
599                                         }
600                                         break;
601                                 
602                                 case 'd':
603                                         if (Prepare (buffer, ref idx, 8, ref align)){
604                                                 result.Add (conv.GetDouble (buffer, idx));
605                                                 idx += 8;
606                                         }
607                                         break;
608                                 
609                                 case 'b':
610                                         if (Prepare (buffer, ref idx, 1, ref align)){
611                                                 result.Add (buffer [idx]);
612                                                 idx++;
613                                         }
614                                         break;
615
616                                 case 'c': case 'C':
617                                         if (Prepare (buffer, ref idx, 1, ref align)){
618                                                 char c;
619                                                 
620                                                 if (description [i] == 'c')
621                                                         c = ((char) ((sbyte)buffer [idx]));
622                                                 else
623                                                         c = ((char) ((byte)buffer [idx]));
624                                                 
625                                                 result.Add (c);
626                                                 idx++;
627                                         }
628                                         break;
629                                         
630                                         // Repeat acount;
631                                 case '1': case '2': case '3': case '4': case '5':
632                                 case '6': case '7': case '8': case '9':
633                                         repeat = ((short) description [i]) - ((short) '0');
634                                         save = i + 1;
635                                         break;
636
637                                 case '*':
638                                         repeat = Int32.MaxValue;
639                                         break;
640                                 
641                                 case '[':
642                                         int count = -1, j;
643                                 
644                                         for (j = i+1; j < description.Length; j++){
645                                                 if (description [j] == ']')
646                                                         break;
647                                                 n = ((short) description [j]) - ((short) '0');
648                                                 if (n >= 0 && n <= 9){
649                                                         if (count == -1)
650                                                                 count = n;
651                                                         else
652                                                                 count = count * 10 + n;
653                                                 }
654                                         }
655                                         if (count == -1)
656                                                 throw new ArgumentException ("invalid size specification");
657                                         i = j;
658                                         save = i + 1;
659                                         repeat = count;
660                                         break;
661                                 
662                                 case '$': case 'z':
663                                         // bool with_null = description [i] == 'z';
664                                         i++;
665                                         if (i >= description.Length)
666                                                 throw new ArgumentException ("$ description needs a type specified", "description");
667                                         char d = description [i];
668                                         Encoding e;
669                                         if (align){
670                                                 idx = Align (idx, 4);
671                                                 align = false;
672                                         }
673                                         if (idx >= buffer.Length)
674                                                 break;
675                                 
676                                         switch (d){
677                                         case '8':
678                                                 e = Encoding.UTF8;
679                                                 n = 1;
680                                                 break;
681                                         case '6':
682                                                 e = Encoding.Unicode;
683                                                 n = 2;
684                                                 break;
685                                         case '7':
686                                                 e = Encoding.UTF7;
687                                                 n = 1;
688                                                 break;
689                                         case 'b':
690                                                 e = Encoding.BigEndianUnicode;
691                                                 n = 2;
692                                                 break;
693                                         case '3':
694                                                 e = Encoding.GetEncoding (12000);
695                                                 n = 4;
696                                                 break;
697                                         case '4':
698                                                 e = Encoding.GetEncoding (12001);
699                                                 n = 4;
700                                                 break;
701                                         
702                                         default:
703                                                 throw new ArgumentException ("Invalid format for $ specifier", "description");
704                                         }
705                                         int k = idx;
706                                         switch (n){
707                                         case 1:
708                                                 for (; k < buffer.Length && buffer [k] != 0; k++)
709                                                         ;
710                                                 result.Add (e.GetChars (buffer, idx, k-idx));
711                                                 if (k == buffer.Length)
712                                                         idx = k;
713                                                 else
714                                                         idx = k+1;
715                                                 break;
716                                                 
717                                         case 2:
718                                                 for (; k < buffer.Length; k++){
719                                                         if (k+1 == buffer.Length){
720                                                                 k++;
721                                                                 break;
722                                                         }
723                                                         if (buffer [k] == 0 && buffer [k+1] == 0)
724                                                                 break;
725                                                 }
726                                                 result.Add (e.GetChars (buffer, idx, k-idx));
727                                                 if (k == buffer.Length)
728                                                         idx = k;
729                                                 else
730                                                         idx = k+2;
731                                                 break;
732                                                 
733                                         case 4:
734                                                 for (; k < buffer.Length; k++){
735                                                         if (k+3 >= buffer.Length){
736                                                                 k = buffer.Length;
737                                                                 break;
738                                                         }
739                                                         if (buffer[k]==0 && buffer[k+1] == 0 && buffer[k+2] == 0 && buffer[k+3]== 0)
740                                                                 break;
741                                                 }
742                                                 result.Add (e.GetChars (buffer, idx, k-idx));
743                                                 if (k == buffer.Length)
744                                                         idx = k;
745                                                 else
746                                                         idx = k+4;
747                                                 break;
748                                         }
749                                         break;
750                                 default:
751                                         throw new ArgumentException (String.Format ("invalid format specified `{0}'",
752                                                                                     description [i]));
753                                 }
754
755                                 if (repeat > 0){
756                                         if (--repeat > 0)
757                                                 i = save;
758                                 } else
759                                         i++;
760                         }
761                         return result;
762                 }
763
764                 internal void Check (byte [] dest, int destIdx, int size)
765                 {
766                         if (dest == null)
767                                 throw new ArgumentNullException ("dest");
768                         if (destIdx < 0 || destIdx > dest.Length - size)
769                                 throw new ArgumentException ("destIdx");
770                 }
771                 
772                 class CopyConverter : DataConverter {
773                         public override double GetDouble (byte [] data, int index)
774                         {
775                                 if (data == null)
776                                         throw new ArgumentNullException ("data");
777                                 if (data.Length - index < 8)
778                                         throw new ArgumentException ("index");
779                                 if (index < 0)
780                                         throw new ArgumentException ("index");
781                                 double ret;
782                                 byte *b = (byte *)&ret;
783
784                                 for (int i = 0; i < 8; i++)
785                                         b [i] = data [index+i];
786
787                                 return ret;
788                         }
789
790                         public override ulong GetUInt64 (byte [] data, int index)
791                         {
792                                 if (data == null)
793                                         throw new ArgumentNullException ("data");
794                                 if (data.Length - index < 8)
795                                         throw new ArgumentException ("index");
796                                 if (index < 0)
797                                         throw new ArgumentException ("index");
798
799                                 ulong ret;
800                                 byte *b = (byte *)&ret;
801
802                                 for (int i = 0; i < 8; i++)
803                                         b [i] = data [index+i];
804
805                                 return ret;
806                         }
807
808                         public override long GetInt64 (byte [] data, int index)
809                         {
810                                 if (data == null)
811                                         throw new ArgumentNullException ("data");
812                                 if (data.Length - index < 8)
813                                         throw new ArgumentException ("index");
814                                 if (index < 0)
815                                         throw new ArgumentException ("index");
816
817                                 long ret;
818                                 byte *b = (byte *)&ret;
819
820                                 for (int i = 0; i < 8; i++)
821                                         b [i] = data [index+i];
822
823                                 return ret;
824                         }
825                         
826                         public override float GetFloat  (byte [] data, int index)
827                         {
828                                 if (data == null)
829                                         throw new ArgumentNullException ("data");
830                                 if (data.Length - index < 4)
831                                         throw new ArgumentException ("index");
832                                 if (index < 0)
833                                         throw new ArgumentException ("index");
834
835                                 float ret;
836                                 byte *b = (byte *)&ret;
837
838                                 for (int i = 0; i < 4; i++)
839                                         b [i] = data [index+i];
840
841                                 return ret;
842                         }
843                         
844                         public override int GetInt32  (byte [] data, int index)
845                         {
846                                 if (data == null)
847                                         throw new ArgumentNullException ("data");
848                                 if (data.Length - index < 4)
849                                         throw new ArgumentException ("index");
850                                 if (index < 0)
851                                         throw new ArgumentException ("index");
852
853                                 int ret;
854                                 byte *b = (byte *)&ret;
855
856                                 for (int i = 0; i < 4; i++)
857                                         b [i] = data [index+i];
858
859                                 return ret;
860                         }
861                         
862                         public override uint GetUInt32 (byte [] data, int index)
863                         {
864                                 if (data == null)
865                                         throw new ArgumentNullException ("data");
866                                 if (data.Length - index < 4)
867                                         throw new ArgumentException ("index");
868                                 if (index < 0)
869                                         throw new ArgumentException ("index");
870
871                                 uint ret;
872                                 byte *b = (byte *)&ret;
873
874                                 for (int i = 0; i < 4; i++)
875                                         b [i] = data [index+i];
876
877                                 return ret;
878                         }
879                         
880                         public override short GetInt16 (byte [] data, int index)
881                         {
882                                 if (data == null)
883                                         throw new ArgumentNullException ("data");
884                                 if (data.Length - index < 2)
885                                         throw new ArgumentException ("index");
886                                 if (index < 0)
887                                         throw new ArgumentException ("index");
888
889                                 short ret;
890                                 byte *b = (byte *)&ret;
891
892                                 for (int i = 0; i < 2; i++)
893                                         b [i] = data [index+i];
894
895                                 return ret;
896                         }
897                         
898                         public override ushort GetUInt16 (byte [] data, int index)
899                         {
900                                 if (data == null)
901                                         throw new ArgumentNullException ("data");
902                                 if (data.Length - index < 2)
903                                         throw new ArgumentException ("index");
904                                 if (index < 0)
905                                         throw new ArgumentException ("index");
906
907                                 ushort ret;
908                                 byte *b = (byte *)&ret;
909
910                                 for (int i = 0; i < 2; i++)
911                                         b [i] = data [index+i];
912
913                                 return ret;
914                         }
915                         
916                         public override void PutBytes (byte [] dest, int destIdx, double value)
917                         {
918                                 Check (dest, destIdx, 8);
919                                 fixed (byte *target = &dest [destIdx]){
920                                         long *source = (long *) &value;
921
922                                         *((long *)target) = *source;
923                                 }
924                         }
925                         
926                         public override void PutBytes (byte [] dest, int destIdx, float value)
927                         {
928                                 Check (dest, destIdx, 4);
929                                 fixed (byte *target = &dest [destIdx]){
930                                         uint *source = (uint *) &value;
931
932                                         *((uint *)target) = *source;
933                                 }
934                         }
935                         
936                         public override void PutBytes (byte [] dest, int destIdx, int value)
937                         {
938                                 Check (dest, destIdx, 4);
939                                 fixed (byte *target = &dest [destIdx]){
940                                         uint *source = (uint *) &value;
941
942                                         *((uint *)target) = *source;
943                                 }
944                         }
945
946                         public override void PutBytes (byte [] dest, int destIdx, uint value)
947                         {
948                                 Check (dest, destIdx, 4);
949                                 fixed (byte *target = &dest [destIdx]){
950                                         uint *source = (uint *) &value;
951
952                                         *((uint *)target) = *source;
953                                 }
954                         }
955                         
956                         public override void PutBytes (byte [] dest, int destIdx, long value)
957                         {
958                                 Check (dest, destIdx, 8);
959                                 fixed (byte *target = &dest [destIdx]){
960                                         long *source = (long *) &value;
961
962                                         *((long*)target) = *source;
963                                 }
964                         }
965                         
966                         public override void PutBytes (byte [] dest, int destIdx, ulong value)
967                         {
968                                 Check (dest, destIdx, 8);
969                                 fixed (byte *target = &dest [destIdx]){
970                                         ulong *source = (ulong *) &value;
971
972                                         *((ulong *) target) = *source;
973                                 }
974                         }
975                         
976                         public override void PutBytes (byte [] dest, int destIdx, short value)
977                         {
978                                 Check (dest, destIdx, 2);
979                                 fixed (byte *target = &dest [destIdx]){
980                                         ushort *source = (ushort *) &value;
981
982                                         *((ushort *)target) = *source;
983                                 }
984                         }
985                         
986                         public override void PutBytes (byte [] dest, int destIdx, ushort value)
987                         {
988                                 Check (dest, destIdx, 2);
989                                 fixed (byte *target = &dest [destIdx]){
990                                         ushort *source = (ushort *) &value;
991
992                                         *((ushort *)target) = *source;
993                                 }
994                         }
995                 }
996
997                 class SwapConverter : DataConverter {
998                         public override double GetDouble (byte [] data, int index)
999                         {
1000                                 if (data == null)
1001                                         throw new ArgumentNullException ("data");
1002                                 if (data.Length - index < 8)
1003                                         throw new ArgumentException ("index");
1004                                 if (index < 0)
1005                                         throw new ArgumentException ("index");
1006
1007                                 double ret;
1008                                 byte *b = (byte *)&ret;
1009
1010                                 for (int i = 0; i < 8; i++)
1011                                         b [7-i] = data [index+i];
1012
1013                                 return ret;
1014                         }
1015
1016                         public override ulong GetUInt64 (byte [] data, int index)
1017                         {
1018                                 if (data == null)
1019                                         throw new ArgumentNullException ("data");
1020                                 if (data.Length - index < 8)
1021                                         throw new ArgumentException ("index");
1022                                 if (index < 0)
1023                                         throw new ArgumentException ("index");
1024
1025                                 ulong ret;
1026                                 byte *b = (byte *)&ret;
1027
1028                                 for (int i = 0; i < 8; i++)
1029                                         b [7-i] = data [index+i];
1030
1031                                 return ret;
1032                         }
1033
1034                         public override long GetInt64 (byte [] data, int index)
1035                         {
1036                                 if (data == null)
1037                                         throw new ArgumentNullException ("data");
1038                                 if (data.Length - index < 8)
1039                                         throw new ArgumentException ("index");
1040                                 if (index < 0)
1041                                         throw new ArgumentException ("index");
1042
1043                                 long ret;
1044                                 byte *b = (byte *)&ret;
1045
1046                                 for (int i = 0; i < 8; i++)
1047                                         b [7-i] = data [index+i];
1048
1049                                 return ret;
1050                         }
1051                         
1052                         public override float GetFloat  (byte [] data, int index)
1053                         {
1054                                 if (data == null)
1055                                         throw new ArgumentNullException ("data");
1056                                 if (data.Length - index < 4)
1057                                         throw new ArgumentException ("index");
1058                                 if (index < 0)
1059                                         throw new ArgumentException ("index");
1060
1061                                 float ret;
1062                                 byte *b = (byte *)&ret;
1063
1064                                 for (int i = 0; i < 4; i++)
1065                                         b [3-i] = data [index+i];
1066
1067                                 return ret;
1068                         }
1069                         
1070                         public override int GetInt32  (byte [] data, int index)
1071                         {
1072                                 if (data == null)
1073                                         throw new ArgumentNullException ("data");
1074                                 if (data.Length - index < 4)
1075                                         throw new ArgumentException ("index");
1076                                 if (index < 0)
1077                                         throw new ArgumentException ("index");
1078
1079                                 int ret;
1080                                 byte *b = (byte *)&ret;
1081
1082                                 for (int i = 0; i < 4; i++)
1083                                         b [3-i] = data [index+i];
1084
1085                                 return ret;
1086                         }
1087                         
1088                         public override uint GetUInt32 (byte [] data, int index)
1089                         {
1090                                 if (data == null)
1091                                         throw new ArgumentNullException ("data");
1092                                 if (data.Length - index < 4)
1093                                         throw new ArgumentException ("index");
1094                                 if (index < 0)
1095                                         throw new ArgumentException ("index");
1096
1097                                 uint ret;
1098                                 byte *b = (byte *)&ret;
1099
1100                                 for (int i = 0; i < 4; i++)
1101                                         b [3-i] = data [index+i];
1102
1103                                 return ret;
1104                         }
1105                         
1106                         public override short GetInt16 (byte [] data, int index)
1107                         {
1108                                 if (data == null)
1109                                         throw new ArgumentNullException ("data");
1110                                 if (data.Length - index < 2)
1111                                         throw new ArgumentException ("index");
1112                                 if (index < 0)
1113                                         throw new ArgumentException ("index");
1114
1115                                 short ret;
1116                                 byte *b = (byte *)&ret;
1117
1118                                 for (int i = 0; i < 2; i++)
1119                                         b [1-i] = data [index+i];
1120
1121                                 return ret;
1122                         }
1123                         
1124                         public override ushort GetUInt16 (byte [] data, int index)
1125                         {
1126                                 if (data == null)
1127                                         throw new ArgumentNullException ("data");
1128                                 if (data.Length - index < 2)
1129                                         throw new ArgumentException ("index");
1130                                 if (index < 0)
1131                                         throw new ArgumentException ("index");
1132
1133                                 ushort ret;
1134                                 byte *b = (byte *)&ret;
1135
1136                                 for (int i = 0; i < 2; i++)
1137                                         b [1-i] = data [index+i];
1138
1139                                 return ret;
1140                         }
1141
1142                         public override void PutBytes (byte [] dest, int destIdx, double value)
1143                         {
1144                                 Check (dest, destIdx, 8);
1145
1146                                 fixed (byte *target = &dest [destIdx]){
1147                                         byte *source = (byte *) &value;
1148
1149                                         for (int i = 0; i < 8; i++)
1150                                                 target [i] = source [7-i];
1151                                 }
1152                         }
1153                         
1154                         public override void PutBytes (byte [] dest, int destIdx, float value)
1155                         {
1156                                 Check (dest, destIdx, 4);
1157
1158                                 fixed (byte *target = &dest [destIdx]){
1159                                         byte *source = (byte *) &value;
1160
1161                                         for (int i = 0; i < 4; i++)
1162                                                 target [i] = source [3-i];
1163                                 }
1164                         }
1165                         
1166                         public override void PutBytes (byte [] dest, int destIdx, int value)
1167                         {
1168                                 Check (dest, destIdx, 4);
1169
1170                                 fixed (byte *target = &dest [destIdx]){
1171                                         byte *source = (byte *) &value;
1172
1173                                         for (int i = 0; i < 4; i++)
1174                                                 target [i] = source [3-i];
1175                                 }
1176                         }
1177                         
1178                         public override void PutBytes (byte [] dest, int destIdx, uint value)
1179                         {
1180                                 Check (dest, destIdx, 4);
1181
1182                                 fixed (byte *target = &dest [destIdx]){
1183                                         byte *source = (byte *) &value;
1184
1185                                         for (int i = 0; i < 4; i++)
1186                                                 target [i] = source [3-i];
1187                                 }
1188                         }
1189                         
1190                         public override void PutBytes (byte [] dest, int destIdx, long value)
1191                         {
1192                                 Check (dest, destIdx, 8);
1193
1194                                 fixed (byte *target = &dest [destIdx]){
1195                                         byte *source = (byte *) &value;
1196
1197                                         for (int i = 0; i < 8; i++)
1198                                                 target [i] = source [7-i];
1199                                 }
1200                         }
1201                         
1202                         public override void PutBytes (byte [] dest, int destIdx, ulong value)
1203                         {
1204                                 Check (dest, destIdx, 8);
1205
1206                                 fixed (byte *target = &dest [destIdx]){
1207                                         byte *source = (byte *) &value;
1208
1209                                         for (int i = 0; i < 8; i++)
1210                                                 target [i] = source [7-i];
1211                                 }
1212                         }
1213                         
1214                         public override void PutBytes (byte [] dest, int destIdx, short value)
1215                         {
1216                                 Check (dest, destIdx, 2);
1217
1218                                 fixed (byte *target = &dest [destIdx]){
1219                                         byte *source = (byte *) &value;
1220
1221                                         for (int i = 0; i < 2; i++)
1222                                                 target [i] = source [1-i];
1223                                 }
1224                         }
1225                         
1226                         public override void PutBytes (byte [] dest, int destIdx, ushort value)
1227                         {
1228                                 Check (dest, destIdx, 2);
1229
1230                                 fixed (byte *target = &dest [destIdx]){
1231                                         byte *source = (byte *) &value;
1232
1233                                         for (int i = 0; i < 2; i++)
1234                                                 target [i] = source [1-i];
1235                                 }
1236                         }
1237                 }
1238                 
1239 #if MONO_DATACONVERTER_STATIC_METHODS
1240                 static unsafe void PutBytesLE (byte *dest, byte *src, int count)
1241                 {
1242                         int i = 0;
1243                         
1244                         if (BitConverter.IsLittleEndian){
1245                                 for (; i < count; i++)
1246                                         *dest++ = *src++;
1247                         } else {
1248                                 dest += count;
1249                                 for (; i < count; i++)
1250                                         *(--dest) = *src++;
1251                         }
1252                 }
1253
1254                 static unsafe void PutBytesBE (byte *dest, byte *src, int count)
1255                 {
1256                         int i = 0;
1257                         
1258                         if (BitConverter.IsLittleEndian){
1259                                 dest += count;
1260                                 for (; i < count; i++)
1261                                         *(--dest) = *src++;
1262                         } else {
1263                                 for (; i < count; i++)
1264                                         *dest++ = *src++;
1265                         }
1266                 }
1267
1268                 static unsafe void PutBytesNative (byte *dest, byte *src, int count)
1269                 {
1270                         int i = 0;
1271                         
1272                         for (; i < count; i++)
1273                                 dest [i-count] = *src++;
1274                 }
1275                 
1276                 static public unsafe double DoubleFromLE (byte[] data, int index)
1277                 {
1278                         if (data == null)
1279                                 throw new ArgumentNullException ("data");
1280                         if (data.Length - index < 8)
1281                                 throw new ArgumentException ("index");
1282                         if (index < 0)
1283                                 throw new ArgumentException ("index");
1284                         
1285                         double ret;
1286                         fixed (byte *src = &data[index]){
1287                                 PutBytesLE ((byte *) &ret, src, 8);
1288                         }
1289                         return ret;
1290                 }
1291
1292                 static public unsafe float FloatFromLE (byte [] data, int index)
1293                 {
1294                         if (data == null)
1295                                 throw new ArgumentNullException ("data");
1296                         if (data.Length - index < 4)
1297                                 throw new ArgumentException ("index");
1298                         if (index < 0)
1299                                 throw new ArgumentException ("index");
1300                         
1301                         float ret;
1302                         fixed (byte *src = &data[index]){
1303                                 PutBytesLE ((byte *) &ret, src, 4);
1304                         }
1305                         return ret;
1306                 }
1307
1308                 static public unsafe long Int64FromLE (byte [] data, int index)
1309                 {
1310                         if (data == null)
1311                                 throw new ArgumentNullException ("data");
1312                         if (data.Length - index < 8)
1313                                 throw new ArgumentException ("index");
1314                         if (index < 0)
1315                                 throw new ArgumentException ("index");
1316                         
1317                         long ret;
1318                         fixed (byte *src = &data[index]){
1319                                 PutBytesLE ((byte *) &ret, src, 8);
1320                         }
1321                         return ret;
1322                 }
1323                 
1324                 static public unsafe ulong UInt64FromLE (byte [] data, int index)
1325                 {
1326                         if (data == null)
1327                                 throw new ArgumentNullException ("data");
1328                         if (data.Length - index < 8)
1329                                 throw new ArgumentException ("index");
1330                         if (index < 0)
1331                                 throw new ArgumentException ("index");
1332                         
1333                         ulong ret;
1334                         fixed (byte *src = &data[index]){
1335                                 PutBytesLE ((byte *) &ret, src, 8);
1336                         }
1337                         return ret;
1338                 }
1339
1340                 static public unsafe int Int32FromLE (byte [] data, int index)
1341                 {
1342                         if (data == null)
1343                                 throw new ArgumentNullException ("data");
1344                         if (data.Length - index < 4)
1345                                 throw new ArgumentException ("index");
1346                         if (index < 0)
1347                                 throw new ArgumentException ("index");
1348                         
1349                         int ret;
1350                         fixed (byte *src = &data[index]){
1351                                 PutBytesLE ((byte *) &ret, src, 4);
1352                         }
1353                         return ret;
1354                 }
1355                 
1356                 static public unsafe uint UInt32FromLE (byte [] data, int index)
1357                 {
1358                         if (data == null)
1359                                 throw new ArgumentNullException ("data");
1360                         if (data.Length - index < 4)
1361                                 throw new ArgumentException ("index");
1362                         if (index < 0)
1363                                 throw new ArgumentException ("index");
1364                         
1365                         uint ret;
1366                         fixed (byte *src = &data[index]){
1367                                 PutBytesLE ((byte *) &ret, src, 4);
1368                         }
1369                         return ret;
1370                 }
1371
1372                 static public unsafe short Int16FromLE (byte [] data, int index)
1373                 {
1374                         if (data == null)
1375                                 throw new ArgumentNullException ("data");
1376                         if (data.Length - index < 2)
1377                                 throw new ArgumentException ("index");
1378                         if (index < 0)
1379                                 throw new ArgumentException ("index");
1380
1381                         short ret;
1382                         fixed (byte *src = &data[index]){
1383                                 PutBytesLE ((byte *) &ret, src, 2);
1384                         }
1385                         return ret;
1386                 }
1387                 
1388                 static public unsafe ushort UInt16FromLE (byte [] data, int index)
1389                 {
1390                         if (data == null)
1391                                 throw new ArgumentNullException ("data");
1392                         if (data.Length - index < 2)
1393                                 throw new ArgumentException ("index");
1394                         if (index < 0)
1395                                 throw new ArgumentException ("index");
1396                         
1397                         ushort ret;
1398                         fixed (byte *src = &data[index]){
1399                                 PutBytesLE ((byte *) &ret, src, 2);
1400                         }
1401                         return ret;
1402                 }
1403
1404                 static public unsafe double DoubleFromBE (byte[] data, int index)
1405                 {
1406                         if (data == null)
1407                                 throw new ArgumentNullException ("data");
1408                         if (data.Length - index < 8)
1409                                 throw new ArgumentException ("index");
1410                         if (index < 0)
1411                                 throw new ArgumentException ("index");
1412                         
1413                         double ret;
1414                         fixed (byte *src = &data[index]){
1415                                 PutBytesBE ((byte *) &ret, src, 8);
1416                         }
1417                         return ret;
1418                 }
1419
1420                 static public unsafe float FloatFromBE (byte [] data, int index)
1421                 {
1422                         if (data == null)
1423                                 throw new ArgumentNullException ("data");
1424                         if (data.Length - index < 4)
1425                                 throw new ArgumentException ("index");
1426                         if (index < 0)
1427                                 throw new ArgumentException ("index");
1428                         
1429                         float ret;
1430                         fixed (byte *src = &data[index]){
1431                                 PutBytesBE ((byte *) &ret, src, 4);
1432                         }
1433                         return ret;
1434                 }
1435
1436                 static public unsafe long Int64FromBE (byte [] data, int index)
1437                 {
1438                         if (data == null)
1439                                 throw new ArgumentNullException ("data");
1440                         if (data.Length - index < 8)
1441                                 throw new ArgumentException ("index");
1442                         if (index < 0)
1443                                 throw new ArgumentException ("index");
1444                         
1445                         long ret;
1446                         fixed (byte *src = &data[index]){
1447                                 PutBytesBE ((byte *) &ret, src, 8);
1448                         }
1449                         return ret;
1450                 }
1451                 
1452                 static public unsafe ulong UInt64FromBE (byte [] data, int index)
1453                 {
1454                         if (data == null)
1455                                 throw new ArgumentNullException ("data");
1456                         if (data.Length - index < 8)
1457                                 throw new ArgumentException ("index");
1458                         if (index < 0)
1459                                 throw new ArgumentException ("index");
1460                         
1461                         ulong ret;
1462                         fixed (byte *src = &data[index]){
1463                                 PutBytesBE ((byte *) &ret, src, 8);
1464                         }
1465                         return ret;
1466                 }
1467
1468                 static public unsafe int Int32FromBE (byte [] data, int index)
1469                 {
1470                         if (data == null)
1471                                 throw new ArgumentNullException ("data");
1472                         if (data.Length - index < 4)
1473                                 throw new ArgumentException ("index");
1474                         if (index < 0)
1475                                 throw new ArgumentException ("index");
1476                         
1477                         int ret;
1478                         fixed (byte *src = &data[index]){
1479                                 PutBytesBE ((byte *) &ret, src, 4);
1480                         }
1481                         return ret;
1482                 }
1483                 
1484                 static public unsafe uint UInt32FromBE (byte [] data, int index)
1485                 {
1486                         if (data == null)
1487                                 throw new ArgumentNullException ("data");
1488                         if (data.Length - index < 4)
1489                                 throw new ArgumentException ("index");
1490                         if (index < 0)
1491                                 throw new ArgumentException ("index");
1492                         
1493                         uint ret;
1494                         fixed (byte *src = &data[index]){
1495                                 PutBytesBE ((byte *) &ret, src, 4);
1496                         }
1497                         return ret;
1498                 }
1499
1500                 static public unsafe short Int16FromBE (byte [] data, int index)
1501                 {
1502                         if (data == null)
1503                                 throw new ArgumentNullException ("data");
1504                         if (data.Length - index < 2)
1505                                 throw new ArgumentException ("index");
1506                         if (index < 0)
1507                                 throw new ArgumentException ("index");
1508
1509                         short ret;
1510                         fixed (byte *src = &data[index]){
1511                                 PutBytesBE ((byte *) &ret, src, 2);
1512                         }
1513                         return ret;
1514                 }
1515                 
1516                 static public unsafe ushort UInt16FromBE (byte [] data, int index)
1517                 {
1518                         if (data == null)
1519                                 throw new ArgumentNullException ("data");
1520                         if (data.Length - index < 2)
1521                                 throw new ArgumentException ("index");
1522                         if (index < 0)
1523                                 throw new ArgumentException ("index");
1524                         
1525                         ushort ret;
1526                         fixed (byte *src = &data[index]){
1527                                 PutBytesBE ((byte *) &ret, src, 2);
1528                         }
1529                         return ret;
1530                 }
1531
1532                 static public unsafe double DoubleFromNative (byte[] data, int index)
1533                 {
1534                         if (data == null)
1535                                 throw new ArgumentNullException ("data");
1536                         if (data.Length - index < 8)
1537                                 throw new ArgumentException ("index");
1538                         if (index < 0)
1539                                 throw new ArgumentException ("index");
1540                         
1541                         double ret;
1542                         fixed (byte *src = &data[index]){
1543                                 PutBytesNative ((byte *) &ret, src, 8);
1544                         }
1545                         return ret;
1546                 }
1547
1548                 static public unsafe float FloatFromNative (byte [] data, int index)
1549                 {
1550                         if (data == null)
1551                                 throw new ArgumentNullException ("data");
1552                         if (data.Length - index < 4)
1553                                 throw new ArgumentException ("index");
1554                         if (index < 0)
1555                                 throw new ArgumentException ("index");
1556                         
1557                         float ret;
1558                         fixed (byte *src = &data[index]){
1559                                 PutBytesNative ((byte *) &ret, src, 4);
1560                         }
1561                         return ret;
1562                 }
1563
1564                 static public unsafe long Int64FromNative (byte [] data, int index)
1565                 {
1566                         if (data == null)
1567                                 throw new ArgumentNullException ("data");
1568                         if (data.Length - index < 8)
1569                                 throw new ArgumentException ("index");
1570                         if (index < 0)
1571                                 throw new ArgumentException ("index");
1572                         
1573                         long ret;
1574                         fixed (byte *src = &data[index]){
1575                                 PutBytesNative ((byte *) &ret, src, 8);
1576                         }
1577                         return ret;
1578                 }
1579                 
1580                 static public unsafe ulong UInt64FromNative (byte [] data, int index)
1581                 {
1582                         if (data == null)
1583                                 throw new ArgumentNullException ("data");
1584                         if (data.Length - index < 8)
1585                                 throw new ArgumentException ("index");
1586                         if (index < 0)
1587                                 throw new ArgumentException ("index");
1588                         
1589                         ulong ret;
1590                         fixed (byte *src = &data[index]){
1591                                 PutBytesNative ((byte *) &ret, src, 8);
1592                         }
1593                         return ret;
1594                 }
1595
1596                 static public unsafe int Int32FromNative (byte [] data, int index)
1597                 {
1598                         if (data == null)
1599                                 throw new ArgumentNullException ("data");
1600                         if (data.Length - index < 4)
1601                                 throw new ArgumentException ("index");
1602                         if (index < 0)
1603                                 throw new ArgumentException ("index");
1604                         
1605                         int ret;
1606                         fixed (byte *src = &data[index]){
1607                                 PutBytesNative ((byte *) &ret, src, 4);
1608                         }
1609                         return ret;
1610                 }
1611                 
1612                 static public unsafe uint UInt32FromNative (byte [] data, int index)
1613                 {
1614                         if (data == null)
1615                                 throw new ArgumentNullException ("data");
1616                         if (data.Length - index < 4)
1617                                 throw new ArgumentException ("index");
1618                         if (index < 0)
1619                                 throw new ArgumentException ("index");
1620                         
1621                         uint ret;
1622                         fixed (byte *src = &data[index]){
1623                                 PutBytesNative ((byte *) &ret, src, 4);
1624                         }
1625                         return ret;
1626                 }
1627
1628                 static public unsafe short Int16FromNative (byte [] data, int index)
1629                 {
1630                         if (data == null)
1631                                 throw new ArgumentNullException ("data");
1632                         if (data.Length - index < 2)
1633                                 throw new ArgumentException ("index");
1634                         if (index < 0)
1635                                 throw new ArgumentException ("index");
1636
1637                         short ret;
1638                         fixed (byte *src = &data[index]){
1639                                 PutBytesNative ((byte *) &ret, src, 2);
1640                         }
1641                         return ret;
1642                 }
1643                 
1644                 static public unsafe ushort UInt16FromNative (byte [] data, int index)
1645                 {
1646                         if (data == null)
1647                                 throw new ArgumentNullException ("data");
1648                         if (data.Length - index < 2)
1649                                 throw new ArgumentException ("index");
1650                         if (index < 0)
1651                                 throw new ArgumentException ("index");
1652                         
1653                         ushort ret;
1654                         fixed (byte *src = &data[index]){
1655                                 PutBytesNative ((byte *) &ret, src, 2);
1656                         }
1657                         return ret;
1658                 }
1659
1660                 unsafe static byte[] GetBytesPtr (byte *ptr, int count)
1661                 {
1662                         byte [] ret = new byte [count];
1663
1664                         for (int i = 0; i < count; i++) {
1665                                 ret [i] = ptr [i];
1666                         }
1667
1668                         return ret;
1669                 }
1670
1671                 unsafe static byte[] GetBytesSwap (bool swap, byte *ptr, int count)
1672                 {
1673                         byte [] ret = new byte [count];
1674
1675                         if (swap){
1676                                 int t = count-1;
1677                                 for (int i = 0; i < count; i++) {
1678                                         ret [t-i] = ptr [i];
1679                                 }
1680                         } else {
1681                                 for (int i = 0; i < count; i++) {
1682                                         ret [i] = ptr [i];
1683                                 }
1684                         }
1685                         return ret;
1686                 }
1687                 
1688                 unsafe public static byte[] GetBytesNative (bool value)
1689                 {
1690                         return GetBytesPtr ((byte *) &value, 1);
1691                 }
1692
1693                 unsafe public static byte[] GetBytesNative (char value)
1694                 {
1695                         return GetBytesPtr ((byte *) &value, 2);
1696                 }
1697
1698                 unsafe public static byte[] GetBytesNative (short value)
1699                 {
1700                         return GetBytesPtr ((byte *) &value, 2);
1701                 }
1702
1703                 unsafe public static byte[] GetBytesNative (int value)
1704                 {
1705                         return GetBytesPtr ((byte *) &value, 4);
1706                 }
1707
1708                 unsafe public static byte[] GetBytesNative (long value)
1709                 {
1710                         return GetBytesPtr ((byte *) &value, 8);
1711                 }
1712
1713                 [CLSCompliant (false)]
1714                 unsafe public static byte[] GetBytesNative (ushort value)
1715                 {
1716                         return GetBytesPtr ((byte *) &value, 2);
1717                 }
1718
1719                 [CLSCompliant (false)]
1720                 unsafe public static byte[] GetBytesNative (uint value)
1721                 {
1722                         return GetBytesPtr ((byte *) &value, 4);
1723                 }
1724
1725                 [CLSCompliant (false)]
1726                 unsafe public static byte[] GetBytesNative (ulong value)
1727                 {
1728                         return GetBytesPtr ((byte *) &value, 8);
1729                 }
1730
1731                 unsafe public static byte[] GetBytesNative (float value)
1732                 {
1733                         return GetBytesPtr ((byte *) &value, 4);
1734                 }
1735
1736                 unsafe public static byte[] GetBytesNative (double value)
1737                 {
1738                         return GetBytesPtr ((byte *) &value, 8);
1739                 }
1740
1741                 unsafe public static byte[] GetBytesLE (bool value)
1742                 {
1743                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 1);
1744                 }
1745
1746                 unsafe public static byte[] GetBytesLE (char value)
1747                 {
1748                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
1749                 }
1750
1751                 unsafe public static byte[] GetBytesLE (short value)
1752                 {
1753                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
1754                 }
1755
1756                 unsafe public static byte[] GetBytesLE (int value)
1757                 {
1758                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
1759                 }
1760
1761                 unsafe public static byte[] GetBytesLE (long value)
1762                 {
1763                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
1764                 }
1765
1766                 [CLSCompliant (false)]
1767                 unsafe public static byte[] GetBytesLE (ushort value)
1768                 {
1769                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
1770                 }
1771
1772                 [CLSCompliant (false)]
1773                 unsafe public static byte[] GetBytesLE (uint value)
1774                 {
1775                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
1776                 }
1777
1778                 [CLSCompliant (false)]
1779                 unsafe public static byte[] GetBytesLE (ulong value)
1780                 {
1781                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
1782                 }
1783
1784                 unsafe public static byte[] GetBytesLE (float value)
1785                 {
1786                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
1787                 }
1788
1789                 unsafe public static byte[] GetBytesLE (double value)
1790                 {
1791                         return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
1792                 }
1793                 
1794                 unsafe public static byte[] GetBytesBE (bool value)
1795                 {
1796                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 1);
1797                 }
1798
1799                 unsafe public static byte[] GetBytesBE (char value)
1800                 {
1801                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
1802                 }
1803
1804                 unsafe public static byte[] GetBytesBE (short value)
1805                 {
1806                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
1807                 }
1808
1809                 unsafe public static byte[] GetBytesBE (int value)
1810                 {
1811                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
1812                 }
1813
1814                 unsafe public static byte[] GetBytesBE (long value)
1815                 {
1816                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
1817                 }
1818
1819                 [CLSCompliant (false)]
1820                 unsafe public static byte[] GetBytesBE (ushort value)
1821                 {
1822                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
1823                 }
1824
1825                 [CLSCompliant (false)]
1826                 unsafe public static byte[] GetBytesBE (uint value)
1827                 {
1828                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
1829                 }
1830
1831                 [CLSCompliant (false)]
1832                 unsafe public static byte[] GetBytesBE (ulong value)
1833                 {
1834                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
1835                 }
1836
1837                 unsafe public static byte[] GetBytesBE (float value)
1838                 {
1839                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
1840                 }
1841
1842                 unsafe public static byte[] GetBytesBE (double value)
1843                 {
1844                         return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
1845                 }
1846 #endif
1847                 
1848         }
1849 }