0

I am trying to convert an NSString to a ResType, as defined below in MacTypes.h.

FourCharCode // A 32-bit value made by packing four 1 byte characters together
typedef FourCharCode ResType;

I think I could use [aString getCharacters:range:], but is there a more straight forward way to make this conversion?

After trying suggestions from David, here is some further information.

I am using GTResourceFork, a Cocoa wrapper for accessing resource forks. The method I am calling is: - (NSArray *)usedResourcesOfType: (ResType)type;

If I hard code a value of 'RTF ', I get the results I expect. I cannot figure out how to convert an NSString containing "RTF " to the hard-coded value. I created a test case using NSString's getCharacters and getBytes, and they all give me different integer values. How can I convert the NSString to give me the same integer value as the hard-coded one?

 Method used:       Value:  Casted int value:
 Hard Coded(Works): 'RTF ' '1381254688'
 getCharacters:     'RTF ' '5505106'
 getBytes(ASCII):   'RTF ' '541480018'
 getBytes(UTF8):    'RTF ' '541480018'

Thanks in advance, Lance

Lance
  • 15
  • 4

1 Answers1

1

The problem with getCharacters:range: is that it gives you UTF-16 characters (unichars), whereas you want ASCII.

*(ResType*)[aString UTF8String] will convert the string to UTF-8 (which is equivalent to ASCII as long as all the characters in the string fit within the ASCII range) and then give you the first four bytes as a ResType value. Whether this is efficient enough depends on how often you want to do these conversions.

Another option is to use getBytes:maxLength:usedLength:encoding:options:range:remainingRange: with the encoding set to NSASCIIStringEncoding or NSUTF8StringEncoding, the destination buffer set to a pointer to an existing ResType variable, and the maximum length set to 4 (or sizeof (ResType)).


Update:

I've figured out why you're not getting the correct result with my suggestion. It turns out that in four-character integer literals, the bytes are stored in the opposite order to how they're written. Here's an example:

#include <Foundation/Foundation.h>

int main() {
    int code = 'RTF ';
    printf("'%c%c%c%c' = %d\n", ((char*)&code)[0], ((char*)&code)[1],
                                ((char*)&code)[2], ((char*)&code)[3],
                                code);
}

The output is ' FTR' = 1381254688. So, if you want to convert from NSStrings to these values, here are a few options:

  • Copy the string into a four-byte buffer (using one of the methods I suggested) and then reverse it by swapping byte 0 with byte 3, and byte 1 with byte 2.
  • The same, but do the reversing using a standard "endianness-swapping" algorithm like the one on this page.
  • Iterate through first (and only) four characters using characterAtIndex:, and insert them into a four-byte buffer in reverse. Remember that characterAtIndex: returns a UTF-16 character, but this can be easily cast to as ASCII character assuming it is within the ASCII range.
David
  • 2,821
  • 20
  • 16
  • Thank you for your quick response. These methods did not work for me, however. I will add more information to my original question. – Lance Sep 27 '10 at 20:08
  • @Lance: I've figured out what the problem is and updated my answer with a few suggestions. – David Sep 28 '10 at 09:02
  • @David: were I needing to swap endianness, I'd use the built-in Cocoa functions for doing it like `NXByteSwap...()`. That way when Apple updates their architecture again (they've had four in recent history) the result is still likely to be correct. –  Sep 28 '10 at 09:04
  • @Graham: Good idea. For the benefit of the OP, could you post the full name of the function(s), or a documentation link? I would do it myself, but for some reason I can't find it. – David Sep 28 '10 at 11:25
  • @David/@Lance: `EndianU32_NtoB()` in Core Endian is one of many APIs to do the conversion. –  Sep 28 '10 at 12:55
  • Your update worked great David. And I'll take a look at Graham's suggestion to make the code cleaner and future proof. Thank you! – Lance Sep 28 '10 at 20:55