package encoding; import util.ByteHelper; import java.math.BigInteger; import java.util.Arrays; import static java.lang.Math.pow; /* * @Author: Wang Feng * @Description:变长无符号整型,用于表示TLV中的T和L * @Version: 1.0.0 * @Date: 18:13 2021/3/1 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class VlInt { // 实际传输的数据 private byte[] VlIntBytes; // 变长整数表示的真实数值 private BigInteger VlIntValue; // 变长整数的长度: 1 3 5 9 ...; 可以通过它来判断是否已经初始化VlInt private int size=-1; // 一些int常量 // @Description: // 1. x < 240 => 1字节表示 => 230 // 2. 241 =< x < uint16::Max => 第一个字节为241,后面连着2字节表示实际数值,总共用3个字节表示 => 246 // 3. uint16::Max =< x < uint32::Max => 第一个字节为242,后面连着4字节表示实际数值,总共用5个字节表示 // 4. int32::Max =< x < int64::Max => 第一个字节为243,后面连着8字节表示实际数值,总共用9个字节表示 // 5. 后续还留有12个字节可以进行指数级扩展,目前留空 public static final int VlIntExtend2=241; public static final int VlIntExtend4=242; public static final int VlIntExtend8=243; public static final int VlIntSize1=1; public static final int VlIntSize3=3; public static final int VlIntSize5=5; public static final int VlIntSize9=9; /** * 测量一个变长整型实际用几个字节表示 * @return */ public int size(){ return this.size; } private static int SizeOfVarNumber(BigInteger bigInteger){ if(bigInteger==null){ throw new Error("VlInt.SizeOfVarNumber: VlInt value is null."); } if(bigInteger.compareTo(BigInteger.valueOf(241)) < 0){ return 1; }else if(bigInteger.compareTo(BigInteger.valueOf( new Double(pow(2, 16)).longValue())) < 0){ return 3; }else if(bigInteger.compareTo(BigInteger.valueOf( new Double(pow(2, 32)).longValue())) < 0){ return 5; }else if(bigInteger.compareTo(BigInteger.valueOf( new Double(pow(2, 64)).longValue())) < 0){ return 9; }else{ //MIN1.0中,VlInt的size最大为9 throw new Error("VlInt.SizeOfVarNumber: VlInt value is out of bound, it should be less than 2^64."); } } /** * 判断bytes是否是一个合法的变长非负整型 * @param vlIntBytes * @return */ private boolean isValidVlIntBytes(byte[] vlIntBytes){ if(vlIntBytes.length<1){ return false; } int firstByteValue=ByteHelper.uint8ToInt(vlIntBytes[0]); if((vlIntBytes.length==1)&&(firstByteValue<=240)){ return true; }else if((vlIntBytes.length==3)&&(firstByteValue==241)){ return true; }else if((vlIntBytes.length==5)&&(firstByteValue==242)){ return true; }else if((vlIntBytes.length==9)&&(firstByteValue==243)){ return true; }else { return false; } } public boolean isValidVlIntBytes(){ return isValidVlIntBytes(this.VlIntBytes); } /** * 判断biginteger是否合法 * @param bigInteger * @return */ private boolean isValidVlIntValue(BigInteger bigInteger){ if(bigInteger.compareTo(BigInteger.valueOf(0))<0){ return false; } if(bigInteger.compareTo(BigInteger.valueOf( new Double(pow(2, 64)).longValue())) >= 0){ return false; } return true; } public boolean isValidVlIntValue(){ return isValidVlIntValue(this.VlIntValue); } /** * 判断是否已经初始化 * @return */ public boolean isInitial(){ return this.size>0; } /** * 传入的应是一个有效的变长整型数组 * @param vlIntBytes */ public VlInt(byte[] vlIntBytes){ if(!isValidVlIntBytes(vlIntBytes)){ throw new Error("VlInt(byte[] bytes): VlIntBytes is invalid."); } this.VlIntBytes=vlIntBytes; this.VlIntValue=vlintBytes2bigInteger(vlIntBytes); this.size = SizeOfVarNumber(this.VlIntValue); } /** * 传入的应是一个有效的变长整型value * @param bigInteger */ public VlInt(BigInteger bigInteger){ if(!isValidVlIntValue(bigInteger)){ throw new Error("VlInt(BigInteger bigInteger): VlIntValue is invalid."); } this.VlIntValue=bigInteger; this.VlIntBytes=bigInteger2vlintBytes(bigInteger); this.size=SizeOfVarNumber(this.VlIntValue); } public VlInt(SizeT sizeT){ if(!sizeT.isInitial()){ throw new Error("VlInt(SizeT sizeT): The sizeT is invalid, it should be initial."); } this.VlIntBytes=sizeT.getVlIntBytes(); this.VlIntValue=sizeT.getVlIntValue(); this.size = sizeT.size(); } public VlInt(VlInt vlInt){ if(!vlInt.isInitial()){ throw new Error("VlInt vlInt: The vlInt is invalid, it should be initial."); } this.VlIntBytes=vlInt.getVlIntBytes(); this.VlIntValue=vlInt.getVlIntValue(); this.size = vlInt.size(); } public VlInt(int i){ this.VlIntValue=BigInteger.valueOf(i); if(!isValidVlIntValue(this.VlIntValue)){ throw new Error("VlInt(int i): The i value is invalid, it is out of the bound."); } this.VlIntBytes=bigInteger2vlintBytes(this.VlIntValue); this.size=SizeOfVarNumber(this.VlIntValue); } public VlInt(long l){ this.VlIntValue=BigInteger.valueOf(l); if(!isValidVlIntValue(this.VlIntValue)){ throw new Error("VlInt(long l): The l value is invalid, it is out of the bound."); } this.VlIntBytes=bigInteger2vlintBytes(this.VlIntValue); this.size=SizeOfVarNumber(this.VlIntValue); } /** * 获取bytes * @return */ public byte[] getVlIntBytes(){ return this.VlIntBytes; } /** * 将vlint转为一个int输出:需要判断size是不是1 or 3 * @return */ public int getVlIntValue2Int() throws VlIntException { if(this.size()<4){ return VlIntValue.intValue(); } throw new VlIntException("getVlIntValue2Int: out of int bound."); } /** * 将vlint转为一个long输出 * todo: 理论上存在越界问题 * @return */ public long getVlIntValue2Long() throws VlIntException { if(this.size()<= 9){ return VlIntValue.longValue(); } throw new VlIntException("getVlIntValue2Long: out of long bound."); } /** * 将vlint转为一个biginteger输出 * @return */ public BigInteger getVlIntValue(){ return this.VlIntValue; } /** * 判断vlint是否与某个值相等 * @param vlInt * @return */ public boolean isEqual(VlInt vlInt){ if(this.VlIntValue.compareTo(vlInt.VlIntValue)==0){ return true; } return false; } public boolean isEqual(int i){ if(this.VlIntValue.compareTo(BigInteger.valueOf(i))==0){ return true; } return false; } public boolean isEqual(long l){ if(this.VlIntValue.compareTo(BigInteger.valueOf(l))==0){ return true; } return false; } /** * 判断与另一个VlInt的数值孰大孰小 * @param vlInt * @return */ public int compareTo(VlInt vlInt){ return this.VlIntValue.compareTo(vlInt.VlIntValue); } public int compareTo(int i){ BigInteger bigInteger=BigInteger.valueOf(i); return this.VlIntValue.compareTo(bigInteger); } public int compareTo(long l){ BigInteger bigInteger=BigInteger.valueOf(l); return this.VlIntValue.compareTo(bigInteger); } /** * 减去另一个VlInt * @param vlInt * @return */ public long subtract(VlInt vlInt){ return this.VlIntValue.subtract(vlInt.VlIntValue).longValue(); } /** * 增加VlInt * @param vlInt * @return */ public long add(VlInt vlInt){ return this.VlIntValue.add(vlInt.VlIntValue).longValue(); } public long add(int i_int){ return this.VlIntValue.longValue()+i_int; } /** * 将BigInteger转为byte[按照变长无符号整数方式转] * @param bigInteger * @return */ private byte[] bigInteger2vlintBytes(BigInteger bigInteger){ byte[] vlintbytes; int size=SizeOfVarNumber(bigInteger); if(size==1){ vlintbytes=new byte[1]; vlintbytes[0]= ByteHelper.uint8ToByte(bigInteger.intValue()); }else if(size==3){ vlintbytes=new byte[3]; vlintbytes[0]=ByteHelper.uint8ToByte(VlIntExtend2); System.arraycopy(ByteHelper.uint16ToByteArray(bigInteger.intValue()),0,vlintbytes,1,2); }else if(size==5){ vlintbytes=new byte[5]; vlintbytes[0]=ByteHelper.uint8ToByte(VlIntExtend4); System.arraycopy(ByteHelper.uint32ToByteArray(bigInteger.longValue()),0,vlintbytes,1,4); }else if(size==9){ vlintbytes=new byte[9]; vlintbytes[0]=ByteHelper.uint8ToByte(VlIntExtend8); System.arraycopy(ByteHelper.uint64ToByteArray(bigInteger.longValue()),0,vlintbytes,1,8); }else{ throw new Error("VlInt.bigInteger2vlintBytes: VlInt value is invalid, it should be in [0, 2^64)."); } return vlintbytes; } /** * 将变长无符号整数数组转为BigInteger * @param vlIntBytes * @return */ private BigInteger vlintBytes2bigInteger(byte[] vlIntBytes){ BigInteger vlintValue; if(vlIntBytes.length==1){ long value=ByteHelper.uint8ToLong(vlIntBytes[0]); vlintValue=BigInteger.valueOf(value); }else if(vlIntBytes.length==3){ byte[] valueByte=new byte[2]; System.arraycopy(vlIntBytes,1,valueByte,0,valueByte.length); long value=ByteHelper.uint16ToLong(valueByte); vlintValue=BigInteger.valueOf(value); }else if(vlIntBytes.length==5){ byte[] valueByte=new byte[4]; System.arraycopy(vlIntBytes,1,valueByte,0,valueByte.length); long value=ByteHelper.uint32ToLong(valueByte); vlintValue=BigInteger.valueOf(value); }else if(vlIntBytes.length==9){ byte[] valueByte=new byte[8]; System.arraycopy(vlIntBytes,1,valueByte,0,valueByte.length); long value=ByteHelper.uint64ToLong(valueByte); vlintValue=BigInteger.valueOf(value); }else{ throw new Error("VlInt.vlintBytes2bigInteger: VlInt bytes length is invalid, it should be in [1,3,5,9]"); } return vlintValue; } @Override public String toString() { return "VlInt{ " + "VlIntBytes=" + Arrays.toString(VlIntBytes) + ", VlIntValue=" + VlIntValue + ", size=" + size + " }"; } }