source: icGREP/icgrep-devel/icgrep/UCD/UTF.h @ 6161

Last change on this file since 6161 was 5782, checked in by nmedfort, 18 months ago

Initial check-in of LookAhead? support; modified LineBreakKernel? to compute CR+LF using LookAhead?(1) + misc. fixes.

File size: 4.3 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include <UCD/unicode_set.h>
8using codepoint_t = UCD::codepoint_t;
9
10template <int Bits> class UTF {
11public:
12    static inline unsigned encoded_length(codepoint_t cp);
13    static inline codepoint_t max_codepoint_of_length(unsigned lgth);
14    static inline bool isLowCodePointAfterNthCodeUnit(codepoint_t cp, unsigned n);
15    static inline bool isHighCodePointAfterNthCodeUnit(codepoint_t cp, unsigned n);
16    static inline codepoint_t minCodePointWithCommonCodeUnits(codepoint_t cp, unsigned common);
17    static inline codepoint_t maxCodePointWithCommonCodeUnits(codepoint_t cp, unsigned common);
18    static inline unsigned nthCodeUnit(codepoint_t cp, unsigned n);
19};
20   
21template<> inline unsigned UTF<8>::encoded_length(codepoint_t cp) {
22    if (cp <= 0x7F) return 1;
23    else if (cp <= 0x7FF) return 2;
24    else if (cp <= 0xFFFF) return 3;
25    else return 4;
26}
27
28template<> inline codepoint_t UTF<8>::max_codepoint_of_length(unsigned length) {
29    if (length == 1) return 0x7F;
30    else if (length == 2) return 0x7FF;
31    else if (length == 3) return 0xFFFF;
32    else {
33        assert(length == 4);
34        return 0x10FFFF;
35    }
36}
37
38template <> inline unsigned UTF<8>::nthCodeUnit(codepoint_t cp, unsigned n) {
39    const auto length = UTF<8>::encoded_length(cp);
40    if (n == 1) {
41        switch (length) {
42            case 1: return static_cast<unsigned>(cp);
43            case 2: return static_cast<unsigned>(0xC0 | (cp >> 6));
44            case 3: return static_cast<unsigned>(0xE0 | (cp >> 12));
45            case 4: return static_cast<unsigned>(0xF0 | (cp >> 18));
46        }
47    }
48    return static_cast<unsigned>(0x80 | ((cp >> (6 * (length - n))) & 0x3F));
49}
50
51template<> inline codepoint_t UTF<8>::minCodePointWithCommonCodeUnits(codepoint_t cp, unsigned common) {
52    const auto length = UTF<8>::encoded_length(cp);
53    const auto mask = (static_cast<codepoint_t>(1) << (length - common) * 6) - 1;
54    const auto lo_cp = cp &~ mask;
55    return (lo_cp == 0) ? mask + 1 : lo_cp;
56}
57
58template<> inline codepoint_t UTF<8>::maxCodePointWithCommonCodeUnits(codepoint_t cp, unsigned common) {
59    const auto length = UTF<8>::encoded_length(cp);
60    const auto mask = (static_cast<codepoint_t>(1) << (length - common) * 6) - 1;
61    return cp | mask;
62}
63
64// Generic for UTF<8> or UTF<16>
65
66template<int Bits> inline bool UTF<Bits>::isLowCodePointAfterNthCodeUnit(codepoint_t cp, unsigned n) {
67    if (cp == 0) return true;
68    else if (UTF<Bits>::encoded_length(cp - 1) < UTF<Bits>::encoded_length(cp)) return true;
69    else return UTF<Bits>::nthCodeUnit(cp - 1, n) != UTF<Bits>::nthCodeUnit(cp, n);
70}
71
72template<int Bits> inline bool UTF<Bits>::isHighCodePointAfterNthCodeUnit(codepoint_t cp, unsigned n) {
73    if (cp == 0x10FFFF) return true;
74    else if (UTF<Bits>::encoded_length(cp + 1) > UTF<Bits>::encoded_length(cp)) return true;
75    else return UTF<Bits>::nthCodeUnit(cp + 1, n) != UTF<Bits>::nthCodeUnit(cp, n);
76}
77
78// UTF-16
79
80template<> inline unsigned UTF<16>::encoded_length(codepoint_t cp) {
81    if (cp <= 0xFFFF) return 1;
82    else return 2;
83}
84
85template<> inline unsigned UTF<16>::max_codepoint_of_length(unsigned length) {
86    if (length == 1) return 0xFFFF;
87    else {
88        assert(length == 2);
89        return 0x10FFFF;
90    }
91}
92
93template <> inline unsigned UTF<16>::nthCodeUnit(codepoint_t cp, unsigned n) {
94    const auto length = UTF<16>::encoded_length(cp);
95    if (length == 1) {
96        assert(n == 1);
97        return static_cast<unsigned>(cp);
98    }
99    else if (n == 1)
100        return static_cast<unsigned>(0xD800 | ((cp - 0x10000) >> 10));
101    else
102        return static_cast<unsigned>(0xDC00 | ((cp - 0x10000) & 0x3FF));
103}
104
105template<> inline codepoint_t UTF<16>::minCodePointWithCommonCodeUnits(codepoint_t cp, unsigned common) {
106    const auto len = UTF<16>::encoded_length(cp);
107    if (len == common) return cp;
108    else {
109        assert(len == 2);
110        assert(common == 1);
111        return cp & 0x1FFC00;
112    }
113}
114
115template<> inline codepoint_t UTF<16>::maxCodePointWithCommonCodeUnits(codepoint_t cp, unsigned common) {
116    const auto len = UTF<16>::encoded_length(cp);
117    const auto mask = (static_cast<codepoint_t>(1) << (len - common) * 10) - 1;
118    return cp | mask;
119}
Note: See TracBrowser for help on using the repository browser.