user1989178
user1989178

Reputation: 25

Alternatives to casting IntPtr to increment it?

Suppose I have the following code:

IntPtr newPtr = new IntPtr( oldPtr.ToInt32() + 12 ); 

Is there any way to make the process of increasing oldPtr more streamlined?
Anything I'm missing or I should know?

edited to clarify: my curiosity was in easing the process itself, I'm just trying to get in the world of unmanaged and it's difficult enough without the need to cast everything.

Upvotes: 2

Views: 447

Answers (1)

Tommaso Belluzzo
Tommaso Belluzzo

Reputation: 23685

Since Framework 4.0 you can use Add() and Substract() methods. If you are developing under an older environment, implement this in your project:

public static class IntPtrExtensions
{
    #region Methods: Arithmetics
    public static IntPtr Decrement(this IntPtr pointer, Int32 value)
    {
        return Increment(pointer, -value);
    }

    public static IntPtr Decrement(this IntPtr pointer, Int64 value)
    {
        return Increment(pointer, -value);
    }

    public static IntPtr Decrement(this IntPtr pointer, IntPtr value)
    {
        switch (IntPtr.Size)
        {
            case sizeof(Int32):
                return (new IntPtr(pointer.ToInt32() - value.ToInt32()));

            default:
                return (new IntPtr(pointer.ToInt64() - value.ToInt64()));
        }
    }

    public static IntPtr Increment(this IntPtr pointer, Int32 value)
    {
        unchecked
        {
            switch (IntPtr.Size)
            {
                case sizeof(Int32):
                    return (new IntPtr(pointer.ToInt32() + value));

                default:
                    return (new IntPtr(pointer.ToInt64() + value));
            }
        }
    }

    public static IntPtr Increment(this IntPtr pointer, Int64 value)
    {
        unchecked
        {
            switch (IntPtr.Size)
            {
                case sizeof(Int32):
                    return (new IntPtr((Int32)(pointer.ToInt32() + value)));

                default:
                    return (new IntPtr(pointer.ToInt64() + value));
            }
        }
    }

    public static IntPtr Increment(this IntPtr pointer, IntPtr value)
    {
        unchecked
        {
            switch (IntPtr.Size)
            {
                case sizeof(Int32):
                    return new IntPtr(pointer.ToInt32() + value.ToInt32());

                default:
                    return new IntPtr(pointer.ToInt64() + value.ToInt64());
            }
        }
    }
    #endregion

    #region Methods: Comparison
    public static Int32 CompareTo(this IntPtr left, Int32 right)
    {
        return left.CompareTo((UInt32)right);
    }

    public static Int32 CompareTo(this IntPtr left, IntPtr right)
    {
        if (left.ToUInt64() > right.ToUInt64())
            return 1;

        if (left.ToUInt64() < right.ToUInt64())
            return -1;

        return 0;
    }

    public static Int32 CompareTo(this IntPtr left, UInt32 right)
    {
        if (left.ToUInt64() > right)
            return 1;

        if (left.ToUInt64() < right)
            return -1;

        return 0;
    }
    #endregion

    #region Methods: Conversion
    public unsafe static UInt32 ToUInt32(this IntPtr pointer)
    {
        return (UInt32)((void*)pointer);
    }

    public unsafe static UInt64 ToUInt64(this IntPtr pointer)
    {
        return (UInt64)((void*)pointer);
    }
    #endregion

    #region Methods: Equality
    public static Boolean Equals(this IntPtr pointer, Int32 value)
    {
        return (pointer.ToInt32() == value);
    }

    public static Boolean Equals(this IntPtr pointer, Int64 value)
    {
        return (pointer.ToInt64() == value);
    }

    public static Boolean Equals(this IntPtr left, IntPtr ptr2)
    {
        return (left == ptr2);
    }

    public static Boolean Equals(this IntPtr pointer, UInt32 value)
    {
        return (pointer.ToUInt32() == value);
    }

    public static Boolean Equals(this IntPtr pointer, UInt64 value)
    {
        return (pointer.ToUInt64() == value);
    }

    public static Boolean GreaterThanOrEqualTo(this IntPtr left, IntPtr right)
    {
        return (left.CompareTo(right) >= 0);
    }

    public static Boolean LessThanOrEqualTo(this IntPtr left, IntPtr right)
    {
        return (left.CompareTo(right) <= 0);
    }
    #endregion

    #region Methods: Logic
    public static IntPtr And(this IntPtr pointer, IntPtr value)
    {
        switch (IntPtr.Size)
        {
            case sizeof(Int32):
                return (new IntPtr(pointer.ToInt32() & value.ToInt32()));

            default:
                return (new IntPtr(pointer.ToInt64() & value.ToInt64()));
        }
    }

    public static IntPtr Not(this IntPtr pointer)
    {
        switch (IntPtr.Size)
        {
            case sizeof(Int32):
                return (new IntPtr(~pointer.ToInt32()));

            default:
                return (new IntPtr(~pointer.ToInt64()));
        }
    }

    public static IntPtr Or(this IntPtr pointer, IntPtr value)
    {
        switch (IntPtr.Size)
        {
            case sizeof(Int32):
                return (new IntPtr(pointer.ToInt32() | value.ToInt32()));

            default:
                return (new IntPtr(pointer.ToInt64() | value.ToInt64()));
        }
    }

    public static IntPtr Xor(this IntPtr pointer, IntPtr value)
    {
        switch (IntPtr.Size)
        {
            case sizeof(Int32):
                return (new IntPtr(pointer.ToInt32() ^ value.ToInt32()));

            default:
                return (new IntPtr(pointer.ToInt64() ^ value.ToInt64()));
        }
    }
    #endregion
}

And, in your example, call:

IntPtr newPtr = oldPtr.Increment(12); 

Upvotes: 2

Related Questions