com.github.bloodshura.sparkium.brainfxck.BrainfuckMemory Maven / Gradle / Ivy
Show all versions of sparkium-brainfxck Show documentation
package com.github.bloodshura.sparkium.brainfxck;
import com.github.bloodshura.ignitium.worker.ArrayWorker;
/**
* This class is responsible for storing the volatile memory used by Brainfuck interpreters.
* Pointers and values, whenever needed by Brainfuck code, are manipulated here.
*
It does have some limitations, like the inability to move the pointer to negative places, but for that reason the class is open and, if necessary, you can override the methods and implement whatever design is needed.
*/
public class BrainfuckMemory {
private final int incrementSize;
private int[] memory;
private int pointer;
/**
* Constructs a new brainfuck memory instance, using 256 as the initial memory size and increment size.
*
* @see #BrainfuckMemory(int, int)
*/
public BrainfuckMemory() {
this(256, 256);
}
/**
* Constructs a new brainfuck memory instance, using the specified initial memory size and increment size.
*
To see how memory increment is done, see {@link #setPointer(int)}.
*
* @param initialSize The initial memory size
* @param incrementSize The memory incremention size
* @see #setPointer(int)
* @see #getSize()
*/
public BrainfuckMemory(int initialSize, int incrementSize) {
this.incrementSize = incrementSize;
this.memory = new int[initialSize];
}
/**
* Moves the pointer one position less.
*
Just a convenient method to it's equivalence: setPointer(pointer() - 1)
.
*
* @return The new pointer after the operation
* @see #getPointer()
* @see #setPointer(int)
*/
public int decreasePointer() {
setPointer(getPointer() - 1);
return getPointer();
}
/**
* Reduces by one the value at the current pointer.
*
Just a convenient method to it's equivalence: setValue(value() - 1)
.
*
* @return The new value after the operation
* @see #setValue(int)
* @see #getValue()
*/
public int decreaseValue() {
setValue(getValue() - 1);
return getValue();
}
/**
* If the pointer exceeds the current memory size (it is, if pointer() >= size()
), the memory will be expanded, using the {@link #incrementSize} defined in the constructor {@link #BrainfuckMemory(int, int)}.
*
If the size() + incrementSize
expression still is not sufficient enough to the pointer be considered valid, then the new memory size will be pointer + 1
.
*
* @param pointer The target pointer
* @return A boolean indicating TRUE if the memory was re-sized, or FALSE if there were no modifications
*/
public boolean ensureSizeFor(int pointer) {
if (pointer >= getSize()) {
this.memory = ArrayWorker.copyOf(memory, Math.max(getSize() + incrementSize, pointer + 1));
return true;
}
return false;
}
/**
* The current pointer, used for reading the value.
*
* @return The current pointer
* @see #setPointer(int)
* @see #getValue()
*/
public int getPointer() {
return pointer;
}
/**
* Returns the current memory size.
*
* @return The memory size
*/
public int getSize() {
return memory.length;
}
/**
* Returns the value on the current pointer.
*
* @return The value on the current pointer
* @see #getPointer()
* @see #getValueAt(int)
*/
public int getValue() {
return getValueAt(getPointer());
}
/**
* Returns the value on the specified pointer.
*
If the pointer is out of memory bounds (that is: if pointer < 0 || pointer >= size()
), then zero is returned.
*
* @param pointer The pointer
* @return The value on the specified pointer, or zero
*/
public int getValueAt(int pointer) {
return pointer >= 0 && pointer < getSize() ? memory[pointer] : 0;
}
/**
* Moves the pointer one position more.
*
Just a convenient method to it's equivalence: setPointer(pointer() + 1)
.
*
* @return The new pointer after the operation
* @see #getPointer()
* @see #setPointer(int)
*/
public int increasePointer() {
setPointer(getPointer() + 1);
return getPointer();
}
/**
* Increases by one the value at the current pointer.
*
Just a convenient method to it's equivalence: setValue(value() + 1)
.
*
* @return The new value after the operation
* @see #setValue(int)
* @see #getValue()
*/
public int increaseValue() {
setValue(getValue() + 1);
return getValue();
}
/**
* Sets the current pointer. No action is taken if the pointer is negative.
*
If the pointer exceeds the current memory size (it is, if pointer() >= size()
), the memory will be expanded. See {@link #ensureSizeFor(int)} for more details.
*
If the pointer is negative, it is restored to zero.
*
* @param pointer The new pointer position
* @see #incrementSize
* @see #getPointer()
* @see #getSize()
*/
public void setPointer(int pointer) {
if (pointer < 0) {
pointer = 0;
}
this.pointer = pointer;
ensureSizeFor(pointer);
}
/**
* Sets the specified value on the current pointer.
*
* @param value The new value
* @see #getPointer()
* @see #setValueAt(int, int)
*/
public void setValue(int value) {
setValueAt(getPointer(), value);
}
/**
* Sets the specified value on the specified pointer.
*
* @param pointer The pointer to insert the value in
* @param value The value appended to the pointer
*/
public void setValueAt(int pointer, int value) {
this.memory[pointer] = value;
}
}