Skip to content

Commit c5419f7

Browse files
committed
Refactor Marshalers
1 parent 277ae16 commit c5419f7

File tree

7 files changed

+178
-177
lines changed

7 files changed

+178
-177
lines changed

LibGit2Sharp/CheckoutCallbacks.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ private int OnGitCheckoutNotify(
103103
int result = 0;
104104
if (this.onCheckoutNotify != null)
105105
{
106-
string path = (pathPtr != IntPtr.Zero) ? FilePathMarshaler.FromNative(pathPtr).Native : string.Empty;
106+
string path = (pathPtr != IntPtr.Zero) ?
107+
((FilePath)Utf8Marshaler.FromNative(pathPtr)).Native : string.Empty;
107108
result = onCheckoutNotify(path, why) ? 0 : 1;
108109
}
109110

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Text;
4+
5+
namespace LibGit2Sharp.Core
6+
{
7+
internal abstract class EncodingMarshaler : ICustomMarshaler
8+
{
9+
private readonly Encoding encoding;
10+
11+
protected EncodingMarshaler(Encoding encoding)
12+
{
13+
this.encoding = encoding;
14+
}
15+
16+
#region ICustomMarshaler
17+
18+
public void CleanUpManagedData(object managedObj)
19+
{
20+
}
21+
22+
public virtual void CleanUpNativeData(IntPtr pNativeData)
23+
{
24+
if (pNativeData == IntPtr.Zero)
25+
{
26+
return;
27+
}
28+
29+
Marshal.FreeHGlobal(pNativeData);
30+
}
31+
32+
public int GetNativeDataSize()
33+
{
34+
// Not a value type
35+
return -1;
36+
}
37+
38+
public virtual IntPtr MarshalManagedToNative(Object managedObj)
39+
{
40+
if (managedObj == null)
41+
{
42+
return IntPtr.Zero;
43+
}
44+
45+
var str = managedObj as string;
46+
47+
if (str == null)
48+
{
49+
throw new MarshalDirectiveException(
50+
string.Format("{0} must be used on a string.", GetType().Name));
51+
}
52+
53+
return FromManaged(encoding, str);
54+
}
55+
56+
public virtual Object MarshalNativeToManaged(IntPtr pNativeData)
57+
{
58+
return FromNative(encoding, pNativeData);
59+
}
60+
61+
#endregion
62+
63+
public static unsafe IntPtr FromManaged(Encoding encoding, String value)
64+
{
65+
if (value == null)
66+
{
67+
return IntPtr.Zero;
68+
}
69+
70+
int length = encoding.GetByteCount(value);
71+
var buffer = (byte*)Marshal.AllocHGlobal(length + 1).ToPointer();
72+
73+
if (length > 0)
74+
{
75+
fixed (char* pValue = value)
76+
{
77+
encoding.GetBytes(pValue, value.Length, buffer, length);
78+
}
79+
}
80+
81+
buffer[length] = 0;
82+
83+
return new IntPtr(buffer);
84+
}
85+
86+
public static unsafe String FromNative(Encoding encoding, IntPtr pNativeData)
87+
{
88+
if (pNativeData == IntPtr.Zero)
89+
{
90+
return null;
91+
}
92+
93+
var start = (byte*)pNativeData;
94+
byte* walk = start;
95+
96+
// Find the end of the string
97+
while (*walk != 0)
98+
{
99+
walk++;
100+
}
101+
102+
if (walk == start)
103+
{
104+
return String.Empty;
105+
}
106+
107+
return new String((sbyte*)pNativeData.ToPointer(), 0, (int)(walk - start), encoding);
108+
}
109+
110+
public static unsafe String FromNative(Encoding encoding, IntPtr pNativeData, int length)
111+
{
112+
if (pNativeData == IntPtr.Zero)
113+
{
114+
return null;
115+
}
116+
117+
if (length == 0)
118+
{
119+
return String.Empty;
120+
}
121+
122+
return new String((sbyte*)pNativeData.ToPointer(), 0, length, encoding);
123+
}
124+
125+
public static String FromBuffer(Encoding encoding, byte[] buffer)
126+
{
127+
if (buffer == null)
128+
{
129+
return null;
130+
}
131+
132+
int length = 0;
133+
int stop = buffer.Length;
134+
135+
while (length < stop &&
136+
0 != buffer[length])
137+
{
138+
length++;
139+
}
140+
141+
if (length == 0)
142+
{
143+
return String.Empty;
144+
}
145+
146+
return encoding.GetString(buffer, 0, length);
147+
}
148+
}
149+
}
Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Globalization;
32
using System.Runtime.InteropServices;
43

54
namespace LibGit2Sharp.Core
@@ -46,36 +45,18 @@ public override void CleanUpNativeData(IntPtr pNativeData)
4645
/// MarshalCookie = UniqueId.UniqueIdentifier,
4746
/// MarshalTypeRef = typeof(FilePathMarshaler))] FilePath indexpath);
4847
/// </summary>
49-
internal class FilePathMarshaler : ICustomMarshaler
48+
internal class FilePathMarshaler : Utf8Marshaler
5049
{
5150
private static readonly FilePathMarshaler staticInstance = new FilePathMarshaler();
5251

53-
public static ICustomMarshaler GetInstance(String cookie)
52+
public new static ICustomMarshaler GetInstance(String cookie)
5453
{
5554
return staticInstance;
5655
}
5756

5857
#region ICustomMarshaler
5958

60-
public void CleanUpManagedData(Object managedObj)
61-
{
62-
}
63-
64-
public virtual void CleanUpNativeData(IntPtr pNativeData)
65-
{
66-
if (IntPtr.Zero != pNativeData)
67-
{
68-
Marshal.FreeHGlobal(pNativeData);
69-
}
70-
}
71-
72-
public int GetNativeDataSize()
73-
{
74-
// Not a value type
75-
return -1;
76-
}
77-
78-
public IntPtr MarshalManagedToNative(Object managedObj)
59+
public override IntPtr MarshalManagedToNative(Object managedObj)
7960
{
8061
if (null == managedObj)
8162
{
@@ -86,59 +67,28 @@ public IntPtr MarshalManagedToNative(Object managedObj)
8667

8768
if (null == filePath)
8869
{
89-
var expectedType = typeof(FilePath);
90-
var actualType = managedObj.GetType();
91-
9270
throw new MarshalDirectiveException(
93-
string.Format(CultureInfo.InvariantCulture,
94-
"FilePathMarshaler must be used on a FilePath. Expected '{0}' from '{1}'; received '{2}' from '{3}'.",
95-
expectedType.FullName, expectedType.Assembly.Location,
96-
actualType.FullName, actualType.Assembly.Location));
71+
string.Format("{0} must be used on a FilePath.", GetType().Name));
9772
}
9873

9974
return FromManaged(filePath);
10075
}
10176

102-
public Object MarshalNativeToManaged(IntPtr pNativeData)
77+
public override Object MarshalNativeToManaged(IntPtr pNativeData)
10378
{
104-
return FromNative(pNativeData);
79+
return (FilePath)FromNative(pNativeData);
10580
}
10681

10782
#endregion
10883

10984
public static IntPtr FromManaged(FilePath filePath)
11085
{
111-
if (null == filePath)
86+
if (filePath == null)
11287
{
11388
return IntPtr.Zero;
11489
}
11590

11691
return Utf8Marshaler.FromManaged(filePath.Posix);
11792
}
118-
119-
public static FilePath FromNative(IntPtr pNativeData)
120-
{
121-
if (IntPtr.Zero == pNativeData)
122-
{
123-
return null;
124-
}
125-
126-
if (0 == Marshal.ReadByte(pNativeData))
127-
{
128-
return FilePath.Empty;
129-
}
130-
131-
return Utf8Marshaler.FromNative(pNativeData);
132-
}
133-
134-
public static FilePath FromNative(IntPtr pNativeData, int length)
135-
{
136-
if (0 == length)
137-
{
138-
return FilePath.Empty;
139-
}
140-
141-
return Utf8Marshaler.FromNative(pNativeData, length);
142-
}
14393
}
14494
}

0 commit comments

Comments
 (0)