Как конвертировать суррогатную пару в скаляр 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>
в кодовую точку UnicodeC
, дан кем-то: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