Spec-Zone.ru › D

std.uni

Модуль std.uni предоставляет реализацию основных алгоритмов и структур данных Юникода. Он не включает в себя примитивы кодирования и декодирования UTF, см. std.utf.decode и std.utf.encode в std.utf для этой функциональности.

Категория Функции
Декодирование byCodePoint byGrapheme decodeGrapheme graphemeStride
Сравнение icmp sicmp
Классификация isAlpha isAlphaNum isCodepointSet isControl isFormat isGraphical isIntegralPair isMark isNonCharacter isNumber isPrivateUse isPunctuation isSpace isSurrogate isSurrogateHi isSurrogateLo isSymbol isWhite
Нормализация NFC NFD NFKD NormalizationForm normalize
Разложение decompose decomposeHangul UnicodeDecomposition
Составление compose composeJamo
Множества CodepointInterval CodepointSet InversionList unicode
Дерево префиксного поиска codepointSetTrie CodepointSetTrie codepointTrie CodepointTrie toTrie toDelegate
Регистр asCapitalized asLowerCase asUpperCase isLower isUpper toLower toLowerInPlace toUpper toUpperInPlace
Utf8Matcher isUtfMatcher MatcherConcept utfMatcher
Разделители lineSep nelSep paraSep
Основные блоки allowedIn combiningClass Grapheme


Все перечисленные примитивы работают с символами Юникода и наборами символов. Для функций, которые работают с символами ASCII и игнорируют Юникод символы, см. std.ascii. Для определений Юникода символа, кодовой точки и других терминов, используемых в данном модуле, см. раздел терминология ниже.

Основное внимание в данном модуле уделяется основным потребностям разработки приложений, учитывающих Юникод. В этой связи он предоставляет следующие оптимизированные примитивы:

  • Классификация символов по категории и общим свойствам: isAlpha, isWhite и другие.
  • Регистронезависимое сравнение строк (sicmp, icmp).
  • Преобразование текста в любой из четырёх форм нормализации с помощью normalize.
  • Декодирование (decodeGrapheme) и итерация (byGrapheme, graphemeStride) по воспринимаемым пользователем символам, то есть по кластерам Grapheme.
  • Разложение и составление отдельных символов в соответствии с каноническими или правилами совместимости, см. compose и decompose, включая специальный вариант для слогов Хангул composeJamo и decomposeHangul.

Признается, что приложение может потребовать дополнительных усовершенствований и расширений, таких как менее известные алгоритмы или адаптация существующих алгоритмов для региональных потребностей. Чтобы помочь пользователям в создании дополнительной функциональности помимо основных примитивов, модуль предоставляет:

  • CodepointSet, тип для удобной работы с наборами символов. Помимо обычной алгебры множеств, он предоставляет необычную функцию: генератор кода на D для обнаружения кодовых точек в этом наборе. Это полезно для метапрограммируемых парсерных фреймворков и используется во внутреннем функционале для классификации в небольших наборах, например, isWhite.
  • Способ создания оптимальных упакованных таблиц с несколькими этапами, также известных как специальный случай Trie. Функции codepointTrie, codepointSetTrie создают пользовательские деревья, которые сопоставляют dchar со значением. Результатом является быстрый и предсказуемый поиск Ο(1), который используется в функциях, таких как isAlpha и combiningClass, но для наборов данных, определённых пользователем.
  • Полезный приём для приложений с поддержкой Юникода, которые выполняют классификацию символов закодированных кодовых точек: избегать ненужного декодирования во что бы то ни стало. utfMatcher обеспечивает улучшение по сравнению с обычным потоком декодировать-классифицировать-обрабатывать, объединяя декодирование и классификацию. Выделяя необходимые биты непосредственно из закодированных единиц кода, обработчики достигают значительных улучшений производительности. См. MatcherConcept для общего интерфейса обработчиков UTF.
  • В целом полезные строительные блоки для пользовательской нормализации: combiningClass для запроса класса объединения и allowedIn для проверки свойства Quick_Check заданной формы нормализации.
  • Доступ к большому количеству часто используемых наборов кодовых точек. Поддерживаемые наборы включают сценарий, блок и общую категорию. Точное содержимое набора можно увидеть в утилите CLDR на странице индекса свойств property index веб-сайта Юникода. См. unicode для легкого и (необязательно) проверенного на этапе компиляции запроса наборы.

Резюме

import std.uni;
void main()
{
    // initialize code point sets using script/block or property name
    // now 'set' contains code points from both scripts.
    auto set = unicode("Cyrillic") | unicode("Armenian");
    // same thing but simpler and checked at compile-time
    auto ascii = unicode.ASCII;
    auto currency = unicode.Currency_Symbol;

    // easy set ops
    auto a = set & ascii;
    assert(a.empty); // as it has no intersection with ascii
    a = set | ascii;
    auto b = currency - a; // subtract all ASCII, Cyrillic and Armenian

    // some properties of code point sets
    assert(b.length > 45); // 46 items in Unicode 6.1, even more in 6.2
    // testing presence of a code point in a set
    // is just fine, it is O(logN)
    assert(!b['$']);
    assert(!b['\u058F']); // Armenian dram sign
    assert(b['¥']);

    // building fast lookup tables, these guarantee O(1) complexity
    // 1-level Trie lookup table essentially a huge bit-set ~262Kb
    auto oneTrie = toTrie!1(b);
    // 2-level far more compact but typically slightly slower
    auto twoTrie = toTrie!2(b);
    // 3-level even smaller, and a bit slower yet
    auto threeTrie = toTrie!3(b);
    assert(oneTrie['£']);
    assert(twoTrie['£']);
    assert(threeTrie['£']);

    // build the trie with the most sensible trie level
    // and bind it as a functor
    auto cyrillicOrArmenian = toDelegate(set);
    auto balance = find!(cyrillicOrArmenian)("Hello ընկեր!");
    assert(balance == "ընկեր!");
    // compatible with bool delegate(dchar)
    bool delegate(dchar) bindIt = cyrillicOrArmenian;

    // Normalization
    string s = "Plain ascii (and not only), is always normalized!";
    assert(s is normalize(s));// is the same string

    string nonS = "A\u0308ffin"; // A ligature
    auto nS = normalize(nonS); // to NFC, the W3C endorsed standard
    assert(nS == "Äffin");
    assert(nS != nonS);
    string composed = "Äffin";

    assert(normalize!NFD(composed) == "A\u0308ffin");
    // to NFKD, compatibility decomposition useful for fuzzy matching/searching
    assert(normalize!NFKD("2¹⁰") == "210");
}

Терминология

Ниже приведён список важных понятий и определений Юникода. Любые соглашения, используемые только в данном модуле, отмечены как таковые. Описания основаны на формальном определении, как указано в главе три Unicode Standard Core Specification.

Абстрактный символ Единица информации, используемая для организации, управления или представления текстовых данных. Обратите внимание:
  • При представлении данных характер данных, как правило, символический, а не какого-либо другого типа (например, визуальный).
  • У абстрактного символа нет конкретной формы и его не следует путать с глифом.
  • Абстрактный символ не обязательно соответствует тому, что пользователь понимает под «символом», и его не следует путать с Grapheme.
  • Абстрактные символы, закодированные (см. Закодированный символ), известны как абстрактные символы Юникода.
  • Абстрактные символы, не закодированные в стандарте Юникод, часто могут быть представлены с помощью последовательностей комбинируемых символов.
Каноническое разложение Разложение символа или последовательности символов, полученное в результате рекурсивного применения канонических отображений, найденных в базе данных символов Юникода, и описанных в поведении объединяемых символов Джомо (раздел 12 Unicode Conformance). Каноническое объединение Точное определение канонического объединения — это алгоритм, как указано в разделе 11 Unicode Conformance. Неформально это процесс, обратный каноническому разложению, с добавлением определённых правил, которые, например, предотвращают появление устаревших символов в результирующей составной последовательности. Канонически эквивалентные Две последовательности символов считаются канонически эквивалентными, если их полные канонические разложения идентичны. Символ Обычно отличается в контексте. В целях этой документации термин «символ» подразумевает «закодированный символ», то есть кодовую точку, имеющую назначенный абстрактный символ (символическое значение). Кодовая точка Любое значение в кодовом пространстве Юникода; то есть диапазон целых чисел от 0 до 10FFFF (шестнадцатеричный). Не все кодовые точки присвоены закодированным символам. Код-единица Минимальная комбинация битов, которые могут представлять единицу закодированного текста для обработки или обмена. В зависимости от кодирования это может быть: 8-битные код-единицы в UTF-8 (char), 16-битные код-единицы в UTF-16 (wchar) и 32-битные код-единицы в UTF-32 (dchar). Обратите внимание, что в UTF-32 код-единица — это кодовая точка и представлена типом D dchar.Комбинирующий символ Символ с общей категорией Комбинирующий знак (M).
  • Все символы с ненулевым классом комбинирования являются комбинирующими символами, но обратное неверно: есть комбинирующие символы с нулевым классом комбинирования.
  • Эти символы обычно не используются изолированно, если только они не описываются. К ним относятся такие символы, как акценты, диакритические знаки, еврейские точки, арабские гласные знаки и индийские матрасы.
