package org.signalml.util.matfiles.elements; import java.io.DataOutputStream; import java.io.IOException; import org.signalml.util.matfiles.types.DataType; /** * This abstract class represents a single element that can be * written to a MAT file. * * @author Piotr Szachewicz */ public abstract class DataElement implements IMatFileElement { /** * From the MATLAB MAT-file format specification: * "All data that is uncompressed must be aligned on 64-bit boundaries." * This means that each data element must start on a 64-bit (8 bytes) boundary. */ protected static int MINIMUM_BLOCK_SIZE_IN_BYTES = 8; /** * The {@link DataType} of this data element. */ protected DataType dataType; /** * The value of the 'Number of Bytes' field in this data element. * This value does not include the 8-byte tag (tag consists of * a 4-byte integer representing the data type of the element and * a 4-byte integer holding the size of the data type). */ private int sizeInBytes; public DataElement(DataType dataType) { this.dataType = dataType; } public DataElement(DataType dataType, int sizeInBytes) { this.dataType = dataType; this.sizeInBytes = sizeInBytes; } /** * Returns the padding size for this element. Padding is used * so that each data element falls on the 64-bit boundaries. * (see: {@link DataElement#MINIMUM_BLOCK_SIZE_IN_BYTES}). * * @return the padding size in bytes. */ protected int getPaddingSizeInBytes() { return calculatePaddingSizeInBytes(getSizeInBytes()); } /** * Calculates the number of bytes that should be written as padding * taking into account the given size. * * @param size the size of the element for which the padding will be * calculated. * @return the padding size. */ protected int calculatePaddingSizeInBytes(int size) { if (size%MINIMUM_BLOCK_SIZE_IN_BYTES == 0) return 0; else return MINIMUM_BLOCK_SIZE_IN_BYTES - size % MINIMUM_BLOCK_SIZE_IN_BYTES; } /** * Writes the padding bytes to the {@link DataOutputStream}. * @param dataOutputStream * @throws IOException */ protected void writePadding(DataOutputStream dataOutputStream) throws IOException { dataOutputStream.write(new byte[getPaddingSizeInBytes()]); } @Override public void write(DataOutputStream dataOutputStream) throws IOException { dataType.write(dataOutputStream); dataOutputStream.writeInt(getSizeInBytes()); } /** * Returns the size in bytes field value. * (This size does not include the tag size). * @return the size of this element not including tag. */ protected int getSizeInBytes() { return sizeInBytes; } @Override public int getTotalSizeInBytes() { return 8 + getSizeInBytes() + getPaddingSizeInBytes(); } }