2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Mono.Debugger.Soft / Mono.Debugger.Soft / DataConverter.cs
blobd0bf0476f602cb04b521e2f24848f65a4a62eedf
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.
12 // MONO_DATACONVERTER_STATIC_METHODS:
13 // Exposes the public static methods.
15 // TODO:
16 // Support for "DoubleWordsAreSwapped" for ARM devices
18 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
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.
39 using System;
40 using System.Collections;
41 using System.Text;
43 #pragma warning disable 3021
45 namespace Mono {
47 #if MONO_DATACONVERTER_PUBLIC
48 unsafe public abstract class DataConverter {
49 #else
50 unsafe internal abstract class DataConverter {
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 #endif
56 static DataConverter SwapConv = new SwapConverter ();
57 static DataConverter CopyConv = new CopyConverter ();
59 public static readonly bool IsLittleEndian = BitConverter.IsLittleEndian;
61 public abstract double GetDouble (byte [] data, int index);
62 public abstract float GetFloat (byte [] data, int index);
63 public abstract long GetInt64 (byte [] data, int index);
64 public abstract int GetInt32 (byte [] data, int index);
66 public abstract short GetInt16 (byte [] data, int index);
68 [CLSCompliant (false)]
69 public abstract uint GetUInt32 (byte [] data, int index);
70 [CLSCompliant (false)]
71 public abstract ushort GetUInt16 (byte [] data, int index);
72 [CLSCompliant (false)]
73 public abstract ulong GetUInt64 (byte [] data, int index);
75 public abstract void PutBytes (byte [] dest, int destIdx, double value);
76 public abstract void PutBytes (byte [] dest, int destIdx, float value);
77 public abstract void PutBytes (byte [] dest, int destIdx, int value);
78 public abstract void PutBytes (byte [] dest, int destIdx, long value);
79 public abstract void PutBytes (byte [] dest, int destIdx, short value);
81 [CLSCompliant (false)]
82 public abstract void PutBytes (byte [] dest, int destIdx, ushort value);
83 [CLSCompliant (false)]
84 public abstract void PutBytes (byte [] dest, int destIdx, uint value);
85 [CLSCompliant (false)]
86 public abstract void PutBytes (byte [] dest, int destIdx, ulong value);
88 public byte[] GetBytes (double value)
90 byte [] ret = new byte [8];
91 PutBytes (ret, 0, value);
92 return ret;
95 public byte[] GetBytes (float value)
97 byte [] ret = new byte [4];
98 PutBytes (ret, 0, value);
99 return ret;
102 public byte[] GetBytes (int value)
104 byte [] ret = new byte [4];
105 PutBytes (ret, 0, value);
106 return ret;
109 public byte[] GetBytes (long value)
111 byte [] ret = new byte [8];
112 PutBytes (ret, 0, value);
113 return ret;
116 public byte[] GetBytes (short value)
118 byte [] ret = new byte [2];
119 PutBytes (ret, 0, value);
120 return ret;
123 [CLSCompliant (false)]
124 public byte[] GetBytes (ushort value)
126 byte [] ret = new byte [2];
127 PutBytes (ret, 0, value);
128 return ret;
131 [CLSCompliant (false)]
132 public byte[] GetBytes (uint value)
134 byte [] ret = new byte [4];
135 PutBytes (ret, 0, value);
136 return ret;
139 [CLSCompliant (false)]
140 public byte[] GetBytes (ulong value)
142 byte [] ret = new byte [8];
143 PutBytes (ret, 0, value);
144 return ret;
147 static public DataConverter LittleEndian {
148 get {
149 return BitConverter.IsLittleEndian ? CopyConv : SwapConv;
153 static public DataConverter BigEndian {
154 get {
155 return BitConverter.IsLittleEndian ? SwapConv : CopyConv;
159 static public DataConverter Native {
160 get {
161 return CopyConv;
165 static int Align (int current, int align)
167 return ((current + align - 1) / align) * align;
170 class PackContext {
171 // Buffer
172 public byte [] buffer;
173 int next;
175 public string description;
176 public int i; // position in the description
177 public DataConverter conv;
178 public int repeat;
181 // if align == -1, auto align to the size of the byte array
182 // if align == 0, do not do alignment
183 // Any other values aligns to that particular size
185 public int align;
187 public void Add (byte [] group)
189 //Console.WriteLine ("Adding {0} bytes to {1} (next={2}", group.Length,
190 // buffer == null ? "null" : buffer.Length.ToString (), next);
192 if (buffer == null){
193 buffer = group;
194 next = group.Length;
195 return;
197 if (align != 0){
198 if (align == -1)
199 next = Align (next, group.Length);
200 else
201 next = Align (next, align);
202 align = 0;
205 if (next + group.Length > buffer.Length){
206 byte [] nb = new byte [System.Math.Max (next, 16) * 2 + group.Length];
207 Array.Copy (buffer, nb, buffer.Length);
208 Array.Copy (group, 0, nb, next, group.Length);
209 next = next + group.Length;
210 buffer = nb;
211 } else {
212 Array.Copy (group, 0, buffer, next, group.Length);
213 next += group.Length;
217 public byte [] Get ()
219 if (buffer == null)
220 return new byte [0];
222 if (buffer.Length != next){
223 byte [] b = new byte [next];
224 Array.Copy (buffer, b, next);
225 return b;
227 return buffer;
232 // Format includes:
233 // Control:
234 // ^ Switch to big endian encoding
235 // _ Switch to little endian encoding
236 // % Switch to host (native) encoding
237 // ! aligns the next data type to its natural boundary (for strings this is 4).
239 // Types:
240 // s Int16
241 // S UInt16
242 // i Int32
243 // I UInt32
244 // l Int64
245 // L UInt64
246 // f float
247 // d double
248 // b byte
249 // c 1-byte signed character
250 // C 1-byte unsigned character
251 // z8 string encoded as UTF8 with 1-byte null terminator
252 // z6 string encoded as UTF16 with 2-byte null terminator
253 // z7 string encoded as UTF7 with 1-byte null terminator
254 // zb string encoded as BigEndianUnicode with 2-byte null terminator
255 // z3 string encoded as UTF32 with 4-byte null terminator
256 // z4 string encoded as UTF32 big endian with 4-byte null terminator
257 // $8 string encoded as UTF8
258 // $6 string encoded as UTF16
259 // $7 string encoded as UTF7
260 // $b string encoded as BigEndianUnicode
261 // $3 string encoded as UTF32
262 // $4 string encoded as UTF-32 big endian encoding
263 // x null byte
265 // Repeats, these are prefixes:
266 // N a number between 1 and 9, indicates a repeat count (process N items
267 // with the following datatype
268 // [N] For numbers larger than 9, use brackets, for example [20]
269 // * Repeat the next data type until the arguments are exhausted
271 static public byte [] Pack (string description, params object [] args)
273 int argn = 0;
274 PackContext b = new PackContext ();
275 b.conv = CopyConv;
276 b.description = description;
278 for (b.i = 0; b.i < description.Length; ){
279 object oarg;
281 if (argn < args.Length)
282 oarg = args [argn];
283 else {
284 if (b.repeat != 0)
285 break;
287 oarg = null;
290 int save = b.i;
292 if (PackOne (b, oarg)){
293 argn++;
294 if (b.repeat > 0){
295 if (--b.repeat > 0)
296 b.i = save;
297 else
298 b.i++;
299 } else
300 b.i++;
301 } else
302 b.i++;
304 return b.Get ();
307 static public byte [] PackEnumerable (string description, IEnumerable args)
309 PackContext b = new PackContext ();
310 b.conv = CopyConv;
311 b.description = description;
313 IEnumerator enumerator = args.GetEnumerator ();
314 bool ok = enumerator.MoveNext ();
316 for (b.i = 0; b.i < description.Length; ){
317 object oarg;
319 if (ok)
320 oarg = enumerator.Current;
321 else {
322 if (b.repeat != 0)
323 break;
324 oarg = null;
327 int save = b.i;
329 if (PackOne (b, oarg)){
330 ok = enumerator.MoveNext ();
331 if (b.repeat > 0){
332 if (--b.repeat > 0)
333 b.i = save;
334 else
335 b.i++;
336 } else
337 b.i++;
338 } else
339 b.i++;
341 return b.Get ();
345 // Packs one datum `oarg' into the buffer `b', using the string format
346 // in `description' at position `i'
348 // Returns: true if we must pick the next object from the list
350 static bool PackOne (PackContext b, object oarg)
352 int n;
354 switch (b.description [b.i]){
355 case '^':
356 b.conv = BigEndian;
357 return false;
358 case '_':
359 b.conv = LittleEndian;
360 return false;
361 case '%':
362 b.conv = Native;
363 return false;
365 case '!':
366 b.align = -1;
367 return false;
369 case 'x':
370 b.Add (new byte [] { 0 });
371 return false;
373 // Type Conversions
374 case 'i':
375 b.Add (b.conv.GetBytes (Convert.ToInt32 (oarg)));
376 break;
378 case 'I':
379 b.Add (b.conv.GetBytes (Convert.ToUInt32 (oarg)));
380 break;
382 case 's':
383 b.Add (b.conv.GetBytes (Convert.ToInt16 (oarg)));
384 break;
386 case 'S':
387 b.Add (b.conv.GetBytes (Convert.ToUInt16 (oarg)));
388 break;
390 case 'l':
391 b.Add (b.conv.GetBytes (Convert.ToInt64 (oarg)));
392 break;
394 case 'L':
395 b.Add (b.conv.GetBytes (Convert.ToUInt64 (oarg)));
396 break;
398 case 'f':
399 b.Add (b.conv.GetBytes (Convert.ToSingle (oarg)));
400 break;
402 case 'd':
403 b.Add (b.conv.GetBytes (Convert.ToDouble (oarg)));
404 break;
406 case 'b':
407 b.Add (new byte [] { Convert.ToByte (oarg) });
408 break;
410 case 'c':
411 b.Add (new byte [] { (byte) (Convert.ToSByte (oarg)) });
412 break;
414 case 'C':
415 b.Add (new byte [] { Convert.ToByte (oarg) });
416 break;
418 // Repeat acount;
419 case '1': case '2': case '3': case '4': case '5':
420 case '6': case '7': case '8': case '9':
421 b.repeat = ((short) b.description [b.i]) - ((short) '0');
422 return false;
424 case '*':
425 b.repeat = Int32.MaxValue;
426 return false;
428 case '[':
429 int count = -1, j;
431 for (j = b.i+1; j < b.description.Length; j++){
432 if (b.description [j] == ']')
433 break;
434 n = ((short) b.description [j]) - ((short) '0');
435 if (n >= 0 && n <= 9){
436 if (count == -1)
437 count = n;
438 else
439 count = count * 10 + n;
442 if (count == -1)
443 throw new ArgumentException ("invalid size specification");
444 b.i = j;
445 b.repeat = count;
446 return false;
448 case '$': case 'z':
449 bool add_null = b.description [b.i] == 'z';
450 b.i++;
451 if (b.i >= b.description.Length)
452 throw new ArgumentException ("$ description needs a type specified", "description");
453 char d = b.description [b.i];
454 Encoding e;
456 switch (d){
457 case '8':
458 e = Encoding.UTF8;
459 n = 1;
460 break;
461 case '6':
462 e = Encoding.Unicode;
463 n = 2;
464 break;
465 case '7':
466 e = Encoding.UTF7;
467 n = 1;
468 break;
469 case 'b':
470 e = Encoding.BigEndianUnicode;
471 n = 2;
472 break;
473 case '3':
474 e = Encoding.GetEncoding (12000);
475 n = 4;
476 break;
477 case '4':
478 e = Encoding.GetEncoding (12001);
479 n = 4;
480 break;
482 default:
483 throw new ArgumentException ("Invalid format for $ specifier", "description");
485 if (b.align == -1)
486 b.align = 4;
487 b.Add (e.GetBytes (Convert.ToString (oarg)));
488 if (add_null)
489 b.Add (new byte [n]);
490 break;
491 default:
492 throw new ArgumentException (String.Format ("invalid format specified `{0}'",
493 b.description [b.i]));
495 return true;
498 static bool Prepare (byte [] buffer, ref int idx, int size, ref bool align)
500 if (align){
501 idx = Align (idx, size);
502 align = false;
504 if (idx + size > buffer.Length){
505 idx = buffer.Length;
506 return false;
508 return true;
511 static public IList Unpack (string description, byte [] buffer, int startIndex)
513 DataConverter conv = CopyConv;
514 ArrayList result = new ArrayList ();
515 int idx = startIndex;
516 bool align = false;
517 int repeat = 0, n;
519 for (int i = 0; i < description.Length && idx < buffer.Length; ){
520 int save = i;
522 switch (description [i]){
523 case '^':
524 conv = BigEndian;
525 break;
526 case '_':
527 conv = LittleEndian;
528 break;
529 case '%':
530 conv = Native;
531 break;
532 case 'x':
533 idx++;
534 break;
536 case '!':
537 align = true;
538 break;
540 // Type Conversions
541 case 'i':
542 if (Prepare (buffer, ref idx, 4, ref align)){
543 result.Add (conv.GetInt32 (buffer, idx));
544 idx += 4;
546 break;
548 case 'I':
549 if (Prepare (buffer, ref idx, 4, ref align)){
550 result.Add (conv.GetUInt32 (buffer, idx));
551 idx += 4;
553 break;
555 case 's':
556 if (Prepare (buffer, ref idx, 2, ref align)){
557 result.Add (conv.GetInt16 (buffer, idx));
558 idx += 2;
560 break;
562 case 'S':
563 if (Prepare (buffer, ref idx, 2, ref align)){
564 result.Add (conv.GetUInt16 (buffer, idx));
565 idx += 2;
567 break;
569 case 'l':
570 if (Prepare (buffer, ref idx, 8, ref align)){
571 result.Add (conv.GetInt64 (buffer, idx));
572 idx += 8;
574 break;
576 case 'L':
577 if (Prepare (buffer, ref idx, 8, ref align)){
578 result.Add (conv.GetUInt64 (buffer, idx));
579 idx += 8;
581 break;
583 case 'f':
584 if (Prepare (buffer, ref idx, 4, ref align)){
585 result.Add (conv.GetDouble (buffer, idx));
586 idx += 4;
588 break;
590 case 'd':
591 if (Prepare (buffer, ref idx, 8, ref align)){
592 result.Add (conv.GetDouble (buffer, idx));
593 idx += 8;
595 break;
597 case 'b':
598 if (Prepare (buffer, ref idx, 1, ref align)){
599 result.Add (buffer [idx]);
600 idx++;
602 break;
604 case 'c': case 'C':
605 if (Prepare (buffer, ref idx, 1, ref align)){
606 char c;
608 if (description [i] == 'c')
609 c = ((char) ((sbyte)buffer [idx]));
610 else
611 c = ((char) ((byte)buffer [idx]));
613 result.Add (c);
614 idx++;
616 break;
618 // Repeat acount;
619 case '1': case '2': case '3': case '4': case '5':
620 case '6': case '7': case '8': case '9':
621 repeat = ((short) description [i]) - ((short) '0');
622 save = i + 1;
623 break;
625 case '*':
626 repeat = Int32.MaxValue;
627 break;
629 case '[':
630 int count = -1, j;
632 for (j = i+1; j < description.Length; j++){
633 if (description [j] == ']')
634 break;
635 n = ((short) description [j]) - ((short) '0');
636 if (n >= 0 && n <= 9){
637 if (count == -1)
638 count = n;
639 else
640 count = count * 10 + n;
643 if (count == -1)
644 throw new ArgumentException ("invalid size specification");
645 i = j;
646 repeat = count;
647 break;
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;
660 if (idx >= buffer.Length)
661 break;
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;
689 default:
690 throw new ArgumentException ("Invalid format for $ specifier", "description");
692 int k = idx;
693 switch (n){
694 case 1:
695 for (; k < buffer.Length && buffer [k] != 0; k++)
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;
704 case 2:
705 for (; k < buffer.Length; k++){
706 if (k+1 == buffer.Length){
707 k++;
708 break;
710 if (buffer [k] == 0 && buffer [k+1] == 0)
711 break;
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;
720 case 4:
721 for (; k < buffer.Length; k++){
722 if (k+3 >= buffer.Length){
723 k = buffer.Length;
724 break;
726 if (buffer[k]==0 && buffer[k+1] == 0 && buffer[k+2] == 0 && buffer[k+3]== 0)
727 break;
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;
736 break;
737 default:
738 throw new ArgumentException (String.Format ("invalid format specified `{0}'",
739 description [i]));
742 if (repeat > 0){
743 if (--repeat > 0)
744 i = save;
745 } else
746 i++;
748 return result;
751 internal void Check (byte [] dest, int destIdx, int size)
753 if (dest == null)
754 throw new ArgumentNullException ("dest");
755 if (destIdx < 0 || destIdx > dest.Length - size)
756 throw new ArgumentException ("destIdx");
759 class CopyConverter : DataConverter {
760 public override double GetDouble (byte [] data, int index)
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;
771 for (int i = 0; i < 8; i++)
772 b [i] = data [index+i];
774 return ret;
777 public override ulong GetUInt64 (byte [] data, int index)
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");
786 ulong ret;
787 byte *b = (byte *)&ret;
789 for (int i = 0; i < 8; i++)
790 b [i] = data [index+i];
792 return ret;
795 public override long GetInt64 (byte [] data, int index)
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");
804 long ret;
805 byte *b = (byte *)&ret;
807 for (int i = 0; i < 8; i++)
808 b [i] = data [index+i];
810 return ret;
813 public override float GetFloat (byte [] data, int index)
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");
822 float ret;
823 byte *b = (byte *)&ret;
825 for (int i = 0; i < 4; i++)
826 b [i] = data [index+i];
828 return ret;
831 public override int GetInt32 (byte [] data, int index)
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");
840 int ret;
841 byte *b = (byte *)&ret;
843 for (int i = 0; i < 4; i++)
844 b [i] = data [index+i];
846 return ret;
849 public override uint GetUInt32 (byte [] data, int index)
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");
858 uint ret;
859 byte *b = (byte *)&ret;
861 for (int i = 0; i < 4; i++)
862 b [i] = data [index+i];
864 return ret;
867 public override short GetInt16 (byte [] data, int index)
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");
876 short ret;
877 byte *b = (byte *)&ret;
879 for (int i = 0; i < 2; i++)
880 b [i] = data [index+i];
882 return ret;
885 public override ushort GetUInt16 (byte [] data, int index)
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");
894 ushort ret;
895 byte *b = (byte *)&ret;
897 for (int i = 0; i < 2; i++)
898 b [i] = data [index+i];
900 return ret;
903 public override void PutBytes (byte [] dest, int destIdx, double value)
905 Check (dest, destIdx, 8);
906 fixed (byte *target = &dest [destIdx]){
907 long *source = (long *) &value;
909 *((long *)target) = *source;
913 public override void PutBytes (byte [] dest, int destIdx, float value)
915 Check (dest, destIdx, 4);
916 fixed (byte *target = &dest [destIdx]){
917 uint *source = (uint *) &value;
919 *((uint *)target) = *source;
923 public override void PutBytes (byte [] dest, int destIdx, int value)
925 Check (dest, destIdx, 4);
926 fixed (byte *target = &dest [destIdx]){
927 uint *source = (uint *) &value;
929 *((uint *)target) = *source;
933 public override void PutBytes (byte [] dest, int destIdx, uint value)
935 Check (dest, destIdx, 4);
936 fixed (byte *target = &dest [destIdx]){
937 uint *source = (uint *) &value;
939 *((uint *)target) = *source;
943 public override void PutBytes (byte [] dest, int destIdx, long value)
945 Check (dest, destIdx, 8);
946 fixed (byte *target = &dest [destIdx]){
947 long *source = (long *) &value;
949 *((long*)target) = *source;
953 public override void PutBytes (byte [] dest, int destIdx, ulong value)
955 Check (dest, destIdx, 8);
956 fixed (byte *target = &dest [destIdx]){
957 ulong *source = (ulong *) &value;
959 *((ulong *) target) = *source;
963 public override void PutBytes (byte [] dest, int destIdx, short value)
965 Check (dest, destIdx, 2);
966 fixed (byte *target = &dest [destIdx]){
967 ushort *source = (ushort *) &value;
969 *((ushort *)target) = *source;
973 public override void PutBytes (byte [] dest, int destIdx, ushort value)
975 Check (dest, destIdx, 2);
976 fixed (byte *target = &dest [destIdx]){
977 ushort *source = (ushort *) &value;
979 *((ushort *)target) = *source;
984 class SwapConverter : DataConverter {
985 public override double GetDouble (byte [] data, int index)
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");
994 double ret;
995 byte *b = (byte *)&ret;
997 for (int i = 0; i < 8; i++)
998 b [7-i] = data [index+i];
1000 return ret;
1003 public override ulong GetUInt64 (byte [] data, int index)
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");
1012 ulong ret;
1013 byte *b = (byte *)&ret;
1015 for (int i = 0; i < 8; i++)
1016 b [7-i] = data [index+i];
1018 return ret;
1021 public override long GetInt64 (byte [] data, int index)
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");
1030 long ret;
1031 byte *b = (byte *)&ret;
1033 for (int i = 0; i < 8; i++)
1034 b [7-i] = data [index+i];
1036 return ret;
1039 public override float GetFloat (byte [] data, int index)
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");
1048 float ret;
1049 byte *b = (byte *)&ret;
1051 for (int i = 0; i < 4; i++)
1052 b [3-i] = data [index+i];
1054 return ret;
1057 public override int GetInt32 (byte [] data, int index)
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");
1066 int ret;
1067 byte *b = (byte *)&ret;
1069 for (int i = 0; i < 4; i++)
1070 b [3-i] = data [index+i];
1072 return ret;
1075 public override uint GetUInt32 (byte [] data, int index)
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");
1084 uint ret;
1085 byte *b = (byte *)&ret;
1087 for (int i = 0; i < 4; i++)
1088 b [3-i] = data [index+i];
1090 return ret;
1093 public override short GetInt16 (byte [] data, int index)
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");
1102 short ret;
1103 byte *b = (byte *)&ret;
1105 for (int i = 0; i < 2; i++)
1106 b [1-i] = data [index+i];
1108 return ret;
1111 public override ushort GetUInt16 (byte [] data, int index)
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");
1120 ushort ret;
1121 byte *b = (byte *)&ret;
1123 for (int i = 0; i < 2; i++)
1124 b [1-i] = data [index+i];
1126 return ret;
1129 public override void PutBytes (byte [] dest, int destIdx, double value)
1131 Check (dest, destIdx, 8);
1133 fixed (byte *target = &dest [destIdx]){
1134 byte *source = (byte *) &value;
1136 for (int i = 0; i < 8; i++)
1137 target [i] = source [7-i];
1141 public override void PutBytes (byte [] dest, int destIdx, float value)
1143 Check (dest, destIdx, 4);
1145 fixed (byte *target = &dest [destIdx]){
1146 byte *source = (byte *) &value;
1148 for (int i = 0; i < 4; i++)
1149 target [i] = source [3-i];
1153 public override void PutBytes (byte [] dest, int destIdx, int value)
1155 Check (dest, destIdx, 4);
1157 fixed (byte *target = &dest [destIdx]){
1158 byte *source = (byte *) &value;
1160 for (int i = 0; i < 4; i++)
1161 target [i] = source [3-i];
1165 public override void PutBytes (byte [] dest, int destIdx, uint value)
1167 Check (dest, destIdx, 4);
1169 fixed (byte *target = &dest [destIdx]){
1170 byte *source = (byte *) &value;
1172 for (int i = 0; i < 4; i++)
1173 target [i] = source [3-i];
1177 public override void PutBytes (byte [] dest, int destIdx, long value)
1179 Check (dest, destIdx, 8);
1181 fixed (byte *target = &dest [destIdx]){
1182 byte *source = (byte *) &value;
1184 for (int i = 0; i < 8; i++)
1185 target [i] = source [7-i];
1189 public override void PutBytes (byte [] dest, int destIdx, ulong value)
1191 Check (dest, destIdx, 8);
1193 fixed (byte *target = &dest [destIdx]){
1194 byte *source = (byte *) &value;
1196 for (int i = 0; i < 4; i++)
1197 target [i] = source [7-i];
1201 public override void PutBytes (byte [] dest, int destIdx, short value)
1203 Check (dest, destIdx, 2);
1205 fixed (byte *target = &dest [destIdx]){
1206 byte *source = (byte *) &value;
1208 for (int i = 0; i < 2; i++)
1209 target [i] = source [1-i];
1213 public override void PutBytes (byte [] dest, int destIdx, ushort value)
1215 Check (dest, destIdx, 2);
1217 fixed (byte *target = &dest [destIdx]){
1218 byte *source = (byte *) &value;
1220 for (int i = 0; i < 2; i++)
1221 target [i] = source [1-i];
1226 #if MONO_DATACONVERTER_STATIC_METHODS
1227 static unsafe void PutBytesLE (byte *dest, byte *src, int count)
1229 int i = 0;
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++;
1241 static unsafe void PutBytesBE (byte *dest, byte *src, int count)
1243 int i = 0;
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++;
1255 static unsafe void PutBytesNative (byte *dest, byte *src, int count)
1257 int i = 0;
1259 for (; i < count; i++)
1260 dest [i-count] = *src++;
1263 static public unsafe double DoubleFromLE (byte[] data, int index)
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");
1272 double ret;
1273 fixed (byte *src = &data[index]){
1274 PutBytesLE ((byte *) &ret, src, 8);
1276 return ret;
1279 static public unsafe float FloatFromLE (byte [] data, int index)
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");
1288 float ret;
1289 fixed (byte *src = &data[index]){
1290 PutBytesLE ((byte *) &ret, src, 4);
1292 return ret;
1295 static public unsafe long Int64FromLE (byte [] data, int index)
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");
1304 long ret;
1305 fixed (byte *src = &data[index]){
1306 PutBytesLE ((byte *) &ret, src, 8);
1308 return ret;
1311 static public unsafe ulong UInt64FromLE (byte [] data, int index)
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");
1320 ulong ret;
1321 fixed (byte *src = &data[index]){
1322 PutBytesLE ((byte *) &ret, src, 8);
1324 return ret;
1327 static public unsafe int Int32FromLE (byte [] data, int index)
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");
1336 int ret;
1337 fixed (byte *src = &data[index]){
1338 PutBytesLE ((byte *) &ret, src, 4);
1340 return ret;
1343 static public unsafe uint UInt32FromLE (byte [] data, int index)
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");
1352 uint ret;
1353 fixed (byte *src = &data[index]){
1354 PutBytesLE ((byte *) &ret, src, 4);
1356 return ret;
1359 static public unsafe short Int16FromLE (byte [] data, int index)
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");
1368 short ret;
1369 fixed (byte *src = &data[index]){
1370 PutBytesLE ((byte *) &ret, src, 2);
1372 return ret;
1375 static public unsafe ushort UInt16FromLE (byte [] data, int index)
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");
1384 ushort ret;
1385 fixed (byte *src = &data[index]){
1386 PutBytesLE ((byte *) &ret, src, 2);
1388 return ret;
1391 static public unsafe double DoubleFromBE (byte[] data, int index)
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");
1400 double ret;
1401 fixed (byte *src = &data[index]){
1402 PutBytesBE ((byte *) &ret, src, 8);
1404 return ret;
1407 static public unsafe float FloatFromBE (byte [] data, int index)
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");
1416 float ret;
1417 fixed (byte *src = &data[index]){
1418 PutBytesBE ((byte *) &ret, src, 4);
1420 return ret;
1423 static public unsafe long Int64FromBE (byte [] data, int index)
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");
1432 long ret;
1433 fixed (byte *src = &data[index]){
1434 PutBytesBE ((byte *) &ret, src, 8);
1436 return ret;
1439 static public unsafe ulong UInt64FromBE (byte [] data, int index)
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");
1448 ulong ret;
1449 fixed (byte *src = &data[index]){
1450 PutBytesBE ((byte *) &ret, src, 8);
1452 return ret;
1455 static public unsafe int Int32FromBE (byte [] data, int index)
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");
1464 int ret;
1465 fixed (byte *src = &data[index]){
1466 PutBytesBE ((byte *) &ret, src, 4);
1468 return ret;
1471 static public unsafe uint UInt32FromBE (byte [] data, int index)
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");
1480 uint ret;
1481 fixed (byte *src = &data[index]){
1482 PutBytesBE ((byte *) &ret, src, 4);
1484 return ret;
1487 static public unsafe short Int16FromBE (byte [] data, int index)
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");
1496 short ret;
1497 fixed (byte *src = &data[index]){
1498 PutBytesBE ((byte *) &ret, src, 2);
1500 return ret;
1503 static public unsafe ushort UInt16FromBE (byte [] data, int index)
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");
1512 ushort ret;
1513 fixed (byte *src = &data[index]){
1514 PutBytesBE ((byte *) &ret, src, 2);
1516 return ret;
1519 static public unsafe double DoubleFromNative (byte[] data, int index)
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");
1528 double ret;
1529 fixed (byte *src = &data[index]){
1530 PutBytesNative ((byte *) &ret, src, 8);
1532 return ret;
1535 static public unsafe float FloatFromNative (byte [] data, int index)
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");
1544 float ret;
1545 fixed (byte *src = &data[index]){
1546 PutBytesNative ((byte *) &ret, src, 4);
1548 return ret;
1551 static public unsafe long Int64FromNative (byte [] data, int index)
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");
1560 long ret;
1561 fixed (byte *src = &data[index]){
1562 PutBytesNative ((byte *) &ret, src, 8);
1564 return ret;
1567 static public unsafe ulong UInt64FromNative (byte [] data, int index)
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");
1576 ulong ret;
1577 fixed (byte *src = &data[index]){
1578 PutBytesNative ((byte *) &ret, src, 8);
1580 return ret;
1583 static public unsafe int Int32FromNative (byte [] data, int index)
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");
1592 int ret;
1593 fixed (byte *src = &data[index]){
1594 PutBytesNative ((byte *) &ret, src, 4);
1596 return ret;
1599 static public unsafe uint UInt32FromNative (byte [] data, int index)
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");
1608 uint ret;
1609 fixed (byte *src = &data[index]){
1610 PutBytesNative ((byte *) &ret, src, 4);
1612 return ret;
1615 static public unsafe short Int16FromNative (byte [] data, int index)
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");
1624 short ret;
1625 fixed (byte *src = &data[index]){
1626 PutBytesNative ((byte *) &ret, src, 2);
1628 return ret;
1631 static public unsafe ushort UInt16FromNative (byte [] data, int index)
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");
1640 ushort ret;
1641 fixed (byte *src = &data[index]){
1642 PutBytesNative ((byte *) &ret, src, 2);
1644 return ret;
1647 unsafe static byte[] GetBytesPtr (byte *ptr, int count)
1649 byte [] ret = new byte [count];
1651 for (int i = 0; i < count; i++) {
1652 ret [i] = ptr [i];
1655 return ret;
1658 unsafe static byte[] GetBytesSwap (bool swap, byte *ptr, int count)
1660 byte [] ret = new byte [count];
1662 if (swap){
1663 int t = count-1;
1664 for (int i = 0; i < count; i++) {
1665 ret [t-i] = ptr [i];
1667 } else {
1668 for (int i = 0; i < count; i++) {
1669 ret [i] = ptr [i];
1672 return ret;
1675 unsafe public static byte[] GetBytesNative (bool value)
1677 return GetBytesPtr ((byte *) &value, 1);
1680 unsafe public static byte[] GetBytesNative (char value)
1682 return GetBytesPtr ((byte *) &value, 2);
1685 unsafe public static byte[] GetBytesNative (short value)
1687 return GetBytesPtr ((byte *) &value, 2);
1690 unsafe public static byte[] GetBytesNative (int value)
1692 return GetBytesPtr ((byte *) &value, 4);
1695 unsafe public static byte[] GetBytesNative (long value)
1697 return GetBytesPtr ((byte *) &value, 8);
1700 [CLSCompliant (false)]
1701 unsafe public static byte[] GetBytesNative (ushort value)
1703 return GetBytesPtr ((byte *) &value, 2);
1706 [CLSCompliant (false)]
1707 unsafe public static byte[] GetBytesNative (uint value)
1709 return GetBytesPtr ((byte *) &value, 4);
1712 [CLSCompliant (false)]
1713 unsafe public static byte[] GetBytesNative (ulong value)
1715 return GetBytesPtr ((byte *) &value, 8);
1718 unsafe public static byte[] GetBytesNative (float value)
1720 return GetBytesPtr ((byte *) &value, 4);
1723 unsafe public static byte[] GetBytesNative (double value)
1725 return GetBytesPtr ((byte *) &value, 8);
1728 unsafe public static byte[] GetBytesLE (bool value)
1730 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 1);
1733 unsafe public static byte[] GetBytesLE (char value)
1735 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
1738 unsafe public static byte[] GetBytesLE (short value)
1740 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
1743 unsafe public static byte[] GetBytesLE (int value)
1745 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
1748 unsafe public static byte[] GetBytesLE (long value)
1750 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
1753 [CLSCompliant (false)]
1754 unsafe public static byte[] GetBytesLE (ushort value)
1756 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
1759 [CLSCompliant (false)]
1760 unsafe public static byte[] GetBytesLE (uint value)
1762 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
1765 [CLSCompliant (false)]
1766 unsafe public static byte[] GetBytesLE (ulong value)
1768 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
1771 unsafe public static byte[] GetBytesLE (float value)
1773 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
1776 unsafe public static byte[] GetBytesLE (double value)
1778 return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
1781 unsafe public static byte[] GetBytesBE (bool value)
1783 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 1);
1786 unsafe public static byte[] GetBytesBE (char value)
1788 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
1791 unsafe public static byte[] GetBytesBE (short value)
1793 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
1796 unsafe public static byte[] GetBytesBE (int value)
1798 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
1801 unsafe public static byte[] GetBytesBE (long value)
1803 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
1806 [CLSCompliant (false)]
1807 unsafe public static byte[] GetBytesBE (ushort value)
1809 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
1812 [CLSCompliant (false)]
1813 unsafe public static byte[] GetBytesBE (uint value)
1815 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
1818 [CLSCompliant (false)]
1819 unsafe public static byte[] GetBytesBE (ulong value)
1821 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
1824 unsafe public static byte[] GetBytesBE (float value)
1826 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
1829 unsafe public static byte[] GetBytesBE (double value)
1831 return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
1833 #endif