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