Change BindingBase to use UTF8, not ASCII, strings

From the OpenGL 4.6 core specification, section 22.2:
        String queries return pointers to UTF-8 encoded,
        null-terminated static strings describing properties of the
        current GL context.

From the GLSL 4.6 specification, section 3.1:
        The source character set used for the OpenGL shading languages
        is Unicode in the UTF-8 encoding scheme.

It used to be that strings were ASCII, but ASCII is a safe subset of
UTF8 so any existing code that assumed strings were encoded as ASCII
will continue to work.
This commit is contained in:
Fraser Waters 2017-08-13 17:03:20 +01:00
parent e9e471f785
commit 440502746a

View file

@ -72,10 +72,13 @@ namespace OpenTK
protected abstract object SyncRoot { get; } protected abstract object SyncRoot { get; }
/// <summary> /// <summary>
/// Marshals a pointer to a null-terminated byte array to the specified <c>StringBuilder</c>. /// Marshals a pointer to a null-terminated byte array to a new <c>System.String</c>.
/// This method supports OpenTK and is not intended to be called by user code. /// This method supports OpenTK and is not intended to be called by user code.
/// </summary> /// </summary>
/// <param name="ptr">A pointer to a null-terminated byte array.</param> /// <param name="ptr">A pointer to a null-terminated byte array.</param>
/// <returns>
/// A <c>System.String</c> with the data from <paramref name="ptr"/>.
/// </returns>
protected static string MarshalPtrToString(IntPtr ptr) protected static string MarshalPtrToString(IntPtr ptr)
{ {
if (ptr == IntPtr.Zero) if (ptr == IntPtr.Zero)
@ -93,13 +96,13 @@ namespace OpenTK
++str; ++str;
} }
return new string((sbyte*)ptr, 0, len, null); return new string((sbyte*)ptr, 0, len, Encoding.UTF8);
} }
} }
/// <summary> /// <summary>
/// Marshal a <c>System.String</c> to unmanaged memory. /// Marshal a <c>System.String</c> to unmanaged memory.
/// The resulting string is encoded in ASCII and must be freed /// The resulting string is encoded in UTF8 and must be freed
/// with <c>FreeStringPtr</c>. /// with <c>FreeStringPtr</c>.
/// </summary> /// </summary>
/// <param name="str">The <c>System.String</c> to marshal.</param> /// <param name="str">The <c>System.String</c> to marshal.</param>
@ -118,20 +121,20 @@ namespace OpenTK
// GetMaxByteCount() appears to allocate space for the final NUL // GetMaxByteCount() appears to allocate space for the final NUL
// character, but allocate an extra one just in case (who knows // character, but allocate an extra one just in case (who knows
// what old Mono version would do here.) // what old Mono version would do here.)
int max_count = Encoding.ASCII.GetMaxByteCount(str.Length) + 1; int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1;
IntPtr ptr = Marshal.AllocHGlobal(max_count); IntPtr ptr = Marshal.AllocHGlobal(max_count);
if (ptr == IntPtr.Zero) if (ptr == IntPtr.Zero)
{ {
throw new OutOfMemoryException(); throw new OutOfMemoryException();
} }
// Pin the managed string and convert it to ASCII using // Pin the managed string and convert it to UTF8 using
// the pointer overload of System.Encoding.ASCII.GetBytes(). // the pointer overload of System.Encoding.UTF8.GetBytes().
unsafe unsafe
{ {
fixed (char* pstr = str) fixed (char* pstr = str)
{ {
int actual_count = Encoding.ASCII.GetBytes(pstr, str.Length, (byte*)ptr, max_count); int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count);
Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string
return ptr; return ptr;
} }