blob: 603ebb8a1deaada475e1e4cf94e03ab4e5c0bd36 [file] [log] [blame]
/*
* Copyright (c) 2016 Audi AG
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.mdm.mdfsorter.mdf3;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.zip.DataFormatException;
import org.eclipse.mdm.mdfsorter.AbstractDataProvider;
import org.eclipse.mdm.mdfsorter.ReadDataCache;
/**
* This Class is used to read Data from a data section, with an given offset. If
* Data is stored in a linked list or in a zipped block, it is this classes job
* to provide the data needed.
*
* @author Tobias Leemann
*
*/
/**
* @author EU2IYD9
*
*/
public class MDF3DataProvider implements AbstractDataProvider {
private FileChannel reader;
private MDF3GenBlock datasectionhead;
/**
* Data Cache.
*/
private ReadDataCache readCache;
/**
* Length of this data section.
*/
private long sectionlength;
private byte[] dataarr;
/**
* This constructer creates a new DataProvider with the given head.
*
* @param datasectionhead
* The header of the data section.
* @param reader
* FileChannel to the input file.
*/
public MDF3DataProvider(MDF3GenBlock datasectionhead, FileChannel reader) {
this.datasectionhead = datasectionhead;
this.reader = reader;
sectionlength = calculateLength();
readCache = new ReadDataCache(this);
}
public MDF3DataProvider(byte[] data) {
dataarr = data;
sectionlength = data.length;
}
public void setDataArray(byte[] dataArray) {
dataarr = dataArray;
sectionlength = dataArray.length;
}
/**
* Read length bytes from this datasection, starting at globaloffset (The
* offset in the datasection) This method physically reads data, and does
* not check the read data cache.
*
* @param globaloffset
* The offset from the start of this section, e.g. DTBLOCK
* @param data
* The ByteBuffer to read in. data.limit bytes are read.
* @throws IOException
* If an I/O-Error occurs.
*/
@Override
public void read(long globaloffset, ByteBuffer data) throws IOException {
if (globaloffset + data.capacity() > sectionlength) {
throw new IllegalArgumentException(
"Invalid read access on Data Provider. Section is only " + sectionlength + " bytes long.");
}
if (dataarr != null) {
data.put(dataarr, (int) globaloffset, data.capacity());
data.rewind();
return;
}
reader.position(datasectionhead.getPos() + globaloffset);
reader.read(data);
data.rewind();
}
/**
* Returns a ByteBuffer with position at globaloffset, where length bytes
* can be read from. If the data is available in the cache, it is taken from
* there.
*
* @param globaloffset
* The place in the data section, where the read should start.
* @param length
* The length to read.
* @return A ByteBuffer with the position at global offset, from which
* length bytes can be read.
* @throws IOException
* If an I/O-Error occurs.
* @throws DataFormatException
* If zipped data is in an invalid Format (this cannot happen
* here)
*/
@Override
public ByteBuffer cachedRead(long globaloffset, int length) throws IOException, DataFormatException {
// argument check
if (globaloffset + length > sectionlength) {
throw new IllegalArgumentException(
"Invalid read access on Data Provider. Section is only " + sectionlength + " bytes long.");
}
if (dataarr != null) {
ByteBuffer data = ByteBuffer.allocate(length);
data.put(dataarr, (int) globaloffset, data.capacity());
data.rewind();
return data;
} else {
return readCache.read(globaloffset, length);
}
}
@Override
public long getLength() {
return sectionlength;
}
/**
* Calculate the length of this data section.
*
* @return The length.
*/
private long calculateLength() {
if (datasectionhead != null) {
return datasectionhead.getLength();
}
return 0;
}
}