mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Runtime: Generate a mangled name as the ObjC runtime name of generic class instances.
Our hack to generate a unique name by appending the class pointer doesn't produce a stable class name that can persist in NSKeyedArchiver, or eventually be used as a key for dynamic runtime instantiation. Generate a proper mangled name for the class instance by building a demangling AST from the metadata nodes and feeding it into the remangler. Should fix rdar://problem/18884563, though I need to try using an archiver with a generic class to verify. Swift SVN r29316
This commit is contained in:
@@ -11,22 +11,77 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Basic/Punycode.h"
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
static bool isContinuationByte(uint8_t unit) {
|
||||
return (unit & 0xC0) == 0x80;
|
||||
}
|
||||
|
||||
/// Reencode well-formed UTF-8 as UTF-32.
|
||||
///
|
||||
/// This entry point is only called from compiler-internal entry points, so does
|
||||
/// only minimal validation. In particular, it does *not* check for overlong
|
||||
/// encodings.
|
||||
static bool convertUTF8toUTF32(StringRef InputUTF8,
|
||||
std::vector<uint32_t> &OutUTF32) {
|
||||
auto ptr = InputUTF8.begin();
|
||||
auto end = InputUTF8.end();
|
||||
while (ptr < end) {
|
||||
uint8_t first = *ptr++;
|
||||
if (first < 0x80) {
|
||||
OutUTF32.push_back(first);
|
||||
} else if (first < 0xC0) {
|
||||
// Invalid continuation byte.
|
||||
return false;
|
||||
} else if (first < 0xE0) {
|
||||
// Two-byte sequence.
|
||||
if (ptr == end)
|
||||
return false;
|
||||
uint8_t second = *ptr++;
|
||||
if (!isContinuationByte(second))
|
||||
return false;
|
||||
OutUTF32.push_back(((first & 0x1F) << 6) | (second & 0x3F));
|
||||
} else if (first < 0xF0) {
|
||||
// Three-byte sequence.
|
||||
if (end - ptr < 2)
|
||||
return false;
|
||||
uint8_t second = *ptr++;
|
||||
uint8_t third = *ptr++;
|
||||
if (!isContinuationByte(second) || !isContinuationByte(third))
|
||||
return false;
|
||||
OutUTF32.push_back(((first & 0xF) << 12) | ((second & 0x3F) << 6)
|
||||
| ( third & 0x3F ));
|
||||
} else if (first < 0xF8) {
|
||||
// Four-byte sequence.
|
||||
if (end - ptr < 3)
|
||||
return false;
|
||||
uint8_t second = *ptr++;
|
||||
uint8_t third = *ptr++;
|
||||
uint8_t fourth = *ptr++;
|
||||
if (!isContinuationByte(second) || !isContinuationByte(third)
|
||||
|| !isContinuationByte(fourth))
|
||||
return false;
|
||||
OutUTF32.push_back(((first & 0x7) << 18) | ((second & 0x3F) << 12)
|
||||
| ((third & 0x3F) << 6)
|
||||
| ( fourth & 0x3F ));
|
||||
} else {
|
||||
// Unused sequence length.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Punycode::encodePunycodeUTF8(StringRef InputUTF8,
|
||||
std::string &OutPunycode) {
|
||||
std::vector<uint32_t> InputCodePoints(InputUTF8.size());
|
||||
const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(InputUTF8.data());
|
||||
UTF32 *TargetStart = InputCodePoints.data();
|
||||
auto ConvStatus = ConvertUTF8toUTF32(
|
||||
&SourceStart, SourceStart + InputUTF8.size(), &TargetStart,
|
||||
InputCodePoints.data() + InputCodePoints.size(), strictConversion);
|
||||
if (ConvStatus != conversionOK)
|
||||
std::vector<uint32_t> InputCodePoints;
|
||||
InputCodePoints.reserve(InputUTF8.size());
|
||||
|
||||
if (!convertUTF8toUTF32(InputUTF8, InputCodePoints))
|
||||
return false;
|
||||
InputCodePoints.resize(TargetStart - InputCodePoints.data());
|
||||
|
||||
return encodePunycode(InputCodePoints, OutPunycode);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user