зеркало из https://github.com/github/libgit2sharp.git
Refactor Marshalers
This commit is contained in:
Родитель
277ae16105
Коммит
c5419f7be3
|
@ -103,7 +103,8 @@ namespace LibGit2Sharp
|
|||
int result = 0;
|
||||
if (this.onCheckoutNotify != null)
|
||||
{
|
||||
string path = (pathPtr != IntPtr.Zero) ? FilePathMarshaler.FromNative(pathPtr).Native : string.Empty;
|
||||
string path = (pathPtr != IntPtr.Zero) ?
|
||||
((FilePath)Utf8Marshaler.FromNative(pathPtr)).Native : string.Empty;
|
||||
result = onCheckoutNotify(path, why) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace LibGit2Sharp.Core
|
||||
{
|
||||
internal abstract class EncodingMarshaler : ICustomMarshaler
|
||||
{
|
||||
private readonly Encoding encoding;
|
||||
|
||||
protected EncodingMarshaler(Encoding encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
#region ICustomMarshaler
|
||||
|
||||
public void CleanUpManagedData(object managedObj)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void CleanUpNativeData(IntPtr pNativeData)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(pNativeData);
|
||||
}
|
||||
|
||||
public int GetNativeDataSize()
|
||||
{
|
||||
// Not a value type
|
||||
return -1;
|
||||
}
|
||||
|
||||
public virtual IntPtr MarshalManagedToNative(Object managedObj)
|
||||
{
|
||||
if (managedObj == null)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
var str = managedObj as string;
|
||||
|
||||
if (str == null)
|
||||
{
|
||||
throw new MarshalDirectiveException(
|
||||
string.Format("{0} must be used on a string.", GetType().Name));
|
||||
}
|
||||
|
||||
return FromManaged(encoding, str);
|
||||
}
|
||||
|
||||
public virtual Object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
return FromNative(encoding, pNativeData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static unsafe IntPtr FromManaged(Encoding encoding, String value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
int length = encoding.GetByteCount(value);
|
||||
var buffer = (byte*)Marshal.AllocHGlobal(length + 1).ToPointer();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
fixed (char* pValue = value)
|
||||
{
|
||||
encoding.GetBytes(pValue, value.Length, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
buffer[length] = 0;
|
||||
|
||||
return new IntPtr(buffer);
|
||||
}
|
||||
|
||||
public static unsafe String FromNative(Encoding encoding, IntPtr pNativeData)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var start = (byte*)pNativeData;
|
||||
byte* walk = start;
|
||||
|
||||
// Find the end of the string
|
||||
while (*walk != 0)
|
||||
{
|
||||
walk++;
|
||||
}
|
||||
|
||||
if (walk == start)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return new String((sbyte*)pNativeData.ToPointer(), 0, (int)(walk - start), encoding);
|
||||
}
|
||||
|
||||
public static unsafe String FromNative(Encoding encoding, IntPtr pNativeData, int length)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return new String((sbyte*)pNativeData.ToPointer(), 0, length, encoding);
|
||||
}
|
||||
|
||||
public static String FromBuffer(Encoding encoding, byte[] buffer)
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
int stop = buffer.Length;
|
||||
|
||||
while (length < stop &&
|
||||
0 != buffer[length])
|
||||
{
|
||||
length++;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return encoding.GetString(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibGit2Sharp.Core
|
||||
|
@ -46,36 +45,18 @@ namespace LibGit2Sharp.Core
|
|||
/// MarshalCookie = UniqueId.UniqueIdentifier,
|
||||
/// MarshalTypeRef = typeof(FilePathMarshaler))] FilePath indexpath);
|
||||
/// </summary>
|
||||
internal class FilePathMarshaler : ICustomMarshaler
|
||||
internal class FilePathMarshaler : Utf8Marshaler
|
||||
{
|
||||
private static readonly FilePathMarshaler staticInstance = new FilePathMarshaler();
|
||||
|
||||
public static ICustomMarshaler GetInstance(String cookie)
|
||||
public new static ICustomMarshaler GetInstance(String cookie)
|
||||
{
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
#region ICustomMarshaler
|
||||
|
||||
public void CleanUpManagedData(Object managedObj)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void CleanUpNativeData(IntPtr pNativeData)
|
||||
{
|
||||
if (IntPtr.Zero != pNativeData)
|
||||
{
|
||||
Marshal.FreeHGlobal(pNativeData);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetNativeDataSize()
|
||||
{
|
||||
// Not a value type
|
||||
return -1;
|
||||
}
|
||||
|
||||
public IntPtr MarshalManagedToNative(Object managedObj)
|
||||
public override IntPtr MarshalManagedToNative(Object managedObj)
|
||||
{
|
||||
if (null == managedObj)
|
||||
{
|
||||
|
@ -86,59 +67,28 @@ namespace LibGit2Sharp.Core
|
|||
|
||||
if (null == filePath)
|
||||
{
|
||||
var expectedType = typeof(FilePath);
|
||||
var actualType = managedObj.GetType();
|
||||
|
||||
throw new MarshalDirectiveException(
|
||||
string.Format(CultureInfo.InvariantCulture,
|
||||
"FilePathMarshaler must be used on a FilePath. Expected '{0}' from '{1}'; received '{2}' from '{3}'.",
|
||||
expectedType.FullName, expectedType.Assembly.Location,
|
||||
actualType.FullName, actualType.Assembly.Location));
|
||||
string.Format("{0} must be used on a FilePath.", GetType().Name));
|
||||
}
|
||||
|
||||
return FromManaged(filePath);
|
||||
}
|
||||
|
||||
public Object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
public override Object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
return FromNative(pNativeData);
|
||||
return (FilePath)FromNative(pNativeData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static IntPtr FromManaged(FilePath filePath)
|
||||
{
|
||||
if (null == filePath)
|
||||
if (filePath == null)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
return Utf8Marshaler.FromManaged(filePath.Posix);
|
||||
}
|
||||
|
||||
public static FilePath FromNative(IntPtr pNativeData)
|
||||
{
|
||||
if (IntPtr.Zero == pNativeData)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (0 == Marshal.ReadByte(pNativeData))
|
||||
{
|
||||
return FilePath.Empty;
|
||||
}
|
||||
|
||||
return Utf8Marshaler.FromNative(pNativeData);
|
||||
}
|
||||
|
||||
public static FilePath FromNative(IntPtr pNativeData, int length)
|
||||
{
|
||||
if (0 == length)
|
||||
{
|
||||
return FilePath.Empty;
|
||||
}
|
||||
|
||||
return Utf8Marshaler.FromNative(pNativeData, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,143 +46,43 @@ namespace LibGit2Sharp.Core
|
|||
/// MarshalCookie = UniqueId.UniqueIdentifier,
|
||||
/// MarshalTypeRef = typeof(Utf8Marshaler))] String tagName);
|
||||
/// </summary>
|
||||
internal class Utf8Marshaler : ICustomMarshaler
|
||||
internal class Utf8Marshaler : EncodingMarshaler
|
||||
{
|
||||
private static readonly Utf8Marshaler staticInstance = new Utf8Marshaler();
|
||||
private static readonly Utf8Marshaler staticInstance;
|
||||
private static readonly Encoding encoding;
|
||||
|
||||
static Utf8Marshaler()
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
staticInstance = new Utf8Marshaler();
|
||||
}
|
||||
|
||||
public Utf8Marshaler() : base(encoding)
|
||||
{ }
|
||||
|
||||
public static ICustomMarshaler GetInstance(String cookie)
|
||||
{
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
#region ICustomMarshaler
|
||||
|
||||
public void CleanUpManagedData(Object managedObj)
|
||||
public static IntPtr FromManaged(String value)
|
||||
{
|
||||
return FromManaged(encoding, value);
|
||||
}
|
||||
|
||||
public virtual void CleanUpNativeData(IntPtr pNativeData)
|
||||
public static string FromNative(IntPtr pNativeData)
|
||||
{
|
||||
if (IntPtr.Zero != pNativeData)
|
||||
{
|
||||
Marshal.FreeHGlobal(pNativeData);
|
||||
}
|
||||
return FromNative(encoding, pNativeData);
|
||||
}
|
||||
|
||||
public int GetNativeDataSize()
|
||||
public static String FromNative(IntPtr pNativeData, int length)
|
||||
{
|
||||
// Not a value type
|
||||
return -1;
|
||||
}
|
||||
|
||||
public IntPtr MarshalManagedToNative(Object managedObj)
|
||||
{
|
||||
if (null == managedObj)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
String str = managedObj as String;
|
||||
|
||||
if (null == str)
|
||||
{
|
||||
throw new MarshalDirectiveException("Utf8Marshaler must be used on a string.");
|
||||
}
|
||||
|
||||
return FromManaged(str);
|
||||
}
|
||||
|
||||
public Object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
return FromNative(pNativeData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static unsafe IntPtr FromManaged(String value)
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
int length = Encoding.UTF8.GetByteCount(value);
|
||||
byte* buffer = (byte*)Marshal.AllocHGlobal(length + 1).ToPointer();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
fixed (char* pValue = value)
|
||||
{
|
||||
Encoding.UTF8.GetBytes(pValue, value.Length, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
buffer[length] = 0;
|
||||
|
||||
return new IntPtr(buffer);
|
||||
}
|
||||
|
||||
public static unsafe String FromNative(IntPtr pNativeData)
|
||||
{
|
||||
if (IntPtr.Zero == pNativeData)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
byte* start = (byte*)pNativeData;
|
||||
byte* walk = start;
|
||||
|
||||
// Find the end of the string
|
||||
while (*walk != 0)
|
||||
{
|
||||
walk++;
|
||||
}
|
||||
|
||||
if (walk == start)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return new String((sbyte*)pNativeData.ToPointer(), 0, (int)(walk - start), Encoding.UTF8);
|
||||
}
|
||||
|
||||
public static unsafe String FromNative(IntPtr pNativeData, int length)
|
||||
{
|
||||
if (IntPtr.Zero == pNativeData)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (0 == length)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return new String((sbyte*)pNativeData.ToPointer(), 0, length, Encoding.UTF8);
|
||||
return FromNative(encoding, pNativeData, length);
|
||||
}
|
||||
|
||||
public static String Utf8FromBuffer(byte[] buffer)
|
||||
{
|
||||
if (null == buffer)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
int stop = buffer.Length;
|
||||
|
||||
while (length < stop &&
|
||||
0 != buffer[length])
|
||||
{
|
||||
length++;
|
||||
}
|
||||
|
||||
if (0 == length)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetString(buffer, 0, length);
|
||||
return FromBuffer(encoding, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace LibGit2Sharp
|
|||
|
||||
GitIndexEntry entry = handle.MarshalAsGitIndexEntry();
|
||||
|
||||
var path = FilePathMarshaler.FromNative(entry.Path);
|
||||
FilePath path = Utf8Marshaler.FromNative(entry.Path);
|
||||
|
||||
return new IndexEntry
|
||||
{
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<Compile Include="CommitFilter.cs" />
|
||||
<Compile Include="CommitSortStrategies.cs" />
|
||||
<Compile Include="CompareOptions.cs" />
|
||||
<Compile Include="Core\EncodingMarshaler.cs" />
|
||||
<Compile Include="UnbornBranchException.cs" />
|
||||
<Compile Include="LockedFileException.cs" />
|
||||
<Compile Include="Core\GitRepositoryInitOptions.cs" />
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace LibGit2Sharp
|
|||
|
||||
private StatusEntry StateChanged(IntPtr filePathPtr, uint state)
|
||||
{
|
||||
var filePath = FilePathMarshaler.FromNative(filePathPtr);
|
||||
FilePath filePath = Utf8Marshaler.FromNative(filePathPtr);
|
||||
var gitStatus = (FileStatus)state;
|
||||
|
||||
foreach (KeyValuePair<FileStatus, Action<RepositoryStatus, string>> kvp in dispatcher)
|
||||
|
|
Загрузка…
Ссылка в новой задаче