blob: a03cacc74cf953bc9aaaad28d7b6c9cf83d8dbe1 [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.mdf4;
//package de.rechner.openatfx_mdf.mdf4;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Utility class having methods to read MDF file contents.
*
* @author Christian Rechner
*/
public abstract class MDF4Util {
// For the strings in the IDBLOCK and for the block identifiers, always
// single byte character (SBC) encoding is used
// (standard ASCII extension ISO-8859-1 Latin character set).
private static final String CHARSET_ISO8859 = "ISO-8859-1";
// The string encoding used in an MDF file is UTF-8 (1-4 Bytes for each
// character).
// This applies to TXBLOCK and MDBLOCK data.
private static final String CHARSET_UTF8 = "UTF-8";
// Size of the first block in MDF
public static int headersize = 64;
/**
* Read an 8-bit signed integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static byte readUInt8(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).get();
}
/**
* Read an 8-bit signed integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static int readInt8(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).get() & 0xff;
}
/**
* Read an 16-bit unsigned integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static int readUInt16(ByteBuffer bb) {
// bb.flip();
return bb.order(ByteOrder.LITTLE_ENDIAN).getShort() & 0xffff;
}
/**
* Get a byte array from an 16-bit unsigned integer. (Little Endian)
*
* @param val
* The number to convert.
* @return The bytes.
*/
public static byte[] getBytesUInt16(int val) {
ByteBuffer b = ByteBuffer.allocate(2);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putShort((short) val);
return b.array();
}
/**
* Read an 16-bit signed integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static short readInt16(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).getShort();
}
/**
* Get a byte array from an 16-bit signed integer. (Little Endian)
*
* @param val
* The number to convert.
* @return The bytes.
*/
public static byte[] getBytesInt16(int val) {
ByteBuffer b = ByteBuffer.allocate(2);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putShort((short) val);
return b.array();
}
/**
* Read an 32-bit unsigned integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static long readUInt32(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).getInt() & 0xffffffffL;
}
/**
* Get a byte array form an 32-bit unsigned integer. (Little Endian)
*
* @param val
* The number to convert.
* @return The bytes.
*/
public static byte[] getBytesUInt32(long val) {
ByteBuffer b = ByteBuffer.allocate(4);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putInt((int) val);
return b.array();
}
/**
* Read an 32-bit signed integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static int readInt32(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
}
/**
* Read an 64-bit unsigned integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static long readUInt64(ByteBuffer bb) {
byte[] data = new byte[8];
bb.get(data);
long l1 = ((long) data[0] & 0xff) << 0 | ((long) data[1] & 0xff) << 8 | ((long) data[2] & 0xff) << 16
| ((long) data[3] & 0xff) << 24;
long l2 = ((long) data[4] & 0xff) << 0 | ((long) data[5] & 0xff) << 8 | ((long) data[6] & 0xff) << 16
| ((long) data[7] & 0xff) << 24;
return l1 << 0 | l2 << 32;
}
/**
* Get a byte array form an 64-bit unsigned integer. (Little Endian)
*
* @param val
* The number to convert.
* @return The bytes.
*/
public static byte[] getBytesUInt64(long val) {
ByteBuffer b = ByteBuffer.allocate(8);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putLong(val);
return b.array();
}
/**
* Read an 64-bit signed integer from the byte buffer.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static long readInt64(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).getLong();
}
/**
* Read a floating-point value compliant with IEEE 754, double precision (64
* bits) (see [IEEE-FP]) from the byte buffer. An infinite value (e.g. for
* tabular ranges in conversion rule) can be expressed using the NaNs
* INFINITY resp.
*
* @param bb
* The byte buffer.
* @return The value.
*/
public static double readReal(ByteBuffer bb) {
return bb.order(ByteOrder.LITTLE_ENDIAN).getDouble();
}
public static byte[] getBytesReal(double val) {
ByteBuffer bb = ByteBuffer.allocate(8);
bb.order(ByteOrder.LITTLE_ENDIAN).putDouble(val);
return bb.array();
}
/**
* Read a 64-bit signed integer from the byte buffer, used as byte position
* within the file. If a LINK is NIL (corresponds to 0), this means the LINK
* cannot be de-referenced. A link must be a multiple of 8.
*
* @param bb
* The byte buffer.
* @return The value as long.
*/
public static long readLink(ByteBuffer bb) {
byte[] data = new byte[8];
bb.get(data);
long l1 = ((long) data[0] & 0xff) << 0 | ((long) data[1] & 0xff) << 8 | ((long) data[2] & 0xff) << 16
| ((long) data[3] & 0xff) << 24;
long l2 = ((long) data[4] & 0xff) << 0 | ((long) data[5] & 0xff) << 8 | ((long) data[6] & 0xff) << 16
| ((long) data[7] & 0xff) << 24;
return l1 << 0 | l2 << 32;
}
/**
* Get a byte array from a link address. (Unsigned 64 bit int, Little
* Endian)
*
* @param lnk
* The link address to convert.
* @return The bytes.
*/
public static byte[] getBytesLink(long lnk) {
ByteBuffer b = ByteBuffer.allocate(8);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putLong(lnk);
return b.array();
}
/**
* Read a String in ISO 8859
*
* @param bb
* The ByteBuffer to use.
* @param length
* Number of chars to read.
* @return The result as String.
* @throws IOException
* If an reading error occurs.
*/
public static String readCharsISO8859(ByteBuffer bb, int length) throws IOException {
byte[] b = new byte[length];
bb.get(b);
return new String(b, 0, length, CHARSET_ISO8859);
}
/**
* Read a String from UTF-8 encoded bytes
*
* @param bb
* The ByteBuffer to use.
* @param length
* Number of chars to read.
* @return The result as String.
* @throws IOException
* If an reading error occurs.
*/
public static String readCharsUTF8(ByteBuffer bb, int length) throws IOException {
byte[] b = new byte[length];
bb.get(b);
return new String(b, 0, length, CHARSET_UTF8);
}
public static byte[] getBytesCharsUTF8(String s) throws IOException {
return s.getBytes(CHARSET_UTF8);
}
public static byte[] getBytesCharsUTF8WithTerminator(String s) throws IOException {
String term = "\0";
return (s + term).getBytes(CHARSET_UTF8);
}
/**
* Shifts an array for compression according to the MDF-Standard
*
* @param data
* The array to shift.
* @param columnsize
* The size of each shift column.
* @param forward
* True: The Input is the original array, output is shifted.
* False: vice versa. Input is shifted, and output is original
* Array.
* @return An array containing the transposed Data.
*/
public static byte[] transposeArray(byte[] data, int columnsize, boolean forward) {
byte[] out = new byte[data.length];
int len = data.length;
int rows = len / columnsize;
int scolumnsize = columnsize;
if (!forward) {
scolumnsize = rows;
rows = columnsize;
}
int counter = 0;
for (int i = 0; i < scolumnsize; i++) {
for (int j = 0; j < rows; j++) {
out[counter++] = data[i + j * scolumnsize];
}
}
System.arraycopy(data, counter, out, counter, len - counter);
return out;
}
}