rusi/unicode.c

558 lines
17 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#включить "руси.з"
// Кодирует символ 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(&п, п);
шир += ширина_символа(зн);
}
возврат шир;
}