TLV data format of OC package

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Authors: Zhu Kefeng

The mailbox:

Reprint please indicate the source: http://blog.csdn.net/linux_zkf



TLV is a variable type, meaning:

The Type type, the length of Lenght, Valuevalue,

Type and Length fixed length, generally it is 2, 4 bytes (here adopt 4 bytes),

The length of the Value Length specified,

Decoding method:

1 read type using ntohl into host byte order to get type, pointer offset+4

2 read lengh using ntohl into host byte order get pointer offset length;+4

3 according to the length of reading value, if the value data type is int, char, short, ntohl into the host byte order, pointer offset + 4; if the value data type is string types, pointer offset+length

Type (Type) field is on the label and encoding type information;,

Length (Length) of field definition number value of length;,

Content (Value) field represents the actual numbervalue.

Therefore, a code value also called TLV (Type, Length, Value) three tuple. Coding is the basic type and structure type, if it represents a simple type, the integrity of the explicit value, then coding is the basic type (primitive); if it says value has a nested structure, the code is structured(constructed).

The above is the simple explanation of TLV, collected from the Internet resources, using C, C+ + to write open source software are very complicated, here I use very little OC code to achieve a simple and practical TLV parsing library, for your reference


The data structure of TLV


//

// TLV.h

// CashBox

//

// Created by ZKF on 13-11-18.

// Copyright (c) In 2013 ZKF. All rights reserved.

//


#import <Foundation/Foundation.h>


@interface TLV : NSObject


@property (nonatomic, assign) NSInteger length;

@property (nonatomic, retain) NSString *value;

@property (nonatomic, retain) NSString *tag;


@end

//

// TLV.m

// CashBox

//

// Created by ZKF on 13-11-18.

// Copyright (c) In 2013 ZKF. All rights reserved.

//


#import "TLV.h"


@implementation TLV

@synthesize tag;

@synthesize value;

@synthesize length;

@end



The analytical data structure


//

// LPositon.h

// CashBox

//

// Created by ZKF on 13-11-18.

// Copyright (c) In 2013 ZKF. All rights reserved.

//


#import <Foundation/Foundation.h>


@interface LPositon : NSObject

@property (nonatomic,assign) NSInteger vl;

@property (nonatomic,assign) NSInteger position;

@end

//

// LPositon.m

// CashBox

//

// Created by ZKF on 13-11-18.

// Copyright (c) In 2013 ZKF. All rights reserved.

//


#import "LPositon.h"


@implementation LPositon

@synthesize vl;

@synthesize position;

@end



Parsing code


//

// SAXUnionFiled55Utils.h

// CashBox

//

// Created by ZKF on 13-11-18.

// Copyright (c) In 2013 ZKF. All rights reserved.

//


#import <Foundation/Foundation.h>

#import "TLV.h"

#import "LPositon.h"

@interface TLVParseUtils : NSObject

-(NSArray*) saxUnionField55_2List:(NSString*) hexfiled55;

@end

//

// SAXUnionFiled55Utils.m

// CashBox

//

// Created by ZKF on 13-11-18.

// Copyright (c) In 2013 ZKF. All rights reserved.

//


#import "TLVParseUtils.h"


@implementation TLVParseUtils


/**

* UnionPay 55 domain

*

* The domain will be different according to the transaction types contain different subfields. Specific data processing center in accepting China UnionPay and the issuer to transfer the applicable to IC card transactions, but they are not any modification and processing.

* In order to adapt to the ever-changing needs of subdomain

* , This domain using TLV (tag-length-value) representation, namely each subdomain by tag label (T), subdomain value length (L) and subdomain value (V).

* Tag tag's attribute is bit

* , Represented by 16 m, accounting for 1 ~ 2 bytes in length. For example, " 9F33" as a occupies two bytes of tag tags. " 95" as an occupying one byte tag Tags

* . If the first byte of tag Tags

* (Note: byte sort direction is from left to right, the first byte is the leftmost byte. Bit collation similarly.) After the five bit for " 11111", the tag occupies two bytes

* , For example, " 9F33"; otherwise accounted for a byte, such as " 95". Subdomain length (L itself) properties for bit, accounting for 1 ~ 3 bytes in length. The specific coding rules are as follows: a)

* When the L field to the left of the left most bit bytes of bit (bit8) 0, said the L field of a byte, the subsequent 7 bit (bit7 ~ Bit1) denote subdomains value of length;,

* The binary number representation subdomain value the length of the decimal number

* . For example, a domain value occupies 3 bytes, so the subdomain value length expressed as " 00000011". So, if the subdomain value the length of the 1~127

* Byte, the L field itself is only one byte. b)

* When the L field to the left of the left most bit bytes of bit (bit8) 1, said that the L field is more than accounted for one byte, so it occupies several bytes from the leftmost byte 7 subsequent bit

* (bit7 ~ Bit1) decimal to produce value said. For example, if the leftmost byte is 10000010, said L field except the byte, and there are two bytes. The following byte

* Decimal to produce value denote subdomains value length. For example, if the L field is " 100000011111, 1111" said the subdomain value 255 bytes.

* So, if the subdomain value in length between 128 ~ 255 bytes, so the L field itself up to two bytes

*

* @return tlv NSArray

*/