Класс комбинирования Числовое значение, используемое алгоритмом канонической упорядоченности Юникода для определения, какие последовательности комбинирующих знаков следует считать канонически эквивалентными, а какие — нет. Декомпозиция совместимости Декомпозиция символа или последовательности символов, полученная путем рекурсивного применения как отображений совместимости, так и канонических отображений, найденных в базе данных символов Юникода, и описанных в поведении объединяемых джамо. Символы больше не могут быть декомпозированы. Совместимые эквиваленты Две последовательности символов считаются совместимыми эквивалентами, если их полные декомпозиции совместимости идентичны. Кодированный символ Ассоциация (или отображение) между абстрактным символом и кодовым значением. Глиф Фактическое, конкретное изображение представления глифа, отсканированного или каким-либо другим образом отображенного на какой-либо поверхности дисплея. База графемы Символ со свойством Grapheme_Base или любой стандартный корейский слоговой блок. Кластер графем Определяется как текст между графемическими границами, как указано в приложении к стандарту Юникода № 29, сегментация текста Юникода. Важные общие свойства графемы:
  • Кластер графем представляет собой горизонтально сегментируемую единицу текста, состоящую из некоторой базы графемы (которая может состоять из корейского слога) вместе с любым количеством знаков без интервалов, примененных к ней.
  • Кластер графем обычно начинается с базы графемы и затем распространяется на любую последующую последовательность знаков без интервалов. Кластер графем наиболее непосредственно относится к отображению текста и процессам, таким как позиционирование курсора и выделение текста в редактировании, но также может быть связан с сравнением и поиском.
  • Для многих процессов кластер графем ведет себя так, как если бы это был один символ с теми же свойствами, что и его база графемы. По существу, знаки без интервалов применяются *графически* к базе, но не изменяют ее свойства.

Этот модуль определяет ряд примитивов, работающих с графемами: Grapheme, decodeGrapheme и graphemeStride. Все они используют границы *расширенной графемы*, как определено в упомянутом выше стандартном приложении.

Знак без интервала Комбинирующий символ с общей категорией Знак без интервала (Mn) или Закрывающий знак (Me). Знак с интервалом Комбинирующий символ, который не является знаком без интервала.

Нормализация

Концепции канонически эквивалентных или совместимых эквивалентных символов в стандарте Юникода требуют полного формального определения эквивалентности для строк Юникода. Эквивалентность строк определяется процессом, называемым нормализацией, при котором строки преобразуются в формы, которые сравниваются напрямую на равенство. Это основная цель процесса нормализации, см. функцию normalize для преобразования в любую из четырех определенных форм.

Очень важным свойством форм нормализации Юникода является то, что они должны оставаться стабильными между версиями стандарта Юникода. Строка Юникода, нормализованная до определенной формы нормализации Юникода в одной версии стандарта, гарантированно останется в этой форме нормализации для реализаций будущих версий стандарта.

Стандарт Юникода определяет четыре формы нормализации. Неформально, две из этих форм определяются максимальной декомпозицией эквивалентных последовательностей, а две из этих форм определяются максимальной *композицией* эквивалентных последовательностей.

  • Форма нормализации D (NFD): каноническая декомпозиция последовательности символов.
  • Форма нормализации KD (NFKD): декомпозиция совместимости последовательности символов.
  • Форма нормализации C (NFC): Каноническое объединение канонической декомпозиции закодированной последовательности символов.
  • Форма нормализации KC (NFKC): Каноническое объединение декомпозиции совместимости последовательности символов

Выбор формы нормализации зависит от конкретного случая использования. NFC — лучшая форма для общего текста, так как она лучше совместима со строками, преобразованными из устаревших кодировок. NFKC — предпочтительная форма для идентификаторов, особенно там, где существуют проблемы безопасности. NFD и NFKD наиболее полезны для внутренней обработки.

Создание таблиц поиска

Стандарт Юникода описывает набор алгоритмов, которые зависят от возможности быстрого поиска различных свойств кодового значения. Учитывая пространство кодирования около 1 миллиона кодовых точек, это нетривиальная задача обеспечить экономичное по памяти решение для множества свойств.

Общие подходы, такие как хеш-таблицы или бинарный поиск по отсортированным интервалам кодовых точек (как в InversionList), недостаточны. Хеш-таблицы имеют огромный объем памяти, а бинарный поиск по интервалам недостаточно быстр для некоторых сложных алгоритмов.

Рекомендуемое решение (см. Руководство по реализации Юникода) — использование таблиц с несколькими этапами, которые являются реализацией структуры данных Trie с целочисленными ключами и фиксированным числом этапов. В дальнейшем это будет называться фиксированным деревом Trie. Ниже описана конкретная реализация, нацеленная на скорость доступа в ущерб идеальной экономии памяти.

Взяв в качестве примера дерево Trie с 2 уровнями, принцип работы таков. Разбейте количество бит в ключе (кодовая точка, 21 бит) на 2 компонента (например, 15 и 8). Первое — количество бит в индексе дерева Trie, а второе — количество бит в каждой странице дерева Trie. Затем расположение дерева Trie — это массив размером 2^^количество бит в индексе, за которым следует массив блоков памяти размером 2^^количество бит в странице/бит на элемент.

Количество страниц является переменным (но не менее 1), в отличие от количества записей в индексе. Все ячейки индекса должны содержать номер присутствующей страницы. Затем поиск — всего лишь несколько операций: вырезание старших битов, поиск индекса для них, взятие страницы в этом индексе и использование младших битов в качестве смещения в этой странице.



Предполагая, что страницы расположены последовательно в одном массиве в pages, псевдокод выглядит следующим образом:
auto elemsPerPage = (2 ^^ bits_per_page) / Value.sizeOfInBits;
pages[index[n >> bits_per_page]][n & (elemsPerPage - 1)];

Где, если elemsPerPage является степенью 2, весь процесс сводится к нескольким простым командам и 2 чтений массива. Последующие уровни дерева Trie вводятся путем рекурсии над этим понятием — массив индекса рассматривается как значения. Затем количество бит в индексе снова делится на 2 части, с страницами над 'текущий-индекс' и новым 'верхний-индекс'.



Для полноты картины дерево Trie уровня 1 — это просто массив. Текущая реализация использует упаковку битов, когда диапазон заранее известен и ограничен (например, bool). См. также BitPacked для принудительного его использования вручную. Однако основное преимущество по размеру заключается в том, что по конструкции сливаются несколько одинаковых страниц на каждом уровне.

Процесс построения дерева Trie более сложен и скрыт от пользователя в виде удобных функций codepointTrie, codepointSetTrie и еще более удобной toTrie. В общем случае множество или встроенный AA с dchar типом можно преобразовать в дерево Trie. Объект Trie в этом модуле является только для чтения (неизменяемым); он фактически замораживается после построения.

Свойства Юникода

Это полный список свойств Юникода, доступных через unicode со специфическими вспомогательными функциями по каждой категории внутри. В случае сомнений обратитесь к утилите CLDR.

Перечисленные ниже наборы общей категории доступны только с помощью сокращенного доступа unicode.

Общая категория
Сокр. Полное название Сокр. Полное название Сокр. Полное название
L Буква Cn Неназначено Po Прочие знаки препинания
Ll Строчная буква Co Частное использование Ps Открывающие знаки препинания
Lm Модификаторная буква Cs Супплемент S Символ
Lo Другая буква N Число Sc Символ валюты
Lt Заглавная буква Nd Десятичное число Sk Символ модификатора
Lu Прописная буква Nl Число-буква Sm Математический символ
M Знак No Другое число So Другой символ
Mc Знак с интервалом P Знак препинания Z Разделитель
Me Закрывающий знак Pc Соединительный знак препинания Zl Разделитель строки
Mn Знак без интервала Pd Знак тире Zp Разделитель абзаца
C Другое Pe Закрывающий знак препинания Zs Пробельный разделитель
Cc Управляющий символ Pf Конечный знак препинания - Любой
Cf Формат Pi Начальный знак препинания - ASCII

Наборы других часто полезных свойств, доступных с помощью unicode:

