2014-12-12 2 views
0

NSData에 대한 다음 범주 메서드가 있습니다. 주어진 인덱스에서 비트 필드를 추출하여 NSNumber로 반환하려고합니다. 나는 그것을 완벽하게 모든 긍정적 인 일을해야하지만 음수와 함께 작동하도록해야합니다. 다음과 같이Objective-C 음수 16 진수 값

내 구현 보이는 :

#import <Foundation/Foundation.h> 
@interface NSData (ExternalDevices) 
@end 
@implementation NSData (ExternalDevices) 
- (NSNumber *)extractLittleEndianBitFieldAtIndex:(int)index forLength:(int)length 
{ 

    //This function has limitations on the "length" parameter that are not yet know/defined 
    //These limitations are due to the max size of "NSInteger intData" defined below 

    int first_byte = index/8;        //Index of the first byte containing this bit field 
    int last_byte = (length+index-1)/8;       //Index of the last byte containing this bit field 
    int byte_length = last_byte - first_byte + 1;     //number of bytes containing this bit field 

    Byte *byteArray = (Byte*)malloc(byte_length); 
    memcpy(byteArray, [[self subdataWithRange:NSMakeRange(first_byte, byte_length)] bytes], byte_length); 

    NSInteger intData = *((NSInteger *)byteArray); 

    free(byteArray); 
    return [NSNumber numberWithInt:intData]; 
} 

+ (NSData *)dataFromHexString:(NSString *)string 
{ 
    string = [string lowercaseString]; 
    NSMutableData *data= [NSMutableData new]; 
    unsigned char whole_byte; 
    char byte_chars[3] = {'\0','\0','\0'}; 
    int i = 0; 
    NSUInteger length = string.length; 
    while (i < length-1) { 
     char c = [string characterAtIndex:i++]; 
     if (c < '0' || (c > '9' && c < 'a') || c > 'f') 
      continue; 
     byte_chars[0] = c; 
     byte_chars[1] = [string characterAtIndex:i++]; 
     whole_byte = strtol(byte_chars, NULL, 16); 
     [data appendBytes:&whole_byte length:1]; 

    } 

    return data; 
} 
@end 



@interface Testing:NSObject 
@end 
@implementation Testing 


- (instancetype)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     { 
      NSData *data = [NSData dataFromHexString:@"e30b"]; 
      NSLog(@"%@ should be 3043", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]); 
     } 

     { 
      NSData *data = [NSData dataFromHexString:@"46e0"]; 
      NSLog(@"%@ should be -8122", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]); 
     } 

     { 
      NSData *data = [NSData dataFromHexString:@"f208"]; 
      NSLog(@"%@ should be 2290", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]); 
     } 

     { 
      NSData *data = [NSData dataFromHexString:@"10e6"]; 
      NSLog(@"%@ should be -6640", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]); 
     } 

     { 
      NSData *data = [NSData dataFromHexString:@"018900"]; 
      NSLog(@"%@ should be 137", [data extractLittleEndianBitFieldAtIndex:8 forLength:16]); 
     } 
    } 
    return self; 
} 

@end 

int main(int argc, char *argv[]) { 
    @autoreleasepool { 
     [[Testing alloc] init]; 
    } 
} 

다음 웹 사이트는 항상 내가 INT16에서 원하는 결과를 얻을 것 같다 - 리틀 엔디안 (BA)은 중요한

http://www.scadacore.com/field-applications/miscellaneous/online-hex-converter.html

이지만 내가 일하는 모든 전화 번호가 INT16이 될 수는 없음을 유의하십시오.

+0

무엇이 작동하지 않습니까 ?? –

답변

1

전화 번호 :

NSInteger intData = *((NSInteger *)byteArray); 

두 가지 이유에 대한 주요 문제 :

  1. byteArray은 (이상, 이하 가능성이) 짧아 질 수있는 NSInteger보다는 당신이 쓰레기를 읽고 끝낼 수 있습니다. 예 : byteArray이 예제에서와 같이 2 바이트이고 NSInteger이 4 바이트 (64 비트)이면 2 바이트의 가비지를 읽습니다.

  2. 부호가있는 값을 변환하는 경우 값을 부호 확장해야합니다. 즉 부호 비트를 더 높은 미사용 비트로 복제해야합니다. 예 : 부호있는 16 비트 필드를 32 비트 부호있는 값으로 변환하는 경우 상위 16 비트는 16 비트 값의 최상위 비트를 복제해야하므로 0x7000 -> 0x00007000 및 0x8000 -> 0xFFFF8000 .

이러한 문제를 처리하는 알고리즘이 필요합니다. 마스킹 (and'ing), oring 및 shifting을 사용하여 한 번에 한 바이트 씩 변환하는 것이 더 쉽습니다.

HTH