Как конвертировать суррогатную пару в скаляр Unicode в Swift

Следующий пример взят из документации по строкам и символам:

Ценности 55357 (U+D83D в шестнадцатеричном виде) и 56374 (U+DC36 в шестнадцатеричном) суррогатные пары, которые образуют скаляр Unicode U+1F436, какой DOG FACE персонаж. Есть ли способ пойти в другом направлении? То есть можно ли преобразовать суррогатную пару в скаляр?

Я старался

let myChar: Character = "\u{D83D}\u{DC36}"

но я получил ошибку "Недопустимый скаляр Unicode".

Этот ответ по Objective C и этот проект кажутся нестандартными решениями, но есть ли что-то встроенное в Swift (особенно Swift 2.0+), которое это делает?

2 ответа

Существуют формулы для расчета исходной кодовой точки на основе суррогатной пары и наоборот. С https://mathiasbynens.be/notes/javascript-encoding:

Раздел 3.7 стандарта Unicode 3.0 определяет алгоритмы для преобразования в и из суррогатных пар.

Кодовая точка C лучше чем 0xFFFF соответствует суррогатной паре <H, L> согласно следующей формуле:

H = Math.floor((C - 0x10000) / 0x400) + 0xD800
L = (C - 0x10000) % 0x400 + 0xDC00

Обратное отображение, т.е. из суррогатной пары <H, L> в кодовую точку Unicode C, дан кем-то:

C = (H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000

Дана последовательность кодовых единиц UTF-16 (то есть 16-битных чисел, таких как String.utf16 или просто массив чисел), вы можете использовать UTF16 тип и его decode способ превратить его в UnicodeScalars, который вы можете затем преобразовать в String,

Это немного шероховатый элемент, который берет генератор (так как он выполняет обработку с сохранением состояния) и возвращает перечисление, которое указывает результат (со связанным типом скаляра), или ошибку или завершение. Сопоставление с образцом Swift 2.0 упрощает использование:

let u16data: [UInt16] = [0xD83D,0xDC36]
//or let u16data = "Hello, ".utf16

var g = u16data.generate()
var s: String = ""
var utf16 = UTF16()
while case let .Result(scalar) = utf16.decode(&g) {
    print(scalar, &s)
}
print(s) // prints 
Другие вопросы по тегам