summaryrefslogtreecommitdiff
path: root/src/vm/fieldmarshaler.cpp
diff options
context:
space:
mode:
authorTijoy Tom Kalathiparambil <tijoytk@microsoft.com>2016-05-03 14:25:22 -0700
committertijoytk <tijoytk@microsoft.com>2016-05-06 18:26:29 -0700
commite63ae93ca3fc777ff25930491332e07cf79a9ce3 (patch)
treea2baee2f867d93cf8ffdc44a1bb146588c808f18 /src/vm/fieldmarshaler.cpp
parent92f671fe9f0fc583805d4f9c3116126444dabcf4 (diff)
downloadcoreclr-e63ae93ca3fc777ff25930491332e07cf79a9ce3.tar.gz
coreclr-e63ae93ca3fc777ff25930491332e07cf79a9ce3.tar.bz2
coreclr-e63ae93ca3fc777ff25930491332e07cf79a9ce3.zip
UTF8 Marshaling support(UnmanagedType.LPUTF8Str)
Usage: [MarshalAs(UnmanagedType.LPUTF8Str)] applied to string and stringbuilder. Implementation mostly use Encoding.UTF8 API to do the byte buffer to string roundtripping. Introducing two new marshalers, UTF8StringMarshaler and UTF8BufferMarshaler which handle string and StringBuilder respectively. [Out] StringBuilder marshaling use builder capacity as the buffer size ie (builder. Capacity + 1) *3 which is enough for any UTF8 char in BMP plane, infact Encoding.UTF8 mscorlib APIs use the same length.All marshaling flags(ThrowOnUnmapable, defaultchar) are ignored since they do not make sense in UTF16 to UTD8 context. The public contracts are not yet updated, the public contracts and public marshaling API (Marshal.PtrToStringUtf8 and StringToHGlobalUtf8) will be added once the implementation is in. The marshal api are anyway going to be a wrapper around Encoding.GetBytes and GetChars.
Diffstat (limited to 'src/vm/fieldmarshaler.cpp')
-rw-r--r--src/vm/fieldmarshaler.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp
index 37ad39eb4f..39465c269d 100644
--- a/src/vm/fieldmarshaler.cpp
+++ b/src/vm/fieldmarshaler.cpp
@@ -770,6 +770,10 @@ do \
case NATIVE_TYPE_LPWSTR:
INITFIELDMARSHALER(NFT_STRINGUNI, FieldMarshaler_StringUni, ());
break;
+
+ case NATIVE_TYPE_LPUTF8STR:
+ INITFIELDMARSHALER(NFT_STRINGUTF8, FieldMarshaler_StringUtf8, ());
+ break;
case NATIVE_TYPE_LPTSTR:
// We no longer support Win9x so LPTSTR always maps to a Unicode string.
@@ -3158,7 +3162,109 @@ VOID FieldMarshaler_StringAnsi::DestroyNativeImpl(LPVOID pNativeValue) const
CoTaskMemFree(sz);
}
+//=======================================================================
+// CoTask Utf8 <--> System.String
+// See FieldMarshaler for details.
+//=======================================================================
+VOID FieldMarshaler_StringUtf8::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pNativeValue));
+ }
+ CONTRACTL_END;
+
+ STRINGREF pString = (STRINGREF)(*pCLRValue);
+ if (pString == NULL)
+ {
+ MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
+ }
+ else
+ {
+ DWORD nc = pString->GetStringLength();
+ if (nc > MAX_SIZE_FOR_INTEROP)
+ COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
+
+ // Characters would be # of characters + 1 in case left over high surrogate is ?
+ // Max 3 bytes per char for basic multi-lingual plane.
+ nc = (nc + 1) * 3;
+ // +1 for '\0'
+ LPUTF8 lpBuffer = (LPUTF8)CoTaskMemAlloc(nc + 1);
+ if (!lpBuffer)
+ COMPlusThrowOM();
+
+ // UTF8Marshaler.ConvertToNative
+ MethodDescCallSite convertToNative(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE);
+
+ ARG_SLOT args[] =
+ {
+ ((ARG_SLOT)(CLR_I4)0),
+ ObjToArgSlot(*pCLRValue),
+ PtrToArgSlot(lpBuffer)
+ };
+ convertToNative.Call(args);
+ MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, lpBuffer);
+ }
+}
+
+
+//=======================================================================
+// CoTask Utf8 <--> System.String
+// See FieldMarshaler for details.
+//=======================================================================
+VOID FieldMarshaler_StringUtf8::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pNativeValue));
+ PRECONDITION(CheckPointer(ppProtectedCLRValue));
+ }
+ CONTRACTL_END;
+
+ STRINGREF pString = NULL;
+ LPCUTF8 sz = (LPCUTF8)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
+ if (!sz)
+ pString = NULL;
+ else
+ {
+ MethodDescCallSite convertToManaged(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED);
+ ARG_SLOT args[] =
+ {
+ PtrToArgSlot(pNativeValue),
+ };
+ pString = convertToManaged.Call_RetSTRINGREF(args);
+ }
+ *((STRINGREF*)ppProtectedCLRValue) = pString;
+}
+
+//=======================================================================
+// CoTask Utf8 <--> System.String
+// See FieldMarshaler for details.
+//=======================================================================
+VOID FieldMarshaler_StringUtf8::DestroyNativeImpl(LPVOID pNativeValue) const
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pNativeValue));
+ }
+ CONTRACTL_END;
+ LPSTR lpBuffer = (LPSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
+ MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
+ if (lpBuffer)
+ CoTaskMemFree(lpBuffer);
+}
//=======================================================================
// FixedString <--> System.String
@@ -4607,6 +4713,7 @@ VOID NStructFieldTypeToString(FieldMarshaler* pFM, SString& strNStructFieldType)
switch (GetNStructFieldType()) { \
case NFT_STRINGUNI: rettype ((FieldMarshaler_StringUni*)this)->name##Impl args; break; \
case NFT_STRINGANSI: rettype ((FieldMarshaler_StringAnsi*)this)->name##Impl args; break; \
+ case NFT_STRINGUTF8: rettype ((FieldMarshaler_StringUtf8*)this)->name##Impl args; break; \
case NFT_FIXEDSTRINGUNI: rettype ((FieldMarshaler_FixedStringUni*)this)->name##Impl args; break; \
case NFT_FIXEDSTRINGANSI: rettype ((FieldMarshaler_FixedStringAnsi*)this)->name##Impl args; break; \
case NFT_FIXEDCHARARRAYANSI: rettype ((FieldMarshaler_FixedCharArrayAnsi*)this)->name##Impl args; break; \
@@ -4649,6 +4756,7 @@ VOID NStructFieldTypeToString(FieldMarshaler* pFM, SString& strNStructFieldType)
switch (GetNStructFieldType()) { \
case NFT_STRINGUNI: rettype ((FieldMarshaler_StringUni*)this)->name##Impl args; break; \
case NFT_STRINGANSI: rettype ((FieldMarshaler_StringAnsi*)this)->name##Impl args; break; \
+ case NFT_STRINGUTF8: rettype ((FieldMarshaler_StringUtf8*)this)->name##Impl args; break; \
case NFT_FIXEDSTRINGUNI: rettype ((FieldMarshaler_FixedStringUni*)this)->name##Impl args; break; \
case NFT_FIXEDSTRINGANSI: rettype ((FieldMarshaler_FixedStringAnsi*)this)->name##Impl args; break; \
case NFT_FIXEDCHARARRAYANSI: rettype ((FieldMarshaler_FixedCharArrayAnsi*)this)->name##Impl args; break; \