using System;
using System.Runtime.InteropServices;
namespace Dalamud.Game.Libc;
///
/// An address wrapper around the class.
///
public sealed partial class OwnedStdString
{
private readonly DeallocatorDelegate dealloc;
///
/// Initializes a new instance of the class.
/// Construct a wrapper around std::string.
///
///
/// Violating any of these might cause an undefined hehaviour.
/// 1. This function takes the ownership of the address.
/// 2. A memory pointed by address argument is assumed to be allocated by Marshal.AllocHGlobal thus will try to call Marshal.FreeHGlobal on the address.
/// 3. std::string object pointed by address must be initialized before calling this function.
///
/// The address of the owned std string.
/// A deallocator function.
internal OwnedStdString(IntPtr address, DeallocatorDelegate dealloc)
{
this.Address = address;
this.dealloc = dealloc;
}
///
/// The delegate type that deallocates a std string.
///
/// Address to deallocate.
internal delegate void DeallocatorDelegate(IntPtr address);
///
/// Gets the address of the std string.
///
public IntPtr Address { get; private set; }
///
/// Read the wrapped StdString.
///
/// The StdString.
public StdString Read() => StdString.ReadFromPointer(this.Address);
}
///
/// Implements IDisposable.
///
public sealed partial class OwnedStdString : IDisposable
{
private bool isDisposed;
///
/// Finalizes an instance of the class.
///
~OwnedStdString() => this.Dispose(false);
///
/// Dispose of managed and unmanaged resources.
///
public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(true);
}
///
/// Dispose of managed and unmanaged resources.
///
/// A value indicating whether this was called via Dispose or finalized.
public void Dispose(bool disposing)
{
if (this.isDisposed)
return;
this.isDisposed = true;
if (disposing)
{
}
if (this.Address == IntPtr.Zero)
{
// Something got seriously fucked.
throw new AccessViolationException();
}
// Deallocate inner string first
this.dealloc(this.Address);
// Free the heap
Marshal.FreeHGlobal(this.Address);
// Better safe (running on a nullptr) than sorry. (running on a dangling pointer)
this.Address = IntPtr.Zero;
}
}