-(NSArray*) saxUnionField55_2List:(NSString*) hexfiled55

{

if (nil == hexfiled55) {

}

return [[[self builderTLV:hexfiled55] retain] autorelease];

}


-(NSArray*) builderTLV:(NSString *)hexString

{

NSMutableArray *arr = [[[NSMutableArray alloc] initWithCapacity:10] autorelease];

int position = 0;

while (position != hexString.length) {

NSString * _hexTag = [self getUnionTag:hexString P:position];

NSLog(@"hex tag :%@",_hexTag);

if ([_hexTag isEqualToString:@"00"] || [_hexTag isEqualToString:@"0000"]) {

position += _hexTag.length;

continue;

}

position += _hexTag.length;

LPositon *l_position = [[[self getUnionLAndPosition:hexString P:position] retain] autorelease];;

int _vl = l_position.vl;

NSLog(@"value len :%i",_vl);

position = l_position.position;

NSString* _value = [hexString substringWithRange:NSMakeRange(position, _vl * 2)];

NSLog(@"value :%@",_value);

position = position + _value.length;

TLV *tlv = [[[TLV alloc] init] autorelease];

tlv.tag = _hexTag;

tlv.value = _value;

tlv.length = _vl;

[arr addObject:tlv];

}

return arr;

}


int ChangeNum(char * str,int length)

{

char revstr[128] = {0}; //According to the sixteen hexadecimal string length, here don't cross array

int num[16] = {0};

int count = 1;

int result = 0;

strcpy(revstr,str);

for (int i = length - 1;i >= 0;i--)

{

if ((revstr[i] >= '0') && (revstr[i] <= '9')) {

num[i] = revstr[i] - 48;//Character 0 is 48 ASCIIvalue

} else if ((revstr[i] >= 'a') && (revstr[i] <= 'f')) {

num[i] = revstr[i] - 'a' + 10;

} else if ((revstr[i] >= 'A') && (revstr[i] <= 'F')) {

num[i] = revstr[i] - 'A' + 10;

} else {

num[i] = 0;

}

result = result+num[i]*count;

count = count*16;//Sixteen hexadecimal (if it is the octal here is multiplied by 8)

}

return result;

}


-(LPositon *)getUnionLAndPosition:(NSString *)hexString P:(NSInteger) position

{

NSString *firstByteString = [hexString substringWithRange:NSMakeRange(position, 2)];

int i = ChangeNum((char *)[firstByteString UTF8String],2);

NSString * hexLength = @"";

if (((i >> 7) & 1) == 0) {

hexLength = [hexString substringWithRange:NSMakeRange(position, 2)];

position = position + 2;

} else {

// When the left side of the bit bit is 1, 7bit is obtainedvalue,

int _L_Len = i & 127;

position = position + 2;

hexLength = [hexString substringWithRange:NSMakeRange(position, _L_Len * 2)];

// Position said the first byte, later said the number of bytes to represent the Value behindvalue

position = position + _L_Len * 2;

}

LPositon *LP = [[[LPositon alloc] init] autorelease];

LP.vl = ChangeNum((char *)[hexLength UTF8String],2);

LP.position = position;

return LP;

}


-(NSString*) getUnionTag:(NSString* )hexString P:(NSInteger) position

{

NSString* firstByte = [hexString substringWithRange:NSMakeRange(position, 2)];

int i = ChangeNum((char *)[firstByte UTF8String],2);

if ((i & 0x1f) == 0x1f) {

return [hexString substringWithRange:NSMakeRange(position, 4)];

} else {

return [hexString substringWithRange:NSMakeRange(position, 2)];

}

}

@end

Test code

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

TLVParseUtils*s = [[[TLVParseUtils alloc] init] autorelease];

NSArray *tlvArr = [s saxUnionField55_2List:@"9F260879CC8EC5A09FB9479F2701809F100807010199A0B806019F3704000000009F360201C2950500001800009A031205089C01609F02060000000000005F2A02015682027D009F1A0201569F03060000000000009F3303E0F0F09F34036003029F3501119F1E0832303033313233318405FFFFFFFFFF9F090220069F4104000000019F74064543433030319F631030313032303030308030303030303030"];

NSLog(@"tlv arr :%@",tlvArr);

}


Access to the source code to the HTTPS://github.com/zhukefeng-ios/TVLParse

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Osmond at December 12, 2013 - 6:44 PM