aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Common/Memory/Ptr.cs
blob: 66bcf569bfe29dc431bee74224e93734dbda168c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;

namespace Ryujinx.Common.Memory
{
    /// <summary>
    /// Represents a pointer to an unmanaged resource.
    /// </summary>
    /// <typeparam name="T">Type of the unmanaged resource</typeparam>
    public unsafe struct Ptr<T> : IEquatable<Ptr<T>> where T : unmanaged
    {
        private IntPtr _ptr;

        /// <summary>
        /// Null pointer.
        /// </summary>
        public static Ptr<T> Null => new Ptr<T>() { _ptr = IntPtr.Zero };

        /// <summary>
        /// True if the pointer is null, false otherwise.
        /// </summary>
        public bool IsNull => _ptr == IntPtr.Zero;

        /// <summary>
        /// Gets a reference to the value.
        /// </summary>
        public ref T Value => ref Unsafe.AsRef<T>((void*)_ptr);

        /// <summary>
        /// Creates a new pointer to an unmanaged resource.
        /// </summary>
        /// <remarks>
        /// For data on the heap, proper pinning is necessary during
        /// use. Failure to do so will result in memory corruption and crashes.
        /// </remarks>
        /// <param name="value">Reference to the unmanaged resource</param>
        public Ptr(ref T value)
        {
            _ptr = (IntPtr)Unsafe.AsPointer(ref value);
        }

        public override bool Equals(object obj)
        {
            return obj is Ptr<T> other && Equals(other);
        }

        public bool Equals([AllowNull] Ptr<T> other)
        {
            return _ptr == other._ptr;
        }

        public override int GetHashCode()
        {
            return _ptr.GetHashCode();
        }

        public static bool operator ==(Ptr<T> left, Ptr<T> right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(Ptr<T> left, Ptr<T> right)
        {
            return !(left == right);
        }
    }
}