Spencer Williams Spencer Williams - 4 months ago 52
iOS Question

iOS/C: Convert "integer" into four character string

A lot of the constants associated with Audio Session programming are really four-character strings (Audio Session Services Reference). The same applies to the OSStatus code returned from functions like

AudioSessionGetProperty
.

The problem is that when I try to print these things out of the box, they look like 1919902568. I can plug that into Calculator and turn on ASCII output and it'll tell me "roch", but there must be a programmatic way to do this.

I've had limited success in one of my C functions with the following block:

char str[20];
// see if it appears to be a four-character code
*(UInt32 *) (str + 1) = CFSwapInt32HostToBig(error);
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
str[0] = str[5] = '\'';
str[6] = '\0';
} else {
// no, format as integer
sprintf(str, "%d", (int)error);
}


What I want to do is to abstract this feature out of its current function, in order to use it elsewhere. I tried doing

char * fourCharCode(UInt32 code) {
// block
}
void someOtherFunction(UInt32 foo){
printf("%s\n",fourCharCode(foo));
}


but that gives me "à*€/3íT:ê*€/+€/", not "roch". My C fu isn't very strong, but my hunch is that the above code tries to interpret the memory address as a string. Or perhaps there's an encoding issue? Any ideas?

Answer

The type you're talking about is a FourCharCode, defined in CFBase.h. It's equivalent to an OSType. The easiest way to convert between OSType and NSString is using NSFileTypeForHFSTypeCode() and NSHFSTypeCodeFromFileType(). These functions, unfortunately, aren't available on iOS.

For iOS and Cocoa-portable code, I like Joachim Bengtsson's FourCC2Str() from his NCCommon.h (plus a little casting cleanup for easier use):

#include <TargetConditionals.h>
#if TARGET_RT_BIG_ENDIAN
#   define FourCC2Str(fourcc) (const char[]){*((char*)&fourcc), *(((char*)&fourcc)+1), *(((char*)&fourcc)+2), *(((char*)&fourcc)+3),0}
#else
#   define FourCC2Str(fourcc) (const char[]){*(((char*)&fourcc)+3), *(((char*)&fourcc)+2), *(((char*)&fourcc)+1), *(((char*)&fourcc)+0),0}
#endif

FourCharCode code = 'APPL';
NSLog(@"%s", FourCC2Str(code));
NSLog(@"%@", @(FourCC2Str(code));

You could of course throw the @() into the macro for even easier use.