这可能是一个老问题,但由于它是在 Core Audio 的上下文中提出的,我只想分享一个我正在尝试的变体。
对于 Core Audio,在某些(但不是全部?)
OSStatus
/
Int32
值使用四个字符定义的情况下,可以从苹果旧的 Core Audio 实用程序类的一些代码中获得灵感(与
链接问题非常相似)。
来自
CAXException.h
:
class CAX4CCStringNoQuote {
public:
CAX4CCStringNoQuote(OSStatus error) {
UInt32 beErr = CFSwapInt32HostToBig(error);
char *str = mStr;
memcpy(str, &beErr, 4);
if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
str[4] = '\0';
} else if (error > -200000 && error < 200000)
snprintf(str, sizeof(mStr), "%d", (int)error);
else
snprintf(str, sizeof(mStr), "0x%x", (int)error);
}
const char *get() const { return mStr; }
operator const char *() const { return mStr; }
private:
char mStr[16];
};
在Swift 5中,一个粗略的翻译(不包括大值的十六进制表示)可能是:
private func osStatusToString(_ value: OSStatus) -> String {
let data = withUnsafeBytes(of: value.bigEndian, { Data($0) })
if data.allSatisfy({ 0x20 <= $0 && $0 <= 0x7e }) {
return String(data: data, encoding: .ascii)!
} else {
return String(value)
}
}
请注意,
Data
初始化器正在复制字节,但如果需要,可以避免这种情况。
当然,对于Core Audio,我们会遇到使用
Int32和
UInt32类型的四字符代码。我以前没有用Swift做过泛型,但在单个函数中处理它们的一种方法可能是:
private func stringifyErrorCode<T: FixedWidthInteger>(_ value: T) -> String {
let data = withUnsafeBytes(of: value.bigEndian, { Data($0) })
if data.allSatisfy({ 0x20 <= $0 && $0 <= 0x7e }) {
return String(data: data, encoding: .ascii)!
} else {
return String(value, radix: 10)
}
}
这可能不适用于一般处理四个字符代码(我看到其他答案支持MacOS Roman编码中的字符,而上面的示例则是ASCII。那里可能有一些历史,我不知道),但对于Core Audio状态/选择器代码可能是合理的。
NSFileTypeForHFSTypeCode
吗?尽管它的名称如此,但它可以将任何来自OSType
的4个字符代码转换为String
。 - Code Different