Re: Hex to NSString or NSData
Re: Hex to NSString or NSData
- Subject: Re: Hex to NSString or NSData
- From: Andreas Grosam <email@hidden>
- Date: Sat, 9 May 2009 19:50:41 +0200
While there are many ways to skin a cat, I would use this plain C
function to do the actual conversion:
int hexDigitToInt(char d)
{
int result;
switch (d) {
case '0': result = 0; break;
case '1': result = 1; break;
case '2': result = 2; break;
case '3': result = 3; break;
case '4': result = 4; break;
case '5': result = 5; break;
case '6': result = 6; break;
case '7': result = 7; break;
case '8': result = 8; break;
case '9': result = 9; break;
case 'a': result = 10; break;
case 'b': result = 11; break;
case 'c': result = 12; break;
case 'd': result = 13; break;
case 'e': result = 14; break;
case 'f': result = 15; break;
case 'A': result = 10; break;
case 'B': result = 11; break;
case 'C': result = 12; break;
case 'D': result = 13; break;
case 'E': result = 14; break;
case 'F': result = 15; break;
default:
result = 0xFF;
}
return result;
}
Although it might look ugly, this is one of the fasted methods using
standard C that converts a hex digit (nibble) to an int (2 machine
instructions).
Since you need two such function calls to convert a byte to an integer
code, you need to call it two times:
int hexToInt(char s[2]) {
return (hextDigitToInt(s[0]) << 4) | hexDigitToInt(s[1]);
}
To convert a NSString, you need it as an ASCII string decoded c-string
and pass it in a loop to this function.
Please: include code to check for errors
What that single "code" or possibly a sequence of codes mean as a
character depends on the encoding. You need to encode it properly.
Regards
Andreas
On May 9, 2009, at 10:43 AM, Gwynne Raskind wrote:
On May 8, 2009, at 11:34 PM, Mr. Gecko wrote:
And how could that make @"68656c6c6f" into @"hello"?
Thinking this will help you understand what I'm trying to do...
On May 8, 2009, at 10:23 PM, Jerry Krinock wrote:
On 2009 May 08, at 20:16, Mr. Gecko wrote:
Hello, I have a string with hex and I want to ether make it into
a NSData or NSString. How might I do that.
-[NSString initWithBytes:length:encoding:]
If you need to scan 32-bit or 64-bit hex numbers, check out:
<http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSScanner_Class/Reference/Reference.html
>
DISCLAIMER: ALL CODE WRITTEN IN MAIL AND UNTESTED (Well, that's not
quite true, I did test the long hex string function out of
curiosity :) ).
Also note: All this code does simplistic error handling by throwing
exceptions. You may want to just return nils or zeroes on failure.
- (uint32_t)unsignedIntFromHexString:(NSString *)str
{
NSScanner *scanner = [NSScanner scannerWithString:str];
uint32_t result = 0;
if (![scanner scanHexInt:&result])
{
[NSException raise:NSInvalidArgumentException format:@"No hex
number found in %@.", str];
}
return result;
}
- (uint64_t)unsignedLongLongFromHexString:(NSString *)str
{
NSScanner *scanner = [NSScanner scannerWithString:str];
uint64_t result = 0;
if (![scanner scanHexLongLong:&result])
{
[NSException raise:NSInvalidArgumentException format:@"No hex
number found in %@.", str];
}
return result;
}
If you need to scan arbitarily-sized hex strings, you'll need
something more complex:
char hexCharToNibble(char nibble)
{
// 0 - 9
if (nibble >= '0' && nibble <= '9')
return (nibble - '0') & 0x0F;
// A - F
else if (nibble >= 'A' && nibble <= 'F')
return (nibble - 'A' + 10) & 0x0F;
// a - f
else if (nibble >= 'a' && nibble <= 'f')
return (nibble - 'a' + 10) & 0x0F;
// Not a hex digit
else
[NSException raise:NSInvalidArgumentException format:@"Character
%c not a hex digit.", nibble];
return 0; // keep compiler happy
}
char hexCharsToByte(char highNibble, char lowNibble)
{
return (hexCharToNibble(highNibble) << 4) |
hexCharToNibble(lowNibble);
}
- (NSString *)interpretHexString:(NSString *)str asEncoding:
(NSStringEncoding)encoding
{
// Get the ASCII data out of the string - hexadecimal numbers are
expressed in pure ASCII
NSData *asciiData = [str dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
const char *chars = (char *)[asciiData bytes]; // chars is NOT NULL-
terminated!
if (([asciiData length] % 2) != 0)
{
// There were an odd number of hex characters in the source string.
return nil;
}
// Set up data storage for the raw bytes we interpret
NSMutableData *dataInEncoding = [NSMutableData dataWithLength:
[asciiData length] / 2];
char *dataChars = [dataInEncoding mutableBytes];
// Loop over the ASCII numbers
for (NSUInteger i = 0; i < [asciiData length]; i += 2)
{
// Interpret each pair of hexadecimal characters into a byte.
*dataChars++ = hexCharsToByte(chars[i], chars[i + 1]);
}
// Create an NSString from the interpreted bytes, using the passed
encoding.
// NSString will return nil (or throw an exception) if the bytes we
parsed can't be
// represented in the given encoding.
return [[[NSString alloc] initWithData:dataInEncoding
encoding:encoding] autorelease];
}
It's very likely there's a faster/better/cleaner/whatever way to do
this, but this does work :).
-- Gwynne, Daughter of the Code
"This whole world is an asylum for the incurable."
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden