[corlib] Add Mono.SafeStringMarshal struct
authorAleksey Kliger <aleksey@xamarin.com>
Tue, 19 Jul 2016 21:51:48 +0000 (17:51 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Fri, 29 Jul 2016 14:24:13 +0000 (10:24 -0400)
Allows safe allocation of native utf8 char* strings from managed
strings.

using (var h = new SafeStringMarshal (str)) {
   /* use h.Value IntPtr */
} // g_free'd by h.Dispose ()

mcs/class/corlib/Mono/SafeStringMarshal.cs [new file with mode: 0644]
mcs/class/corlib/corlib.dll.sources
mono/metadata/icall-def.h
mono/metadata/icall.c

diff --git a/mcs/class/corlib/Mono/SafeStringMarshal.cs b/mcs/class/corlib/Mono/SafeStringMarshal.cs
new file mode 100644 (file)
index 0000000..7950abb
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Safe wrapper for a string and its UTF8 encoding
+//
+// Authors:
+//   Aleksey Kliger <aleksey@xamarin.com>
+//   Rodrigo Kumpera <kumpera@xamarin.com>
+//
+// Copyright 2016 Dot net foundation.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Mono  {
+       internal struct SafeStringMarshal : IDisposable {
+               readonly string str;
+               IntPtr marshaled_string;
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern static IntPtr StringToUtf8 (string str);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern static void GFree (IntPtr ptr);
+
+               public SafeStringMarshal (string str) {
+                       this.str = str;
+               }
+
+               public IntPtr Value {
+                       get {
+                               if (marshaled_string == IntPtr.Zero)
+                                       marshaled_string = StringToUtf8 (str);
+                               return marshaled_string;
+                       }
+               }
+
+               public void Dispose () {
+                       if (marshaled_string != IntPtr.Zero) {
+                               GFree (marshaled_string);
+                               marshaled_string = IntPtr.Zero;
+                       }
+               }
+       }
+}
index b36d3d446bc4cea25a3674a2ca7ffe6724df5484..e17878fe2cfe735aa501c9016a50327c67728d03 100644 (file)
@@ -26,6 +26,7 @@ Mono/Runtime.cs
 Mono/RuntimeStructs.cs
 Mono/RuntimeHandles.cs
 Mono/SafeGPtrArrayHandle.cs
+Mono/SafeStringMarshal.cs
 Mono/DataConverter.cs
 Mono.Interop/ComInteropProxy.cs
 Mono.Interop/IDispatch.cs
index 757ed8c5be79f0dbc270a476f5eb2c9c359d997a..a4093bd76bc27ec034f9f19c358fc3317ae2da3e 100644 (file)
@@ -68,6 +68,10 @@ ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFr
 ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1)
 ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree)
 
+ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1)
+ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree)
+ICALL(SAFESTRMARSHAL_2, "StringToUtf8", ves_icall_Mono_SafeStringMarshal_StringToUtf8)
+
 #ifndef PLATFORM_RO_FS
 ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1)
 ICALL(KPAIR_1, "_CanSecure", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure)
index 587fd8c1c129ebef17fd779112b96696c87631a9..39192b10110d4eb106f1e865a80ffe894965b7d7 100644 (file)
@@ -1541,6 +1541,21 @@ ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
        g_ptr_array_free (ptr_array, TRUE);
 }
 
+ICALL_EXPORT void
+ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
+{
+       g_free (c_str);
+}
+
+ICALL_EXPORT char*
+ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
+{
+       MonoError error;
+       char *res = mono_string_to_utf8_checked (s, &error);
+       mono_error_set_pending_exception (&error);
+       return res;
+}
+
 /* System.TypeCode */
 typedef enum {
        TYPECODE_EMPTY,