rusi/unicode.c

558 lines
17 KiB
C
Raw Normal View History

#включить "руси.з"
// Кодирует символ Unicode в последовательность UTF-8.
// Возвращает количество записанных байт (от 1 до 4).
цел encode_utf8(символ *буф, uint32_t зн) {
стат конст uint32_t МАСКИ[] = {
0x00000000,
0x0000007F,
0x000007FF,
0x0000FFFF,
0x0010FFFF,
};
цел длина;
если (зн <= 0x7F)
длина = 1;
иначе если (зн <= 0x7FF)
длина = 2;
иначе если (зн <= 0xFFFF)
длина = 3;
иначе если (зн <= 0x10FFFF)
длина = 4;
иначе
возврат 0;
если (зн >= 0xD800 && зн <= 0xDFFF)
возврат 0;
символ врем[4];
цел поз = 0;
для (цел ш = 0; ш < длина - 1; ш++) {
врем[поз++] = 0x80 | (зн & 0x3F);
зн >>= 6;
}
стат конст uint8_t МЕТКАЕРВОГО[] = {
0x00,
0x00,
0xC0,
0xE0,
0xF0,
};
врем[поз++] = МЕТКАЕРВОГО[длина] | зн;
для (цел ш = 0; ш < длина; ш++)
буф[ш] = врем[длина - 1 - ш];
возврат длина;
}
uint32_t decode_utf8(символ **нов_поз, символ *п) {
беззнак символ первый = (беззнак символ)*п;
если (первый < 0x80) {
*нов_поз = п + 1;
возврат первый;
}
цел длина;
uint32_t рез;
uint32_t мин_знач;
если ((первый & 0xF8) == 0xF0) {
длина = 4;
рез = первый & 0x07;
мин_знач = 0x10000;
} иначе если ((первый & 0xF0) == 0xE0) {
длина = 3;
рез = первый & 0x0F;
мин_знач = 0x800;
} иначе если ((первый & 0xE0) == 0xC0) {
длина = 2;
рез = первый & 0x1F;
мин_знач = 0x80;
} иначе {
error_at(п, "некорректная UTF-8 последовательность");
}
для (цел ш = 1; ш < длина; ш++) {
беззнак символ байт = (беззнак символ)п[ш];
если ((байт & 0xC0) != 0x80)
error_at(п, "некорректная UTF-8 последовательность");
рез = (рез << 6) | (байт & 0x3F);
}
если (рез < мин_знач)
error_at(п, "избыточная UTF-8 последовательность");
если (рез >= 0xD800 && рез <= 0xDFFF)
error_at(п, "суррогатные пары недопустимы в UTF-8");
если (рез > 0x10FFFF)
error_at(п, "кодпоинт превышает U+10FFFF");
*нов_поз = п + длина;
возврат рез;
}
стат бул в_диапазоне(uint32_t *диап, uint32_t зн) {
для (цел ш = 0; диап[ш] != (uint32_t)-1; ш += 2) {
если (зн >= диап[ш] && зн <= диап[ш + 1])
возврат истина;
}
возврат ложь;
}
бул is_ident1(uint32_t зн) {
если (зн == '_' || зн == '$')
возврат истина;
если (зн >= 'a' && зн <= 'z')
возврат истина;
если (зн >= 'A' && зн <= 'Z')
возврат истина;
если (зн < 0x80)
возврат ложь;
если (зн == 0x00A8 || зн == 0x00AA || зн == 0x00AD || зн == 0x00AF)
возврат истина;
если (зн >= 0x00B2 && зн <= 0x00B5)
возврат истина;
если (зн >= 0x00B7 && зн <= 0x00BA)
возврат истина;
если (зн >= 0x00BC && зн <= 0x00BE)
возврат истина;
если (зн >= 0x00C0 && зн <= 0x00D6)
возврат истина;
если (зн >= 0x00D8 && зн <= 0x00F6)
возврат истина;
если (зн >= 0x00F8 && зн <= 0x00FF)
возврат истина;
если (зн >= 0x0100 && зн <= 0x02FF)
возврат истина;
если (зн >= 0x0370 && зн <= 0x167F)
возврат истина;
если (зн >= 0x1681 && зн <= 0x180D)
возврат истина;
если (зн >= 0x180F && зн <= 0x1DBF)
возврат истина;
если (зн >= 0x1E00 && зн <= 0x1FFF)
возврат истина;
если (зн == 0x200B || зн == 0x200D)
возврат истина;
если (зн >= 0x202A && зн <= 0x202E)
возврат истина;
если (зн == 0x203F || зн == 0x2040 || зн == 0x2054)
возврат истина;
если (зн >= 0x2060 && зн <= 0x206F)
возврат истина;
если (зн >= 0x2070 && зн <= 0x20CF)
возврат истина;
если (зн >= 0x2100 && зн <= 0x218F)
возврат истина;
если (зн >= 0x2460 && зн <= 0x24FF)
возврат истина;
если (зн >= 0x2776 && зн <= 0x2793)
возврат истина;
если (зн >= 0x2C00 && зн <= 0x2DFF)
возврат истина;
если (зн >= 0x2E80 && зн <= 0x2FFF)
возврат истина;
если (зн == 0x3004 || зн == 0x3007)
возврат истина;
если (зн >= 0x3021 && зн <= 0x302F)
возврат истина;
если (зн >= 0x3031 && зн <= 0x303F)
возврат истина;
если (зн >= 0x3040 && зн <= 0xD7FF)
возврат истина;
если (зн >= 0xF900 && зн <= 0xFD3D)
возврат истина;
если (зн >= 0xFD40 && зн <= 0xFDCF)
возврат истина;
если (зн >= 0xFDF0 && зн <= 0xFE1F)
возврат истина;
если (зн >= 0xFE30 && зн <= 0xFE44)
возврат истина;
если (зн >= 0xFE47 && зн <= 0xFFFD)
возврат истина;
если (зн >= 0x10000 && зн <= 0xEFFFD) {
стат конст uint32_t НАЧ_ПЛОСКОСТЕЙ[] = {
0x10000, 0x20000, 0x30000, 0x40000, 0x50000,
0x60000, 0x70000, 0x80000, 0x90000, 0xA0000,
0xB0000, 0xC0000, 0xD0000, 0xE0000
};
стат конст цел ЧИСЛО_ПЛОСК = размер(НАЧ_ПЛОСКОСТЕЙ) / размер(НАЧ_ПЛОСКОСТЕЙ[0]);
для (цел ш = 0; ш < ЧИСЛО_ПЛОСК; ш++) {
если (зн >= НАЧ_ПЛОСКОСТЕЙ[ш] && зн <= НАЧ_ПЛОСКОСТЕЙ[ш] + 0xFFFD)
возврат истина;
}
}
если (зн >= 0x0400 && зн <= 0x04FF)
возврат истина;
если (зн >= 0x0500 && зн <= 0x052F)
возврат истина;
возврат ложь;
}
бул is_ident2(uint32_t зн) {
если (зн >= '0' && зн <= '9')
возврат истина;
если (зн == '$')
возврат истина;
если (is_ident1(зн))
возврат истина;
если (зн >= 0x0300 && зн <= 0x036F)
возврат истина;
если (зн >= 0x1DC0 && зн <= 0x1DFF)
возврат истина;
если (зн >= 0x20D0 && зн <= 0x20FF)
возврат истина;
если (зн >= 0xFE20 && зн <= 0xFE2F)
возврат истина;
возврат ложь;
}
стат цел ширина_символа(uint32_t зн) {
если (зн < 0x20)
возврат 0;
если (зн == 0x7F)
возврат 0;
если (зн == 0xA0)
возврат 0;
если (зн >= 0x0300 && зн <= 0x036F)
возврат 0;
если (зн >= 0x0483 && зн <= 0x0489)
возврат 0;
если (зн >= 0x0591 && зн <= 0x05BD)
возврат 0;
если (зн == 0x05BF || зн == 0x05C1 || зн == 0x05C2 || зн == 0x05C4 ||
зн == 0x05C5 || зн == 0x05C7)
возврат 0;
если (зн >= 0x0610 && зн <= 0x061A)
возврат 0;
если (зн >= 0x064B && зн <= 0x065F)
возврат 0;
если (зн == 0x0670)
возврат 0;
если (зн >= 0x06D6 && зн <= 0x06DC)
возврат 0;
если (зн >= 0x06DF && зн <= 0x06E4)
возврат 0;
если (зн == 0x06E7 || зн == 0x06E8 || зн == 0x06EA || зн == 0x06ED)
возврат 0;
если (зн == 0x0711)
возврат 0;
если (зн >= 0x0730 && зн <= 0x074A)
возврат 0;
если (зн >= 0x07A6 && зн <= 0x07B0)
возврат 0;
если (зн >= 0x0901 && зн <= 0x0902)
возврат 0;
если (зн == 0x093C)
возврат 0;
если (зн >= 0x0941 && зн <= 0x0948)
возврат 0;
если (зн == 0x094D)
возврат 0;
если (зн >= 0x0951 && зн <= 0x0954)
возврат 0;
если (зн == 0x0962 || зн == 0x0963)
возврат 0;
если (зн == 0x0981)
возврат 0;
если (зн == 0x09BC)
возврат 0;
если (зн == 0x09C1 || зн == 0x09C2 || зн == 0x09C3 || зн == 0x09C4)
возврат 0;
если (зн == 0x09CD)
возврат 0;
если (зн == 0x09E2 || зн == 0x09E3)
возврат 0;
если (зн == 0x0A01 || зн == 0x0A02)
возврат 0;
если (зн == 0x0A3C)
возврат 0;
если (зн == 0x0A41 || зн == 0x0A42)
возврат 0;
если (зн == 0x0A47 || зн == 0x0A48)
возврат 0;
если (зн >= 0x0A4B && зн <= 0x0A4D)
возврат 0;
если (зн == 0x0A70 || зн == 0x0A71)
возврат 0;
если (зн == 0x0A81 || зн == 0x0A82)
возврат 0;
если (зн == 0x0ABC)
возврат 0;
если (зн >= 0x0AC1 && зн <= 0x0AC5)
возврат 0;
если (зн == 0x0AC7 || зн == 0x0AC8)
возврат 0;
если (зн == 0x0ACD)
возврат 0;
если (зн == 0x0AE2 || зн == 0x0AE3)
возврат 0;
если (зн == 0x0B01)
возврат 0;
если (зн == 0x0B3C)
возврат 0;
если (зн == 0x0B3F)
возврат 0;
если (зн == 0x0B41 || зн == 0x0B42 || зн == 0x0B43)
возврат 0;
если (зн == 0x0B4D)
возврат 0;
если (зн == 0x0B56)
возврат 0;
если (зн == 0x0B82)
возврат 0;
если (зн == 0x0BC0)
возврат 0;
если (зн == 0x0BCD)
возврат 0;
если (зн >= 0x0C3E && зн <= 0x0C40)
возврат 0;
если (зн >= 0x0C46 && зн <= 0x0C48)
возврат 0;
если (зн >= 0x0C4A && зн <= 0x0C4D)
возврат 0;
если (зн == 0x0C55 || зн == 0x0C56)
возврат 0;
если (зн == 0x0CBC)
возврат 0;
если (зн == 0x0CBF)
возврат 0;
если (зн == 0x0CC6)
возврат 0;
если (зн == 0x0CCC || зн == 0x0CCD)
возврат 0;
если (зн == 0x0CE2 || зн == 0x0CE3)
возврат 0;
если (зн == 0x0D41 || зн == 0x0D42 || зн == 0x0D43)
возврат 0;
если (зн == 0x0D4D)
возврат 0;
если (зн == 0x0DCA)
возврат 0;
если (зн == 0x0DD2 || зн == 0x0DD3 || зн == 0x0DD4)
возврат 0;
если (зн == 0x0DD6)
возврат 0;
если (зн == 0x0E31)
возврат 0;
если (зн >= 0x0E34 && зн <= 0x0E3A)
возврат 0;
если (зн >= 0x0E47 && зн <= 0x0E4E)
возврат 0;
если (зн == 0x0EB1)
возврат 0;
если (зн >= 0x0EB4 && зн <= 0x0EB9)
возврат 0;
если (зн == 0x0EBB || зн == 0x0EBC)
возврат 0;
если (зн >= 0x0EC8 && зн <= 0x0ECD)
возврат 0;
если (зн == 0x0F18 || зн == 0x0F19)
возврат 0;
если (зн == 0x0F35)
возврат 0;
если (зн == 0x0F37)
возврат 0;
если (зн == 0x0F39)
возврат 0;
если (зн >= 0x0F71 && зн <= 0x0F7E)
возврат 0;
если (зн >= 0x0F80 && зн <= 0x0F84)
возврат 0;
если (зн == 0x0F86 || зн == 0x0F87)
возврат 0;
если (зн >= 0x0F90 && зн <= 0x0F97)
возврат 0;
если (зн >= 0x0F99 && зн <= 0x0FBC)
возврат 0;
если (зн == 0x0FC6)
возврат 0;
если (зн >= 0x102D && зн <= 0x1030)
возврат 0;
если (зн == 0x1032)
возврат 0;
если (зн == 0x1036 || зн == 0x1037)
возврат 0;
если (зн == 0x1039)
возврат 0;
если (зн == 0x1058 || зн == 0x1059)
возврат 0;
если (зн >= 0x1160 && зн <= 0x11FF)
возврат 0;
если (зн == 0x135F)
возврат 0;
если (зн == 0x1712 || зн == 0x1713 || зн == 0x1714)
возврат 0;
если (зн == 0x1732 || зн == 0x1733 || зн == 0x1734)
возврат 0;
если (зн == 0x1752 || зн == 0x1753)
возврат 0;
если (зн == 0x1772 || зн == 0x1773)
возврат 0;
если (зн >= 0x17B4 && зн <= 0x17B5)
возврат 0;
если (зн >= 0x17B7 && зн <= 0x17BD)
возврат 0;
если (зн == 0x17C6)
возврат 0;
если (зн >= 0x17C9 && зн <= 0x17D3)
возврат 0;
если (зн == 0x17DD)
возврат 0;
если (зн >= 0x180B && зн <= 0x180D)
возврат 0;
если (зн == 0x18A9)
возврат 0;
если (зн == 0x1920 || зн == 0x1921 || зн == 0x1922)
возврат 0;
если (зн == 0x1927 || зн == 0x1928)
возврат 0;
если (зн == 0x1932)
возврат 0;
если (зн == 0x1939 || зн == 0x193A || зн == 0x193B)
возврат 0;
если (зн == 0x1A17 || зн == 0x1A18)
возврат 0;
если (зн >= 0x1B00 && зн <= 0x1B03)
возврат 0;
если (зн == 0x1B34)
возврат 0;
если (зн >= 0x1B36 && зн <= 0x1B3A)
возврат 0;
если (зн == 0x1B3C)
возврат 0;
если (зн == 0x1B42)
возврат 0;
если (зн >= 0x1B6B && зн <= 0x1B73)
возврат 0;
если (зн >= 0x1DC0 && зн <= 0x1DCA)
возврат 0;
если (зн == 0x1DFE || зн == 0x1DFF)
возврат 0;
если (зн >= 0x200B && зн <= 0x200F)
возврат 0;
если (зн >= 0x202A && зн <= 0x202E)
возврат 0;
если (зн >= 0x2060 && зн <= 0x2063)
возврат 0;
если (зн >= 0x206A && зн <= 0x206F)
возврат 0;
если (зн >= 0x20D0 && зн <= 0x20EF)
возврат 0;
если (зн >= 0x302A && зн <= 0x302F)
возврат 0;
если (зн == 0x3099 || зн == 0x309A)
возврат 0;
если (зн == 0xA806)
возврат 0;
если (зн == 0xA80B)
возврат 0;
если (зн == 0xA825 || зн == 0xA826)
возврат 0;
если (зн == 0xFB1E)
возврат 0;
если (зн >= 0xFE00 && зн <= 0xFE0F)
возврат 0;
если (зн >= 0xFE20 && зн <= 0xFE23)
возврат 0;
если (зн == 0xFEFF)
возврат 0;
если (зн >= 0xFFF9 && зн <= 0xFFFB)
возврат 0;
если (зн == 0x10A01 || зн == 0x10A02 || зн == 0x10A03)
возврат 0;
если (зн == 0x10A05 || зн == 0x10A06)
возврат 0;
если (зн >= 0x10A0C && зн <= 0x10A0F)
возврат 0;
если (зн == 0x10A38 || зн == 0x10A39 || зн == 0x10A3A)
возврат 0;
если (зн == 0x10A3F)
возврат 0;
если (зн >= 0x1D167 && зн <= 0x1D169)
возврат 0;
если (зн >= 0x1D173 && зн <= 0x1D182)
возврат 0;
если (зн >= 0x1D185 && зн <= 0x1D18B)
возврат 0;
если (зн >= 0x1D1AA && зн <= 0x1D1AD)
возврат 0;
если (зн >= 0x1D242 && зн <= 0x1D244)
возврат 0;
если (зн == 0xE0001)
возврат 0;
если (зн >= 0xE0020 && зн <= 0xE007F)
возврат 0;
если (зн >= 0xE0100 && зн <= 0xE01EF)
возврат 0;
если (зн >= 0x1100 && зн <= 0x115F)
возврат 2;
если (зн == 0x2329 || зн == 0x232A)
возврат 2;
если (зн >= 0x2E80 && зн <= 0x303E)
возврат 2;
если (зн >= 0x3040 && зн <= 0xA4CF)
возврат 2;
если (зн >= 0xAC00 && зн <= 0xD7A3)
возврат 2;
если (зн >= 0xF900 && зн <= 0xFAFF)
возврат 2;
если (зн >= 0xFE10 && зн <= 0xFE19)
возврат 2;
если (зн >= 0xFE30 && зн <= 0xFE6F)
возврат 2;
если (зн >= 0xFF00 && зн <= 0xFF60)
возврат 2;
если (зн >= 0xFFE0 && зн <= 0xFFE6)
возврат 2;
если (зн >= 0x1F000 && зн <= 0x1F644)
возврат 2;
если (зн >= 0x20000 && зн <= 0x3FFFD)
возврат 2;
возврат 1;
}
цел display_width(символ *п, цел длина) {
символ *конец = п + длина;
цел шир = 0;
пока (п < конец) {
uint32_t зн = decode_utf8(&п, п);
шир += ширина_символа(зн);
}
возврат шир;
}