using System; using System.Globalization; using System.Runtime.InteropServices; using System.Text; namespace LibGit2Sharp.Core { /// /// This marshaler is to be used for capturing a UTF-8 string owned by libgit2 and /// converting it to a managed String instance. The marshaler will not attempt to /// free the native pointer after conversion, because the memory is owned by libgit2. /// /// Use this marshaler for return values, for example: /// [return: MarshalAs(UnmanagedType.CustomMarshaler, /// MarshalCookie = UniqueId.UniqueIdentifier, /// MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] /// internal class LaxUtf8NoCleanupMarshaler : LaxUtf8Marshaler { private static readonly LaxUtf8NoCleanupMarshaler staticInstance = new LaxUtf8NoCleanupMarshaler(); public new static ICustomMarshaler GetInstance(String cookie) { return staticInstance; } #region ICustomMarshaler public override void CleanUpNativeData(IntPtr pNativeData) { } #endregion } /// /// This marshaler is to be used for sending managed String instances to libgit2. /// The marshaler will allocate a buffer in native memory to hold the UTF-8 string /// and perform the encoding conversion using that buffer as the target. The pointer /// received by libgit2 will be to this buffer. After the function call completes, the /// native buffer is freed. /// /// Use this marshaler for function parameters, for example: /// [DllImport(libgit2)] /// internal static extern int git_tag_delete(RepositorySafeHandle repo, /// [MarshalAs(UnmanagedType.CustomMarshaler, /// MarshalCookie = UniqueId.UniqueIdentifier, /// MarshalTypeRef = typeof(StrictUtf8Marshaler))] String tagName); /// internal class StrictUtf8Marshaler : EncodingMarshaler { private static readonly StrictUtf8Marshaler staticInstance; private static readonly Encoding encoding; static StrictUtf8Marshaler() { encoding = new UTF8Encoding(false, true); staticInstance = new StrictUtf8Marshaler(); } public StrictUtf8Marshaler() : base(encoding) { } public static ICustomMarshaler GetInstance(String cookie) { return staticInstance; } #region ICustomMarshaler public override Object MarshalNativeToManaged(IntPtr pNativeData) { throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "{0} cannot be used to retrieve data from libgit2.", GetType().Name)); } #endregion public static IntPtr FromManaged(String value) { return FromManaged(encoding, value); } } /// /// This marshaler is to be used for capturing a UTF-8 string allocated by libgit2 and /// converting it to a managed String instance. The marshaler will free the native pointer /// after conversion. /// internal class LaxUtf8Marshaler : EncodingMarshaler { private static readonly LaxUtf8Marshaler staticInstance = new LaxUtf8Marshaler(); private static readonly Encoding encoding = new UTF8Encoding(false, false); public LaxUtf8Marshaler() : base(encoding) { } public static ICustomMarshaler GetInstance(String cookie) { return staticInstance; } #region ICustomMarshaler public override IntPtr MarshalManagedToNative(object managedObj) { throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "{0} cannot be used to pass data to libgit2.", GetType().Name)); } #endregion public static string FromNative(IntPtr pNativeData) { return FromNative(encoding, pNativeData); } public static string FromNative(IntPtr pNativeData, int length) { return FromNative(encoding, pNativeData, length); } public static string FromBuffer(byte[] buffer) { return FromBuffer(encoding, buffer); } public static string FromBuffer(byte[] buffer, int length) { return FromBuffer(encoding, buffer, length); } } }