Общие двоичные свойства
Имя Имя Имя
Буква Идеографическое Другие_заглавные
ASCII_шестнадцатеричная_цифра IDS_двоичный_оператор Синтаксис_шаблона
Управление_биди Начало_IDS Пробел_шаблона
С заглавной буквы IDS_троичный_оператор Знак_кавычек
Игнорируемая_с_точки_зрения_регистра Управление_соединением Корень
Дефис Исключение_порядка_логики Мягкая_точка
Знак_по умолчанию_игнорируемый_код_символа Строчные STerm
Устаревший Математический Заключительная_пунктуация
Диакритический Код_символа_без_символа Объединённый_идеографический
Расширитель Другие_буквенные Прописные
Основная_часть_графического_символа Другие_знаки_по_умолчанию_игнорируемые_код_символа Селектор_варианта
Расширение_графического_символа Другие_расширение_графического_символа Пробел
Связь_графического_символа Другие_ID_продолжение XID_продолжение
Шестнадцатеричная_цифра Другие_ID_начало XID_начало
Тире Другие_строчные
ID_продолжение Другие_математические

Ниже приведена таблица с именами блоков, которые принимаются unicode.block. Обратите внимание, что сокращённая версия unicode требует добавления «In» перед именами блоков для устранения неоднозначности между письменностями и блоками.

Блоки
Числа_Эгейского_мира Расширенный_эфиопский Монгольский
Символы_алхимии Расширенный_эфиопский-A Музыкальные_символы
Формы_представления_алфавитов Дополнительный_эфиопский Мьянма
Древнегреческая_нотация_музыки Общие_знаки_препинания Расширенный_мьянма-A
Древнегреческие_числа Геометрические_фигуры Новый_тай_люй
Древние_символы Грузинский NKo
Арабский Дополнительный_грузинский Формы_чисел
Расширенный_арабский-A Глаголический Огам
Арабские_математические_символы_алфавита Готский Ол_чики
Арабские_формы_представления-A Греческий_и_коптский Староиталийский
Арабские_формы_представления-B Расширенный_греческий Староперсидский
Дополнительный_арабский Гуджарати Староаравийский
Армянский Гурмукхи Старотурецкий
Стрелки Формы_полуширин_и_полных_ширин Оптическое_распознавание_символов
Авестийский Совместимость_хангуля_джамо Ориясский
Балийский Хангуль_джамо Османский
Бамум Расширенный_хангуль_джамо-A Фагс-па
Дополнительный_бамум Расширенный_хангуль_джамо-B Диск_Фаистоса
Основной_латинский Слоги_хангуля Финикийский
Батак Хануну Фонемные_расширения
Бенгальский Иврит Дополнительные_фонемные_расширения
Элементы_блока Символы_идеографического_описания Карты_для_игры
Брахими Императорский_арамейский Рунический
Узоры_брайля Надписи_пахлави Самартианский
Бугинезийский Надписи_парфянский Саураштра
Бухид Расширения_МФА Шарида
Византийские_символы_музыки Яванский Шавьин
Карийский Кайти Сингальский
Чакма Дополнительный_канадский Малые_варианты_форм
Чам Канбун Сора_Сомпэн
Чернокожий Корни_Канкси Пробельные_модификаторы_букв
Совместимость_CJK Каннада Спецсимволы
Формы_совместимости_CJK Катакана Сунданийский
Идеограммы_совместимости_CJK Фонемные_расширения_катаканы Дополнительный_сунданийский
Дополнительные_идеограммы_совместимости_CJK Кайя_Ли Надстрочные_и_подстрочные_символы
Дополнительные_корни_CJK Кхароштхи Дополнительные_стрелки-A
Штрихи_CJK Кхмерский Дополнительные_стрелки-B
Символы_и_знаки_препинания_CJK Символы_кхмерского Дополнительные_математические_операторы
Объединённые_идеограммы_CJK Лаосский Дополнительные_знаки_препинания
Расширение_объединённых_идеограмм_CJK_A Дополнительный_латинский-1 Дополнительная_область_для_частного_использования-A
Расширение_объединённых_идеограмм_CJK_B Дополнительный_латинский_A Дополнительная_область_для_частного_использования-B
Расширение_объединённых_идеограмм_CJK_C Дополнительный_дополнительный_латинский Силоти_Нагри
Расширение_объединённых_идеограмм_CJK_D Дополнительный_латинский_B Сирийский
Комбинирующие_диакритические_знаки Дополнительный_латинский_C Тагалог
Комбинирующие_диакритические_знаки_для_символов Дополнительный_латинский_D Тагбануа
Дополнительные_комбинирующие_диакритические_знаки Лэпча Теги
Комбинирующие_полузнаки Символы_в_виде_букв Тай_Люй
Общие_индийские_формы_чисел Лимбу Тай_Там
Изображения_управления Идеограммы_линейного_B Тай_Вьет
Кптский Силлабический_линейный_B Символы_тай_сюань_цзин
Числа_счёта_палочек Лисю Такри
Клинопись Низкие_суперпозиции Тамильский
Клинописные_числа_и_знаки_препинания Ликийский Телугу
Символы_валют Лидийский Таана
Кипрский_силлабический Плитка_для_маджонга Тай
Кириллический Малаялам Тибетский
Расширенный_кириллический-A Мандейский Символы_тифинага
Расширенный_кириллический-B Математические_алфавитно-цифровые_символы Символы_транспорта_и_карт
Дополнительный_кириллический Математические_операторы Угаритский
Дезерет Метей_Маек Объединённые_канадские_символы_коренных_народов
Деванагари Расширения_Метей_Маек Расширенные_объединённые_канадские_символы_коренных_народов
Расширенный_деванагари Мероитский_курсив Вай
Символы_динбатов Мероитские_иероглифы Расширения_ведических
Кости_домино Мьяо Вертикальные_формы
Египетские_иероглифы Разные_математические_символы_A Символы_и_гексаграммы_ИЦзин
Иконки Разные_математические_символы_B Корни_И
Вложенные_алфавитно-цифровые_знаки Разные_символы
Дополнительные_вложенные_алфавитно-цифровые_знаки Разные_символы_и_стрелки
Вложенные_буквы_и_месяцы_CJK Разные_символы_и_пиктограммы
Дополнительные_вложенные_идеограммы Разные_технические
Эфиопский Модификаторы_тональных_букв

Ниже приведена таблица с именами письменностей, принятых unicode.script и сокращённой версией unicode:

Письменности
Арабский Хануну Староиталийский
Армянский Иврит Староперсидский
Авестийский Хирагана Староаравийский
Балийский Императорский_арамейский Старотурецкий
Бамум Наследуемый Ориясский
Батак Надписи_пахлави Османский
Бенгальский Надписи_парфянский Фагс-па
Бопомофо Яванский Финикийский
Брахими Кайти Рунический
Брайль Каннада Самартианский
Бугинезийский Катакана Саураштра
Бухид Кайя_Ли Шарида
Канадский_коренной Кхароштхи Шавьин
Карийский Кхмерский Сингальский
Чакма Лаосский Сора_Сомпэн
Чам Латинский Сунданийский
Чернокожий Лэпча Силоти_Нагри
Общий Лимбу Сирийский
Коптский Линейный_B Тагалог
Клинопись Лисю Тагбануа
Кипрский Ликийский Тай_Люй
Кириллический Лидийский Тай_Там
Дезерет Малаялам Тай_Вьет
Деванагари Мандейский Такри
Египетские_иероглифы Метей_Маек Тамильский
Эфиопский Мероитский_курсив Телугу
Грузинский Мероитские_иероглифы Таана
Глаголический Мьяо Тай
Готский Монгольский Тибетский
Греческий Мьянма Тифинаг
Гуджарати Новый_тай_люй Угаритский
Гурмукхи NKo Вай
Хан Огам И
Хангуль Ол_чики

Ниже приведена таблица имён, принятых unicode.hangulSyllableType.

Тип_слога_хангуля
Сокр. Полная_форма
L Ведущая_джамо
LV LV_слог
LVT LVT_слог
T Завершающая_джамо
V Гласная_джамо
Ссылки
Таблица_ASCII, Википедия, Консорциум_Unicode, Формы_нормализации_Unicode, Сегментация_текста_Unicode Руководство_по_реализации_Unicode Соответствие_Unicode
Торговые_знаки
Unicode(tm) — торговая_марка_Unicode, Inc.
Лицензия:
Лицензия_Boost_1.0.
Авторы:
Дмитрий_Ольшанский
END_OF_DOCUMENT_MARKER
Источник
std/uni/package.d
Стандарты:
Unicode v6.2
enum dchar lineSep;

Постоянная кодовая точка (0x2028) — разделитель строк.

enum dchar paraSep;

Постоянная кодовая точка (0x2029) — разделитель абзацев.

enum dchar nelSep;

