// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.gui.hexview;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import tv.porst.jhexview.DataChangedEvent;
import tv.porst.jhexview.IDataChangedListener;
import tv.porst.jhexview.IDataProvider;
import tv.porst.jhexview.SimpleDataProvider;
/**
* A slightly improved version of {@link SimpleDataProvider} which allows to change size
* of the data buffer with the {@link #setDataLength(int)} method.
*/
public class VariableDataProvider implements IDataProvider
{
private final List<IDataChangedListener> listeners = new ArrayList<IDataChangedListener>();
private byte[] buffer;
public VariableDataProvider()
{
buffer = new byte[0];
}
public VariableDataProvider(byte[] data)
{
buffer = data;
}
@Override
public void addListener(IDataChangedListener listener)
{
if (listener != null && !listeners.contains(listener)) {
listeners.add(listener);
}
}
@Override
public byte[] getData(long offset, int length)
{
if (offset + length > getDataLength()) {
length = getDataLength() - (int)offset;
}
if (length > 0) {
return Arrays.copyOfRange(buffer, (int) offset, (int) (offset + length));
} else {
return new byte[0];
}
}
@Override
public int getDataLength()
{
return buffer.length;
}
/**
* Resizes the current data buffer to the specified length in bytes.
* Old data will be retained as best as possible.
* @param newLength The new size of the data buffer in bytes.
* @return The old length of the data buffer in bytes.
*/
public int setDataLength(int newLength)
{
newLength = Math.max(0, newLength);
byte[] temp = new byte[newLength];
int copySize = Math.min(buffer.length, temp.length);
System.arraycopy(buffer, 0, temp, 0, copySize);
int retVal = buffer.length;
buffer = temp;
return retVal;
}
@Override
public boolean hasData(long start, int length)
{
return ((int)start + length <= getDataLength());
}
@Override
public boolean isEditable()
{
return true;
}
@Override
public boolean keepTrying()
{
return false;
}
@Override
public void removeListener(IDataChangedListener listener)
{
if (listener != null) {
listeners.remove(listener);
}
}
@Override
public void setData(long offset, byte[] data)
{
int length = data.length;
if (offset + data.length > getDataLength()) {
length = getDataLength() - (int)offset;
}
if (length > 0) {
System.arraycopy(data, 0, buffer, (int) offset, data.length);
fireDataChangedListener();
}
}
protected void fireDataChangedListener()
{
if (!listeners.isEmpty()) {
DataChangedEvent event = new DataChangedEvent(this);
for (final IDataChangedListener l: listeners) {
l.dataChanged(event);
}
}
}
}