mirror of
https://gitee.com/willfree/min-dev-java.git
synced 2026-10-04 19:42:01 +08:00
357 lines
11 KiB
Java
357 lines
11 KiB
Java
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 +
|
|
" }";
|
|
}
|
|
|
|
}
|