Convert NSString that represents HEX value to hex (#"0d" to 0x0d) [duplicate] - ios

This question already has answers here:
NSString (hex) to bytes
(7 answers)
Closed 5 years ago.
I want to convert ObjectiveC NSString, that contains for example string "0d" to hex value 0x0d. What's the easiest way to achieve that?
Example:
NSString *str = #"50";
unsigned char mac[1];
mac[0] = 0x50; //<- how to set mac[0] to 0x50 from "str" string?

- (NSData *)dataFromHexString {
const char *chars = [self UTF8String];
int i = 0, len = self.length;
NSMutableData *data = [NSMutableData dataWithCapacity:len/2];
char byteChars[3] = {chars[0],chars[1],'\0'};
unsigned long wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
return data;
}

Related

Convert string to byte array in iOS

I have a string variable in iOS and I would like to convert that to a character array and then to a hex bytes like 0xD6, 0xD6 etc.
It will be great if there is a library in Objective-C that I can use for this
swift 4
string to byte:
let strChar = "A"
let data1 = [UInt8](self.strChar.utf8)
may be answer is here:
string to chars:
NSString *s = #"Some string";
const char *c = [s UTF8String];
chars to hex:
- (NSData *)dataFromHexString {
const char *chars = [self UTF8String];
int i = 0, len = self.length;
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}
reference:NSString (hex) to bytes

Best way to get length of UTF-8 string in bytes?

I want to get a cString from NSString.
So we used c​String​Using​Encoding:​ method.
However, the return value of the c​String​Using​Encoding:​ method is not guaranteed.
(Apple's doc: The returned C string is guaranteed to be valid only until either the receiver is freed.)
So Apple recommends the get​CString:​max​Length:​encoding: method.
I want to pass the exact length to maxLength.
Example 1)
NSString *tmp = #"中日韓" // cString 9bytes
char *buffer = new tmp[9 + 1];
[tmp getCString:buffer maxLength:9+1 encoding:NSUTF8String​Encoding];
Example 2)
NSString *tmp = #"中日韓123" // cString 12bytes
char *buffer = new tmp[12 + 1];
[tmp getCString:buffer maxLength:12+1 encoding:NSUTF8String​Encoding];
Is there a way to know the lengths of 9 and 12 in the example above?
// Add one because this doesn't include the NULL
NSUInteger maxLength = [string maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
You can use cStringUsingEncoding to get the length. If you need the resulting char * to live longer than tmp, then simply copy the C-string:
NSString *tmp = #"中日韓" // cString 9bytes
const char *cStr = [tmp cStringUsingEncoding:NSUTF8StringEncoding];
size_t len = strlen(cStr);
char *buffer = new tmp[len + 1];
strcpy(buffer, cStr);

How do I convert an NSString of hex numbers (#"54 2E") to a byte array? [duplicate]

Is there any method in Objective-C that converts a hex string to bytes? For example #"1156FFCD3430AA22" to an unsigned char array {0x11, 0x56, 0xFF, ...}.
Fastest NSString category implementation that I could think of (cocktail of some examples):
- (NSData *)dataFromHexString {
const char *chars = [self UTF8String];
int i = 0, len = self.length;
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}
It is close to 8 times faster than wookay's solution. NSScanner is quite slow.
#interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
#end
#implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= self.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [self substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
#end
/// example
unsigned char bytes[] = { 0x11, 0x56, 0xFF, 0xCD, 0x34, 0x30, 0xAA, 0x22 };
NSData* expectedData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSLog(#"data %#", [#"1156FFCD3430AA22" hexToBytes]);
NSLog(#"expectedData isEqual:%d", [expectedData isEqual:[#"1156FFCD3430AA22" hexToBytes]]);
The scanHexInt: and similar methods of NSScanner might be helpful in doing what you want, but you'd probably need to break the string up into smaller chunks first, in which case doing the translation manually might be simpler than using NSScanner.
Not in the way you are doing it. You'll need to write your own method to take every two characters, interpret them as an int, and store them in an array.
Modified approach,
/* Converts a hex string to bytes.
Precondition:
. The hex string can be separated by space or not.
. the string length without space or 0x, must be even. 2 symbols for one byte/char
. sample input: 23 3A F1 OR 233AF1, 0x23 0X231f 2B
*/
+ (NSData *) dataFromHexString:(NSString*)hexString
{
NSString * cleanString = [Util cleanNonHexCharsFromHexString:hexString];
if (cleanString == nil) {
return nil;
}
NSMutableData *result = [[NSMutableData alloc] init];
int i = 0;
for (i = 0; i+2 <= cleanString.length; i+=2) {
NSRange range = NSMakeRange(i, 2);
NSString* hexStr = [cleanString substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
unsigned char uc = (unsigned char) intValue;
[result appendBytes:&uc length:1];
}
NSData * data = [NSData dataWithData:result];
[result release];
return data;
}
/* Clean a hex string by removing spaces and 0x chars.
. The hex string can be separated by space or not.
. sample input: 23 3A F1; 233AF1; 0x23 0x3A 0xf1
*/
+ (NSString *) cleanNonHexCharsFromHexString:(NSString *)input
{
if (input == nil) {
return nil;
}
NSString * output = [input stringByReplacingOccurrencesOfString:#"0x" withString:#""
options:NSCaseInsensitiveSearch range:NSMakeRange(0, input.length)];
NSString * hexChars = #"0123456789abcdefABCDEF";
NSCharacterSet *hexc = [NSCharacterSet characterSetWithCharactersInString:hexChars];
NSCharacterSet *invalidHexc = [hexc invertedSet];
NSString * allHex = [[output componentsSeparatedByCharactersInSet:invalidHexc] componentsJoinedByString:#""];
return allHex;
}
First attempt in Swift 2.2:
func hexStringToBytes(hexString: String) -> NSData? {
guard let chars = hexString.cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
var i = 0
let length = hexString.characters.count
let data = NSMutableData(capacity: length/2)
var byteChars: [CChar] = [0, 0, 0]
var wholeByte: CUnsignedLong = 0
while i < length {
byteChars[0] = chars[i]
i+=1
byteChars[1] = chars[i]
i+=1
wholeByte = strtoul(byteChars, nil, 16)
data?.appendBytes(&wholeByte, length: 1)
}
return data
}
Or, as an extension on String:
extension String {
func dataFromHexString() -> NSData? {
guard let chars = cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
var i = 0
let length = characters.count
let data = NSMutableData(capacity: length/2)
var byteChars: [CChar] = [0, 0, 0]
var wholeByte: CUnsignedLong = 0
while i < length {
byteChars[0] = chars[i]
i+=1
byteChars[1] = chars[i]
i+=1
wholeByte = strtoul(byteChars, nil, 16)
data?.appendBytes(&wholeByte, length: 1)
}
return data
}
}
This is a continuous work-in-progress, but appears to work well so far.
Further optimizations and a more in-depth discussion can be found on Code Review.
Several solution is returned wrong value if the string like this
"DBA"
The correct data for "DBA" string is "\x0D\xBA" (int value : 3514)
if you got a data is not like this "\x0D\xBA" it mean you got a wrong byte because the value will be different, for example you got data like this "\xDB\x0A" the int value is 56074
Here is rewrite the solution:
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [#"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}

Trouble converting NSData to int

I have an NSData object that contains just <64> which is supposed to represent the int 100
How can I convert this NSData to an int?
I can convert it to it's Chr equivalent d using
NSString *string = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
but I need the Dec equivalent of 100
Thanks
<64> means that the NSData object contains a single byte with the value 0x64 = 100,
so the following should work;
const uint8_t *bytes = [data bytes]; // pointer to the bytes in data
int value = bytes[0]; // first byte
int *b = (int *)data.bytes;
printf("%d",*b); //prints 100
Below logic converts NSData to integer perefctly. Length of bytes does not matter. It just works.
NSData *data;
NSString *stringData = [data description];
stringData = [stringData substringWithRange:NSMakeRange(1, [stringData length]-2)];
unsigned dataAsInt = 0;
NSScanner *scanner = [NSScanner scannerWithString: stringData];
[scanner scanHexInt:& dataAsInt];

SHA1 for Specific String in iOS

According to my requirement:
The input string has to be converted into Byte Values.
Each character of string , which are 16 bit values , has to be converted to low 8 bits.
The Sha1 is then computed over the byte Array.
The resulting SHA-1 is converted into a 40 character string.
I know how to convert a string into SHA1 , but the rest of part is a bit gloomy to me.
I have been able to do the last two steps.
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
NSData *dataString = [yourString dataUsingEncoding: NSUTF8StringEncoding];
if (CC_SHA1([dataString bytes], [dataString length], digest)) {
//Sha1 is calculated & stored in digest.
}
Any help will be appreciated.
I have created this function , which works fine according to your requirement . You just have to input a string.
#import <CommonCrypto/CommonDigest.h>
- (NSString *)calculateSHA:(NSString *)yourString
{
const char *ptr = [yourString UTF8String];
int i =0;
int len = strlen(ptr);
Byte byteArray[len];
while (i!=len)
{
unsigned eachChar = *(ptr + i);
unsigned low8Bits = eachChar & 0xFF;
byteArray[i] = low8Bits;
i++;
}
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(byteArray, len, digest);
NSMutableString *hex = [NSMutableString string];
for (int i=0; i<20; i++)
[hex appendFormat:#"%02x", digest[i]];
NSString *immutableHex = [NSString stringWithString:hex];
return immutableHex;
}
Then you just have to call the above method.
[self calculateSHA:yourString];
NSData *dataString = [yourString dataUsingEncoding: NSUTF8StringEncoding];
converts the string to UTF-8 bytes, e.g. "é" = Unicode 00E9 is converted to the two bytes C3 A9, and "€" = Unicode 20AC is converted to three bytes E2 82 AC.
If your requirement is to "truncate" the Unicode characters to the lower 8 bits, you have to do this "manually", I do not know a built-in encoding that could be used for that:
NSMutableData *dataString = [NSMutableData dataWithLength:[yourString length]];
uint8_t *dataBytes = [dataString mutableBytes];
for (NSUInteger i = 0; i < [yourString length]; i++) {
// assigning the character to a uint_8 truncates to the lower 8 bit:
dataBytes[i] = [yourString characterAtIndex:i];
}
Based on your code snippet, you want to do something like:
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
NSData *dataString = [yourString dataUsingEncoding: NSUTF8StringEncoding];
NSMutableString *outString;
if (CC_SHA1([dataString bytes], [dataString length], digest)) {
for (int i=0;i<CC_SHA1_DIGEST_LENGTH;i++) {
[outString appendFormat:#"%02x", digest[i]];
}
}
Where outString will be your 40-char string.
Here's an NSString category for creating a SHA1 hash of an NSString.
Creating SHA1 Hash from NSString

Resources