1

What's an equivalent of the PHP function pack:

pack('H*', '01234567989abcdef' );

in Objective-C?

Kamchatka
  • 3,597
  • 4
  • 38
  • 69

2 Answers2

2

Assuming that you want the results as an NSData, you can use a function similar to this:

NSData *CreateDataWithHexString(NSString *inputString)
{
    NSUInteger inLength = [inputString length];

    unichar *inCharacters = alloca(sizeof(unichar) * inLength);
    [inputString getCharacters:inCharacters range:NSMakeRange(0, inLength)];

    UInt8 *outBytes = malloc(sizeof(UInt8) * ((inLength / 2) + 1));

    NSInteger i, o = 0;
    UInt8 outByte = 0;
    for (i = 0; i < inLength; i++) {
        UInt8 c = inCharacters[i];
        SInt8 value = -1;

        if      (c >= '0' && c <= '9') value =      (c - '0');
        else if (c >= 'A' && c <= 'F') value = 10 + (c - 'A');
        else if (c >= 'a' && c <= 'f') value = 10 + (c - 'a');            

        if (value >= 0) {
            if (i % 2 == 1) {
                outBytes[o++] = (outByte << 4) | value;
                outByte = 0;
            } else if (i == (inLength - 1)) {
                outBytes[o++] = value << 4;
            } else {
                outByte = value;
            }

        } else {
            if (o != 0) break;
        }        
    }

    return [[NSData alloc] initWithBytesNoCopy:outBytes length:o freeWhenDone:YES];
}
iccir
  • 5,078
  • 2
  • 22
  • 34
  • Thanks this works. There is nothing doing that in the Cocoa libraries already? – Kamchatka Jan 21 '12 at 04:48
  • Also it looks like you're leaking `inCharacters` – Kamchatka Jan 21 '12 at 04:48
  • inCharacters is allocated using alloca, which allocates space on the stack rather than the heap. If you are dealing with large strings and don't feel comfortable advancing the stack pointer that far, you probably want to change inCharacters to a malloc() and free() it before the return. – iccir Jan 21 '12 at 04:53
  • Oops, didn't see your first reply. It depends on your use case - If the hex value is short enough that you can store it an unsigned int or unsigned long long, there is -[NSScanner scanHexLongLong:]. If you need to do additional extraction, you could use the wscanf() family on -[NSString characters] – iccir Jan 21 '12 at 04:56
  • oops sorry for alloca() of course that makes sense. Looks like your solution works well. – Kamchatka Jan 22 '12 at 04:31
  • @iccir can you translate this in Swift please. – Qadir Hussain Oct 22 '14 at 06:51
  • No, sorry. I haven't touched Swift yet. – iccir Oct 23 '14 at 00:14
  • 1
    This will not work for hex strings with odd-numbers. You need to change the else clause to { outByte = value; if ( i == inLength - 1 ) // this is going to be the last iteration { outBytes[o++] = outByte << 4; } } otherwise you're missing data. – DrMickeyLauer Sep 17 '15 at 15:11
1

See the -scanHex... methods of NSScanner.

NSResponder
  • 16,861
  • 7
  • 32
  • 46