com.payneteasy.tlv.BerTlvParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ber-tlv Show documentation
Show all versions of ber-tlv Show documentation
BER-TLV reader and writer
The newest version!
package com.payneteasy.tlv;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
public class BerTlvParser {
private static final BerTagFactory DEFAULT_TAG_FACTORY = new DefaultBerTagFactory();
private final BerTagFactory tagFactory;
private final IBerTlvLogger log;
public BerTlvParser() {
this(DEFAULT_TAG_FACTORY, EMPTY_LOGGER);
}
public BerTlvParser(IBerTlvLogger aLogger) {
this(DEFAULT_TAG_FACTORY, aLogger);
}
public BerTlvParser(BerTagFactory aTagFactory) {
this(aTagFactory, EMPTY_LOGGER);
}
public BerTlvParser(BerTagFactory aTagFactory, IBerTlvLogger aLogger) {
tagFactory = aTagFactory;
log = aLogger;
}
public BerTlv parseConstructed(byte[] aBuf) {
return parseConstructed(aBuf, 0, aBuf.length);
}
public BerTlv parseConstructed(byte[] aBuf, int aOffset, int aLen) {
ParseResult result = parseWithResult(0, aBuf, aOffset, aLen);
return result.tlv;
}
public BerTlvs parse(byte[] aBuf) {
return parse(aBuf, 0, aBuf.length);
}
public BerTlvs parse(byte[] aBuf, final int aOffset, int aLen) {
List tlvs = new ArrayList();
if(aLen==0) return new BerTlvs(tlvs);
int offset = aOffset;
for(int i=0; i<100; i++) {
ParseResult result = parseWithResult(0, aBuf, offset, aLen-offset);
tlvs.add(result.tlv);
if(result.offset>=aOffset+aLen) {
break;
}
offset = result.offset;
}
return new BerTlvs(tlvs);
}
private ParseResult parseWithResult(int aLevel, byte[] aBuf, int aOffset, int aLen) {
String levelPadding = createLevelPadding(aLevel);
if(aOffset+aLen > aBuf.length) {
throw new IllegalStateException("Length is out of the range [offset="+aOffset+", len="+aLen+", array.length="+aBuf.length+", level="+aLevel+"]");
}
if(log.isDebugEnabled()) {
log.debug("{}parseWithResult(level={}, offset={}, len={}, buf={})", levelPadding, aLevel, aOffset, aLen, HexUtil.toFormattedHexString(aBuf, aOffset, aLen));
}
// tag
int tagBytesCount = getTagBytesCount(aBuf, aOffset);
BerTag tag = createTag(levelPadding, aBuf, aOffset, tagBytesCount);
if(log.isDebugEnabled()) {
log.debug("{}tag = {}, tagBytesCount={}, tagBuf={}", levelPadding, tag, tagBytesCount, HexUtil.toFormattedHexString(aBuf, aOffset, tagBytesCount));
}
// length
int lengthBytesCount = getLengthBytesCount(aBuf, aOffset + tagBytesCount);
int valueLength = getDataLength(aBuf, aOffset + tagBytesCount);
if(log.isDebugEnabled()) {
log.debug("{}lenBytesCount = {}, len = {}, lenBuf = {}"
, levelPadding, lengthBytesCount, valueLength, HexUtil.toFormattedHexString(aBuf, aOffset + tagBytesCount, lengthBytesCount));
}
// value
if(tag.isConstructed()) {
ArrayList list = new ArrayList();
addChildren(aLevel, aBuf, aOffset + tagBytesCount + lengthBytesCount, levelPadding, lengthBytesCount, valueLength, list);
int resultOffset = aOffset + tagBytesCount + lengthBytesCount + valueLength;
if(log.isDebugEnabled()) {
log.debug("{}returning constructed offset = {}", levelPadding, resultOffset);
}
return new ParseResult(new BerTlv(tag, list), resultOffset);
} else {
// value
byte[] value = new byte[valueLength];
System.arraycopy(aBuf, aOffset+tagBytesCount+lengthBytesCount, value, 0, valueLength);
int resultOffset = aOffset + tagBytesCount + lengthBytesCount + valueLength;
if(log.isDebugEnabled()) {
log.debug("{}value = {}", levelPadding, HexUtil.toFormattedHexString(value));
log.debug("{}returning primitive offset = {}", levelPadding, resultOffset);
}
return new ParseResult(new BerTlv(tag, value), resultOffset);
}
}
/**
*
* @param aLevel level for debug
* @param aBuf buffer
* @param aOffset offset (first byte)
* @param levelPadding level padding (for debug)
* @param aDataBytesCount data bytes count
* @param valueLength length
* @param list list to add
*/
private void addChildren(int aLevel, byte[] aBuf, int aOffset, String levelPadding, int aDataBytesCount, int valueLength, ArrayList list) {
int startPosition = aOffset;
int len = valueLength;
while (startPosition < aOffset + valueLength ) {
ParseResult result = parseWithResult(aLevel+1, aBuf, startPosition, len);
list.add(result.tlv);
startPosition = result.offset;
len = (aOffset + valueLength) - startPosition;
if(log.isDebugEnabled()) {
log.debug("{}level {}: adding {} with offset {}, startPosition={}, aDataBytesCount={}, valueLength={}"
, levelPadding, aLevel, result.tlv.getTag(), result.offset, startPosition, aDataBytesCount, valueLength);
}
}
}
private String createLevelPadding(int aLevel) {
if(!log.isDebugEnabled()) {
return "";
}
StringBuilder sb = new StringBuilder();
for(int i=0; i3) {
throw new IllegalStateException(String.format("At position %d the len is more then 3 [%d]", aOffset, numberOfBytes));
}
length = 0;
for(int i=aOffset+1; i