mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-09-26 04:09:39 +03:00
* OESS-98 convert plugin option to FetchContent, add tests * Fixes for pkcfg files because of plugin option * OESS-98 fix tools test for plugins * Keep doxygen comments under 100 chars long - format hint * Whitespace * HDFFV-11144 - Reclassify CMake messages * HDFFV-11099/11100 added help text * Reworked switch statement to compare string instead * Fix typo * Update CDash mode * Correct name of threadsafe * Correct option name * Undo accidental commit * Note LLVM 10 to 11 format default changes * Update format plugin * Undo clang-format version 11 changes * One more correction * Update supported platforms * Revert whitespace changes * Correct whitespace * Changes from PR#3 * HDFFV-11213 added option to control gcc10 warnings diagnostics * HDFFV-11212 Use the new references correctly in JNI utility and tests * format source * Fix typo * Add new test file * HDFFV-11212 - update test and remove unused arg * Minor non-space formatting changes * Use H5I_INVALID_ID instead of "-1" * source formatting * add missing testfile, update jni function * Undo commit of debug code * remove mislocated file * Fix h5repack test for handling of fapls and id close * Update h5diff test files usage text * HDFFV-11212 add new ref tests for JNI export dataset * src format update * Remove blank line typo * src format typo * long double requires %Lg * Another long double foramt specifer S.B. %Lg * issue with t128bit test * Windows issue with h5dump and type. * Fix review issues * refactor function nesting and fix error checks * format fixes * Remove untested functions and javadoc quiet comments * Restore TRY block. * Change string append errors to memory exception * revert to H5_JNI_FATAL_ERROR - support functions need work * Add assertion error for h5util functions * remove duplicate function * format fix * Revert HD function error handling * Update copyright comments * GH #386 java folder copyright corrections * Whitespace * GH #359 implement and fix tools 1.6 API usage * remove excessive comments * Flip inits to correct ifdef section * rework ifdef to be simpler * format issue * Reformat ifdef inits * remove static attribute * format compliance * Update names * Revert because logic relies on float not being int * Changes noticed from creating merge of #412 * Double underscore change * Correct compiler version variable used * Remove header guard underscores * Whitespace cleanup * Split format source and commit changes on repo push * remove pre-split setting * Change windows TS to use older VS. * correct window os name * HDFFV-11212 JNI export util and Javadoc * Suggested review changes * Another change found * Committing clang-format changes Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
937 lines
37 KiB
Java
937 lines
37 KiB
Java
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* Copyright by the Board of Trustees of the University of Illinois. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the COPYING file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
package hdf.hdf5lib;
|
|
|
|
import hdf.hdf5lib.exceptions.HDF5Exception;
|
|
import hdf.hdf5lib.exceptions.HDF5JavaException;
|
|
import java.util.Arrays;
|
|
|
|
/**
|
|
* This is a class for handling multidimensional arrays for HDF.
|
|
* <p>
|
|
* The purpose is to allow the storage and retrieval of arbitrary array types containing scientific data.
|
|
* <p>
|
|
* The methods support the conversion of an array to and from Java to a one-dimensional array of bytes suitable for I/O
|
|
* by the C library.
|
|
* <p>
|
|
* This class heavily uses the <a href="./hdf.hdf5lib.HDFNativeData.html">HDFNativeData</a> class to convert between
|
|
* Java and C representations.
|
|
*/
|
|
|
|
public class HDFArray {
|
|
private Object _theArray = null;
|
|
private ArrayDescriptor _desc = null;
|
|
private byte[] _barray = null;
|
|
|
|
// public HDFArray() {}
|
|
|
|
/**
|
|
* The input must be a Java Array (possibly multidimensional) of primitive numbers or sub-classes of Number.
|
|
* <p>
|
|
* The input is analysed to determine the number of dimensions and size of each dimension, as well as the type of
|
|
* the elements.
|
|
* <p>
|
|
* The description is saved in private variables, and used to convert data.
|
|
*
|
|
* @param anArray
|
|
* The array object.
|
|
* @exception hdf.hdf5lib.exceptions.HDF5Exception
|
|
* object is not an array.
|
|
*/
|
|
public HDFArray(Object anArray) throws HDF5Exception
|
|
{
|
|
if (anArray == null) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: array is null?: ");
|
|
}
|
|
Class tc = anArray.getClass();
|
|
if (tc.isArray() == false) {
|
|
/* exception: not an array */
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: not an array?: ");
|
|
throw (ex);
|
|
}
|
|
_theArray = anArray;
|
|
_desc = new ArrayDescriptor(_theArray);
|
|
|
|
/* extra error checking -- probably not needed */
|
|
if (_desc == null) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: internal error: array description failed?: ");
|
|
throw (ex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Allocate a one-dimensional array of bytes sufficient to store the array.
|
|
*
|
|
* @return A one-D array of bytes, filled with zeroes. The bytes are sufficient to hold the data of the Array passed
|
|
* to the constructor.
|
|
* @exception hdf.hdf5lib.exceptions.HDF5JavaException
|
|
* Allocation failed.
|
|
*/
|
|
|
|
public byte[] emptyBytes()
|
|
throws HDF5JavaException
|
|
{
|
|
byte[] b = null;
|
|
|
|
if ((ArrayDescriptor.dims == 1)
|
|
&& (ArrayDescriptor.NT == 'B')) {
|
|
b = (byte[]) _theArray;
|
|
}
|
|
else {
|
|
b = new byte[ArrayDescriptor.totalSize];
|
|
}
|
|
if (b == null) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: emptyBytes: allocation failed");
|
|
throw (ex);
|
|
}
|
|
return (b);
|
|
}
|
|
|
|
/**
|
|
* Given a Java array of numbers, convert it to a one-dimensional array of bytes in correct native order.
|
|
*
|
|
* @return A one-D array of bytes, constructed from the Array passed to the constructor.
|
|
* @exception hdf.hdf5lib.exceptions.HDF5JavaException
|
|
* the object not an array or other internal error.
|
|
*/
|
|
public byte[] byteify()
|
|
throws HDF5JavaException
|
|
{
|
|
if (_barray != null) {
|
|
return _barray;
|
|
}
|
|
|
|
if (_theArray == null) {
|
|
/* exception: not an array */
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify not an array?: ");
|
|
throw (ex);
|
|
}
|
|
|
|
if (ArrayDescriptor.dims == 1) {
|
|
/* special case */
|
|
if (ArrayDescriptor.NT == 'B') {
|
|
/* really special case! */
|
|
_barray = (byte[]) _theArray;
|
|
return _barray;
|
|
}
|
|
else {
|
|
try {
|
|
_barray = new byte[ArrayDescriptor.totalSize];
|
|
|
|
byte[] therow;
|
|
if (ArrayDescriptor.NT == 'I') {
|
|
therow = HDFNativeData.intToByte(0, ArrayDescriptor.dimlen[1], (int[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'S') {
|
|
therow = HDFNativeData.shortToByte(0, ArrayDescriptor.dimlen[1], (short[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'F') {
|
|
therow = HDFNativeData.floatToByte(0, ArrayDescriptor.dimlen[1], (float[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'J') {
|
|
therow = HDFNativeData.longToByte(0, ArrayDescriptor.dimlen[1], (long[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'D') {
|
|
therow = HDFNativeData.doubleToByte(0, ArrayDescriptor.dimlen[1], (double[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'L') {
|
|
if (ArrayDescriptor.className.equals("java.lang.Byte")) {
|
|
therow = ByteObjToByte((Byte[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Integer")) {
|
|
therow = IntegerToByte((Integer[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Short")) {
|
|
therow = ShortToByte((Short[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Float")) {
|
|
therow = FloatObjToByte((Float[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Double")) {
|
|
therow = DoubleObjToByte((Double[]) _theArray);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Long")) {
|
|
therow = LongObjToByte((Long[]) _theArray);
|
|
}
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: unknown type of Object?");
|
|
throw (ex);
|
|
}
|
|
}
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: unknown type of data?");
|
|
throw (ex);
|
|
}
|
|
System.arraycopy(therow, 0, _barray, 0, (ArrayDescriptor.dimlen[1] * ArrayDescriptor.NTsize));
|
|
return _barray;
|
|
}
|
|
catch (OutOfMemoryError err) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify array too big?");
|
|
throw (ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
_barray = new byte[ArrayDescriptor.totalSize];
|
|
}
|
|
catch (OutOfMemoryError err) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify array too big?");
|
|
throw (ex);
|
|
}
|
|
|
|
Object oo = _theArray;
|
|
int n = 0; /* the current byte */
|
|
int index = 0;
|
|
int i;
|
|
while (n < ArrayDescriptor.totalSize) {
|
|
oo = ArrayDescriptor.objs[0];
|
|
index = n / ArrayDescriptor.bytetoindex[0];
|
|
index %= ArrayDescriptor.dimlen[0];
|
|
for (i = 0; i < (ArrayDescriptor.dims); i++) {
|
|
index = n / ArrayDescriptor.bytetoindex[i];
|
|
index %= ArrayDescriptor.dimlen[i];
|
|
|
|
if (index == ArrayDescriptor.currentindex[i]) {
|
|
/* then use cached copy */
|
|
oo = ArrayDescriptor.objs[i];
|
|
}
|
|
else {
|
|
/* check range of index */
|
|
if (index > (ArrayDescriptor.dimlen[i] - 1)) {
|
|
throw new java.lang.IndexOutOfBoundsException("HDFArray: byteify index OOB?");
|
|
}
|
|
oo = java.lang.reflect.Array.get(oo, index);
|
|
ArrayDescriptor.currentindex[i] = index;
|
|
ArrayDescriptor.objs[i] = oo;
|
|
}
|
|
}
|
|
|
|
/* byte-ify */
|
|
byte arow[];
|
|
try {
|
|
if (ArrayDescriptor.NT == 'J') {
|
|
arow = HDFNativeData.longToByte(0, ArrayDescriptor.dimlen[ArrayDescriptor.dims],
|
|
(long[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
arow = HDFNativeData.longToByte(0, ArrayDescriptor.dimlen[ArrayDescriptor.dims],
|
|
(long[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'I') {
|
|
arow = HDFNativeData.intToByte(0, ArrayDescriptor.dimlen[ArrayDescriptor.dims],
|
|
(int[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'S') {
|
|
arow = HDFNativeData.shortToByte(0, ArrayDescriptor.dimlen[ArrayDescriptor.dims],
|
|
(short[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'B') {
|
|
arow = (byte[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1];
|
|
}
|
|
else if (ArrayDescriptor.NT == 'F') {
|
|
/* 32 bit float */
|
|
arow = HDFNativeData.floatToByte(0, ArrayDescriptor.dimlen[ArrayDescriptor.dims],
|
|
(float[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'D') {
|
|
/* 64 bit float */
|
|
arow = HDFNativeData.doubleToByte(0, ArrayDescriptor.dimlen[ArrayDescriptor.dims],
|
|
(double[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.NT == 'L') {
|
|
if (ArrayDescriptor.className.equals("java.lang.Byte")) {
|
|
arow = ByteObjToByte((Byte[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Integer")) {
|
|
arow = IntegerToByte((Integer[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Short")) {
|
|
arow = ShortToByte((Short[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Float")) {
|
|
arow = FloatObjToByte((Float[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Double")) {
|
|
arow = DoubleObjToByte((Double[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Long")) {
|
|
arow = LongObjToByte((Long[]) ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
|
|
}
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify Object type not implemented?");
|
|
throw (ex);
|
|
}
|
|
}
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify unknown type not implemented?");
|
|
throw (ex);
|
|
}
|
|
System.arraycopy(arow, 0, _barray, n,
|
|
(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * ArrayDescriptor.NTsize));
|
|
n += ArrayDescriptor.bytetoindex[ArrayDescriptor.dims - 1];
|
|
}
|
|
catch (OutOfMemoryError err) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify array too big?");
|
|
throw (ex);
|
|
}
|
|
}
|
|
/* assert: the whole array is completed--currentindex should == len - 1 */
|
|
/* error checks */
|
|
if (n < ArrayDescriptor.totalSize) {
|
|
throw new java.lang.InternalError(new String("HDFArray::byteify: Panic didn't complete all input data: n= "
|
|
+ n + " size = " + ArrayDescriptor.totalSize));
|
|
}
|
|
for (i = 0; i < ArrayDescriptor.dims; i++) {
|
|
if (ArrayDescriptor.currentindex[i] != ArrayDescriptor.dimlen[i] - 1) {
|
|
throw new java.lang.InternalError(new String(
|
|
"Panic didn't complete all data: currentindex[" + i + "] = " + ArrayDescriptor.currentindex[i]
|
|
+ " (should be " + (ArrayDescriptor.dimlen[i] - 1) + " ?)"));
|
|
}
|
|
}
|
|
return _barray;
|
|
}
|
|
|
|
/**
|
|
* Given a one-dimensional array of bytes representing numbers, convert it to a java array of the shape and size
|
|
* passed to the constructor.
|
|
*
|
|
* @param bytes
|
|
* The bytes to construct the Array.
|
|
* @return
|
|
* An Array (possibly multidimensional) of primitive or number objects.
|
|
* @exception
|
|
* hdf.hdf5lib.exceptions.HDF5JavaException the object not an array or other internal error.
|
|
*/
|
|
public Object arrayify(byte[] bytes) throws HDF5JavaException
|
|
{
|
|
if (_theArray == null) {
|
|
/* exception: not an array */
|
|
HDF5JavaException ex = new HDF5JavaException("arrayify: not an array?: ");
|
|
throw (ex);
|
|
}
|
|
|
|
if (java.lang.reflect.Array.getLength(bytes) != ArrayDescriptor.totalSize) {
|
|
/* exception: array not right size */
|
|
HDF5JavaException ex = new HDF5JavaException("arrayify: array is wrong size?: ");
|
|
throw (ex);
|
|
}
|
|
_barray = bytes; /* hope that the bytes are correct.... */
|
|
|
|
if (ArrayDescriptor.dims == 1) {
|
|
/* special case */
|
|
/* 2 data copies here! */
|
|
try {
|
|
if (ArrayDescriptor.NT == 'I') {
|
|
int[] x = HDFNativeData.byteToInt(_barray);
|
|
System.arraycopy(x, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.NT == 'S') {
|
|
short[] x = HDFNativeData.byteToShort(_barray);
|
|
System.arraycopy(x, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.NT == 'F') {
|
|
float x[] = HDFNativeData.byteToFloat(_barray);
|
|
System.arraycopy(x, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.NT == 'J') {
|
|
long x[] = HDFNativeData.byteToLong(_barray);
|
|
System.arraycopy(x, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.NT == 'D') {
|
|
double x[] = HDFNativeData.byteToDouble(_barray);
|
|
System.arraycopy(x, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.NT == 'B') {
|
|
System.arraycopy(_barray, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.NT == 'L') {
|
|
if (ArrayDescriptor.className.equals("java.lang.Byte")) {
|
|
Byte I[] = ByteToByteObj(_barray);
|
|
System.arraycopy(I, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Integer")) {
|
|
Integer I[] = ByteToInteger(_barray);
|
|
System.arraycopy(I, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Short")) {
|
|
Short I[] = ByteToShort(_barray);
|
|
System.arraycopy(I, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Float")) {
|
|
Float I[] = ByteToFloatObj(_barray);
|
|
System.arraycopy(I, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Double")) {
|
|
Double I[] = ByteToDoubleObj(_barray);
|
|
System.arraycopy(I, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else if (ArrayDescriptor.className.equals("java.lang.Long")) {
|
|
Long I[] = ByteToLongObj(_barray);
|
|
System.arraycopy(I, 0, _theArray, 0, ArrayDescriptor.dimlen[1]);
|
|
return _theArray;
|
|
}
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("arrayify: Object type not implemented yet...");
|
|
throw (ex);
|
|
}
|
|
}
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("arrayify: unknown type not implemented yet...");
|
|
throw (ex);
|
|
}
|
|
}
|
|
catch (OutOfMemoryError err) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: arrayify array too big?");
|
|
throw (ex);
|
|
}
|
|
}
|
|
/* Assert dims >= 2 */
|
|
|
|
Object oo = _theArray;
|
|
int n = 0; /* the current byte */
|
|
int m = 0; /* the current array index */
|
|
int index = 0;
|
|
int i;
|
|
Object flattenedArray = null;
|
|
|
|
switch (ArrayDescriptor.NT) {
|
|
case 'J':
|
|
flattenedArray = (Object) HDFNativeData.byteToLong(_barray);
|
|
break;
|
|
case 'S':
|
|
flattenedArray = (Object) HDFNativeData.byteToShort(_barray);
|
|
break;
|
|
case 'I':
|
|
flattenedArray = (Object) HDFNativeData.byteToInt(_barray);
|
|
break;
|
|
case 'F':
|
|
flattenedArray = (Object) HDFNativeData.byteToFloat(_barray);
|
|
break;
|
|
case 'D':
|
|
flattenedArray = (Object) HDFNativeData.byteToDouble(_barray);
|
|
break;
|
|
case 'B':
|
|
flattenedArray = (Object) _barray;
|
|
break;
|
|
case 'L':
|
|
{
|
|
if (ArrayDescriptor.className.equals("java.lang.Byte"))
|
|
flattenedArray = (Object) ByteToByteObj(_barray);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Short"))
|
|
flattenedArray = (Object) ByteToShort(_barray);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Integer"))
|
|
flattenedArray = (Object) ByteToInteger(_barray);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Long"))
|
|
flattenedArray = (Object) ByteToLongObj(_barray);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Float"))
|
|
flattenedArray = (Object) ByteToFloatObj(_barray);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Double"))
|
|
flattenedArray = (Object) ByteToDoubleObj(_barray);
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: unsupported Object type: " + ArrayDescriptor.NT);
|
|
throw (ex);
|
|
}
|
|
} // end of statement for arrays of boxed objects
|
|
default:
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: unknown or unsupported type: " + ArrayDescriptor.NT);
|
|
throw (ex);
|
|
} // end of switch statement for arrays of primitives
|
|
|
|
while (n < ArrayDescriptor.totalSize) {
|
|
oo = ArrayDescriptor.objs[0];
|
|
index = n / ArrayDescriptor.bytetoindex[0];
|
|
index %= ArrayDescriptor.dimlen[0];
|
|
for (i = 0; i < (ArrayDescriptor.dims); i++) {
|
|
index = n / ArrayDescriptor.bytetoindex[i];
|
|
index %= ArrayDescriptor.dimlen[i];
|
|
|
|
if (index == ArrayDescriptor.currentindex[i]) {
|
|
/* then use cached copy */
|
|
oo = ArrayDescriptor.objs[i];
|
|
}
|
|
else {
|
|
/* check range of index */
|
|
if (index > (ArrayDescriptor.dimlen[i] - 1)) {
|
|
System.out.println("out of bounds?");
|
|
return null;
|
|
}
|
|
oo = java.lang.reflect.Array.get(oo, index);
|
|
ArrayDescriptor.currentindex[i] = index;
|
|
ArrayDescriptor.objs[i] = oo;
|
|
}
|
|
}
|
|
|
|
/* array-ify */
|
|
try {
|
|
Object arow = null;
|
|
int mm = m + ArrayDescriptor.dimlen[ArrayDescriptor.dims];
|
|
switch (ArrayDescriptor.NT) {
|
|
case 'B':
|
|
arow = (Object) Arrays.copyOfRange((byte[]) flattenedArray, m, mm);
|
|
break;
|
|
case 'S':
|
|
arow = (Object) Arrays.copyOfRange((short[]) flattenedArray, m, mm);
|
|
break;
|
|
case 'I':
|
|
arow = (Object) Arrays.copyOfRange((int[]) flattenedArray, m, mm);
|
|
break;
|
|
case 'J':
|
|
arow = (Object) Arrays.copyOfRange((long[]) flattenedArray, m, mm);
|
|
break;
|
|
case 'F':
|
|
arow = (Object) Arrays.copyOfRange((float[]) flattenedArray, m, mm);
|
|
break;
|
|
case 'D':
|
|
arow = (Object) Arrays.copyOfRange((double[]) flattenedArray, m, mm);
|
|
break;
|
|
case 'L':
|
|
{
|
|
if (ArrayDescriptor.className.equals("java.lang.Byte"))
|
|
arow = (Object) Arrays.copyOfRange((Byte[]) flattenedArray, m, mm);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Short"))
|
|
arow = (Object) Arrays.copyOfRange((Short[]) flattenedArray, m, mm);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Integer"))
|
|
arow = (Object) Arrays.copyOfRange((Integer[]) flattenedArray, m, mm);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Long"))
|
|
arow = (Object) Arrays.copyOfRange((Long[]) flattenedArray, m, mm);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Float"))
|
|
arow = (Object) Arrays.copyOfRange((Float[]) flattenedArray, m, mm);
|
|
else if (ArrayDescriptor.className.equals("java.lang.Double"))
|
|
arow = (Object) Arrays.copyOfRange((Double[]) flattenedArray, m, mm);
|
|
else {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: unsupported Object type: " + ArrayDescriptor.NT);
|
|
throw (ex);
|
|
}
|
|
} // end of statement for arrays of boxed numerics
|
|
} // end of switch statement for arrays of primitives
|
|
|
|
java.lang.reflect.Array.set(ArrayDescriptor.objs[ArrayDescriptor.dims - 2],
|
|
(ArrayDescriptor.currentindex[ArrayDescriptor.dims - 1]), arow);
|
|
n += ArrayDescriptor.bytetoindex[ArrayDescriptor.dims - 1];
|
|
ArrayDescriptor.currentindex[ArrayDescriptor.dims - 1]++;
|
|
m = mm;
|
|
}
|
|
catch (OutOfMemoryError err) {
|
|
HDF5JavaException ex = new HDF5JavaException("HDFArray: arrayify array too big?");
|
|
throw (ex);
|
|
}
|
|
}
|
|
|
|
/* assert: the whole array is completed--currentindex should == len - 1 */
|
|
/* error checks */
|
|
if (n < ArrayDescriptor.totalSize) {
|
|
throw new java.lang.InternalError(new String("HDFArray::arrayify Panic didn't complete all input data: n= "
|
|
+ n + " size = " + ArrayDescriptor.totalSize));
|
|
}
|
|
for (i = 0; i <= ArrayDescriptor.dims - 2; i++) {
|
|
if (ArrayDescriptor.currentindex[i] != ArrayDescriptor.dimlen[i] - 1) {
|
|
throw new java.lang.InternalError(
|
|
new String("HDFArray::arrayify Panic didn't complete all data: currentindex[" + i + "] = "
|
|
+ ArrayDescriptor.currentindex[i] + " (should be " + (ArrayDescriptor.dimlen[i] - 1)
|
|
+ "?"));
|
|
}
|
|
}
|
|
if (ArrayDescriptor.currentindex[ArrayDescriptor.dims - 1] != ArrayDescriptor.dimlen[ArrayDescriptor.dims
|
|
- 1]) {
|
|
throw new java.lang.InternalError(
|
|
new String("HDFArray::arrayify Panic didn't complete all data: currentindex[" + i + "] = "
|
|
+ ArrayDescriptor.currentindex[i] + " (should be " + (ArrayDescriptor.dimlen[i]) + "?"));
|
|
}
|
|
|
|
return _theArray;
|
|
}
|
|
|
|
private byte[] IntegerToByte(Integer in[])
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength(in);
|
|
int[] out = new int[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = in[i].intValue();
|
|
}
|
|
return HDFNativeData.intToByte(0, nelems, out);
|
|
}
|
|
|
|
private Integer[] ByteToInteger(byte[] bin)
|
|
{
|
|
int in[] = HDFNativeData.byteToInt(bin);
|
|
int nelems = java.lang.reflect.Array.getLength(in);
|
|
Integer[] out = new Integer[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Integer(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Integer[] ByteToInteger(int start, int len, byte[] bin)
|
|
{
|
|
int in[] = HDFNativeData.byteToInt(start, len, bin);
|
|
int nelems = java.lang.reflect.Array.getLength(in);
|
|
Integer[] out = new Integer[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Integer(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private byte[] ShortToByte(Short in[])
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength(in);
|
|
short[] out = new short[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = in[i].shortValue();
|
|
}
|
|
return HDFNativeData.shortToByte(0, nelems, out);
|
|
}
|
|
|
|
private Short[] ByteToShort(byte[] bin)
|
|
{
|
|
short in[] = HDFNativeData.byteToShort(bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Short[] out = new Short[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Short(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Short[] ByteToShort(int start, int len, byte[] bin)
|
|
{
|
|
short in[] = (short[]) HDFNativeData.byteToShort(start, len, bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Short[] out = new Short[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Short(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private byte[] ByteObjToByte(Byte in[])
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
byte[] out = new byte[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = in[i].byteValue();
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Byte[] ByteToByteObj(byte[] bin)
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength((Object) bin);
|
|
Byte[] out = new Byte[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Byte(bin[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Byte[] ByteToByteObj(int start, int len, byte[] bin)
|
|
{
|
|
Byte[] out = new Byte[len];
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
out[i] = new Byte(bin[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private byte[] FloatObjToByte(Float in[])
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
float[] out = new float[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = in[i].floatValue();
|
|
}
|
|
return HDFNativeData.floatToByte(0, nelems, out);
|
|
}
|
|
|
|
private Float[] ByteToFloatObj(byte[] bin)
|
|
{
|
|
float in[] = (float[]) HDFNativeData.byteToFloat(bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Float[] out = new Float[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Float(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Float[] ByteToFloatObj(int start, int len, byte[] bin)
|
|
{
|
|
float in[] = (float[]) HDFNativeData.byteToFloat(start, len, bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Float[] out = new Float[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Float(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private byte[] DoubleObjToByte(Double in[])
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
double[] out = new double[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = in[i].doubleValue();
|
|
}
|
|
return HDFNativeData.doubleToByte(0, nelems, out);
|
|
}
|
|
|
|
private Double[] ByteToDoubleObj(byte[] bin)
|
|
{
|
|
double in[] = (double[]) HDFNativeData.byteToDouble(bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Double[] out = new Double[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Double(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Double[] ByteToDoubleObj(int start, int len, byte[] bin)
|
|
{
|
|
double in[] = (double[]) HDFNativeData.byteToDouble(start, len, bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Double[] out = new Double[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Double(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private byte[] LongObjToByte(Long in[])
|
|
{
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
long[] out = new long[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = in[i].longValue();
|
|
}
|
|
return HDFNativeData.longToByte(0, nelems, out);
|
|
}
|
|
|
|
private Long[] ByteToLongObj(byte[] bin)
|
|
{
|
|
long in[] = (long[]) HDFNativeData.byteToLong(bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Long[] out = new Long[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Long(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private Long[] ByteToLongObj(int start, int len, byte[] bin)
|
|
{
|
|
long in[] = (long[]) HDFNativeData.byteToLong(start, len, bin);
|
|
int nelems = java.lang.reflect.Array.getLength((Object) in);
|
|
Long[] out = new Long[nelems];
|
|
|
|
for (int i = 0; i < nelems; i++) {
|
|
out[i] = new Long(in[i]);
|
|
}
|
|
return out;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This private class is used by HDFArray to discover the shape and type of an arbitrary array.
|
|
* <p>
|
|
* We use java.lang.reflection here.
|
|
*/
|
|
class ArrayDescriptor {
|
|
static String theType = "";
|
|
static Class theClass = null;
|
|
static int[] dimlen = null;
|
|
static int[] dimstart = null;
|
|
static int[] currentindex = null;
|
|
static int[] bytetoindex = null;
|
|
static int totalSize = 0;
|
|
static int totalElements = 0;
|
|
static Object[] objs = null;
|
|
static char NT = ' '; /* must be B,S,I,L,F,D, else error */
|
|
static int NTsize = 0;
|
|
static int dims = 0;
|
|
static String className;
|
|
|
|
public ArrayDescriptor(Object anArray) throws HDF5Exception
|
|
{
|
|
Class tc = anArray.getClass();
|
|
if (tc.isArray() == false) {
|
|
/* exception: not an array */
|
|
HDF5Exception ex = new HDF5JavaException("ArrayDescriptor: not an array?: ");
|
|
throw (ex);
|
|
}
|
|
|
|
theClass = tc;
|
|
|
|
/*
|
|
* parse the type descriptor to discover the shape of the array
|
|
*/
|
|
String ss = tc.toString();
|
|
theType = ss;
|
|
int n = 6;
|
|
dims = 0;
|
|
char c = ' ';
|
|
while (n < ss.length()) {
|
|
c = ss.charAt(n);
|
|
n++;
|
|
if (c == '[') {
|
|
dims++;
|
|
}
|
|
}
|
|
|
|
String css = ss.substring(ss.lastIndexOf('[') + 1);
|
|
Class compC = tc.getComponentType();
|
|
String cs = compC.toString();
|
|
NT = c; /* must be B,S,I,L,F,D, else error */
|
|
if (NT == 'B') {
|
|
NTsize = 1;
|
|
}
|
|
else if (NT == 'S') {
|
|
NTsize = 2;
|
|
}
|
|
else if ((NT == 'I') || (NT == 'F')) {
|
|
NTsize = 4;
|
|
}
|
|
else if ((NT == 'J') || (NT == 'D')) {
|
|
NTsize = 8;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.Byte")) {
|
|
NT = 'L';
|
|
className = "java.lang.Byte";
|
|
NTsize = 1;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.Short")) {
|
|
NT = 'L';
|
|
className = "java.lang.Short";
|
|
NTsize = 2;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.Integer")) {
|
|
NT = 'L';
|
|
className = "java.lang.Integer";
|
|
NTsize = 4;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.Float")) {
|
|
NT = 'L';
|
|
className = "java.lang.Float";
|
|
NTsize = 4;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.Double")) {
|
|
NT = 'L';
|
|
className = "java.lang.Double";
|
|
NTsize = 8;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.Long")) {
|
|
NT = 'L';
|
|
className = "java.lang.Long";
|
|
NTsize = 8;
|
|
}
|
|
else if (css.startsWith("Ljava.lang.String")) {
|
|
NT = 'L';
|
|
className = "java.lang.String";
|
|
NTsize = 1;
|
|
throw new HDF5JavaException(new String("ArrayDesciptor: Warning: String array not fully supported yet"));
|
|
}
|
|
else {
|
|
/*
|
|
* exception: not a numeric type
|
|
*/
|
|
throw new HDF5JavaException(
|
|
new String("ArrayDesciptor: Error: array is not numeric (type is " + css + ") ?"));
|
|
}
|
|
|
|
/* fill in the table */
|
|
dimlen = new int[dims + 1];
|
|
dimstart = new int[dims + 1];
|
|
currentindex = new int[dims + 1];
|
|
bytetoindex = new int[dims + 1];
|
|
objs = new Object[dims + 1];
|
|
|
|
Object o = anArray;
|
|
objs[0] = o;
|
|
dimlen[0] = 1;
|
|
dimstart[0] = 0;
|
|
currentindex[0] = 0;
|
|
int elements = 1;
|
|
int i;
|
|
for (i = 1; i <= dims; i++) {
|
|
dimlen[i] = java.lang.reflect.Array.getLength((Object) o);
|
|
o = java.lang.reflect.Array.get((Object) o, 0);
|
|
objs[i] = o;
|
|
dimstart[i] = 0;
|
|
currentindex[i] = 0;
|
|
elements *= dimlen[i];
|
|
}
|
|
totalElements = elements;
|
|
|
|
int j;
|
|
int dd;
|
|
bytetoindex[dims] = NTsize;
|
|
for (i = dims; i >= 0; i--) {
|
|
dd = NTsize;
|
|
for (j = i; j < dims; j++) {
|
|
dd *= dimlen[j + 1];
|
|
}
|
|
bytetoindex[i] = dd;
|
|
}
|
|
|
|
totalSize = bytetoindex[0];
|
|
}
|
|
|
|
/**
|
|
* Debug dump
|
|
*/
|
|
public void dumpInfo()
|
|
{
|
|
System.out.println("Type: " + theType);
|
|
System.out.println("Class: " + theClass);
|
|
System.out.println("NT: " + NT + " NTsize: " + NTsize);
|
|
System.out.println("Array has " + dims + " dimensions (" + totalSize
|
|
+ " bytes, " + totalElements + " elements)");
|
|
int i;
|
|
for (i = 0; i <= dims; i++) {
|
|
Class tc = objs[i].getClass();
|
|
String ss = tc.toString();
|
|
System.out.println(i + ": start " + dimstart[i] + ": len " + dimlen[i] + " current " + currentindex[i]
|
|
+ " bytetoindex " + bytetoindex[i] + " object " + objs[i] + " otype " + ss);
|
|
}
|
|
}
|
|
}
|