232 lines
6.3 KiB
C#

//
// Ptr.cs - i'm not sure what this is for now but it looks interesting
//
// Author:
// Michael Becker <alcexhim@gmail.com>
//
// Copyright (c) 2011-2020 Mike Becker's Software
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Diagnostics;
namespace UniversalEditor
{
[DebuggerNonUserCode()]
public struct Ptr<T>
{
private T[] value;
private int index;
private int length;
/// <summary>
/// Gets the capacity of the underlying array.
/// </summary>
public int Capacity
{
get { return value.Length; }
}
/// <summary>
/// Gets the size of the <see cref="Ptr" />.
/// </summary>
public int Size
{
get { return length; }
}
public Ptr(T[] value, int index = -1)
{
this.value = value;
this.length = value.Length;
this.mvarAutoResize = false;
if (index < -1 || index > value.Length - 1) throw new IndexOutOfRangeException();
this.index = index;
}
public static Ptr<T> operator + (Ptr<T> value, int addend)
{
return new Ptr<T>(value.value, value.index + 1);
}
public static Ptr<T> operator - (Ptr<T> value, int addend)
{
return new Ptr<T>(value.value, value.index - 1);
}
/// <summary>
/// Increments the index, then sets the value stored at that position to the given value.
/// </summary>
/// <param name="value">The value to set.</param>
public void IncrementThenSetValue(T value)
{
this.Increment();
SetValue(value);
}
/// <summary>
/// Decrements the index, then sets the value stored at that position to the given value.
/// </summary>
/// <param name="value">The value to set.</param>
public void DecrementThenSetValue(T value)
{
Decrement();
SetValue(value);
}
/// <summary>
/// Sets the value at the current position to the given value, then increments the index.
/// </summary>
/// <param name="value">The value to set.</param>
public void SetValueThenIncrement(T value)
{
SetValue(value);
Increment();
}
/// <summary>
/// Sets the value at the current position to the given value, then decrements the index.
/// </summary>
/// <param name="value">The value to set.</param>
public void SetValueThenDecrement(T value)
{
SetValue(value);
Decrement();
}
public void Increment()
{
this.index++;
AutoResizeIfNeeded(this.index);
}
public void Decrement()
{
if (this.index - 1 < 0) throw new IndexOutOfRangeException();
this.index--;
}
/// <summary>
/// Increments the index, then gets the value stored at that position.
/// </summary>
/// <returns>The value stored at the position after the index has been incremented.</returns>
public T IncrementThenGetValue()
{
this.index++;
T value = this.value[this.index];
return value;
}
/// <summary>
/// Decrements the index, then gets the value stored at that position.
/// </summary>
/// <returns>The value stored at the position after the index has been decremented.</returns>
public T DecrementThenGetValue()
{
this.index--;
T value = this.value[this.index];
return value;
}
/// <summary>
/// Gets the value stored at the current position, then increments the index.
/// </summary>
/// <returns>The value stored at the position before the index has been incremented.</returns>
public T GetValueThenIncrement()
{
T value = this.value[this.index];
this.index++;
return value;
}
/// <summary>
/// Gets the value stored at the current position, then decrements the index.
/// </summary>
/// <returns>The value stored at the position before the index has been decremented.</returns>
public T GetValueThenDecrement()
{
T value = this.value[this.index];
this.index--;
return value;
}
/// <summary>
/// Retrieves all elements of this <see cref="Ptr" /> as an array.
/// </summary>
/// <returns>An array of all items in this <see cref="Ptr" />.</returns>
public T[] ToArray()
{
return (T[])this.value.Clone();
}
/// <summary>
/// Sets the value at the specified index to the given value.
/// </summary>
/// <param name="value">The value to set.</param>
/// <param name="index">The index in the underlying array of the value to set, or -1 to set the current value.</param>
public void SetValue(T value, int index = -1)
{
if (index == -1) index = this.index;
AutoResizeIfNeeded(index);
if (index < 0 || index > this.value.Length - 1) throw new IndexOutOfRangeException();
this.value[index] = value;
}
/// <summary>
/// Determines whether an auto-resize is needed.
/// </summary>
/// <param name="index"></param>
/// <returns>-1 if auto-resize is disabled, 0 if no resize was needed, or the number of elements added to the underlying array.</returns>
private int AutoResizeIfNeeded(int index)
{
if (mvarAutoResize) return -1;
if (index > this.length - 1 && mvarAutoResize)
{
if (this.length + 1 > this.value.Length - 1)
{
Array.Resize<T>(ref this.value, this.value.Length * 2);
this.length++;
}
}
return 0;
}
/// <summary>
/// Retrieves the value at the specified index.
/// </summary>
/// <param name="index">The index in the underlying array of the value to retrieve, or -1 to retrieve the current value.</param>
/// <returns></returns>
public T GetValue(int index = -1)
{
if (index == -1) index = this.index;
return this.value[index];
}
public T this[int index]
{
get
{
return this.value[index];
}
set
{
this.value[index] = value;
}
}
private bool mvarAutoResize;
/// <summary>
/// Determines if the underlying array will automatically resize when an attempt is made to address memory outside of the array boundaries.
/// </summary>
public bool AutoResize { get { return mvarAutoResize; } set { mvarAutoResize = value; } }
}
}