add test: IdentifierFieldTest

This commit is contained in:
free will committed 2021-03-29 20:28:04 +08:00
1 parent 4e8193e275
commit dc060c2fc2
9 files changed
+392 -360

No files matched your search

+26 -31
View File
@@ -18,10 +18,9 @@ import java.util.List;
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
class IdentifierComponentContainer {
private List<IdentifierComponent> identifierComponents;
private List<IdentifierComponent> identifierComponents=new LinkedList<>();
public IdentifierComponentContainer() {
identifierComponents = new LinkedList<>();
}
/**
@@ -102,10 +101,9 @@ class IdentifierComponentContainer {
}
public class Identifier implements TlvComponentBase, IEncodingAble {
private IdentifierComponentContainer components;
private IdentifierComponentContainer components=new IdentifierComponentContainer();
public Identifier() {
components = new IdentifierComponentContainer();
}
/**
@@ -125,7 +123,7 @@ public class Identifier implements TlvComponentBase, IEncodingAble {
*/
public Identifier(String identifierString) throws ComponentException {
components = new IdentifierComponentContainer();
if(!this.buildIdentifierByString(identifierString)){
if (!this.buildIdentifierByString(identifierString)) {
throw new ComponentException
("Identifier(String): identifierString does not starts with \"/\". ");
}
@@ -211,41 +209,37 @@ public class Identifier implements TlvComponentBase, IEncodingAble {
*/
@Override
public int wireEncode(Encoder encoder) throws ComponentException {
int totalLength = 0;
// 编码 TLV-VALUE
for (int i = 0; i < components.length(); i++) {
int tmpLen = 0;
tmpLen = components.getElement(i).wireEncode(encoder);
try {
int totalLength = 0;
// 编码 TLV-VALUE
for (int i = components.length()-1; i >=0 ; i--) {
int tmpLen = components.getElement(i).wireEncode(encoder);
if (tmpLen <= 0) {
return -1;
}
totalLength += tmpLen;
}
// 编码 TLV-LENGTH
int tmpLen = encoder.prependVarNumber(new VlInt(totalLength));
if (tmpLen <= 0) {
return -1;
}
totalLength += tmpLen;
}
// 编码 TLV-LENGTH
int tmpLen = 0;
try {
tmpLen = encoder.prependVarNumber(new VlInt(totalLength));
} catch (EncoderException e) {
throw new ComponentException("Identifier.wireEncode: " + e.getMessage());
}
if (tmpLen <= 0) {
return -1;
}
totalLength += tmpLen;
// 编码 TLV-TYPE
// 编码 TLV-TYPE
try {
tmpLen = encoder.prependVarNumber(new VlInt(TLV.TlvIdentifier));
if (tmpLen <= 0) {
return -1;
}
totalLength += tmpLen;
return totalLength;
} catch (EncoderException e) {
throw new ComponentException("Identifier.wireEncode: " + e.getMessage());
}
if (tmpLen <= 0) {
return -1;
}
totalLength += tmpLen;
return totalLength;
}
/**
@@ -361,9 +355,10 @@ public class Identifier implements TlvComponentBase, IEncodingAble {
/**
* 标识后面新增一个名称组件
*
* @param component
*/
public void append(IdentifierComponent component){
public void append(IdentifierComponent component) {
this.components.addElement(component);
}
}
@@ -30,7 +30,7 @@ import java.util.Arrays;
// 0x01 非负整数(可以用1、2、4、8个字节表示)
// 0x02 任意字节数组
public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
private Block identifierBlock; // IdentifierComponent数据以TLV形式存储下来
private Block identifierBlock=new Block(); // IdentifierComponent数据以TLV形式存储下来
private byte marker; // 标记 => 用来区分不同类型的 IdentifierComponent
private String stringValue; // 如果 Marker == 0x00,则本组件存储一个字符串
private long intValue; // 如果 Marker == 0x01,则本组件存储一个非负整型
@@ -59,7 +59,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
}
public IdentifierComponent(){
this.identifierBlock = new Block();
}
/**
@@ -68,7 +67,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
* @param nameComponent
*/
public IdentifierComponent(String nameComponent) {
this.identifierBlock = new Block();
this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent));
int len=nameComponent.getBytes(StandardCharsets.UTF_8).length;
this.identifierBlock.setLength(new VlInt(len + 1));
@@ -86,7 +84,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
* @param intValue
*/
public IdentifierComponent(long intValue) {
this.identifierBlock = new Block();
this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent));
byte[] uint64Array=Encoder.buildNonNegativeIntegerArr(intValue);
this.identifierBlock.setLength(new VlInt( uint64Array.length+ 1));
@@ -104,7 +101,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
* @param arr
*/
public IdentifierComponent(byte[] arr) {
this.identifierBlock = new Block();
this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent));
this.identifierBlock.setLength(new VlInt(arr.length + 1));
byte[] value = new byte[arr.length+1];
@@ -135,7 +131,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
* @param fragmentNumber
*/
public void buildFragmentNumberIdentifierComponent(long fragmentNumber){
this.identifierBlock = new Block();
this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent));
int len=TLV.SizeOfNonNegativeInteger(fragmentNumber) + 1;
this.identifierBlock.setLength(new VlInt(len));
@@ -286,7 +281,11 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble {
*/
@Override
public int wireEncode(Encoder encoder) throws ComponentException {
return this.identifierBlock.encode(encoder);
try {
return this.identifierBlock.encode(encoder);
} catch (BlockException e) {
throw new ComponentException("IdentifierComponent.wireEncode: "+e.getMessage());
}
}
/**
+32 -36
View File
@@ -14,10 +14,9 @@ import java.util.List;
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
class IdentifierContainer {
private List<IdentifierWrapper> identifierWrappers;
private List<IdentifierWrapper> identifierWrappers=new LinkedList<>();
public IdentifierContainer() {
identifierWrappers = new LinkedList<>();
}
/**
@@ -82,10 +81,9 @@ class IdentifierContainer {
}
public class IdentifierField implements TlvComponentBase, IEncodingAble {
private IdentifierContainer identifiers;
private IdentifierContainer identifiers=new IdentifierContainer();
public IdentifierField() {
identifiers = new IdentifierContainer();
}
/**
@@ -151,46 +149,44 @@ public class IdentifierField implements TlvComponentBase, IEncodingAble {
*/
@Override
public int wireEncode(Encoder encoder) throws ComponentException {
// 如果标识区不存在标识,则是一个无效的MIN包,直接抛出错误
if (this.identifiers.length() == 0) {
return 0;
}
int totalLength = 0;
// 编码 TLV-VALUE
// 反向遍历,可以保证解码的时候正向输出
for (int i = this.identifiers.length() - 1; i >= 0; i--) {
int tmplen = 0;
tmplen = this.identifiers.getElement(i).wireEncode(encoder);
try {
// 如果标识区不存在标识,则是一个无效的MIN包,直接抛出错误
if (this.identifiers.length() <= 0) {
return -1;
}
int totalLength = 0;
// 编码 TLV-VALUE
// 反向遍历,可以保证解码的时候正向输出
for (int i = this.identifiers.length() - 1; i >= 0; i--) {
int tmplen = this.identifiers.getElement(i).wireEncode(encoder);
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
}
// 编码 TLV-LENGTH
int tmplen = encoder.prependVarNumber(new VlInt(totalLength));
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
}
// 编码 TLV-LENGTH
int tmplen = 0;
try {
tmplen = encoder.prependVarNumber(new VlInt(totalLength));
// 编码 TLV-LENGTH
try {
tmplen = encoder.prependVarNumber(new VlInt(TLV.TlvIdentifierField));
} catch (EncoderException e) {
throw new ComponentException("IdentifierField.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
return totalLength;
} catch (EncoderException e) {
throw new ComponentException("IdentifierField.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
// 编码 TLV-LENGTH
try {
tmplen = encoder.prependVarNumber(new VlInt(TLV.TlvIdentifierField));
} catch (EncoderException e) {
throw new ComponentException("IdentifierField.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
return totalLength;
}
/**
+37 -38
View File
@@ -10,8 +10,8 @@ import encoding.*;
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
public class IdentifierWrapper implements TlvComponentBase, IEncodingAble {
private Identifier identifier=new Identifier();
private VlInt tlvType=new VlInt(TLV.TlvInvalid);
private Identifier identifier = new Identifier();
private VlInt tlvType = new VlInt(TLV.TlvInvalid);
public IdentifierWrapper() {
}
@@ -40,9 +40,13 @@ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble {
}
}
public IdentifierWrapper(VlInt tlvType,Identifier identifier){
this.tlvType=tlvType;
this.identifier=identifier;
public IdentifierWrapper(VlInt tlvType, Identifier identifier) throws ComponentException {
if (!TLV.isValidIdentifierType(tlvType)) {
throw new ComponentException("IdentifierWrapper(VlInt tlvType,String identifierString): "
+ "tlvType invalid");
}
this.tlvType = tlvType;
this.identifier = identifier;
}
/**
@@ -96,7 +100,7 @@ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble {
+ "tlvType invalid");
}
this.tlvType = tlvType;
if(!this.identifier.buildIdentifierByBlock(block)){
if (!this.identifier.buildIdentifierByBlock(block)) {
throw new ComponentException
("IdentifierWrapper(VlInt tlvType, Block block): Identifier block is valid");
}
@@ -294,43 +298,38 @@ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble {
*/
@Override
public int wireEncode(Encoder encoder) throws ComponentException {
int totalLength = 0;
// 编码 TLV-VALUE
int tmplen = 0;
try {
tmplen = this.identifier.wireEncode(encoder);
} catch (ComponentException e) {
throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
int totalLength = 0;
// 编码 TLV-LENGTH
try {
// 编码 TLV-VALUE
int tmplen = this.identifier.wireEncode(encoder);
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
// 编码 TLV-LENGTH
tmplen = encoder.prependVarNumber(new VlInt(totalLength));
} catch (EncoderException e) {
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
// 编码 TLV-TYPE
try {
tmplen = encoder.prependVarNumber(this.tlvType);
} catch (EncoderException e) {
throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
return totalLength;
} catch (ComponentException | EncoderException e) {
throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
// 编码 TLV-TYPE
try {
tmplen = encoder.prependVarNumber(this.tlvType);
} catch (EncoderException e) {
throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage());
}
if (tmplen <= 0) {
return -1;
}
totalLength += tmplen;
return totalLength;
}
/**
+139 -141
View File
@@ -12,146 +12,146 @@ import util.ByteHelper;
*/
public class Block {
private VlInt tlvType; // TLV-TYPE
private VlInt length; // TLV-LENGTH
private VlInt tlvType = new VlInt(TLV.TlvInvalid); // TLV-TYPE
private VlInt length = new VlInt(0); // TLV-LENGTH
private byte[] value; // TLV-VALUE
private ElementContainer elements; // TLV-sub-elements
private ElementContainer elements = new ElementContainer(); // TLV-sub-elements
private byte[] raw; // TLV编码后的字节数组
public Block(){
this.tlvType=new VlInt(TLV.TlvInvalid);
this.length=new VlInt(0);
this.elements=new ElementContainer();
public Block() {
}
public Block(byte[] buffer,boolean verifyLength) throws BlockException {
if(buffer.length==0){
public Block(byte[] buffer, boolean verifyLength) throws BlockException {
if (buffer.length == 0) {
throw new BlockException("createBlockByBuffer: buffer.length==0");
}
// 读取type
VlInt tlvType= null;
VlInt tlvType = null;
try {
tlvType = TLV.readType(buffer,new VlInt(0));
tlvType = TLV.readType(buffer, new VlInt(0));
} catch (TLVException e) {
throw new BlockException("createBlockByBuffer: tlvType read error & "+e.getMessage());
throw new BlockException("createBlockByBuffer: tlvType read error & " + e.getMessage());
}
if(tlvType==null){
if (tlvType == null) {
throw new BlockException("createBlockByBuffer: tlvType read error");
}
// 读取length
VlInt tlvLength= null;
VlInt tlvLength = null;
try {
tlvLength = TLV.readVarNumber(buffer,new VlInt(tlvType.size()));
tlvLength = TLV.readVarNumber(buffer, new VlInt(tlvType.size()));
} catch (TLVException e) {
throw new BlockException("createBlockByBuffer: tlvLength read error"+e.getMessage());
throw new BlockException("createBlockByBuffer: tlvLength read error" + e.getMessage());
}
if(tlvLength==null){
if (tlvLength == null) {
throw new BlockException("createBlockByBuffer: tlvLength read error");
}
this.buildBlockByTypeLengthBuffer(tlvType,tlvLength,
ByteHelper.getLenBytes(buffer,new VlInt(tlvType.size()+tlvLength.size()),
buffer.length-(tlvType.size()+tlvLength.size())),verifyLength);
this.buildBlockByTypeLengthBuffer(tlvType, tlvLength,
ByteHelper.getLenBytes(buffer, new VlInt(tlvType.size() + tlvLength.size()),
buffer.length - (tlvType.size() + tlvLength.size())), verifyLength);
}
/**
* 从一个包含TLV的字节数组中构造一个 Block 对象
*
* @param buffer
* @param verifyLength 是否要验证TLV的长度是否匹配,如果true,
* 则会对比解析到的 TLV-LENGTH 与 TLV-VALUE的实际长度是否匹配
* @return
*/
public static Block createBlockByBuffer(byte[] buffer,boolean verifyLength) throws BlockException {
return new Block(buffer,verifyLength);
public static Block createBlockByBuffer(byte[] buffer, boolean verifyLength) throws BlockException {
return new Block(buffer, verifyLength);
}
/**
* 传入 T、L、V 构造一个 TLV Block
*
* @param tlvType
* @param tlvLength
* @param buffer
* @param verifyLength
* @return
*/
public static Block createBlockByTypeLengthBuffer(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength) throws BlockException {
return new Block(tlvType,tlvLength,buffer,verifyLength);
public static Block createBlockByTypeLengthBuffer(VlInt tlvType, VlInt tlvLength, byte[] buffer, boolean verifyLength) throws BlockException {
return new Block(tlvType, tlvLength, buffer, verifyLength);
}
/**
* 构造函数
*
* @param tlvType
* @param tlvLength
* @param buffer
* @param verifyLength
*/
public Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength) throws BlockException{
this.buildBlockByTypeLengthBuffer(tlvType,tlvLength,buffer,verifyLength);
public Block(VlInt tlvType, VlInt tlvLength, byte[] buffer, boolean verifyLength) throws BlockException {
this.buildBlockByTypeLengthBuffer(tlvType, tlvLength, buffer, verifyLength);
}
public Block(Block block){
this.tlvType=block.tlvType;
this.length=block.length;
this.value=block.value;
this.elements=block.elements;
this.raw=block.raw;
public Block(Block block) {
this.tlvType = block.tlvType;
this.length = block.length;
this.value = block.value;
this.elements = block.elements;
this.raw = block.raw;
}
public void buildBlockByTypeLengthBuffer(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength) throws BlockException {
this.tlvType=tlvType;
this.length=tlvLength;
this.elements=new ElementContainer();
public void buildBlockByTypeLengthBuffer(VlInt tlvType, VlInt tlvLength, byte[] buffer, boolean verifyLength) throws BlockException {
this.tlvType = tlvType;
this.length = tlvLength;
this.elements = new ElementContainer();
// 检查长度是否正确
if(verifyLength && (!this.length.isEqual(buffer.length))){
if (verifyLength && (!this.length.isEqual(buffer.length))) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): invalid length.");
}
// 设置 Raw
Encoder encoder=new Encoder();
boolean resetBool= false;
Encoder encoder = new Encoder();
boolean resetBool = false;
try {
resetBool = encoder.encoderReset(new SizeT(tlvType.size()+tlvLength.size()+buffer.length),new SizeT(0));
resetBool = encoder.encoderReset(new SizeT(tlvType.size() + tlvLength.size() + buffer.length), new SizeT(0));
} catch (EncoderException e) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): encoderReset error"
+e.getMessage());
+ e.getMessage());
}
if(!resetBool){
if (!resetBool) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): encoderReset error");
}
try {
if(encoder.prependByteArray(buffer,new SizeT(buffer.length))<0){
if (encoder.prependByteArray(buffer, new SizeT(buffer.length)) < 0) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prepenndByteArray buffer error");
}
} catch (EncoderException e) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prepenndByteArray buffer error"
+e.getMessage());
+ e.getMessage());
}
try {
if(encoder.prependVarNumber(tlvLength)<=0){
if (encoder.prependVarNumber(tlvLength) <= 0) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvLength error");
}
} catch (EncoderException e) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvLength error"
+e.getMessage());
+ e.getMessage());
}
try {
if(encoder.prependVarNumber(tlvType)<=0){
if (encoder.prependVarNumber(tlvType) <= 0) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvType error");
}
} catch (EncoderException e) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvType error"
+e.getMessage());
+ e.getMessage());
}
byte[] encodedBuffer=encoder.getBuffer();
if(encodedBuffer==null){
byte[] encodedBuffer = encoder.getBuffer();
if (encodedBuffer == null) {
throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): encoder.getBuffer error");
}
this.raw=encodedBuffer;
this.raw = encodedBuffer;
// 设置value
this.value=buffer;
this.value = buffer;
}
public VlInt getType() {
@@ -184,29 +184,32 @@ public class Block {
/**
* 整个TLV编码后的大小,包含T和L
*
* @return
*/
public SizeT Size(){
if(!this.isValid()){
public SizeT Size() {
if (!this.isValid()) {
return null;
}
return new SizeT(this.tlvType.size()+this.length.size()+this.value.length);
return new SizeT(this.tlvType.size() + this.length.size() + this.value.length);
}
/**
* 判断当前的 Block 对象是否含有 value
*
* @return
*/
public boolean hasValue(){
return this.value.length!=0;
public boolean hasValue() {
return this.value.length != 0;
}
/**
* 判断当前的 Block 对象是否含有 raw数组
*
* @return
*/
public boolean hasRaw(){
return this.raw.length!=0;
public boolean hasRaw() {
return (this.raw != null) && (this.raw.length != 0);
}
// ************** Sub-Elements **************
@@ -214,86 +217,89 @@ public class Block {
/**
* 判断当前 TLV Block 是否包含子 TLV
* 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法,
* 才会去解析一级子TLV
* 才会去解析一级子TLV
*
* @return
*/
public boolean hasSubElement(){
return this.elements.length()!=0;
public boolean hasSubElement() {
return this.elements.length() != 0;
}
/**
* 获取所有的一级子TLV Block
* * 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法,
* * 才会去解析一级子TLV
* * 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法,
* * 才会去解析一级子TLV
*
* @return
*/
public ElementContainer getSubElements(){
public ElementContainer getSubElements() {
return this.elements;
}
/**
* 从 value 字节数组中解析出所有的一级子 TLV Block
* 1. 这要求这个TLV确实存在嵌套的子TLV,或者为空;
* 2. 如果TLV的value不为空,且不存在嵌套的子TLV,则会抛出错误
* 1. 这要求这个TLV确实存在嵌套的子TLV,或者为空;
* 2. 如果TLV的value不为空,且不存在嵌套的子TLV,则会抛出错误
*
* @return
*/
public boolean parseSubElements() throws BlockException {
if((this.value.length==0)||this.elements.length()!=0){
if ((this.value.length == 0) || this.elements.length() != 0) {
return true;
}
// 循环解析所有的一级子TLV
for (int start = 0; start < this.value.length; ) {
// 读取 TLV-TYPE
VlInt tlvType= null;
VlInt tlvType = null;
try {
tlvType = TLV.readType(this.value,new VlInt(start));
tlvType = TLV.readType(this.value, new VlInt(start));
} catch (TLVException e) {
throw new BlockException("parseSubElements"+e.getMessage());
throw new BlockException("parseSubElements" + e.getMessage());
}
if(tlvType==null){
if (tlvType == null) {
this.clearElements();
return false;
}
start+=tlvType.size();
start += tlvType.size();
// 读取 TLV-LENGTH
VlInt tlvLength= null;
VlInt tlvLength = null;
try {
tlvLength = TLV.readVarNumber(this.value,new VlInt(start));
tlvLength = TLV.readVarNumber(this.value, new VlInt(start));
} catch (TLVException e) {
throw new BlockException("parseSubElements"+e.getMessage());
throw new BlockException("parseSubElements" + e.getMessage());
}
if(tlvType==null){
if (tlvType == null) {
this.clearElements();
return false;
}
start+=tlvLength.size();
start += tlvLength.size();
// 检查 buffer 中是否有足够的字节
if(tlvLength.add(start)>this.value.length){
if (tlvLength.add(start) > this.value.length) {
this.clearElements();
return false;
}
// 创建一个子 TLV Block 并添加到elements当中
byte[] subBlockValue= new byte[0];
byte[] subBlockValue = new byte[0];
try {
subBlockValue = new byte[tlvLength.getVlIntValue2Int()];
System.arraycopy(this.value,start,subBlockValue,0,tlvLength.getVlIntValue2Int());
Block block= null;
System.arraycopy(this.value, start, subBlockValue, 0, tlvLength.getVlIntValue2Int());
Block block = null;
try {
block = createBlockByTypeLengthBuffer(tlvType,tlvLength,subBlockValue,true);
block = createBlockByTypeLengthBuffer(tlvType, tlvLength, subBlockValue, true);
} catch (BlockException e) {
return false;
}
if(block==null){
if (block == null) {
return false;
}
this.addElement(block);
start+=tlvLength.getVlIntValue2Int();
start += tlvLength.getVlIntValue2Int();
} catch (VlIntException e) {
return false;
return false;
}
}
return true;
@@ -302,6 +308,7 @@ public class Block {
/**
* 从 elements 中找到第一个指定type的子TLV
*
* @param tlvType
* @return
*/
@@ -311,101 +318,92 @@ public class Block {
/**
* 移除所有指定type的子tlv
*
* @param tlvType
*/
public void removeElements(VlInt tlvType){
public void removeElements(VlInt tlvType) {
this.elements.removeElements(tlvType);
}
/**
* 往 elements 中添加一个子tlv
*
* @param block
*/
public void addElement(Block block){
public void addElement(Block block) {
this.elements.addElement(block);
}
/**
* 清除 elements 中所有的子TLV
*/
public void clearElements(){
public void clearElements() {
this.elements.clear();
}
/**
* 判断是否有效
*
* @return
*/
public boolean isValid(){
public boolean isValid() {
// return this.tlvType.isEqual(TLV.TlvInvalid);
return !this.tlvType.isEqual(TLV.TlvInvalid);
}
/**
* 将当前的 TLV Block 编码成字节数组,存放在 raw 当中
*
* @param encoder
* @return
*/
public int encode(Encoder encoder) throws ComponentException {
// 如果已经有raw,则说明编码过,或者是解码而来的,不用在此Encode
if(this.hasRaw()){
try {
return encoder.prependByteArray(this.raw,new SizeT(this.raw.length));
} catch (EncoderException e) {
throw new ComponentException("encode: "+e.getMessage());
public int encode(Encoder encoder) throws BlockException {
try {
// 如果已经有raw,则说明编码过,或者是解码而来的,不用在此Encode
if (this.hasRaw()) {
return encoder.prependByteArray(this.raw, new SizeT(this.raw.length));
}
}
int len=0;
int len = 0;
// 编码 TLV-VALUE
if(this.hasValue()){
// 如果设置了 value ,则直接使用
int tmplen= 0;
try {
tmplen = encoder.appendByteArray(this.value,new SizeT(this.value.length));
} catch (EncoderException e) {
throw new ComponentException("encode: "+e.getMessage());
}
if(tmplen<=0){
return -1;
}
len+=tmplen;
}else{
// 如果 value 为空,则看 elements 中有没有子TLV Block,有则编码后插入
for(Block subBlock:this.elements.getElements()){
int tmplen=subBlock.encode(encoder);
if(tmplen<=0){
// 编码 TLV-VALUE
if (this.hasValue()) {
// 如果设置了 value ,则直接使用
int tmplen = encoder.prependByteArray(this.value, new SizeT(this.value.length));
if (tmplen <= 0) {
return -1;
}
len+=tmplen;
len += tmplen;
} else {
// 如果 value 为空,则看 elements 中有没有子TLV Block,有则编码后插入
for (Block subBlock : this.elements.getElements()) {
int tmplen = subBlock.encode(encoder);
if (tmplen <= 0) {
return -1;
}
len += tmplen;
}
}
}
// 编码 TLV-LENGTH
int tmplen= 0;
try {
tmplen = encoder.prependVarNumber(new VlInt(len));
// 编码 TLV-LENGTH
int tmplen = encoder.prependVarNumber(new VlInt(len));
if (tmplen <= 0) {
return -1;
}
len += tmplen;
// 编码 TLV-TYPE
tmplen = encoder.prependVarNumber(this.tlvType);
if (tmplen <= 0) {
return -1;
}
len += tmplen;
return len;
} catch (EncoderException e) {
throw new ComponentException("encode: "+e.getMessage());
throw new BlockException("encode: " + e.getMessage());
}
if(tmplen<=0){
return -1;
}
len+=tmplen;
// 编码 TLV-TYPE
try {
tmplen=encoder.prependVarNumber(this.tlvType);
} catch (EncoderException e) {
throw new ComponentException("encode: "+e.getMessage());
}
if(tmplen<=0){
return -1;
}
len+=tmplen;
return len;
}
}
+1 -2
View File
@@ -14,9 +14,8 @@ import java.util.List;
*/
// TLV 组件容器
public class ElementContainer{
private List<Block> elementContainer;
private List<Block> elementContainer = new LinkedList<>();
public ElementContainer(){
elementContainer = new LinkedList<>();
}
/**
+109 -103
View File
@@ -16,78 +16,81 @@ public class Encoder {
public boolean isEstimator;// 是否仅测量编码后的长度,而不实际进行编码
public SizeT totalReserve; // 编码缓存数组的大小
public static final int MaxPacketSize=8800;
public static final int MaxPacketSize = 8800;
/**
* 编码测量初始化
* @Description:
* 1. 一旦调用这个函数进行初始化,则调用所有的编码函数只会测量编码后的长度,不会执行实际的编码
*
* @Description: 1. 一旦调用这个函数进行初始化,则调用所有的编码函数只会测量编码后的长度,不会执行实际的编码
*/
public void estimatorReset(){
this.left=0;
this.right=1;
this.isInitial=true;
this.isEstimator=true;
this.totalReserve=new SizeT(Long.MAX_VALUE);
public void estimatorReset() {
this.left = 0;
this.right = 1;
this.isInitial = true;
this.isEstimator = true;
this.totalReserve = new SizeT(Long.MAX_VALUE);
}
/**
* 编码初始化
* @Description:
* @param totalReserve 总的存储编码结果的数组长度
* @param reserveFromBack 默认情况下,左右指针都指向数组的最右侧,表示totalReserve指定的所有空间都是预留给 Prepend* 操作的
* reserveFromBack 可以指定需要预留多少空间给 Append*操作
*
* @param totalReserve 总的存储编码结果的数组长度
* @param reserveFromBack 默认情况下,左右指针都指向数组的最右侧,表示totalReserve指定的所有空间都是预留给 Prepend* 操作的
* reserveFromBack 可以指定需要预留多少空间给 Append*操作
* @Description:
*/
public boolean encoderReset(SizeT totalReserve,SizeT reserveFromBack) throws EncoderException{
if(reserveFromBack.compareTo(totalReserve)>0){
public boolean encoderReset(SizeT totalReserve, SizeT reserveFromBack) throws EncoderException {
if (reserveFromBack.compareTo(totalReserve) > 0) {
throw new EncoderException("encoderReset: reserveFromBack > totalReserve");
}
this.isInitial=true;
this.isEstimator=false;
this.totalReserve=totalReserve;
int len=0;
this.isInitial = true;
this.isEstimator = false;
this.totalReserve = totalReserve;
int len = 0;
try {
len=totalReserve.getVlIntValue2Int();
len = totalReserve.getVlIntValue2Int();
} catch (VlIntException e) {
throw new EncoderException("encoderReset: "+e.getMessage());
throw new EncoderException("encoderReset: " + e.getMessage());
}
this.buffer=new byte[len]; //todo: 特殊情况下,可能越界。
this.left= (int) (totalReserve.subtract(reserveFromBack)-1);//todo: 特殊情况下,可能越界。
this.right= (int) totalReserve.subtract(reserveFromBack);//todo: 特殊情况下,可能越界。
this.buffer = new byte[len]; //todo: 特殊情况下,可能越界。
this.left = (int) (totalReserve.subtract(reserveFromBack) - 1);//todo: 特殊情况下,可能越界。
this.right = (int) totalReserve.subtract(reserveFromBack);//todo: 特殊情况下,可能越界。
return true;
}
/**
* 判断是否为空
*
* @return
*/
public boolean empty(){
return (this.left+1)>=this.right;
public boolean empty() {
return (this.left + 1) >= this.right;
}
/**
* 编码后的大小
*
* @return
*/
public SizeT size(){
return new SizeT(this.right-this.left-1);
public SizeT size() {
return new SizeT(this.right - this.left - 1);
}
/**
* 在每个操作之前进行有效性检查
* @Description:
* 1. 首先检查 Encoder 实例有没有初始化,没有初始化则返回错误;
* 2. 然后检查预计新增 size 个字节,会不会超出最大包限制,超出则返回错误;
* 3. 否则返回 nil
*
* @param size
* @return
* @Description: 1. 首先检查 Encoder 实例有没有初始化,没有初始化则返回错误;
* 2. 然后检查预计新增 size 个字节,会不会超出最大包限制,超出则返回错误;
* 3. 否则返回 nil
*/
public boolean check(SizeT size){
if(!this.isInitial){
public boolean check(SizeT size) {
if (!this.isInitial) {
return false;
}
if(this.totalReserve.compareTo(this.size().add(size))<0){
if (this.totalReserve.compareTo(this.size().add(size)) < 0) {
return false;
}
return true;
@@ -95,19 +98,20 @@ public class Encoder {
/**
* Prepend a byte
*
* @param value
* @return 返回成功插入的字节数
*/
public int prependByte(byte value){
if(this.isEstimator){
public int prependByte(byte value) {
if (this.isEstimator) {
this.left--;
return 1;
}
if(check(new SizeT(1))){
this.buffer[this.left]=value;
if (check(new SizeT(1))) {
this.buffer[this.left] = value;
this.left--;
return 1;
}else{
} else {
return -1;
}
}
@@ -116,16 +120,16 @@ public class Encoder {
* @param value
* @return 返回插入成功的字节数
*/
public int appendByte(byte value){
if(this.isEstimator){
public int appendByte(byte value) {
if (this.isEstimator) {
this.right++;
return 1;
}
if(check(new SizeT(1))){
this.buffer[this.right]=value;
if (check(new SizeT(1))) {
this.buffer[this.right] = value;
this.right++;
return 1;
}else{
} else {
return -1;
}
}
@@ -134,17 +138,18 @@ public class Encoder {
/**
* 编码一个非负整数到一个数组当中
* todo: 越界问题
*
* @param uint64
* @return
*/
public static byte[] buildNonNegativeIntegerArr(long uint64){
VlInt vlInt=new VlInt(uint64);
int len=vlInt.getVlIntBytes().length;
if(uint64<=255){
public static byte[] buildNonNegativeIntegerArr(long uint64) {
VlInt vlInt = new VlInt(uint64);
int len = vlInt.getVlIntBytes().length;
if (uint64 <= 255) {
return new byte[]{(byte) uint64};
}else {
} else {
byte[] res = new byte[len - 1];
System.arraycopy(vlInt.getVlIntBytes(),1,res,0,len-1);
System.arraycopy(vlInt.getVlIntBytes(), 1, res, 0, len - 1);
return res;
}
}
@@ -152,23 +157,25 @@ public class Encoder {
/**
* 在前向插入一个非负整数,最大为 uint64::Max
* todo: 越界问题
*
* @param uint64_value
* @return
*/
public int prependNonNegativeInteger(long uint64_value) throws EncoderException {
byte[] bytes=buildNonNegativeIntegerArr(uint64_value);
return this.prependByteArray(bytes,new SizeT(bytes.length));
byte[] bytes = buildNonNegativeIntegerArr(uint64_value);
return this.prependByteArray(bytes, new SizeT(bytes.length));
}
/**
* 在后向插入一个非负整数,最大为 uint64::Max
* todo: 越界问题
*
* @param uint64_value
* @return
*/
public int appendNonNegativeInteger(long uint64_value) throws EncoderException {
byte[] bytes=buildNonNegativeIntegerArr(uint64_value);
return this.appendByteArray(bytes,new SizeT(bytes.length));
byte[] bytes = buildNonNegativeIntegerArr(uint64_value);
return this.appendByteArray(bytes, new SizeT(bytes.length));
}
/**
@@ -176,27 +183,27 @@ public class Encoder {
* @param size
* @return 返回插入成功的字节数
*/
public int prependByteArray(byte[] array,SizeT size) throws EncoderException {
if(check(size)&&(size.compareTo(array.length)<=0)){
if(this.isEstimator){
this.left-=array.length;
public int prependByteArray(byte[] array, SizeT size) throws EncoderException {
if (check(size) && (size.compareTo(array.length) <= 0)) {
if (this.isEstimator) {
this.left -= array.length;
try {
return size.getVlIntValue2Int();
} catch (VlIntException e) {
throw new EncoderException("prependByteArray: "+e.getMessage());
throw new EncoderException("prependByteArray: " + e.getMessage());
}
}else{
} else {
try {
System.arraycopy(array,0,this.buffer,
this.left-size.getVlIntValue2Int()+1,size.getVlIntValue2Int());
System.arraycopy(array, 0, this.buffer,
this.left - size.getVlIntValue2Int() + 1, size.getVlIntValue2Int());
} catch (VlIntException e) {
throw new EncoderException("prependByteArray: "+e.getMessage());
throw new EncoderException("prependByteArray: " + e.getMessage());
}
this.left-=array.length;
this.left -= array.length;
try {
return size.getVlIntValue2Int();
} catch (VlIntException e) {
throw new EncoderException("prependByteArray: "+e.getMessage());
throw new EncoderException("prependByteArray: " + e.getMessage());
}
}
}
@@ -208,115 +215,114 @@ public class Encoder {
* @param size
* @return 返回插入成功的字节数
*/
public int appendByteArray(byte[] array,SizeT size) throws EncoderException {
if(check(size)&&(size.compareTo(array.length)<=0)){
if(this.isEstimator){
this.right+=array.length;
try {
public int appendByteArray(byte[] array, SizeT size) throws EncoderException {
try {
if (check(size) && (size.compareTo(array.length) <= 0)) {
if (this.isEstimator) {
this.right += array.length;
return size.getVlIntValue2Int();
} catch (VlIntException e) {
throw new EncoderException("appendByteArray: "+e.getMessage());
}
}else{
try {
System.arraycopy(array,0,this.buffer,
this.right,size.getVlIntValue2Int());
} catch (VlIntException e) {
throw new EncoderException("appendByteArray: "+e.getMessage());
}
this.right+=array.length;
try {
} else {
System.arraycopy(array, 0, this.buffer,
this.right, size.getVlIntValue2Int());
this.right += array.length;
return size.getVlIntValue2Int();
} catch (VlIntException e) {
throw new EncoderException("appendByteArray: "+e.getMessage());
}
}
return -1;
} catch (VlIntException e) {
throw new EncoderException("appendByteArray: " + e.getMessage());
}
return -1;
}
/**
* 在前向插入一个可变长度的数字
*
* @param varNumber
* @return
*/
public int prependVarNumber(VlInt varNumber) throws EncoderException {
return this.prependByteArray(varNumber.getVlIntBytes(),new SizeT(varNumber.size()));
return this.prependByteArray(varNumber.getVlIntBytes(), new SizeT(varNumber.size()));
}
/**
* 在后向插入一个可变长度的数字
*
* @param varNumber
* @return
*/
public int appendVarNumber(VlInt varNumber) throws EncoderException {
return this.appendByteArray(varNumber.getVlIntBytes(),new SizeT(varNumber.size()));
return this.appendByteArray(varNumber.getVlIntBytes(), new SizeT(varNumber.size()));
}
//todo: 在前向&后向插入一个非负整数
/**
* 根据TLV-TYPE和一个字节数组,在前向插入一个 TLV Block
*
* @param tlvType
* @param array
* @param size
* @return
*/
public int prependByteArrayBlock(VlInt tlvType,byte[] array,SizeT size) throws EncoderException {
int totalLength=this.prependByteArray(array,size);
totalLength+=this.prependVarNumber(new VlInt(size));
totalLength+=this.prependVarNumber(tlvType);
public int prependByteArrayBlock(VlInt tlvType, byte[] array, SizeT size) throws EncoderException {
int totalLength = this.prependByteArray(array, size);
totalLength += this.prependVarNumber(new VlInt(size));
totalLength += this.prependVarNumber(tlvType);
return totalLength;
}
/**
* 根据TLV-TYPE和一个字节数组,在后向插入一个 TLV Block
*
* @param tlvType
* @param array
* @param size
* @return
*/
public int appendByteArrayBlock(VlInt tlvType,byte[] array,SizeT size) throws EncoderException {
int totalLength=0;
public int appendByteArrayBlock(VlInt tlvType, byte[] array, SizeT size) throws EncoderException {
int totalLength = 0;
// Append TLV-TYPE
totalLength+=this.appendVarNumber(tlvType);
totalLength += this.appendVarNumber(tlvType);
// Append TLV-LENGTH
totalLength+=this.appendVarNumber(new VlInt(size));
totalLength += this.appendVarNumber(new VlInt(size));
// Append TLV-VALUE
totalLength+=this.appendByteArray(array,size);
totalLength += this.appendByteArray(array, size);
return totalLength;
}
/**
* 在前向插入一个 TLV Block
*
* @param block
* @return
*/
public int prependBlock(Block block) throws EncoderException {
return this.prependByteArrayBlock(block.getType(),block.getValue(),new SizeT(block.getLength()));
return this.prependByteArrayBlock(block.getType(), block.getValue(), new SizeT(block.getLength()));
}
/**
* 在后向插入一个 TLV Block
*
* @param block
* @return
*/
public int appendBlock(Block block) throws EncoderException {
return this.appendByteArrayBlock(block.getType(),block.getValue(),new SizeT(block.getLength()));
return this.appendByteArrayBlock(block.getType(), block.getValue(), new SizeT(block.getLength()));
}
/**
* 获取编码后的字节数组
*
* @return
*/
public byte[] getBuffer() {
if((!this.isInitial)||this.isEstimator){
if ((!this.isInitial) || this.isEstimator) {
return null;
}
int len=this.right-this.left-1;
byte[] res=new byte[len];
System.arraycopy(this.buffer,this.left+1,res,0,len);
int len = this.right - this.left - 1;
byte[] res = new byte[len];
System.arraycopy(this.buffer, this.left + 1, res, 0, len);
return res;
}
}
@@ -0,0 +1,40 @@
package component;
import encoding.*;
import org.junit.Test;
/*
* @Author: Wang Feng
* @Description:
* @Version: 1.0.0
* @Date: 17:23 2021/3/29
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
public class IdentifierFieldTest {
@Test
public void TestIdentifierField_WireEncode() throws ComponentException, EncoderException, BlockException {
IdentifierWrapper wrapper=new IdentifierWrapper().
createCommonIdentifierByString("/min/pku/sz");
IdentifierWrapper wrapper1=new IdentifierWrapper(new VlInt(105),"/install/mnfd");
IdentifierWrapper wrapper2=new IdentifierWrapper(new VlInt(106),"/1");
IdentifierField field=new IdentifierField();
field.addIdentifier(wrapper);
field.addIdentifier(wrapper1);
field.addIdentifier(wrapper2);
for (int i = 0; i < field.getIdentifiers().length(); i++) {
System.out.println(field.getIdentifiers().getElement(i).toUri());
}
Encoder encoder=new Encoder();
encoder.encoderReset(new SizeT(Encoder.MaxPacketSize),new SizeT(0));
field.wireEncode(encoder);
byte[] buf=encoder.getBuffer();
Block block=new Block(buf,false);
IdentifierField field1=new IdentifierField();
System.out.println(field1.wireDecode(block));
for (int i = 0; i < field1.getIdentifiers().length(); i++) {
System.out.println(field1.getIdentifiers().getElement(i).toUri());
}
}
}
@@ -162,9 +162,9 @@ public class IdentifierWrapperTest {
@Test
public void TestCreateIdentifierWrapperByTypeAndIdentifier() throws ComponentException {
Identifier identifier=new Identifier("/min/pku/王");
for (int i = 100; i < 200; i++) {
for (int i = 199; i >0; i--) {
IdentifierWrapper got=new IdentifierWrapper(new VlInt(i),identifier);
System.out.println(got.toUri());
System.out.println(i+":"+got.toUri());
}
}
}