Постоянная кодовая точка (0x0085) — следующая строка.

template isCodepointSet(T)

Проверяет, является ли T каким-то типом набора кодовых точек. Предназначено для ограничений шаблонов.

enum auto isIntegralPair(T, V = uint);

Проверяет, является ли T парой целых чисел, которые неявно преобразуются в V. Следующий код должен компилироваться для любой пары T:

(T x){ V a = x[0]; V b = x[1];}
Следующее не должно компилироваться:
(T x){ V c = x[2];}

alias CodepointSet = InversionList!(GcPolicy).InversionList;

Рекомендуемый тип по умолчанию для набора кодовых точек. Подробнее см. текущую реализацию: InversionList.

struct CodepointInterval;

Рекомендуемый тип std.typecons.Tuple для представления интервалов [a, b) кодовых точек. Используется в InversionList. Любой тип интервала должен удовлетворять свойству isIntegralPair.

struct InversionList(SP = GcPolicy);

InversionList — это множество кодовых точек, представленное в виде массива интервалов открытых справа [a, b) (см. CodepointInterval выше). Название происходит от способа чтения представления слева направо. Например, множество всех значений [10, 50), [80, 90) плюс отдельное значение 60 выглядит следующим образом:

10, 50, 60, 61, 80, 90

Способ чтения: начинаем с отрицательного значения, обозначающего, что все числа, меньшие следующего, отсутствуют в этом множестве (и положительного — наоборот). Затем меняем положительное/отрицательное после каждого пройденного числа слева направо.

Таким образом, отрицательные значения продолжаются до 10, затем положительные до 50, затем отрицательные до 60, затем положительные до 61 и так далее. Как видно, это обеспечивает экономичное хранение высокоизбыточных данных, которые встречаются длинными сериями. Описание, которое хорошо подходит для свойств Unicode символов. Сам метод можно рассматривать как разновидность RLE-кодирования.

Множества — это значения типов (так же, как и int), поэтому они никогда не дублируются.

Пример
auto a = CodepointSet('a', 'z'+1);
auto b = CodepointSet('A', 'Z'+1);
auto c = a;
a = a | b;
assert(a == CodepointSet('A', 'Z'+1, 'a', 'z'+1));
assert(a != c);

См. также unicode для более простого создания наборов из предварительно заданных.

Объем памяти составляет 8 байт на каждый смежный интервал в наборе. Семантика значений достигается с помощью техники COW, и поэтому не безопасно приводить этот тип к типу shared.

Примечание

Не рекомендуется полагаться на параметры шаблона или точный тип текущего набора кодовых точек в std.uni. Тип и параметры могут измениться при окончательном проектировании стандартных аллокаторов. Используйте isCodepointSet с шаблонами или просто придерживайтесь по умолчанию псевдонима CodepointSet по всему коду.

pure this(Set)(Set set)
Constraints: if (isCodepointSet!Set);

Создание из другого набора кодовых точек любого типа.

pure this(Range)(Range intervals)
Constraints: if (isForwardRange!Range && isIntegralPair!(ElementType!Range));

Создание множества из упорядоченного диапазона интервалов кодовых точек.

this()(uint[] intervals...);

Создание множества из простых значений интервалов кодовых точек.

Примеры:
import std.algorithm.comparison : equal;

auto set = CodepointSet('a', 'z'+1, 'а', 'я'+1);
foreach (v; 'a'..'z'+1)
    assert(set[v]);
// Cyrillic lowercase interval
foreach (v; 'а'..'я'+1)
    assert(set[v]);
//specific order is not required, intervals may interesect
auto set2 = CodepointSet('а', 'я'+1, 'a', 'd', 'b', 'z'+1);
//the same end result
assert(set2.byInterval.equal(set.byInterval));
// test constructor this(Range)(Range intervals)
auto chessPiecesWhite = CodepointInterval(9812, 9818);
auto chessPiecesBlack = CodepointInterval(9818, 9824);
auto set3 = CodepointSet([chessPiecesWhite, chessPiecesBlack]);
foreach (v; '♔'..'♟'+1)
    assert(set3[v]);
@property scope auto byInterval();

Получение диапазона, охватывающего все интервалы кодовых точек в этом InversionList.

const bool opIndex(uint val);

Проверка наличия кодовой точки val в этом наборе.

Примеры:
auto gothic = unicode.Gothic;
// Gothic letter ahsa
assert(gothic['\U00010330']);
// no ascii in Gothic obviously
assert(!gothic['$']);
@property size_t length();

Количество кодовых точек в этом наборе.

This opBinary(string op, U)(U rhs)
Constraints: if (isCodepointSet!U || is(U : dchar));

Множества поддерживают естественный синтаксис для алгебры множеств, а именно:

Оператор Математическая запись Описание
& a ∩ b пересечение
| a ∪ b объединение
- a ∖ b вычитание
~ a ~ b симметрическая разность, т.е. (a ∪ b) \ (a ∩ b)
Примеры:
import std.algorithm.comparison : equal;
import std.range : iota;

auto lower = unicode.LowerCase;
auto upper = unicode.UpperCase;
auto ascii = unicode.ASCII;

assert((lower & upper).empty); // no intersection
auto lowerASCII = lower & ascii;
assert(lowerASCII.byCodepoint.equal(iota('a', 'z'+1)));
// throw away all of the lowercase ASCII
writeln((ascii - lower).length); // 128 - 26

auto onlyOneOf = lower ~ ascii;
assert(!onlyOneOf['Δ']); // not ASCII and not lowercase
assert(onlyOneOf['$']); // ASCII and not lowercase
assert(!onlyOneOf['a']); // ASCII and lowercase
assert(onlyOneOf['я']); // not ASCII but lowercase

// throw away all cased letters from ASCII
auto noLetters = ascii - (lower | upper);
writeln(noLetters.length); // 128 - 26 * 2
ref This opOpAssign(string op, U)(U rhs)
Constraints: if (isCodepointSet!U || is(U : dchar));

Версии 'op=' перечисленных выше перегруженных операторов.

const bool opBinaryRight(string op : "in", U)(U ch)
Constraints: if (is(U : dchar));

Проверка наличия кодовой точки ch в этом наборе, то же, что и opIndex.

Примеры:
assert('я' in unicode.Cyrillic);
assert(!('z' in unicode.Cyrillic));
auto opUnary(string op : "!")();

Получение набора, являющегося инверсией этого набора.

См. также:
inverted
@property auto byCodepoint();

Диапазон, охватывающий каждую кодовую точку в этом наборе.

Примеры:
import std.algorithm.comparison : equal;
import std.range : iota;

auto set = unicode.ASCII;
set.byCodepoint.equal(iota(0, 0x80));
void toString(Writer)(scope Writer sink, ref scope const FormatSpec!char fmt);

Получение текстового представления этого InversionList в виде интервалов открытых справа.

