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