2007-08-17 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / Mono / DataConverter.cs
index 175c65d52f1c4be76f590a022d68f9f673012c98..34ff82ee1d9b02c98a6f6da8078a4f6ada0218f2 100644 (file)
 //
 // TODO:
 //   Support for "DoubleWordsAreSwapped" for ARM devices
-//   Add PutBytes (byte [] dest, int destIdx, xx value)
-//   Make GetBytes use the above.
-//
-//   Make all the GetBtesXXX use a byte [] dest, int dest
 //
 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
 //
@@ -50,6 +46,10 @@ namespace Mono {
        unsafe public abstract class DataConverter {
 #else
        unsafe internal abstract class DataConverter {
+
+// Disables the warning: CLS compliance checking will not be performed on
+//  `XXXX' because it is not visible from outside this assembly
+#pragma warning disable  3019
 #endif
                static DataConverter SwapConv = new SwapConverter ();
                static DataConverter CopyConv = new CopyConverter ();
@@ -70,18 +70,77 @@ namespace Mono {
                 [CLSCompliant (false)]
                public abstract ulong  GetUInt64 (byte [] data, int index);
                
-               public abstract byte[] GetBytes (double value);
-               public abstract byte[] GetBytes (float value);
-               public abstract byte[] GetBytes (int value);
-               public abstract byte[] GetBytes (long value);
-               public abstract byte[] GetBytes (short value);
+               public abstract void PutBytes (byte [] dest, int destIdx, double value);
+               public abstract void PutBytes (byte [] dest, int destIdx, float value);
+               public abstract void PutBytes (byte [] dest, int destIdx, int value);
+               public abstract void PutBytes (byte [] dest, int destIdx, long value);
+               public abstract void PutBytes (byte [] dest, int destIdx, short value);
 
                 [CLSCompliant (false)]
-               public abstract byte[] GetBytes (ushort value);
+               public abstract void PutBytes (byte [] dest, int destIdx, ushort value);
                 [CLSCompliant (false)]
-               public abstract byte[] GetBytes (uint value);
+               public abstract void PutBytes (byte [] dest, int destIdx, uint value);
                 [CLSCompliant (false)]
-               public abstract byte[] GetBytes (ulong value);
+               public abstract void PutBytes (byte [] dest, int destIdx, ulong value);
+
+               public byte[] GetBytes (double value)
+               {
+                       byte [] ret = new byte [8];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+               
+               public byte[] GetBytes (float value)
+               {
+                       byte [] ret = new byte [4];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+               
+               public byte[] GetBytes (int value)
+               {
+                       byte [] ret = new byte [4];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+               
+               public byte[] GetBytes (long value)
+               {
+                       byte [] ret = new byte [8];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+               
+               public byte[] GetBytes (short value)
+               {
+                       byte [] ret = new byte [2];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+
+                [CLSCompliant (false)]
+               public byte[] GetBytes (ushort value)
+               {
+                       byte [] ret = new byte [2];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+               
+                [CLSCompliant (false)]
+               public byte[] GetBytes (uint value)
+               {
+                       byte [] ret = new byte [4];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
+               
+                [CLSCompliant (false)]
+               public byte[] GetBytes (ulong value)
+               {
+                       byte [] ret = new byte [8];
+                       PutBytes (ret, 0, value);
+                       return ret;
+               }
                
                static public DataConverter LittleEndian {
                        get {
@@ -138,7 +197,6 @@ namespace Mono {
                                                next = Align (next, group.Length);
                                        else
                                                next = Align (next, align);
-                                       Console.WriteLine ("Aligned to {0}", next);
                                        align = 0;
                                }
 
@@ -225,12 +283,10 @@ namespace Mono {
                                        oarg = null;
                                }
 
-                               Console.WriteLine ("processing instruction {0} -> {1}", description [b.i], oarg);
                                int save = b.i;
                                
                                if (PackOne (b, oarg)){
                                        argn++;
-                                       Console.WriteLine ("Repeat={0}", b.repeat);
                                        if (b.repeat > 0){
                                                if (--b.repeat > 0)
                                                        b.i = save;
@@ -289,6 +345,8 @@ namespace Mono {
                //
                static bool PackOne (PackContext b, object oarg)
                {
+                       int n;
+                       
                        switch (b.description [b.i]){
                        case '^':
                                b.conv = BigEndian;
@@ -369,7 +427,7 @@ namespace Mono {
                                for (j = b.i+1; j < b.description.Length; j++){
                                        if (b.description [j] == ']')
                                                break;
-                                       int n = ((short) b.description [j]) - ((short) '0');
+                                       n = ((short) b.description [j]) - ((short) '0');
                                        if (n >= 0 && n <= 9){
                                                if (count == -1)
                                                        count = n;
@@ -385,7 +443,6 @@ namespace Mono {
                                
                        case '$': case 'z':
                                bool add_null = b.description [b.i] == 'z';
-                               int n;
                                b.i++;
                                if (b.i >= b.description.Length)
                                        throw new ArgumentException ("$ description needs a type specified", "description");
@@ -452,7 +509,7 @@ namespace Mono {
                        ArrayList result = new ArrayList ();
                        int idx = startIndex;
                        bool align = false;
-                       int repeat = 0;
+                       int repeat = 0, n;
                        
                        for (int i = 0; i < description.Length && idx < buffer.Length; ){
                                int save = i;
@@ -569,7 +626,7 @@ namespace Mono {
                                        for (j = i+1; j < description.Length; j++){
                                                if (description [j] == ']')
                                                        break;
-                                               int n = ((short) description [j]) - ((short) '0');
+                                               n = ((short) description [j]) - ((short) '0');
                                                if (n >= 0 && n <= 9){
                                                        if (count == -1)
                                                                count = n;
@@ -585,7 +642,6 @@ namespace Mono {
                                
                                case '$': case 'z':
                                        // bool with_null = description [i] == 'z';
-                                       int n;
                                        i++;
                                        if (i >= description.Length)
                                                throw new ArgumentException ("$ description needs a type specified", "description");
@@ -685,6 +741,14 @@ namespace Mono {
                        }
                        return result;
                }
+
+               internal void Check (byte [] dest, int destIdx, int size)
+               {
+                       if (dest == null)
+                               throw new ArgumentNullException ("dest");
+                       if (destIdx < 0 || destIdx > dest.Length - size)
+                               throw new ArgumentException ("destIdx");
+               }
                
                class CopyConverter : DataConverter {
                        public override double GetDouble (byte [] data, int index)
@@ -830,100 +894,84 @@ namespace Mono {
                                return ret;
                        }
                        
-                       public override byte[] GetBytes (double value)
+                       public override void PutBytes (byte [] dest, int destIdx, double value)
                        {
-                               byte [] ret = new byte [8];
-                               fixed (byte *target = (&ret [0])){
+                               Check (dest, destIdx, 8);
+                               fixed (byte *target = &dest [destIdx]){
                                        long *source = (long *) &value;
 
                                        *((long *)target) = *source;
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (float value)
+                       public override void PutBytes (byte [] dest, int destIdx, float value)
                        {
-                               byte [] ret = new byte [4];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 4);
+                               fixed (byte *target = &dest [destIdx]){
                                        uint *source = (uint *) &value;
 
                                        *((uint *)target) = *source;
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (int value)
+                       public override void PutBytes (byte [] dest, int destIdx, int value)
                        {
-                               byte [] ret = new byte [4];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 4);
+                               fixed (byte *target = &dest [destIdx]){
                                        uint *source = (uint *) &value;
 
                                        *((uint *)target) = *source;
                                }
-
-                               return ret;
                        }
 
-                       public override byte[] GetBytes (uint value)
+                       public override void PutBytes (byte [] dest, int destIdx, uint value)
                        {
-                               byte [] ret = new byte [4];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 4);
+                               fixed (byte *target = &dest [destIdx]){
                                        uint *source = (uint *) &value;
 
                                        *((uint *)target) = *source;
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (long value)
+                       public override void PutBytes (byte [] dest, int destIdx, long value)
                        {
-                               byte [] ret = new byte [8];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 8);
+                               fixed (byte *target = &dest [destIdx]){
                                        long *source = (long *) &value;
 
                                        *((long*)target) = *source;
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (ulong value)
+                       public override void PutBytes (byte [] dest, int destIdx, ulong value)
                        {
-                               byte [] ret = new byte [8];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 8);
+                               fixed (byte *target = &dest [destIdx]){
                                        ulong *source = (ulong *) &value;
 
                                        *((ulong *) target) = *source;
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (short value)
+                       public override void PutBytes (byte [] dest, int destIdx, short value)
                        {
-                               byte [] ret = new byte [2];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 2);
+                               fixed (byte *target = &dest [destIdx]){
                                        ushort *source = (ushort *) &value;
 
                                        *((ushort *)target) = *source;
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (ushort value)
+                       public override void PutBytes (byte [] dest, int destIdx, ushort value)
                        {
-                               byte [] ret = new byte [2];
-                               fixed (byte *target = &ret [0]){
+                               Check (dest, destIdx, 2);
+                               fixed (byte *target = &dest [destIdx]){
                                        ushort *source = (ushort *) &value;
 
                                        *((ushort *)target) = *source;
                                }
-
-                               return ret;
                        }
                }
 
@@ -1072,116 +1120,100 @@ namespace Mono {
                                return ret;
                        }
 
-                       public override byte[] GetBytes (double value)
+                       public override void PutBytes (byte [] dest, int destIdx, double value)
                        {
-                               byte [] ret = new byte [8];
+                               Check (dest, destIdx, 8);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 8; i++)
                                                target [i] = source [7-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (float value)
+                       public override void PutBytes (byte [] dest, int destIdx, float value)
                        {
-                               byte [] ret = new byte [4];
+                               Check (dest, destIdx, 4);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 4; i++)
                                                target [i] = source [3-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (int value)
+                       public override void PutBytes (byte [] dest, int destIdx, int value)
                        {
-                               byte [] ret = new byte [4];
+                               Check (dest, destIdx, 4);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 4; i++)
                                                target [i] = source [3-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (uint value)
+                       public override void PutBytes (byte [] dest, int destIdx, uint value)
                        {
-                               byte [] ret = new byte [4];
+                               Check (dest, destIdx, 4);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 4; i++)
                                                target [i] = source [3-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (long value)
+                       public override void PutBytes (byte [] dest, int destIdx, long value)
                        {
-                               byte [] ret = new byte [8];
+                               Check (dest, destIdx, 8);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 8; i++)
                                                target [i] = source [7-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (ulong value)
+                       public override void PutBytes (byte [] dest, int destIdx, ulong value)
                        {
-                               byte [] ret = new byte [8];
+                               Check (dest, destIdx, 8);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 4; i++)
                                                target [i] = source [7-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (short value)
+                       public override void PutBytes (byte [] dest, int destIdx, short value)
                        {
-                               byte [] ret = new byte [2];
+                               Check (dest, destIdx, 2);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 2; i++)
                                                target [i] = source [1-i];
                                }
-
-                               return ret;
                        }
                        
-                       public override byte[] GetBytes (ushort value)
+                       public override void PutBytes (byte [] dest, int destIdx, ushort value)
                        {
-                               byte [] ret = new byte [2];
+                               Check (dest, destIdx, 2);
 
-                               fixed (byte *target = &ret [0]){
+                               fixed (byte *target = &dest [destIdx]){
                                        byte *source = (byte *) &value;
 
                                        for (int i = 0; i < 2; i++)
                                                target [i] = source [1-i];
                                }
-
-                               return ret;
                        }
                }
                
@@ -1194,8 +1226,9 @@ namespace Mono {
                                for (; i < count; i++)
                                        *dest++ = *src++;
                        } else {
+                               dest += count;
                                for (; i < count; i++)
-                                       dest [i-count] = *src++;
+                                       *(--dest) = *src++;
                        }
                }
 
@@ -1204,8 +1237,9 @@ namespace Mono {
                        int i = 0;
                        
                        if (BitConverter.IsLittleEndian){
+                               dest += count;
                                for (; i < count; i++)
-                                       dest [i-count] = *src++;
+                                       *(--dest) = *src++;
                        } else {
                                for (; i < count; i++)
                                        *dest++ = *src++;