Флаг форматирования применяется индивидуально к каждому значению, например:

  • %s и %d форматируют интервалы как диапазон [низкое .. высокое) целых чисел
  • %x форматирует интервалы как диапазон [низкое .. высокое) строчных шестнадцатеричных символов
  • %X форматирует интервалы как диапазон [низкое .. высокое) прописных шестнадцатеричных символов
  • Примеры:
    import std.conv : to;
    import std.format : format;
    import std.uni : unicode;
    
    assert(unicode.Cyrillic.to!string ==
        "[1024..1157) [1159..1320) [7467..7468) [7544..7545) [11744..11776) [42560..42648) [42655..42656)");
    
    // The specs '%s' and '%d' are equivalent to the to!string call above.
    writeln(format("%d", unicode.Cyrillic)); // unicode.Cyrillic.to!string
    
    assert(format("%#x", unicode.Cyrillic) ==
        "[0x400..0x485) [0x487..0x528) [0x1d2b..0x1d2c) [0x1d78..0x1d79) [0x2de0..0x2e00) "
        ~"[0xa640..0xa698) [0xa69f..0xa6a0)");
    
    assert(format("%#X", unicode.Cyrillic) ==
        "[0X400..0X485) [0X487..0X528) [0X1D2B..0X1D2C) [0X1D78..0X1D79) [0X2DE0..0X2E00) "
        ~"[0XA640..0XA698) [0XA69F..0XA6A0)");
    
    ref auto add()(uint a, uint b);

    Добавление интервала [a, b) в этот набор.

    Примеры:
    CodepointSet someSet;
    someSet.add('0', '5').add('A','Z'+1);
    someSet.add('5', '9'+1);
    assert(someSet['0']);
    assert(someSet['5']);
    assert(someSet['9']);
    assert(someSet['Z']);
    
    @property auto inverted();

    Получение набора, являющегося инверсией этого набора.

    См. '!' opUnary для того же, но с использованием операторов.

    Примеры:
    auto set = unicode.ASCII;
    // union with the inverse gets all of the code points in the Unicode
    writeln((set | set.inverted).length); // 0x110000
    // no intersection with the inverse
    assert((set & set.inverted).empty);
    
    string toSourceCode(string funcName = "");

    Генерирует строку с кодом D унарной функции с именем funcName, принимающей один аргумент dchar. Если funcName пуста, код корректируется для создания лямбда-функции.

    Созданная функция проверяет, принадлежит ли переданная кодовая точка этому набору или нет. Результат должен использоваться с миксином строк. Предполагаемая область использования — агрессивная оптимизация с помощью метапрограммирования в генераторах парсеров и подобных инструментах.

    Примечание
    Используйте с осторожностью для относительно небольших или регулярных наборов. Это может оказаться медленнее, чем использование многоступенчатых таблиц.
    Пример
    import std.stdio;
    
    // construct set directly from [a, b$RPAREN intervals
    auto set = CodepointSet(10, 12, 45, 65, 100, 200);
    writeln(set);
    writeln(set.toSourceCode("func"));
    
    Выше приводится что-то вроде:
    bool func(dchar ch)  @safe pure nothrow @nogc
    {
        if (ch < 45)
        {
            if (ch == 10 || ch == 11) return true;
            return false;
        }
        else if (ch < 65) return true;
        else
        {
            if (ch < 100) return false;
            if (ch < 200) return true;
            return false;
        }
    }
    
    const @property bool empty();

    Истинно, если этот набор не содержит кодовых точек.

    Примеры:
    CodepointSet emptySet;
    writeln(emptySet.length); // 0
    assert(emptySet.empty);
    
    template codepointSetTrie(sizes...) if (sumOfIntegerTuple!sizes == 21)

    Сокращенное обозначение для создания настраиваемого фиксированного дерева Trie нескольких уровней из CodepointSet. sizes — это числа битов на уровень, начиная с наиболее значимых битов.

    Примечание
    Сумма sizes должна быть равна 21.
    См. также:
    toTrie, что еще проще.
    Пример
    {
        import std.stdio;
        auto set = unicode("Number");
        auto trie = codepointSetTrie!(8, 5, 8)(set);
        writeln("Input code points to test:");
        foreach (line; stdin.byLine)
        {
            int count=0;
            foreach (dchar ch; line)
                if (trie[ch])// is number
                    count++;
            writefln("Contains %d number code points.", count);
        }
    }
    
    template CodepointSetTrie(sizes...) if (sumOfIntegerTuple!sizes == 21)

    Тип дерева Trie, сгенерированного функцией codepointSetTrie.

    template codepointTrie(T, sizes...) if (sumOfIntegerTuple!sizes == 21)

    template CodepointTrie(T, sizes...) if (sumOfIntegerTuple!sizes == 21)

    Несколько более универсальный инструмент для построения фиксированных Trie для данных Юникода.

    В частности, в отличие от codepointSetTrie, он позволяет создавать отображения dchar на произвольный тип T.

    Примечание
    Перегрузка, принимающая CodepointSet, будет естественным образом преобразовывать только в булево отображение Trie.
    CodepointTrie — это тип Trie, сгенерированный функцией codepointTrie.
    auto codepointTrie()(T[dchar] map, T defValue = T.init);
    auto codepointTrie(R)(R range, T defValue = T.init)
    Constraints: if (isInputRange!R && is(typeof(ElementType!R.init[0]) : T) && is(typeof(ElementType!R.init[1]) : dchar));
    struct MatcherConcept;

    Концептуальный тип, описывающий общие свойства всех UTF-матчеров.

    Примечание
    Только для иллюстративных целей, каждый вызов метода приводит к ошибке утверждения. Используйте utfMatcher для получения конкретного матчера для кодировок UTF-8 или UTF-16.
    bool match(Range)(ref Range inp)
    Constraints: if (isRandomAccessRange!Range && is(ElementType!Range : char));

    bool skip(Range)(ref Range inp)
    Constraints: if (isRandomAccessRange!Range && is(ElementType!Range : char));

    bool test(Range)(ref Range inp)
    Constraints: if (isRandomAccessRange!Range && is(ElementType!Range : char));

    Выполняет семантически эквивалентные 2 операции: декодирование кодовой точки в начале inp и проверка принадлежности ее к набору кодовых точек этого матчера.

    Воздействие на inp зависит от вызываемой функции:



    Match. Если кодовая точка найдена в наборе, то диапазон inp сдвигается на свою длину в кодовых единицах, в противном случае диапазон не изменяется.



    Skip. Диапазон всегда сдвигается на длину тестируемой кодовой точки, независимо от результата проверки.



    Test. Диапазон остается неизменным независимо от результата проверки.

    Примеры:
    string truth = "2² = 4";
    auto m = utfMatcher!char(unicode.Number);
    assert(m.match(truth)); // '2' is a number all right
    assert(truth == "² = 4"); // skips on match
    assert(m.match(truth)); // so is the superscript '2'
    assert(!m.match(truth)); // space is not a number
    assert(truth == " = 4"); // unaffected on no match
    assert(!m.skip(truth)); // same test ...
    assert(truth == "= 4"); // but skips a codepoint regardless
    assert(!m.test(truth)); // '=' is not a number
    assert(truth == "= 4"); // test never affects argument
    
    @property auto subMatcher(Lengths...)();

    Дополнительно - обеспечивает прямой доступ к подмножеству матчера на основе набора известных длин кодирования. Длины указываются в кодовых единицах. Подматчер затем может выполнять меньше операций на каждые test/match.

    Используйте с осторожностью, так как подматчер не будет соответствовать никаким кодовым точкам, длина кодирования которых не принадлежит выбранному набору длин. Также объект подматчера ссылается на родительский матчер и не должен использоваться после окончания срока службы последнего.

    Еще одним недостатком использования подматчера является то, что skip недоступен именно потому, что подматчер не обнаруживает все длины.

    enum auto isUtfMatcher(M, C);

    Проверка, является ли M UTF-матчером для диапазонов Char.

    auto utfMatcher(Char, Set)(Set set)
    Constraints: if (isCodepointSet!Set);

    Создает объект матчера для классификации кодовых точек из set для кодирования, у которого Char является кодовой единицей.

    См. MatcherConcept для обзора API.

    auto toTrie(size_t level, Set)(Set set)
    Constraints: if (isCodepointSet!Set);

    Удобная функция для построения оптимальных конфигураций упакованного Trie из любого set кодовых точек.

    Параметр level указывает количество уровней trie для использования, допустимые значения: 1, 2, 3 или 4. Уровни представляют различные компромиссы со скоростью и размером.

    Уровень 1 самый быстрый и самый емкий в памяти (массив битов).

    Уровень 4 самый медленный и имеет наименьший объем памяти.



    См. раздел Synopsis для примера.
    Примечание
    Уровень 4 остается очень практичным (быстрее и предсказуемее), по сравнению с использованием прямого поиска в самом set.
    auto toDelegate(Set)(Set set)
    Constraints: if (isCodepointSet!Set);

    Строит Trie с типично оптимальным компромиссом между скоростью и размером и оборачивает его в делегат следующего типа: bool delegate(dchar ch).

    По сути, это создает лямбда-«тестер», подходящий для алгоритмов, таких как std.algorithm.find, которые принимают унарные предикаты.



    См. раздел Synopsis для примера.
    struct unicode;

    Единственная точка входа для поиска наборов Юникод кодовых точек по имени или псевдониму блока, сценария или общей категории.

    Использует хорошо определенные стандартные правила поиска по имени свойства. Это включает в себя нечеткое соответствие имен, поэтому «White_Space», «white-SpAce» и «whitespace» считаются равными и приводят к одному и тому же набору пробельных символов.

    pure @property auto opDispatch(string name)();

    Выполняет поиск набора кодовых точек с проверкой корректности на этапе компиляции. Эта короткая версия объединяет 3 поиска: по блокам, сценариям и общим двоичным свойствам.

    Обратите внимание, что поскольку сценарии и блоки перекрываются, используется обычный трюк для устранения неоднозначности — для получения блока используйте unicode.InBlockName, для поиска сценария используйте unicode.ScriptName.

    См. также:
    block, script и (не включено в этот поиск) hangulSyllableType.
    auto opCall(C)(scope const C[] name)
    Constraints: if (is(C : dchar));

    Тот же поиск по блокам, сценариям или двоичным свойствам, но выполняемый во время выполнения. Эта версия предоставляется для случаев, когда name не известны заранее; в противном случае проверенная на этапе компиляции opDispatch обычно является лучшим выбором.

    См. таблицу свойств Юникода для доступных наборов.

    struct block;

    Сужает поиск наборов кодовых точек до всех блоков Юникода.

    Примечание
    Здесь имена блоков недвусмысленные, так как сценарии не проверяются, и таким образом для поиска используется просто обозначение unicode.block.BlockName.
    См. таблицу свойств Юникода для доступных наборов.
    См. также:
    таблица свойств.
    Примеры:
    // use .block for explicitness
    writeln(unicode.block.Greek_and_Coptic); // unicode.InGreek_and_Coptic
    
    struct script;

    Сужает поиск наборов кодовых точек до всех сценариев Юникода.

    См. таблицу свойств Юникода для доступных наборов.

    Примеры:
    auto arabicScript = unicode.script.arabic;
    auto arabicBlock = unicode.block.arabic;
    // there is an intersection between script and block
    assert(arabicBlock['؁']);
    assert(arabicScript['؁']);
    // but they are different
    assert(arabicBlock != arabicScript);
    writeln(arabicBlock); // unicode.inArabic
    writeln(arabicScript); // unicode.arabic
    
    struct hangulSyllableType;

    Получение набора кодовых точек, имеющих заданный тип слога хангул.

    Другие свойства, не являющиеся двоичными (если будут поддерживаться), следуют той же нотации — unicode.propertyName.propertyValue для проверки на этапе компиляции и unicode.propertyName(propertyValue) для проверки во время выполнения.

    См. таблицу свойств Юникода для доступных наборов.

    Примеры:
    // L here is syllable type not Letter as in unicode.L short-cut
    auto leadingVowel = unicode.hangulSyllableType("L");
    // check that some leading vowels are present
    foreach (vowel; '\u1110'..'\u115F')
        assert(leadingVowel[vowel]);
    writeln(leadingVowel); // unicode.hangulSyllableType.L
    
    CodepointSet parseSet(Range)(ref Range range, bool casefold = false)
    Constraints: if (isInputRange!Range && is(ElementType!Range : dchar));

    Парсинг набора кодовых точек Юникода из заданного range с использованием стандартного синтаксиса регулярных выражений '[...]'. Диапазон сдвигается, пропуская определение набора регулярных выражений. Параметр casefold определяет, должен ли набор быть преобразован в регистр — то есть, включать как строчные, так и прописные версии для любых букв в наборе.

    pure @safe size_t graphemeStride(C)(scope const C[] input, size_t index)
    Constraints: if (is(C : dchar));

    Вычисляет длину кластера графем, начинающегося с index. И полученная длина, и index измеряются в кодовых единицах.

    Параметры:
    C тип, неявно преобразуемый в dchars
    C[] input массив кластеров графем
    size_t index начальный индекс в input[]
    Возвращает:
    длину кластера графем
    Примеры:
    writeln(graphemeStride("  ", 1)); // 1
    // A + combing ring above
    string city = "A\u030Arhus";
    size_t first = graphemeStride(city, 0);
    assert(first == 3); //\u030A has 2 UTF-8 code units
    writeln(city[0 .. first]); // "A\u030A"
    writeln(city[first .. $]); // "rhus"
    
    Grapheme decodeGrapheme(Input)(ref Input inp)
    Constraints: if (isInputRange!Input && is(immutable(ElementType!Input) == immutable(dchar)));

    Читает один полный кластер графем из диапазона входных значений dchar inp.

    Примеры см. ниже в Grapheme.

    Примечание
    Эта функция изменяет inp, и поэтому inp должен быть значением-ссылкой.
    auto byGrapheme(Range)(Range range)
    Constraints: if (isInputRange!Range && is(immutable(ElementType!Range) == immutable(dchar)));

    Итерация строки по Grapheme.

    Полезно для работы со строками, которые должны учитывать графемы.

    См. также:
    byCodePoint
    Примеры:
    import std.algorithm.comparison : equal;
    import std.range.primitives : walkLength;
    import std.range : take, drop;
    auto text = "noe\u0308l"; // noël using e + combining diaeresis
    assert(text.walkLength == 5); // 5 code points
    
    auto gText = text.byGrapheme;
    assert(gText.walkLength == 4); // 4 graphemes
    
    assert(gText.take(3).equal("noe\u0308".byGrapheme));
    assert(gText.drop(3).equal("l".byGrapheme));
    
    auto byCodePoint(Range)(Range range)
    Constraints: if (isInputRange!Range && is(immutable(ElementType!Range) == immutable(Grapheme)));

    auto byCodePoint(Range)(Range range)
    Constraints: if (isInputRange!Range && is(immutable(ElementType!Range) == immutable(dchar)));

    Лениво преобразует диапазон Grapheme в диапазон кодовых точек.

    Полезно для преобразования результата в строку после выполнения операций над графемами.



    Если на вход подается диапазон кодовых точек, возвращает диапазон с эквивалентными возможностями.

    Примеры:
    import std.array : array;
    import std.conv : text;
    import std.range : retro;
    
    string s = "noe\u0308l"; // noël
    
    // reverse it and convert the result to a string
    string reverse = s.byGrapheme
        .array
        .retro
        .byCodePoint
        .text;
    
    assert(reverse == "le\u0308on"); // lëon
    
    struct Grapheme;

    Структура, предназначенная для эффективного группирования символов кластера графем.

    Grapheme имеет семантику значений, поэтому 2 копии Grapheme всегда ссылаются на разные объекты. В большинстве реальных сценариев Grapheme помещается в стеке и избегает накладных расходов на выделение памяти, за исключением довольно длинных кластеров.

    См. также:
    decodeGrapheme, graphemeStride
    this(C)(scope const C[] chars...)
    Constraints: if (is(C : dchar));

    this(Input)(Input seq)
    Constraints: if (!isDynamicArray!Input && isInputRange!Input && is(ElementType!Input : dchar));

    Конструктор

    const pure nothrow @nogc @trusted dchar opIndex(size_t index);

    Возвращает кодовую точку по заданному индексу в этом кластере.

    pure nothrow @nogc @trusted void opIndexAssign(dchar ch, size_t index);

    Записывает кодовую точку ch по заданному индексу в этом кластере.

    Предупреждение
    Использование этого механизма может привести к недействительности кластера графем, см. также Grapheme.valid.
    Примеры:
    auto g = Grapheme("A\u0302");
    writeln(g[0]); // 'A'
    assert(g.valid);
    g[1] = '~'; // ASCII tilda is not a combining mark
    writeln(g[1]); // '~'
    assert(!g.valid);
    
    pure nothrow @nogc @safe SliceOverIndexed!Grapheme opSlice(size_t a, size_t b) return;

    pure nothrow @nogc @safe SliceOverIndexed!Grapheme opSlice() return;

    Диапазон произвольного доступа к символам Grapheme.

    Предупреждение
    Становится недействительным при выходе Grapheme из области видимости. Попытка использовать его затем приведет к повреждению памяти.
    const pure nothrow @nogc @property @safe size_t length();

    Длина кластера графем в кодовых точках.

    ref @trusted auto opOpAssign(string op)(dchar ch);

    Добавить символ ch к этой графеме.

    Предупреждение
    Использование этого механизма может привести к недействительности кластера графем, см. также valid.
    См. также:
    Grapheme.valid
    Примеры:
    import std.algorithm.comparison : equal;
    auto g = Grapheme("A");
    assert(g.valid);
    g ~= '\u0301';
    assert(g[].equal("A\u0301"));
    assert(g.valid);
    g ~= "B";
    // not a valid grapheme cluster anymore
    assert(!g.valid);
    // still could be useful though
    assert(g[].equal("A\u0301B"));
    
    ref auto opOpAssign(string op, Input)(scope Input inp)
    Constraints: if (isInputRange!Input && is(ElementType!Input : dchar));

    Добавить все символы из входного диапазона inp в эту графему.

    @property bool valid()();

    Истина, если этот объект содержит действительный расширенный кластер графем. Примитивы декодирования этого модуля всегда возвращают действительную Grapheme.

    Добавление и прямое манипулирование символами графемы могут сделать ее недействительной. Некоторые приложения могут выбрать использование Grapheme как "малой строки" любых кодовых точек и полностью проигнорировать это свойство.

    int sicmp(S1, S2)(scope S1 r1, scope S2 r2)
    Constraints: if (isInputRange!S1 && isSomeChar!(ElementEncodingType!S1) && isInputRange!S2 && isSomeChar!(ElementEncodingType!S2));

    Выполняет базовое сравнение строк без учета регистра r1 и r2. Эта функция использует более простые правила сравнения, что обеспечивает лучшую производительность, чем icmp. Однако имейте в виду предупреждение ниже.

    Параметры:
    S1 r1 входной диапазон символов
    S2 r2 входной диапазон символов
    Возвращает:
    Значение, которое равно 0, если строки совпадают, < 0, если r1 лексикографически "меньше", чем r2, > 0, если r1 лексикографически "больше", чем r2
    Предупреждение
    Эта функция обрабатывает только соответствие 1:1 кодовых точек и поэтому не подходит для некоторых алфавитов, таких как немецкий, греческий и некоторых других.
    См. также:
    icmp std.algorithm.comparison.cmp
    Примеры:
    writeln(sicmp("Август", "авгусТ")); // 0
    // Greek also works as long as there is no 1:M mapping in sight
    writeln(sicmp("ΌΎ", "όύ")); // 0
    // things like the following won't get matched as equal
    // Greek small letter iota with dialytika and tonos
    assert(sicmp("ΐ", "\u03B9\u0308\u0301") != 0);
    
    // while icmp has no problem with that
    writeln(icmp("ΐ", "\u03B9\u0308\u0301")); // 0
    writeln(icmp("ΌΎ", "όύ")); // 0
    
    int icmp(S1, S2)(S1 r1, S2 r2)
    Constraints: if (isForwardRange!S1 && isSomeChar!(ElementEncodingType!S1) && isForwardRange!S2 && isSomeChar!(ElementEncodingType!S2));

    Выполняет сравнение строк без учета регистра r1 и r2. Следует правилам полного преобразования в нижний регистр, в том числе соответствует немецкой ß с "ss" и другим соответствиям 1:N кодовых точек, в отличие от sicmp. Стоимость точной корректности icmp несколько ухудшает производительность.

    Параметры:
    S1 r1 диапазон символов
    S2 r2 диапазон символов
    Возвращает:
    Значение, которое равно 0, если строки совпадают, < 0, если str1 лексикографически "меньше", чем str2, > 0, если str1 лексикографически "больше", чем str2
    См. также:
    sicmp std.algorithm.comparison.cmp
    Примеры:
    writeln(icmp("Rußland", "Russland")); // 0
    writeln(icmp("ᾩ -> \u1F70\u03B9", "\u1F61\u03B9 -> ᾲ")); // 0
    
    Примеры:
    Используя std.utf.byUTF и его аналоги, можно избежать выделения памяти GC при автоматическом декодировании и исключений, что делает icmp @safe @nogc nothrow pure.
    import std.utf : byDchar;
    
    writeln(icmp("Rußland".byDchar, "Russland".byDchar)); // 0
    writeln(icmp("ᾩ -> \u1F70\u03B9".byDchar, "\u1F61\u03B9 -> ᾲ".byDchar)); // 0
    
    pure nothrow @nogc @safe ubyte combiningClass(dchar ch);

    Возвращает комбинирующий класс ch.

    Примеры:
    // shorten the code
    alias CC = combiningClass;
    
    // combining tilda
    writeln(CC('\u0303')); // 230
    // combining ring below
    writeln(CC('\u0325')); // 220
    // the simple consequence is that  "tilda" should be
    // placed after a "ring below" in a sequence
    
    enum UnicodeDecomposition: int;

    Тип разложения символов Юникода.

    Canonical

    Каноническое разложение. Результат является канонически эквивалентной последовательностью.

    Compatibility

    Разложение по совместимости. Результат является последовательностью, эквивалентной по совместимости.

    Примечание
    Разложение по совместимости — это **потерянное** преобразование, обычно подходящее только для нечеткого поиска и внутренней обработки.
    pure nothrow @safe dchar compose(dchar first, dchar second);

    Попытка канонически объединить 2 символа. Возвращает объединенный символ, если они объединяются, и dchar.init в противном случае.

    Предполагается, что first идет перед second в исходном тексте, обычно означая, что первый — это стартовый символ.

    Примечание
    Силлабические структуры Хангль не обрабатываются этой функцией. См. composeJamo ниже.
    Примеры:
    writeln(compose('A', '\u0308')); // '\u00C4'
    writeln(compose('A', 'B')); // dchar.init
    writeln(compose('C', '\u0301')); // '\u0106'
    // note that the starter is the first one
    // thus the following doesn't compose
    writeln(compose('\u0308', 'A')); // dchar.init
    
    @safe Grapheme decompose(UnicodeDecomposition decompType = Canonical)(dchar ch);

    Возвращает полное каноническое (по умолчанию) или разложение по совместимости символа ch. Если разложение недоступно, возвращает Grapheme с самим ch.

    Примечание
    Эта функция также выполняет разложение силлабических структур хангуль согласно стандарту.
    См. также:
    decomposeHangul для ограниченной версии, которая учитывает только силлабические структуры хангуль, но не другие разложения.
    Примеры:
    import std.algorithm.comparison : equal;
    
    writeln(compose('A', '\u0308')); // '\u00C4'
    writeln(compose('A', 'B')); // dchar.init
    writeln(compose('C', '\u0301')); // '\u0106'
    // note that the starter is the first one
    // thus the following doesn't compose
    writeln(compose('\u0308', 'A')); // dchar.init
    
    assert(decompose('Ĉ')[].equal("C\u0302"));
    assert(decompose('D')[].equal("D"));
    assert(decompose('\uD4DC')[].equal("\u1111\u1171\u11B7"));
    assert(decompose!Compatibility('¹')[].equal("1"));
    
    @safe Grapheme decomposeHangul(dchar ch);

    Разлагает силлабическую структуру хангуль. Если ch не является составной силлабической структурой, эта функция возвращает Grapheme, содержащую только ch как есть.

    Примеры:
    import std.algorithm.comparison : equal;
    assert(decomposeHangul('\uD4DB')[].equal("\u1111\u1171\u11B6"));
    
    pure nothrow @nogc @safe dchar composeJamo(dchar lead, dchar vowel, dchar trailing = (dchar).init);

    Попытка составить силлабическую структуру хангуль из ведущего согласного (lead), гласного (vowel) и необязательного конечного согласного (trailing) джамо.

    При успехе возвращает составленную силлабическую структуру хангуль LV или LVT.

    Если какой-либо из lead и vowel не является действительным джамо хангуль соответствующего класса символов, возвращает dchar.init.

    Примеры:
    writeln(composeJamo('\u1111', '\u1171', '\u11B6')); // '\uD4DB'
    // leaving out T-vowel, or passing any codepoint
    // that is not trailing consonant composes an LV-syllable
    writeln(composeJamo('\u1111', '\u1171')); // '\uD4CC'
    writeln(composeJamo('\u1111', '\u1171', ' ')); // '\uD4CC'
    writeln(composeJamo('\u1111', 'A')); // dchar.init
    writeln(composeJamo('A', '\u1171')); // dchar.init
    
    END_OF_DOCUMENT_MARKER
    enum NormalizationForm: int;

    Тип перечисления для форм нормализации, передаваемый в качестве шаблонного параметра для функций, таких как normalize.

    NFC

    NFD

    NFKC

    NFKD

    Сокращённые псевдонимы значений, указывающих формы нормализации.

    inout(C)[] normalize(NormalizationForm norm = NFC, C)(inout(C)[] input);

    Возвращает input строку, нормализованную до выбранной формы. По умолчанию используется форма C.

    Дополнительную информацию о формах нормализации см. в разделе нормализации.

    Примечание
    В тех случаях, когда интересующая строка уже нормализована, она возвращается без изменений, и выделение памяти не происходит.
    Примеры:
    // any encoding works
    wstring greet = "Hello world";
    assert(normalize(greet) is greet); // the same exact slice
    
    // An example of a character with all 4 forms being different:
    // Greek upsilon with acute and hook symbol (code point 0x03D3)
    writeln(normalize!NFC("ϓ")); // "\u03D3"
    writeln(normalize!NFD("ϓ")); // "\u03D2\u0301"
    writeln(normalize!NFKC("ϓ")); // "\u038E"
    writeln(normalize!NFKD("ϓ")); // "\u03A5\u0301"
    
    bool allowedIn(NormalizationForm norm)(dchar ch);

    Проверяет, разрешен ли dchar ch всегда (Quick_Check=YES) в форме нормализации norm.

    Примеры:
    // e.g. Cyrillic is always allowed, so is ASCII
    assert(allowedIn!NFC('я'));
    assert(allowedIn!NFD('я'));
    assert(allowedIn!NFKC('я'));
    assert(allowedIn!NFKD('я'));
    assert(allowedIn!NFC('Z'));
    
    pure nothrow @nogc @safe bool isWhite(dchar c);

    Является ли c символом Unicode пробела символа. (общая категория Unicode: часть C0 (табуляция, вертикальная табуляция, подача формы, возврат каретки и перевод строки), Zs, Zl, Zp и NEL (U+0085)).

    pure nothrow @nogc @safe bool isLower(dchar c);

    Возвращает значение, показывающее, является ли c символом Unicode строчной буквы символа.

    pure nothrow @nogc @safe bool isUpper(dchar c);

    Возвращает значение, показывающее, является ли c символом Unicode заглавной буквы символа.

    auto asLowerCase(Range)(Range str)
    Constraints: if (isInputRange!Range && isSomeChar!(ElementEncodingType!Range) && !isConvertibleToString!Range);

    auto asUpperCase(Range)(Range str)
    Constraints: if (isInputRange!Range && isSomeChar!(ElementEncodingType!Range) && !isConvertibleToString!Range);

    Преобразование диапазона ввода или строки в верхний или нижний регистр.

    Не выделяет память. Символы в формате UTF-8 или UTF-16, которые не могут быть декодированы, обрабатываются как std.utf.replacementDchar.

    Параметры:
    Диапазон str строка или диапазон символов
    Возвращает:
    диапазон ввода dchar
    См. также:
    toUpper, toLower
    Примеры:
    import std.algorithm.comparison : equal;
    
    assert("hEllo".asUpperCase.equal("HELLO"));
    
    auto asCapitalized(Range)(Range str)
    Constraints: if (isInputRange!Range && isSomeChar!(ElementEncodingType!Range) && !isConvertibleToString!Range);

    Преобразование диапазона ввода или строки в заглавные буквы, что означает преобразование первого символа в верхний регистр, а последующих – в нижний.

    Не выделяет память. Символы в формате UTF-8 или UTF-16, которые не могут быть декодированы, обрабатываются как std.utf.replacementDchar.

    Параметры:
    Диапазон str строка или диапазон символов
    Возвращает:
    диапазон ввода dchar
    См. также:
    toUpper, toLower asUpperCase, asLowerCase
    Примеры:
    import std.algorithm.comparison : equal;
    
    assert("hEllo".asCapitalized.equal("Hello"));
    
    pure @trusted void toLowerInPlace(C)(ref C[] s)
    Constraints: if (is(C == char) || is(C == wchar) || is(C == dchar));

    Преобразует s в нижний регистр (путем выполнения отображения Unicode в нижний регистр) на месте. Для некоторых символов длина строки может увеличиться после преобразования, в этом случае функция перераспределяет память ровно один раз. Если s не содержит символов верхнего регистра, то s остается без изменений.

    pure @trusted void toUpperInPlace(C)(ref C[] s)
    Constraints: if (is(C == char) || is(C == wchar) || is(C == dchar));

    Преобразует s в верхний регистр (путем выполнения отображения Unicode в верхний регистр) на месте. Для некоторых символов длина строки может увеличиться после преобразования, в этом случае функция перераспределяет память ровно один раз. Если s не содержит символов нижнего регистра, то s остается без изменений.

    pure nothrow @nogc @safe dchar toLower(dchar c);

    Если c является символом Unicode верхнего регистра символа, то возвращается его эквивалент в нижнем регистре. В противном случае возвращается c.

    Предупреждение
    некоторые алфавиты, такие как немецкий и греческий, не имеют взаимно однозначного отображения верхнего и нижнего регистра. Используйте перегрузку toLower, которая принимает всю строку.
    ElementEncodingType!S[] toLower(S)(S s)
    Constraints: if (isSomeString!S || isRandomAccessRange!S && hasLength!S && hasSlicing!S && isSomeChar!(ElementType!S));

    Создаёт новый массив, идентичный s, за исключением того, что все его символы преобразуются в нижний регистр (путем выполнения отображения Unicode в нижний регистр). Если ни один из s символов не был изменён, то возвращается s само по себе, если s является типом наподобие string.

    Параметры:
    S s Диапазон случайного доступа символов
    Возвращает:
    Массив с тем же типом элементов, что и s.
    pure nothrow @nogc @safe dchar toUpper(dchar c);

    Если c является символом Unicode нижнего регистра символа, то возвращается его эквивалент в верхнем регистре. В противном случае возвращается c.

    Предупреждение
    некоторые алфавиты, такие как немецкий и греческий, не имеют взаимно однозначного отображения верхнего и нижнего регистра. Используйте перегрузку toUpper, которая принимает всю строку вместо этого.
    toUpper может использоваться как аргумент к std.algorithm.iteration.map для создания алгоритма, который может преобразовывать диапазон символов в верхний регистр без выделения памяти. Строка затем может быть создана с помощью std.algorithm.mutation.copy для отправки в std.array.appender.
    Примеры:
    import std.algorithm.iteration : map;
    import std.algorithm.mutation : copy;
    import std.array : appender;
    
    auto abuf = appender!(char[])();
    "hello".map!toUpper.copy(abuf);
    writeln(abuf.data); // "HELLO"
    
    ElementEncodingType!S[] toUpper(S)(S s)
    Constraints: if (isSomeString!S || isRandomAccessRange!S && hasLength!S && hasSlicing!S && isSomeChar!(ElementType!S));

    Выделяет новый массив, идентичный s, за исключением того, что все его символы преобразуются в верхний регистр (путем выполнения отображения Unicode в верхний регистр). Если ни один из s символов не был изменён, то возвращается s само по себе, если s является типом наподобие string.

    Параметры:
    S s Диапазон случайного доступа символов
    Возвращает:
    Новый массив с тем же типом элементов, что и s.
    pure nothrow @nogc @safe bool isAlpha(dchar c);

    Возвращает значение, показывающее, является ли c буквенным символом Unicode символа (общая категория Unicode: Буквенный).

    pure nothrow @nogc @safe bool isMark(dchar c);

    Возвращает значение, показывающее, является ли c символом-меткой Unicode (общая категория Unicode: Mn, Me, Mc).

    pure nothrow @nogc @safe bool isNumber(dchar c);

    Возвращает значение, показывающее, является ли c числовым символом Unicode символа (общая категория Unicode: Nd, Nl, No).

    pure nothrow @nogc @safe bool isAlphaNum(dchar c);

    Возвращает значение, показывающее, является ли c буквенным символом Unicode символа или числом. (общая категория Unicode: Буквенный, Nd, Nl, No).

    Параметры:
    dchar c любой символ Unicode
    Возвращает:
    true, если символ принадлежит категориям Unicode Alphabetic, Nd, Nl или No
    pure nothrow @nogc @safe bool isPunctuation(dchar c);

    Возвращает значение, показывающее, является ли c символом пунктуации Unicode символа (общая категория Unicode: Pd, Ps, Pe, Pc, Po, Pi, Pf).

    pure nothrow @nogc @safe bool isSymbol(dchar c);

    Возвращает значение, показывающее, является ли c символом Unicode символа (общая категория Unicode: Sm, Sc, Sk, So).

    pure nothrow @nogc @safe bool isSpace(dchar c);

    Возвращает значение, показывающее, является ли c символом пробела Unicode символа (общая категория Unicode: Zs)

    Примечание
    Это не включает '\n', '\r', '\t' и другие символы, не являющиеся пробелами символа. Для более распространенных менее строгих семантик см. isWhite.
    pure nothrow @nogc @safe bool isGraphical(dchar c);

    Возвращает, является ли c графическим символом Юникода (общая категория Юникода: L, M, N, P, S, Zs).

    pure nothrow @nogc @safe bool isControl(dchar c);

    Возвращает, является ли c управляющим символом Юникода (общая категория Юникода: Cc).

    pure nothrow @nogc @safe bool isFormat(dchar c);

    Возвращает, является ли c символом форматирования Юникода (общая категория Юникода: Cf).

    pure nothrow @nogc @safe bool isPrivateUse(dchar c);

    Возвращает, является ли c кодовой точкой Юникода для частного использования (общая категория Юникода: Co).

    pure nothrow @nogc @safe bool isSurrogate(dchar c);

    Возвращает, является ли c кодовой точкой Юникода, являющейся суррогатом (общая категория Юникода: Cs).

    pure nothrow @nogc @safe bool isSurrogateHi(dchar c);

    Возвращает, является ли c старшим суррогатом Юникода (ведущий суррогат).

    pure nothrow @nogc @safe bool isSurrogateLo(dchar c);

    Возвращает, является ли c младшим суррогатом Юникода (завершающий суррогат).

    pure nothrow @nogc @safe bool isNonCharacter(dchar c);

    Возвращает, является ли c символом Юникода, не являющимся символом, т. е. кодовой точкой без назначенного абстрактного символа. (общая категория Юникода: Cn)

    © 1999–2021 The D Language Foundation
    Licensed under the Boost License 1.0.
    https://dlang.org/phobos/std_uni.html

    Spec-Zone.ru

    Настройки Оффлайн Что нового Помощь О нас
    Spec-Zone .ru
    спецификации, руководства, описания, API