views:

270

answers:

3

Hi!

is there something like Python's unhexlify for objc / cocoa?

>>> from binascii import unhexlify
>>> help(unhexlify)
Help on built-in function unhexlify in module binascii:

unhexlify(...)
a2b_hex(hexstr) -> s; Binary data of hexadecimal representation.

hexstr must contain an even number of hex digits (upper or lower case).
This function is also available as "unhexlify()"

>>> unhexlify('abc123d35d')
'\xab\xc1#\xd3]'
+3  A: 

Edit: I didn't grok what unhexlify does. I still don't grok why it might be useful (commenters?).

You would have to pick off the hex characters two at a time, convert them to an int, and spit out the characters.

char *hex = "abc123d35d";

NSData *data = [NSData dataWithBytesNoCopy:hex length:strlen(hex)];

NSInputStream *input = [NSInputStream inputStreamWithWithData:data];
NSOutputStream *output = [NSOutputStream outputStreamToMemory];

[input open];
[output open];

uint8_t buffer[2], result;

while ([input hasBytesAvailable]) {
   [input read:buffer maxLength:2];

   if (sscanf(buffer, "%x", &result) != 1)
       // die

   if (![output hasSpaceAvailable])
       // die

   [output write:&result length:1];
}

[input close];
[output close];

id output = [output propertyForKey:NSStreamDataWrittenToMemoryStreamKey];

This solution would only really be useful if you were reading a fair amount of data.

But as others have said, there may be a better way to do what you're trying to do that doesn't involve unhexlify. By way of analogy, there's no built-in way to read a YAML file, but reading a plist is a one-liner, and they can both do roughly the same things.

Frank Schmitt
Does this assume that `hex` is a value that fits into `int` ?
stefanB
Question *appears* to want to scan a char[2*n] into a byte[n], but it's not all that clear...
ephemient
What I need to accomplish is to get the binary data of the hexadecimal representation.
versatilemind
@versatilemind: That's not clear enough. Arbitrary-length hex/data, or only fixed size?
ephemient
@ephemient: only fixed size.
versatilemind
-1: this (certainly the first version) doesn't `unhexlify` a string of hex digits to a binary string, it converts the whole string to a single integer, which is a completely different thing.
mhawke
+1  A: 

Here is some very rough, naive, inefficient, and insecure code that implements unhexlify. It's main limitation is that it doesn't check that hexstr contains only hex digits. But this should be enough to get you started.

#include <stdio.h>
#include <string.h>
#include <assert.h>

void unhexlify(const char *hexstr, char *binstr)
{
    char *p, *q;

    assert(strlen(hexstr) > 0);
    assert(strlen(hexstr) % 2 == 0);    // even length

    for (p=hexstr,q=binstr; *p; p+=2,q++)
        sscanf(p, "%2x", q);
    *q = '\0';
}

int main()
{
    char *s = "abc123d35d";
    char buf[100];

    unhexlify(s, buf);
    printf(buf);
}

Call this unhexlify.c, then running this program:

$ ./unhexlify | hexdump -C
00000000  ab c1 23 d3 5d                                    |..#.]|

EDIT: A more robust example of Python's unhexlify is of course to be found in the actual Python source code for the binascii module which can be viewed here. Look at the to_int() and binascii_unhexlify() functions.

mhawke
It seems to be quite a bit work to get this done. I was hoping for a build in function like in python ...
versatilemind
Well, you now have a very simple `unhexlify()` function. Just be aware of its limitations and handle these if required. Or, you can take the example from the Python source which will be more robust. This is not complicated to implement if you put in a little effort.
mhawke
Thank you for this.
versatilemind
A: 

How about just the strtol function?

It'd be something like this:

NSString * abc = @"abc";
NSInteger intVal = strtol([abc cStringUsingEncoding:NSASCIIStringEncoding], nil, 16);
NSLog(@"%lld", intVal);
//prints 2748
Dave DeLong
Equivalent to Frank's earlier answer. OP has so far not communicated the requirements very clearly to answerers...
ephemient