package org.yamcs.parameterarchive;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.List;
import org.yamcs.parameter.Value;
import org.yamcs.utils.DecodingException;
import org.yamcs.utils.FloatArray;
import org.yamcs.utils.ValueUtility;
import org.yamcs.utils.VarIntUtil;
public class FloatValueSegment extends BaseSegment implements ValueSegment {
final static byte SUBFORMAT_ID_RAW = 0;
final static byte SUBFORMAT_ID_COMPRESSED = 1;
FloatArray values;
FloatValueSegment() {
super(FORMAT_ID_FloatValueSegment);
values = new FloatArray();
}
@Override
public void writeTo(ByteBuffer bb) {
int position = bb.position();
//try to write it compressed, if we get an buffer overflow, revert to raw encoding
bb.put(SUBFORMAT_ID_COMPRESSED);
int n = values.size();
VarIntUtil.writeVarInt32(bb, n);
try {
FloatCompressor.compress(values.array(), values.size(), bb);
} catch (BufferOverflowException e) {
bb.position(position);
writeRaw(bb);
}
}
private void writeRaw(ByteBuffer bb) {
bb.put(SUBFORMAT_ID_RAW);
int n = values.size();
VarIntUtil.writeVarInt32(bb, n);
for(int i=0; i<n; i++) {
bb.putFloat(values.get(i));
}
}
private void parse(ByteBuffer bb) throws DecodingException {
byte b= bb.get();
int n = VarIntUtil.readVarInt32(bb);
float[] floats;
if(b==SUBFORMAT_ID_RAW) {
floats = new float[n];
for(int i=0;i<n;i++) {
floats[i] = bb.getFloat();
}
} else if(b==SUBFORMAT_ID_COMPRESSED) {
floats = FloatCompressor.decompress(bb, n);
} else {
throw new DecodingException("Unknown SUBFORMAT_ID: "+b);
}
values = FloatArray.wrap(floats);
}
public static FloatValueSegment parseFrom(ByteBuffer bb) throws DecodingException {
FloatValueSegment r = new FloatValueSegment();
r.parse(bb);
return r;
}
@Override
public Value getValue(int index) {
return ValueUtility.getFloatValue(values.get(index));
}
@Override
public int getMaxSerializedSize() {
return 5+4*values.size()+1;
}
@Override
public float[] getRange(int posStart, int posStop, boolean ascending) {
float[] r = new float[posStop-posStart];
if(ascending) {
for(int i = posStart; i<posStop; i++) {
r[i-posStart] = values.get(i);
}
} else {
for(int i = posStop; i>posStart; i--) {
r[posStop-i] = values.get(i);
}
}
return r;
}
static FloatValueSegment consolidate(List<Value> values) {
FloatValueSegment fvs = new FloatValueSegment();
int n = values.size();
fvs.values = new FloatArray(n);
for(int i=0; i<n; i++) {
fvs.values.add(values.get(i).getFloatValue());
}
return fvs;
}
@Override
public int size() {
return values.size();
}
@Override
public void add(int pos, Value engValue) {
values.add(pos, engValue.getFloatValue());
}
@Override
public BaseSegment consolidate() {
return this;
}
}