package org.das2.qds.buffer; import java.nio.ByteBuffer; import java.text.ParseException; import org.das2.datum.EnumerationUnits; import org.das2.datum.Units; import org.das2.qds.QDataSet; /** * Sometimes you might just have numbers encoded in ASCII within a binary stream, * or fixed-length fields allow such parsing. If the unit has been set to an enumeration (or nominal) * unit, then strings can be extracted as well, but this must be done using the setUnits * method. * @author jbf */ public class AsciiDataSet extends BufferDataSet { int lenBytes; double fill= -1e38; private Units units= Units.dimensionless; /** * Like the other constructors, but the type is needed as well to get the * number of bytes. * @param rank * @param reclen * @param recoffs * @param len0 * @param len1 * @param len2 * @param len3 * @param back * @param type string "asciiXX" where XX is number of bytes, between 1 and 24. */ public AsciiDataSet(int rank, int reclen, int recoffs, int len0, int len1, int len2, int len3, ByteBuffer back, Object type ) { super(rank, reclen, recoffs, len0, len1, len2, len3, type, back ); this.lenBytes= Integer.parseInt( type.toString().substring(5) ); if ( this.lenBytes<1 ) throw new IllegalArgumentException("ascii1 is the shortest field supported."); if ( this.lenBytes>32 ) throw new IllegalArgumentException("ascii24 is the longest field supported."); putProperty( QDataSet.FILL_VALUE, fill ); } public void setLengthBytes( int length ) { this.lenBytes= length; } public void setUnits( Units units ) { this.units= units; } private double parseDouble( ByteBuffer back, int offset ) { byte[] buff= new byte[lenBytes]; for ( int i=0; i<lenBytes; i++ ) buff[i]= back.get(i+offset); if ( buff[lenBytes-1]==',' ) buff[lenBytes-1]=' '; // allow the field to contain delimiter. String s= new String(buff); if ( units instanceof EnumerationUnits ) { return ((EnumerationUnits)units).createDatum(s.trim()).doubleValue(units); } else { try { return units.parse(s).doubleValue( units ); } catch (ParseException ex) { return fill; } } } @Override public double value() { return parseDouble(back, offset()); } @Override public double value(int i0) { return parseDouble(back, offset(i0)); } @Override public double value(int i0, int i1) { return parseDouble(back, offset(i0, i1)); } @Override public double value(int i0, int i1, int i2) { return parseDouble(back, offset(i0, i1, i2)); } @Override public double value(int i0, int i1, int i2, int i3) { return parseDouble(back, offset(i0, i1, i2, i3)); } private byte[] getBytes( double d ) { String s= units.createDatum(d).toString(); //TODO: 24 byte limit is here. return s.substring(0,lenBytes).getBytes(); } @Override public void putValue(double d) { ensureWritable(); int offs= offset(); byte[] bb= getBytes( d ); for ( int i=0; i<lenBytes; i++ ) back.put( offs+i, bb[i] ); } @Override public void putValue(int i0, double d) { ensureWritable(); int offs= offset(i0); byte[] bb= getBytes( d ); for ( int i=0; i<lenBytes; i++ ) back.put( offs+i, bb[i] ); } @Override public void putValue(int i0, int i1, double d) { ensureWritable(); int offs= offset(i0,i1); byte[] bb= getBytes( d ); for ( int i=0; i<lenBytes; i++ ) back.put( offs+i, bb[i] ); } @Override public void putValue(int i0, int i1, int i2, double d) { ensureWritable(); int offs= offset(i0,i1,i2); byte[] bb= getBytes( d ); for ( int i=0; i<lenBytes; i++ ) back.put( offs+i, bb[i] ); } @Override public void putValue(int i0, int i1, int i2, int i3, double d) { ensureWritable(); int offs= offset(i0,i1,i2,i3); byte[] bb= getBytes( d ); for ( int i=0; i<lenBytes; i++ ) back.put( offs+i, bb[i] ); } }