My method parseTLV()
sometimes does not properly decend into constructed values (child TLVs). I use a filter ((tag & 0x20)! = 0)
to detect constructed values, but sometimes it doesn't work as expected.
For example
70178C159F02069F03069F1A0295055F2A029A039C019F3704
leads to the following result for parseTLV
:
70
- Value: 8C159F02069F03069F1A0295055F2A029A039C019F3704
8C
- Value: 9F02069F03069F1A0295055F2A029A039C019F3704
However, I would expect to get
70
- Value: 8C159F02069F03069F1A0295055F2A029A039C019F3704
8C
- Value: 9F02069F03069F1A0295055F2A029A039C019F3704
9F02
- Value: 06
9F03
- Value: 06
9F1A
- Value: 02
95
- Value: 05
5F2A
- Value: 02
9A
- Value: 03
9C
- Value: 01
9F37
- Value: 04
private ITlv.ITlvDataObjList parseTLV(byte[] src) {
try {
if (isBytesEmpty(src)) {
return null;
}
_tlvList = _tlv.createTlvDataObjectList();
int start = 0;
int end = start + src.length;
while (start < end) {
// tag has 1 byte (0xFF)
int tag = src[start++] & 0xFF;
//
if (tag == 0x00 || tag == 0xFF) {
continue;
}
// tag has more bytes?
if ((tag & 0x1F) == 0x1F) {
if (start >= src.length) {
break;
}
// tag has 2 bytes (0xFFFF)
tag = (tag << 8) | src[start++] & 0xFF;
// tag has 3 bytes (0xFFFFFF)
if ((tag & 0x80) != 0) {
if (start >= src.length) {
break;
}
tag = (tag << 8) | src[start++] & 0xFF;
}
// break when tag > 3 bytes
if ((tag & 0x80) != 0) {
continue;
}
}
// length 1 byte (0x7F)
int length = src[start++] & 0xFF;
// length has more bytes?
if (length >= 0x80) {
// break when length > 2 bytes
int count = length & 0x7F;
if (count > 3) {
continue;
}
// length 1 bytes (0x80-0xFF) or 2 bytes (0x100-0xFFFF)
length = 0;
for (int k = 0; k < count; k++) {
if (start >= src.length) {
break;
}
length = (length << 8) | src[start++] & 0xFF;
}
}
// values
byte[] value = new byte[length];
System.arraycopy(src, start, value, 0, length);
//
// create tlv object
ITlv.ITlvDataObj tlvObj = _tlv.createTlvDataObject();
tlvObj.setTag(tag);
tlvObj.setValue(value);
// save tlv object to list
_tlvList.addDataObj(tlvObj);
//
// next tag
while (tag > 0xFF) {
tag = tag >> 8;
}
// is constructed (has child)?
if ((tag & 0x20) != 0) {
continue;
}
start = start + value.length;
}
return _tlvList;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
The tag 8C
does not contain a constructed value. Consequently, your test for ((tag & 0x20) != 0)
fails correctly. Instead, that TLV contains a data object list as its value. When you look at the value 9F02069F03069F1A0295055F2A029A039C019F3704
, you'll find that these are not complete TLV onbjects but only tags + lengths.
Consequently, you will have to find out based on the tag whether that TLV object contains a data object list. Then you can parse that list in a similar way to parsing complete TLV objects except that you skip the empty value field.