mirror of
https://github.com/zhigang1992/transshift.git
synced 2026-06-11 08:49:31 +08:00
161 lines
3.7 KiB
Objective-C
161 lines
3.7 KiB
Objective-C
//
|
|
// Bencoding.m
|
|
// TransmissionRPCClient
|
|
//
|
|
// Created by Alexey Chechetkin on 19.07.15.
|
|
// Copyright (c) 2015 Alexey Chechetkin. All rights reserved.
|
|
//
|
|
|
|
#import "Bencoding.h"
|
|
|
|
#define UTF8_ACCEPT 0
|
|
#define UTF8_REJECT 1
|
|
#define ISDIGIT(c) ( ((c) >= '0' && (c) <= '9') )
|
|
#define DATA_ALWAYS_UTF8 0
|
|
|
|
|
|
static char *p, *p0;
|
|
static NSUInteger dataLength;
|
|
|
|
id decodeNextObject(void); // forward declaration
|
|
|
|
static const uint8_t utf8d[] = {
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
|
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
|
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
|
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
|
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
|
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
|
|
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
|
|
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
|
|
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
|
};
|
|
|
|
|
|
BOOL isUTF8(char *str, int len)
|
|
{
|
|
int type, state = UTF8_ACCEPT;
|
|
|
|
for ( int i = 0; i < len; i++)
|
|
{
|
|
type = utf8d[(uint8_t)str[i]];
|
|
state = utf8d[256 + state * 16 + type];
|
|
|
|
if (state == UTF8_REJECT)
|
|
break;
|
|
}
|
|
|
|
return state == UTF8_ACCEPT;
|
|
}
|
|
|
|
|
|
long long decodeInt()
|
|
{
|
|
p0 = p;
|
|
|
|
while ( *p != 'e' && *p != ':' ) p++;
|
|
|
|
*p++ = '\0';
|
|
|
|
return atoll(p0);
|
|
}
|
|
|
|
id decodeData()
|
|
{
|
|
// get data length
|
|
int count = (int)decodeInt();
|
|
|
|
// test data if it's a string
|
|
if( isUTF8(p, count) )
|
|
{
|
|
p0 = p;
|
|
p += count;
|
|
char c = *p;
|
|
*p = '\0';
|
|
NSString *str = [NSString stringWithCString:p0 encoding: NSUTF8StringEncoding];
|
|
*p = c;
|
|
return str;
|
|
}
|
|
|
|
NSData *data = [NSData dataWithBytes:p length:count];
|
|
p += count;
|
|
|
|
return data;
|
|
}
|
|
|
|
NSString* decodeString()
|
|
{
|
|
int count = (int)decodeInt();
|
|
|
|
p0 = p;
|
|
p += count;
|
|
char c = *p;
|
|
*p = '\0';
|
|
NSString *str = [NSString stringWithCString:p0 encoding: NSUTF8StringEncoding];
|
|
*p = c;
|
|
return str;
|
|
}
|
|
|
|
NSArray* decodeArray()
|
|
{
|
|
NSMutableArray *list = [NSMutableArray array];
|
|
|
|
while ( *p != 'e' )
|
|
[list addObject:decodeNextObject()];
|
|
|
|
p++;
|
|
return list;
|
|
}
|
|
|
|
NSDictionary *decodeDictionary()
|
|
{
|
|
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
|
|
|
while ( *p != 'e' )
|
|
dict[ decodeString() ] = decodeNextObject();
|
|
|
|
p++;
|
|
return dict;
|
|
}
|
|
|
|
id decodeNextObject()
|
|
{
|
|
char c = *p++;
|
|
|
|
if( c == 'i' )
|
|
return @(decodeInt());
|
|
|
|
if( c == 'l' )
|
|
return decodeArray();
|
|
|
|
if( c == 'd' )
|
|
return decodeDictionary();
|
|
|
|
if( ISDIGIT(c) )
|
|
{
|
|
p--;
|
|
return DATA_ALWAYS_UTF8 ? decodeString() : decodeData();
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
id decodeObjectFromBencodedData(NSData *data)
|
|
{
|
|
// alloc buffer for duplicated data
|
|
dataLength = data.length;
|
|
char *mp = malloc(dataLength);
|
|
p = mp;
|
|
|
|
[data getBytes:p length:dataLength];
|
|
id obj = decodeNextObject();
|
|
|
|
free(mp);
|
|
return obj;
|
|
}
|