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