
ucar.nc2.iosp.IospHelper Maven / Gradle / Ivy
/*
* Copyright 1998-2014 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2.iosp;
import ucar.nc2.constants.CDM;
import ucar.unidata.io.RandomAccessFile;
import ucar.unidata.io.PositioningDataInputStream;
import ucar.ma2.*;
import ucar.nc2.ParsedSectionSpec;
import ucar.nc2.Variable;
import ucar.nc2.Structure;
import ucar.nc2.stream.NcStream;
import java.io.OutputStream;
import java.nio.*;
import java.nio.channels.WritableByteChannel;
import java.nio.channels.Channels;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.ArrayList;
/**
* Helper methods for IOSP's
*
* @author caron
* @since Jan 3, 2008
*/
public class IospHelper {
static private boolean showLayoutTypes = false;
/**
* Read data subset from RandomAccessFile, create primitive array of size Layout.getTotalNelems.
* Reading is controlled by the Layout object.
*
* @param raf read from here.
* @param index handles skipping around in the file.
* @param dataType dataType of the variable
* @param fillValue must Byte, Short, Integer, Long, Float, Double, or String, matching dataType, or null for none
* @param byteOrder if equal to RandomAccessFile.ORDER_XXXX, set the byte order just before reading
* @return primitive array with data read in
* @throws java.io.IOException on read error
*/
static public Object readDataFill(RandomAccessFile raf, Layout index, DataType dataType, Object fillValue,
int byteOrder) throws java.io.IOException {
Object arr = (fillValue == null) ? makePrimitiveArray((int) index.getTotalNelems(), dataType) :
makePrimitiveArray((int) index.getTotalNelems(), dataType, fillValue);
return readData(raf, index, dataType, arr, byteOrder, true);
}
static public Object readDataFill(RandomAccessFile raf, Layout index, DataType dataType, Object fillValue,
int byteOrder, boolean convertChar) throws java.io.IOException {
Object arr = (fillValue == null) ? makePrimitiveArray((int) index.getTotalNelems(), dataType) :
makePrimitiveArray((int) index.getTotalNelems(), dataType, fillValue);
return readData(raf, index, dataType, arr, byteOrder, convertChar);
}
/**
* Read data subset from RandomAccessFile, place in given primitive array.
* Reading is controlled by the Layout object.
*
* @param raf read from here.
* @param layout handles skipping around in the file.
* @param dataType dataType of the variable
* @param arr primitive array to read data into
* @param byteOrder if equal to RandomAccessFile.ORDER_XXXX, set the byte order just before reading
* @param convertChar true if bytes should be converted to char for dataType CHAR
* @return primitive array with data read in
* @throws java.io.IOException on read error
*/
static public Object readData(RandomAccessFile raf, Layout layout, DataType dataType, Object arr, int byteOrder, boolean convertChar) throws java.io.IOException {
if (showLayoutTypes) System.out.println("***RAF LayoutType=" + layout.getClass().getName());
if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR) || (dataType == DataType.ENUM1)) {
byte[] pa = (byte[]) arr;
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readFully(pa, (int) chunk.getDestElem(), chunk.getNelems());
}
//return (convertChar && dataType == DataType.CHAR) ? convertByteToChar(pa) : pa;
if (convertChar && dataType == DataType.CHAR) return convertByteToChar(pa);
else return pa; // javac ternary compile error
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
short[] pa = (short[]) arr;
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readShort(pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
int[] pa = (int[]) arr;
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readInt(pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.FLOAT) {
float[] pa = (float[]) arr;
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readFloat(pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.DOUBLE) {
double[] pa = (double[]) arr;
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readDouble(pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.LONG) {
long[] pa = (long[]) arr;
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readLong(pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.STRUCTURE) {
byte[] pa = (byte[]) arr;
int recsize = layout.getElemSize();
while (layout.hasNext()) {
Layout.Chunk chunk = layout.next();
raf.order(byteOrder);
raf.seek(chunk.getSrcPos());
raf.readFully(pa, (int) chunk.getDestElem() * recsize, chunk.getNelems() * recsize);
}
return pa;
}
throw new IllegalStateException("unknown type= " + dataType);
}
/**
* Read data subset from PositioningDataInputStream, create primitive array of size Layout.getTotalNelems.
* Reading is controlled by the Layout object.
*
* @param is read from here.
* @param index handles skipping around in the file.
* @param dataType dataType of the variable
* @param fillValue must Byte, Short, Integer, Long, Float, Double, or String, matching dataType, or null for none
* @return primitive array with data read in
* @throws java.io.IOException on read error
*/
static public Object readDataFill(PositioningDataInputStream is, Layout index, DataType dataType, Object fillValue) throws java.io.IOException {
Object arr = (fillValue == null) ? makePrimitiveArray((int) index.getTotalNelems(), dataType) :
makePrimitiveArray((int) index.getTotalNelems(), dataType, fillValue);
return readData(is, index, dataType, arr);
}
/**
* Read data subset from PositioningDataInputStream, place in given primitive array.
* Reading is controlled by the Layout object.
*
* @param raf read from here.
* @param index handles skipping around in the file.
* @param dataType dataType of the variable
* @param arr primitive array to read data into
* @return primitive array with data read in
* @throws java.io.IOException on read error
*/
static public Object readData(PositioningDataInputStream raf, Layout index, DataType dataType, Object arr) throws java.io.IOException {
if (showLayoutTypes) System.out.println("***PositioningDataInputStream LayoutType=" + index.getClass().getName());
if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR) || (dataType == DataType.OPAQUE) || (dataType == DataType.ENUM1)) {
byte[] pa = (byte[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.read(chunk.getSrcPos(), pa, (int) chunk.getDestElem(), chunk.getNelems());
}
//return (dataType == DataType.CHAR) ? convertByteToChar(pa) : pa;
if (dataType == DataType.CHAR) return convertByteToChar(pa);
else return pa;
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
short[] pa = (short[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.readShort(chunk.getSrcPos(), pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
int[] pa = (int[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.readInt(chunk.getSrcPos(), pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.FLOAT) {
float[] pa = (float[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.readFloat(chunk.getSrcPos(), pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.DOUBLE) {
double[] pa = (double[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.readDouble(chunk.getSrcPos(), pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.LONG) {
long[] pa = (long[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.readLong(chunk.getSrcPos(), pa, (int) chunk.getDestElem(), chunk.getNelems());
}
return pa;
} else if (dataType == DataType.STRUCTURE) {
int recsize = index.getElemSize();
byte[] pa = (byte[]) arr;
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
raf.read(chunk.getSrcPos(), pa, (int) chunk.getDestElem() * recsize, chunk.getNelems() * recsize);
}
return pa;
}
throw new IllegalStateException();
} //
/**
* Read data subset from ByteBuffer, create primitive array of size Layout.getTotalNelems.
* Reading is controlled by the Layout object.
*
* @param layout handles skipping around in the file, privide ByteBuffer to read from
* @param dataType dataType of the variable
* @param fillValue must Byte, Short, Integer, Long, Float, Double, or String, matching dataType, or null for none
* @return primitive array with data read in
* @throws java.io.IOException on read error
*/
static public Object readDataFill(LayoutBB layout, DataType dataType, Object fillValue) throws java.io.IOException {
long size = layout.getTotalNelems();
if (dataType == DataType.STRUCTURE) size *= layout.getElemSize();
Object arr = (fillValue == null) ? makePrimitiveArray((int) size, dataType) :
makePrimitiveArray((int) size, dataType, fillValue);
return readData(layout, dataType, arr);
}
/**
* Read data subset from ByteBuffer, place in given primitive array.
* Reading is controlled by the LayoutBB object.
*
* @param layout handles skipping around in the file, privide ByteBuffer to read from
* @param dataType dataType of the variable
* @param arr primitive array to read data into
* @return the primitive array with data read in
* @throws java.io.IOException on read error
*/
static public Object readData(LayoutBB layout, DataType dataType, Object arr) throws java.io.IOException {
if (showLayoutTypes) System.out.println("***BB LayoutType=" + layout.getClass().getName());
if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR) || (dataType == DataType.ENUM1)) {
byte[] pa = (byte[]) arr;
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
ByteBuffer bb = chunk.getByteBuffer();
bb.position(chunk.getSrcElem());
int pos = (int) chunk.getDestElem();
for (int i = 0; i < chunk.getNelems(); i++)
pa[pos++] = bb.get();
}
//return (dataType == DataType.CHAR) ? convertByteToChar(pa) : pa;
if (dataType == DataType.CHAR) return convertByteToChar(pa);
else return pa;
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
short[] pa = (short[]) arr;
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
ShortBuffer buff = chunk.getShortBuffer();
buff.position(chunk.getSrcElem());
int pos = (int) chunk.getDestElem();
for (int i = 0; i < chunk.getNelems(); i++)
pa[pos++] = buff.get();
}
return pa;
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
int[] pa = (int[]) arr;
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
IntBuffer buff = chunk.getIntBuffer();
buff.position(chunk.getSrcElem());
int pos = (int) chunk.getDestElem();
for (int i = 0; i < chunk.getNelems(); i++)
pa[pos++] = buff.get();
}
return pa;
} else if (dataType == DataType.FLOAT) {
float[] pa = (float[]) arr;
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
FloatBuffer buff = chunk.getFloatBuffer();
buff.position(chunk.getSrcElem());
int pos = (int) chunk.getDestElem();
for (int i = 0; i < chunk.getNelems(); i++)
pa[pos++] = buff.get();
}
return pa;
} else if (dataType == DataType.DOUBLE) {
double[] pa = (double[]) arr;
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
DoubleBuffer buff = chunk.getDoubleBuffer();
buff.position(chunk.getSrcElem());
int pos = (int) chunk.getDestElem();
for (int i = 0; i < chunk.getNelems(); i++)
pa[pos++] = buff.get();
}
return pa;
} else if (dataType == DataType.LONG) {
long[] pa = (long[]) arr;
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
LongBuffer buff = chunk.getLongBuffer();
buff.position(chunk.getSrcElem());
int pos = (int) chunk.getDestElem();
for (int i = 0; i < chunk.getNelems(); i++)
pa[pos++] = buff.get();
}
return pa;
} else if (dataType == DataType.STRUCTURE) {
byte[] pa = (byte[]) arr;
int recsize = layout.getElemSize();
while (layout.hasNext()) {
LayoutBB.Chunk chunk = layout.next();
ByteBuffer bb = chunk.getByteBuffer();
bb.position(chunk.getSrcElem() * recsize);
int pos = (int) chunk.getDestElem() * recsize;
for (int i = 0; i < chunk.getNelems() * recsize; i++)
pa[pos++] = bb.get();
}
return pa;
}
throw new IllegalStateException();
}
/**
* Copy data to a channel. Used by ncstream. Not doing Structures correctly yet.
*
* @param data copy from here
* @param channel copy to here
* @return number of bytes copied
* @throws java.io.IOException on write error
*/
public static long copyToByteChannel(Array data, WritableByteChannel channel) throws java.io.IOException {
Class classType = data.getElementType();
if (data instanceof ArrayStructure) { // use NcStream encoding
DataOutputStream os = new DataOutputStream(Channels.newOutputStream(channel));
return NcStream.encodeArrayStructure((ArrayStructure) data, os);
}
DataOutputStream outStream = new DataOutputStream(Channels.newOutputStream(channel));
IndexIterator iterA = data.getIndexIterator();
if (classType == double.class) {
while (iterA.hasNext())
outStream.writeDouble(iterA.getDoubleNext());
} else if (classType == float.class) {
while (iterA.hasNext())
outStream.writeFloat(iterA.getFloatNext());
} else if (classType == long.class) {
while (iterA.hasNext())
outStream.writeLong(iterA.getLongNext());
} else if (classType == int.class) {
while (iterA.hasNext())
outStream.writeInt(iterA.getIntNext());
} else if (classType == short.class) {
while (iterA.hasNext())
outStream.writeShort(iterA.getShortNext());
} else if (classType == char.class) { // LOOK why are we using chars anyway ?
byte[] pa = convertCharToByte((char[]) data.get1DJavaArray(char.class));
outStream.write(pa, 0, pa.length);
} else if (classType == byte.class) {
while (iterA.hasNext())
outStream.writeByte(iterA.getByteNext());
} else if (classType == boolean.class) {
while (iterA.hasNext())
outStream.writeBoolean(iterA.getBooleanNext());
} else if (classType == String.class) {
long size = 0;
while (iterA.hasNext()) {
String s = (String) iterA.getObjectNext();
size += NcStream.writeVInt(outStream, s.length());
byte[] b = s.getBytes(CDM.utf8Charset);
outStream.write(b);
size += b.length;
}
return size;
} else if (classType == ByteBuffer.class) { // OPAQUE
long size = 0;
while (iterA.hasNext()) {
ByteBuffer bb = (ByteBuffer) iterA.getObjectNext();
size += NcStream.writeVInt(outStream, bb.limit());
bb.rewind();
channel.write(bb);
size += bb.limit();
}
return size;
} else if (data instanceof ArrayObject) { // vlen
long size = 0;
//size += NcStream.writeVInt(outStream, (int) data.getSize()); // nelems already written
while (iterA.hasNext()) {
Array row = (Array) iterA.getObjectNext();
ByteBuffer bb = row.getDataAsByteBuffer();
byte[] result = bb.array();
size += NcStream.writeVInt(outStream, result.length); // size in bytes
outStream.write(result); // array
size += result.length;
}
return size;
} else
throw new UnsupportedOperationException("Class type = " + classType.getName());
return data.getSizeBytes();
}
/**
* Copy data to a channel. Used by ncstream. Not doing Structures correctly yet.
*
* @param data copy from here
* @param out copy to here
* @return number of bytes copied
* @throws java.io.IOException on write error
*/
public static long copyToOutputStream(Array data, OutputStream out) throws java.io.IOException {
Class classType = data.getElementType();
DataOutputStream dataOut;
if (out instanceof DataOutputStream)
dataOut = (DataOutputStream) out;
else
dataOut = new DataOutputStream(out);
if (data instanceof ArrayStructure) { // use NcStream encoding
return NcStream.encodeArrayStructure((ArrayStructure) data, dataOut);
}
IndexIterator iterA = data.getIndexIterator();
if (classType == double.class) {
while (iterA.hasNext())
dataOut.writeDouble(iterA.getDoubleNext());
} else if (classType == float.class) {
while (iterA.hasNext())
dataOut.writeFloat(iterA.getFloatNext());
} else if (classType == long.class) {
while (iterA.hasNext())
dataOut.writeLong(iterA.getLongNext());
} else if (classType == int.class) {
while (iterA.hasNext())
dataOut.writeInt(iterA.getIntNext());
} else if (classType == short.class) {
while (iterA.hasNext())
dataOut.writeShort(iterA.getShortNext());
} else if (classType == char.class) { // LOOK why are we using chars anyway ?
byte[] pa = convertCharToByte((char[]) data.get1DJavaArray(char.class));
dataOut.write(pa, 0, pa.length);
} else if (classType == byte.class) {
while (iterA.hasNext())
dataOut.writeByte(iterA.getByteNext());
} else if (classType == boolean.class) {
while (iterA.hasNext())
dataOut.writeBoolean(iterA.getBooleanNext());
} else if (classType == String.class) {
long size = 0;
while (iterA.hasNext()) {
String s = (String) iterA.getObjectNext();
size += NcStream.writeVInt(dataOut, s.length());
byte[] b = s.getBytes(CDM.utf8Charset);
dataOut.write(b);
size += b.length;
}
return size;
} else if (classType == ByteBuffer.class) { // OPAQUE
long size = 0;
while (iterA.hasNext()) {
ByteBuffer bb = (ByteBuffer) iterA.getObjectNext();
size += NcStream.writeVInt(dataOut, bb.limit());
bb.rewind();
dataOut.write(bb.array());
size += bb.limit();
}
return size;
} else if (data instanceof ArrayObject) { // vlen
long size = 0;
//size += NcStream.writeVInt(outStream, (int) data.getSize()); // nelems already written
while (iterA.hasNext()) {
Array row = (Array) iterA.getObjectNext();
ByteBuffer bb = row.getDataAsByteBuffer();
byte[] result = bb.array();
size += NcStream.writeVInt(dataOut, result.length); // size in bytes
dataOut.write(result); // array
size += result.length;
}
return size;
} else
throw new UnsupportedOperationException("Class type = " + classType.getName());
return data.getSizeBytes();
}
/**
* @deprecated use StructureDataDeep.copyToArrayBB
*/
static public ArrayStructureBB makeArrayBB(ArrayStructure as) throws IOException {
if (as.getClass().equals(ArrayStructureBB.class)) // no subclasses
return (ArrayStructureBB) as;
StructureMembers smo = as.getStructureMembers();
StructureMembers sm = new StructureMembers(smo);
ArrayStructureBB abb = new ArrayStructureBB(sm, as.getShape());
ArrayStructureBB.setOffsets(sm);
StructureDataIterator iter = as.getStructureDataIterator();
try {
while (iter.hasNext())
StructureDataDeep.copyToArrayBB(iter.next(), abb);
} finally {
iter.finish();
}
return abb;
}
/**
* @deprecated use StructureDataDeep.copyToArrayBB
*/
static public ArrayStructureBB copyToArrayBB(StructureData sdata) {
StructureMembers sm = new StructureMembers(sdata.getStructureMembers());
int size = sm.getStructureSize();
ByteBuffer bb = ByteBuffer.allocate(size); // default is big endian
ArrayStructureBB abb = new ArrayStructureBB(sm, new int[]{1}, bb, 0);
ArrayStructureBB.setOffsets(sm);
StructureDataDeep.copyToArrayBB(sdata, abb);
return abb;
}
/**
* Create 1D primitive array of the given size and type
*
* @param size the size of the array to create
* @param dataType dataType of the variable
* @return primitive array with data read in
*/
static public Object makePrimitiveArray(int size, DataType dataType) {
Object arr = null;
if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR) || (dataType == DataType.ENUM1)
|| (dataType == DataType.OPAQUE) || (dataType == DataType.STRUCTURE)) {
arr = new byte[size];
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
arr = new short[size];
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
arr = new int[size];
} else if (dataType == DataType.LONG) {
arr = new long[size];
} else if (dataType == DataType.FLOAT) {
arr = new float[size];
} else if (dataType == DataType.DOUBLE) {
arr = new double[size];
}
return arr;
}
/**
* Create 1D primitive array of the given size and type, fill it with the given value
*
* @param size the size of the array to create
* @param dataType dataType of the variable
* @param fillValue must be Byte, Short, Integer, Long, Float, Double, or String, matching dataType
* @return primitive array with data read in
*/
static public Object makePrimitiveArray(int size, DataType dataType, Object fillValue) {
if ((dataType == DataType.BYTE) || (dataType == DataType.CHAR) || (dataType == DataType.ENUM1)) {
byte[] pa = new byte[size];
byte val = (Byte) fillValue;
if (val != 0)
for (int i = 0; i < size; i++) pa[i] = val;
return pa;
} else if (dataType == DataType.OPAQUE) {
return new byte[size];
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
short[] pa = new short[size];
short val = (Short) fillValue;
if (val != 0)
for (int i = 0; i < size; i++) pa[i] = val;
return pa;
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
int[] pa = new int[size];
int val = (Integer) fillValue;
if (val != 0)
for (int i = 0; i < size; i++) pa[i] = val;
return pa;
} else if (dataType == DataType.LONG) {
long[] pa = new long[size];
long val = (Long) fillValue;
if (val != 0)
for (int i = 0; i < size; i++) pa[i] = val;
return pa;
} else if (dataType == DataType.FLOAT) {
float[] pa = new float[size];
float val = (Float) fillValue;
if (val != 0.0)
for (int i = 0; i < size; i++) pa[i] = val;
return pa;
} else if (dataType == DataType.DOUBLE) {
double[] pa = new double[size];
double val = (Double) fillValue;
if (val != 0.0)
for (int i = 0; i < size; i++) pa[i] = val;
return pa;
} else if (dataType == DataType.STRING) {
String[] pa = new String[size];
for (int i = 0; i < size; i++) pa[i] = (String) fillValue;
return pa;
} else if (dataType == DataType.STRUCTURE) {
byte[] pa = new byte[size];
if (fillValue != null) {
byte[] val = (byte[]) fillValue;
int count = 0;
while (count < size)
for (byte aVal : val) pa[count++] = aVal;
}
return pa;
}
throw new IllegalStateException();
}
// convert byte array to char array, assuming UTF-8 encoding
static public char[] convertByteToCharUTF(byte[] byteArray) {
Charset c = CDM.utf8Charset;
CharBuffer output = c.decode(ByteBuffer.wrap(byteArray));
return output.array();
}
// convert char array to byte array, assuming UTF-8 encoding
static public byte[] convertCharToByteUTF(char[] from) {
Charset c = CDM.utf8Charset;
ByteBuffer output = c.encode(CharBuffer.wrap(from));
return output.array();
}
// convert byte array to char array
static public char[] convertByteToChar(byte[] byteArray) {
int size = byteArray.length;
char[] cbuff = new char[size];
for (int i = 0; i < size; i++)
cbuff[i] = (char) DataType.unsignedByteToShort(byteArray[i]); // NOTE: not Unicode !
return cbuff;
}
// convert char array to byte array
static public byte[] convertCharToByte(char[] from) {
int size = from.length;
byte[] to = new byte[size];
for (int i = 0; i < size; i++)
to[i] = (byte) from[i]; // LOOK wrong, convert back to unsigned byte ???
return to;
}
static public long transferData(Array result, WritableByteChannel channel)
throws java.io.IOException, ucar.ma2.InvalidRangeException {
// LOOK should we buffer ??
DataOutputStream outStream = new DataOutputStream(Channels.newOutputStream(channel));
IndexIterator iterA = result.getIndexIterator();
Class classType = result.getElementType();
if (classType == double.class) {
while (iterA.hasNext())
outStream.writeDouble(iterA.getDoubleNext());
} else if (classType == float.class) {
while (iterA.hasNext())
outStream.writeFloat(iterA.getFloatNext());
} else if (classType == long.class) {
while (iterA.hasNext())
outStream.writeLong(iterA.getLongNext());
} else if (classType == int.class) {
while (iterA.hasNext())
outStream.writeInt(iterA.getIntNext());
} else if (classType == short.class) {
while (iterA.hasNext())
outStream.writeShort(iterA.getShortNext());
} else if (classType == char.class) {
while (iterA.hasNext())
outStream.writeChar(iterA.getCharNext());
} else if (classType == byte.class) {
while (iterA.hasNext())
outStream.writeByte(iterA.getByteNext());
} else if (classType == boolean.class) {
while (iterA.hasNext())
outStream.writeBoolean(iterA.getBooleanNext());
} else
throw new UnsupportedOperationException("Class type = " + classType.getName());
return 0;
}
// section reading for member data
static public ucar.ma2.Array readSection(ParsedSectionSpec cer) throws IOException, InvalidRangeException {
Variable inner = null;
List totalRanges = new ArrayList<>();
ParsedSectionSpec current = cer;
while (current != null) {
totalRanges.addAll(current.section.getRanges());
inner = current.v;
current = current.child;
}
assert inner != null;
Section total = new Section(totalRanges);
Array result = Array.factory(inner.getDataType(), total.getShape());
// must be a Structure
Structure outer = (Structure) cer.v;
Structure outerSubset = outer.select(cer.child.v.getShortName()); // allows IOSPs to optimize for this case
ArrayStructure outerData = (ArrayStructure) outerSubset.read(cer.section);
extractSection(cer.child, outerData, result.getIndexIterator());
result.setUnsigned(cer.v.isUnsigned());
return result;
}
static private void extractSection(ParsedSectionSpec child, ArrayStructure outerData, IndexIterator to) throws IOException, InvalidRangeException {
long wantNelems = child.section.computeSize();
StructureMembers.Member m = outerData.findMember(child.v.getShortName());
for (int recno = 0; recno < outerData.getSize(); recno++) {
Array innerData = outerData.getArray(recno, m);
if (child.child == null) { // inner variable
if (wantNelems != innerData.getSize())
innerData = innerData.section(child.section.getRanges());
MAMath.copy(child.v.getDataType(), innerData.getIndexIterator(), to);
} else { // not an inner variable - must be an ArrayStructure
if (innerData instanceof ArraySequence)
extractSectionFromSequence(child.child, (ArraySequence) innerData, to);
else {
if (wantNelems != innerData.getSize())
innerData = sectionArrayStructure(child, (ArrayStructure) innerData, m);
extractSection(child.child, (ArrayStructure) innerData, to);
}
}
}
}
static private void extractSectionFromSequence(ParsedSectionSpec child, ArraySequence outerData, IndexIterator to) throws IOException, InvalidRangeException {
StructureDataIterator sdataIter = outerData.getStructureDataIterator();
try {
while (sdataIter.hasNext()) {
StructureData sdata = sdataIter.next();
StructureMembers.Member m = outerData.findMember(child.v.getShortName());
Array innerData = sdata.getArray(child.v.getShortName());
MAMath.copy(m.getDataType(), innerData.getIndexIterator(), to);
}
} finally {
sdataIter.finish();
}
}
// LOOK could be used in createView ??
static private ArrayStructure sectionArrayStructure(ParsedSectionSpec child, ArrayStructure innerData, StructureMembers.Member m) throws IOException, InvalidRangeException {
StructureMembers membersw = new StructureMembers(m.getStructureMembers()); // no data arrays get propagated
ArrayStructureW result = new ArrayStructureW(membersw, child.section.getShape());
int count = 0;
Section.Iterator iter = child.section.getIterator(child.v.getShape());
while (iter.hasNext()) {
int recno = iter.next(null);
StructureData sd = innerData.getStructureData(recno);
result.setStructureData(sd, count++);
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy