Merge pull request #4793 from tijoytom/master
[platform/upstream/coreclr.git] / src / mscorlib / src / System / StubHelpers.cs
index 633becd..13437c0 100644 (file)
@@ -125,6 +125,111 @@ namespace  System.StubHelpers {
         }
     }  // class CSTRMarshaler
 
+    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+    internal static class UTF8Marshaler
+    {
+        const int MAX_UTF8_CHAR_SIZE = 3;
+        static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer)
+        {
+            if (null == strManaged)
+            {
+                return IntPtr.Zero;
+            }
+            StubHelpers.CheckStringLength(strManaged.Length);
+
+            int nb;
+            byte* pbNativeBuffer = (byte*)pNativeBuffer;
+
+            // If we are marshaling into a stack buffer allocated by the ILStub
+            // we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer.   
+            // else we will allocate the precise native heap memory.
+            if (pbNativeBuffer != null)
+            {
+                // this is the number of bytes allocated by the ILStub.
+                nb = (strManaged.Length + 1) * MAX_UTF8_CHAR_SIZE;
+
+                // nb is the actual number of bytes written by Encoding.GetBytes.
+                // use nb to de-limit the string since we are allocating more than 
+                // required on stack
+                nb = strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
+            }
+            // required bytes > 260 , allocate required bytes on heap
+            else
+            {
+                nb = Encoding.UTF8.GetByteCount(strManaged);
+                // + 1 for the null character.
+                pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 1);
+                strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
+            }
+            pbNativeBuffer[nb] = 0x0;
+            return (IntPtr)pbNativeBuffer;
+        }
+
+        static internal unsafe string ConvertToManaged(IntPtr cstr)
+        {
+            if (IntPtr.Zero == cstr)
+                return null;
+            int nbBytes = StubHelpers.strlen((sbyte*)cstr);
+            return String.CreateStringFromEncoding((byte*)cstr, nbBytes, Encoding.UTF8);
+        }
+
+        static internal void ClearNative(IntPtr pNative)
+        {
+            if (pNative != IntPtr.Zero)
+            {
+                Win32Native.CoTaskMemFree(pNative);
+            }
+        }
+    }
+
+    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+    internal static class UTF8BufferMarshaler
+    {
+        static internal unsafe IntPtr ConvertToNative(StringBuilder sb, IntPtr pNativeBuffer, int flags)
+        {
+            if (null == sb)
+            {
+                return IntPtr.Zero;
+            }
+
+            // Convert to string first  
+            string strManaged = sb.ToString();
+
+            // Get byte count 
+            int nb = Encoding.UTF8.GetByteCount(strManaged);
+
+            // EmitConvertSpaceCLRToNative allocates memory
+            byte* pbNativeBuffer = (byte*)pNativeBuffer;
+            nb = strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
+
+            pbNativeBuffer[nb] = 0x0;
+            return (IntPtr)pbNativeBuffer;
+        }
+
+        static internal unsafe void ConvertToManaged(StringBuilder sb, IntPtr pNative)
+        {
+            if (pNative == null)
+                return;
+
+            int nbBytes = StubHelpers.strlen((sbyte*)pNative);
+            int numChar = Encoding.UTF8.GetCharCount((byte*)pNative, nbBytes);
+
+            // +1 GetCharCount return 0 if the pNative points to a 
+            // an empty buffer.We still need to allocate an empty 
+            // buffer with a '\0' to distingiush it from null.
+            // Note that pinning on (char *pinned = new char[0])
+            // return null and  Encoding.UTF8.GetChars do not like 
+            // null argument.
+            char[] cCharBuffer = new char[numChar + 1];
+            cCharBuffer[numChar] = '\0';
+            fixed (char* pBuffer = cCharBuffer)
+            {
+                numChar = Encoding.UTF8.GetChars((byte*)pNative, nbBytes, pBuffer, numChar);
+                // replace string builder internal buffer
+                sb.ReplaceBufferInternal(pBuffer, numChar);
+            }
+        }
+    }
 
 #if FEATURE_COMINTEROP