This commit is contained in:
nulltoken 2013-10-11 17:48:00 +02:00
Родитель 277ae16105
Коммит c5419f7be3
7 изменённых файлов: 180 добавлений и 179 удалений

Просмотреть файл

@ -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)