package org.yamcs.parameterarchive; import java.nio.ByteBuffer; import java.util.List; import org.yamcs.parameter.Value; import org.yamcs.utils.DecodingException; import org.yamcs.utils.LongArray; import org.yamcs.utils.ValueUtility; import org.yamcs.utils.VarIntUtil; public class LongValueSegment extends BaseSegment implements ValueSegment { boolean signed; final static int SUBFORMAT_ID_RAW = 0; LongArray values; LongValueSegment(boolean signed) { super(FORMAT_ID_LongValueSegment); values = new LongArray(); this.signed = signed; } private LongValueSegment() { super(FORMAT_ID_IntValueSegment); } @Override public void writeTo(ByteBuffer bb) { writeHeader(SUBFORMAT_ID_RAW, bb); int n = values.size(); VarIntUtil.writeVarInt32(bb, n); for(int i=0; i<n; i++) { bb.putLong(values.get(i)); } } //write header: // 1st byte: spare signed/unsigned subformatid // 3 bits 1 bit 4 bits private void writeHeader(int subFormatId, ByteBuffer bb) { int x = signed?1:0; x=(x<<4)|subFormatId; bb.put((byte)x); } private void parse(ByteBuffer bb) throws DecodingException { byte x = bb.get(); int subFormatId = x&0xF; if(subFormatId!=SUBFORMAT_ID_RAW) throw new DecodingException("Unknown subformatId "+subFormatId+" for LongValueSegment"); signed = (((x>>4)&1)==1); int n = VarIntUtil.readVarInt32(bb); if(bb.limit()-bb.position() < 8*n) { throw new DecodingException("Cannot decode long segment: expected "+(8*n)+" bytes and only "+(bb.limit()-bb.position())+ " available"); } values = new LongArray(n); for(int i=0; i<n; i++) { values.add(bb.getLong()); } } public static LongValueSegment parseFrom(ByteBuffer bb) throws DecodingException { LongValueSegment r = new LongValueSegment(); r.parse(bb); return r; } public static LongValueSegment consolidate(List<Value> values, boolean signed) { LongValueSegment segment = new LongValueSegment(signed); segment.signed = signed; int n = values.size(); if(signed) { for(int i =0;i<n; i++) { segment.add(values.get(i).getSint64Value()); } } else { for(int i =0;i<n; i++) { segment.add(values.get(i).getUint64Value()); } } return segment; } private void add(long x) { values.add(x); } @Override public int getMaxSerializedSize() { return 4+8*values.size(); //4 for the size plus 8 for each element } @Override public long[] getRange(int posStart, int posStop, boolean ascending) { long[] r = new long[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; } @Override public Value getValue(int index) { if(signed) { return ValueUtility.getSint64Value(values.get(index)); } else { return ValueUtility.getUint64Value(values.get(index)); } } @Override public int size() { return values.size(); } @Override public void add(int pos, Value v) { if(signed) { values.add(pos, v.getSint64Value()); } else { values.add(pos, v.getUint64Value()); } } @Override public LongValueSegment consolidate() { return this; } }