2015-08-09 3 views
2

Учитывая строку UTF-8 (&str), я хочу узнать любой диапазон символов, которые не нормализованы (например, a\u{300} вместо \u{e0}).Как определить символы Unicode, которые не нормированы?

Как это сделать?

Редактировать: Благодаря DK для исправления моей неисправной последовательности UTF-8. Комбинирующий символ приходит послеa, не раньше.

ответ

1

Edit: Я просто понял, что причина результатов я получал то, что ваш пример строки имеет обратную. Комбинированная кодовая точка должна быть второй, а не первой. Я соответствующим образом обновил ответ.

Ну, это зависит от определения «нормализованного».

Например:

/*! 
Add this to a `Cargo.toml` manifest: 

```cargo 
[dependencies] 
unicode-normalization = "0.1.1" 
``` 
*/ 
extern crate unicode_normalization; 

fn main() { 
    for test_str in vec!["a\u{300}", "\u{e0}"] { 
     is_nfd(test_str); 
     is_nfkd(test_str); 
     is_nfc(test_str); 
     is_nfkc(test_str); 
    } 
} 

macro_rules! norm_test { 
    ($fn_name:ident, $norm_name:ident) => { 
     fn $fn_name(s: &str) { 
      use unicode_normalization::UnicodeNormalization; 
      println!("is_{}({:?}):", stringify!($norm_name), s); 
      let is_norm = s.chars().zip(s.$norm_name()) 
       .inspect(|&(a, b)| println!(" - ({:x}, {:x})", a as u32, b as u32)) 
       .all(|(a, b)| a == b); 
      println!(" is_norm: {}", is_norm); 
     } 
    }; 
} 

norm_test! { is_nfd, nfd } 
norm_test! { is_nfkd, nfkd } 
norm_test! { is_nfc, nfc } 
norm_test! { is_nfkc, nfkc } 

Это дает следующий результат:

is_nfd("a\u{300}"): 
- (61, 61) 
- (300, 300) 
is_norm: true 
is_nfkd("a\u{300}"): 
- (61, 61) 
- (300, 300) 
is_norm: true 
is_nfc("a\u{300}"): 
- (61, e0) 
is_norm: false 
is_nfkc("a\u{300}"): 
- (61, e0) 
is_norm: false 
is_nfd("\u{e0}"): 
- (e0, 61) 
is_norm: false 
is_nfkd("\u{e0}"): 
- (e0, 61) 
is_norm: false 
is_nfc("\u{e0}"): 
- (e0, e0) 
is_norm: true 
is_nfkc("\u{e0}"): 
- (e0, e0) 
is_norm: true 

Так "a\u{300}" является NFD и NFKD, в то время как это "\u{e0}" NFC и NFKC. Я не знаю никаких примеров, которые отличаются между вариантами K и non-K, хотя Unicode FAQ on Normalization, вероятно, объяснит все, что я могу.

+0

Так что, если я хочу обнаружить ненормированные диапазоны внутри строки, мне нужно сначала найти диапазоны символов, где только первый имеет «unicode_combining_class», равный нулю, конспектированный). – llogiq

+1

@DK: Вы можете увидеть пример форм K в http://www.unicode.org/reports/tr15/ (например, рисунок 6). По сути, NFD и NFC являются канонической эквивалентностью, а их коллеги K - более слабой эквивалентностью совместимости, которые включают в себя изменение подстрочного сценария/супер-скрипта на обычные персонажи (среди прочего). Например, 2 закодирован как 0032 2075 в NFD или NFC (где 2075 - 5 в позиции супер-сценария), но это 0032 0035 в NFKD или NFKC (где 0035 является обычным 5). –