Skip to content

Commit

Permalink
make use of Encoding.GetString(byte*, int) when available; poly-fill …
Browse files Browse the repository at this point in the history
…when not available (NET45); move related logic to extension class
  • Loading branch information
mgravell committed Jul 4, 2019
1 parent e95f329 commit b6e104f
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 31 deletions.
17 changes: 2 additions & 15 deletions src/csharp/Grpc.Core.Api/Metadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Grpc.Core.Api.Utils;

using Grpc.Core.Utils;

Expand Down Expand Up @@ -364,20 +364,7 @@ internal static unsafe Entry CreateUnsafe(string key, byte* source, int length)
}
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);
}
}
Expand Down
36 changes: 36 additions & 0 deletions src/csharp/Grpc.Core.Api/Utils/EncodingExtensions.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}

}
23 changes: 7 additions & 16 deletions src/csharp/Grpc.Core/Internal/MarshalUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -32,22 +33,10 @@ internal static class MarshalUtils
/// <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>
Expand All @@ -66,6 +55,7 @@ public static unsafe int GetBytesUTF8(string str, byte* destination, int destina
/// <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);
Expand All @@ -74,6 +64,7 @@ public static int GetMaxByteCountUTF8(string str)
/// <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);
Expand Down

0 comments on commit b6e104f

Please sign in to comment.