make use of Encoding.GetString(byte*, int) when available; poly-fill when not available (NET45); move related logic to extension class

pull/19511/head
mgravell 6 years ago
parent e95f3297aa
commit b6e104f22f
  1. 17
      src/csharp/Grpc.Core.Api/Metadata.cs
  2. 36
      src/csharp/Grpc.Core.Api/Utils/EncodingExtensions.cs
  3. 23
      src/csharp/Grpc.Core/Internal/MarshalUtils.cs

@ -19,7 +19,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Grpc.Core.Api.Utils;
using Grpc.Core.Utils;
@ -364,20 +364,7 @@ namespace Grpc.Core
}
else
{
string s;
if (length == 0)
{
s = "";
}
else
{
int charCount = EncodingASCII.GetCharCount(source, length);
s = new string('\0', charCount);
fixed (char* cPtr = s)
{
EncodingASCII.GetChars(source, length, cPtr, charCount);
}
}
string s = length == 0 ? "" : EncodingASCII.GetString(source, length);
return new Entry(key, s, null);
}
}

@ -0,0 +1,36 @@
using System;
using System.Text;
namespace Grpc.Core.Api.Utils
{
internal static class EncodingExtensions
{
#if NET45 // back-fill over a method missing in NET45
/// <summary>
/// Converts <c>byte*</c> pointing to an encoded byte array to a <c>string</c> using the provided <c>Encoding</c>.
/// </summary>
public static unsafe string GetString(this Encoding encoding, byte* source, int byteCount)
{
if (byteCount == 0) return ""; // most callers will have already checked, but: make sure
// allocate a right-sized string and decode into it
int charCount = encoding.GetCharCount(source, byteCount);
string s = new string('\0', charCount);
fixed (char* cPtr = s)
{
encoding.GetChars(source, byteCount, cPtr, charCount);
}
return s;
}
#endif
/// <summary>
/// Converts <c>IntPtr</c> pointing to a encoded byte array to a <c>string</c> using the provided <c>Encoding</c>.
/// </summary>
public static unsafe string GetString(this Encoding encoding, IntPtr ptr, int len)
{
return len == 0 ? "" : encoding.GetString((byte*)ptr.ToPointer(), len);
}
}
}

@ -17,8 +17,9 @@
#endregion
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Text;
using Grpc.Core.Api.Utils;
namespace Grpc.Core.Internal
{
@ -32,22 +33,10 @@ namespace Grpc.Core.Internal
/// <summary>
/// Converts <c>IntPtr</c> pointing to a UTF-8 encoded byte array to <c>string</c>.
/// </summary>
public static unsafe string PtrToStringUTF8(IntPtr ptr, int len)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string PtrToStringUTF8(IntPtr ptr, int len)
{
if (len == 0)
{
return "";
}
// allocate a right-sized string and decode into it
byte* source = (byte*)ptr.ToPointer();
int charCount = EncodingUTF8.GetCharCount(source, len);
string s = new string('\0', charCount);
fixed(char* cPtr = s)
{
EncodingUTF8.GetChars(source, len, cPtr, charCount);
}
return s;
return EncodingUTF8.GetString(ptr, len);
}
/// <summary>
@ -66,6 +55,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Returns the maximum number of bytes required to encode a given string.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetMaxByteCountUTF8(string str)
{
return EncodingUTF8.GetMaxByteCount(str.Length);
@ -74,6 +64,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Returns the actual number of bytes required to encode a given string.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetByteCountUTF8(string str)
{
return EncodingUTF8.GetByteCount(str);

Loading…
Cancel
Save