Ответ 1
Нет ни одного канонического метода, подходящего для всех видов использования, но хорошей отправной точкой является алгоритм Unicode Grapheme Cluster Boundary на странице Unicode.org, на которую вы ссылаетесь. В принципе, Unicode предоставляет базу данных каждого свойства breakpheme break-функции кода, а затем описывает алгоритм, позволяющий решить, разрешен ли разрыв графема между двумя кодовыми точками на основе их назначенных свойств разрыва grapheme.
Вот часть реализации (на С++), с которой я играл некоторое время назад:
bool BoundaryAllowed(char32_t cp, char32_t cp2) {
// lbp: left break property; rbp: right break property
auto lbp = get_property_for_codepoint(cp),
rbp = get_property_for_codepoint(cp2);
// Do not break between a CR and LF. Otherwise, break before and after
// controls.
if ((CR == lbp && LF == rbp)) {
// The Unicode grapheme boundary algorithm does not handle LFCR new lines
return false;
}
if (Control == lbp || CR == lbp || LF == lbp || Control == rbp || CR == rbp ||
LF == rbp) {
return true;
}
// Do not break Hangul syllable sequences.
if ((L == lbp && (L == rbp || V == rbp || LV == rbp || LVT == rbp)) ||
((LV == lbp || V == lbp) && (V == rbp || T == rbp)) ||
((LVT == lbp || T == lbp) && (T == rbp))) {
return false;
}
// Do not break before extending characters.
if (Extend == rbp) {
return false;
}
// Do not break before SpacingMarks, or after Prepend characters.
if (Prepend == lbp || SpacingMark == rbp) {
return false;
}
return true; // Otherwise, break everywhere.
}
Чтобы получить диапазоны для разных типов кодовых точек, вам просто нужно посмотреть на базу данных символов Юникода. Файл с характеристиками разрыва графмы, который описывает их в терминах диапазонов, составляет около 1200 строк: http://www.unicode.org/Public/6.1.0/ucd/auxiliary/
Я не уверен, сколько стоит в игнорировании несимвольных кодовых точек, но если ваше использование требует этого, вы добавите это к своей реализации.