loom

Форк
0
/
InputStream.cpp 
139 строк · 3.1 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo
7
*/
8

9
#include "simodo/inout/token/InputStream.h"
10

11
#include <cassert>
12
#include <cstdint>
13

14
namespace
15
{
16
    template <int size>
17
    struct UTF_BOM
18
    {
19
        const unsigned char bytes[size];
20
    };
21

22
    static constexpr UTF_BOM<3> UTF8_BOM = {
23
        {0xEF, 0xBB, 0xBF}
24
    };
25
    static constexpr UTF_BOM<2> UTF16BE_BOM = {
26
        {0xFE, 0xFF}
27
    };
28
    static constexpr UTF_BOM<2> UTF16LE_BOM = {
29
        {0xFF, 0xFE}
30
    };
31
    static constexpr UTF_BOM<4> UTF32BE_BOM = {
32
        {0x00, 0x00, 0xFE, 0xFF}
33
    };
34
    static constexpr UTF_BOM<4> UTF32LE_BOM = {
35
        {0xFF, 0xFE, 0x00, 0x00}
36
    };
37

38
    template <int bom_size>
39
    static bool skipUtfBom(
40
        std::istream & is
41
        , const UTF_BOM<bom_size> bom)
42
    {    
43
        int i = 0;
44
        for (
45
            ; is.peek() == bom.bytes[i] && i < bom_size
46
            ; is.get(), ++i
47
        );
48

49
        if (i == bom_size) return true;
50

51
        for (
52
            ; 0 < i
53
            ; is.unget(), --i
54
        );
55

56
        return false;
57
    }
58
}
59

60
namespace simodo::inout
61
{
62
    char16_t InputStream::get() const
63
    {
64
        if (_surrogate_pair != 0)
65
        {
66
            char16_t ch = _surrogate_pair;
67
            _surrogate_pair = 0;
68
            return ch;
69
        }
70

71
        if (_in.eof())
72
            return std::char_traits<char16_t>::eof();
73

74
        if (_untouched)
75
        {
76
            skipUtfBom(_in, UTF8_BOM)
77
                || skipUtfBom(_in, UTF16BE_BOM)
78
                || skipUtfBom(_in, UTF16LE_BOM)
79
                || skipUtfBom(_in, UTF32BE_BOM)
80
                || skipUtfBom(_in, UTF32LE_BOM);
81

82
            _untouched = false;
83
        }
84

85
        int ch1 = _in.get();
86

87
        if (ch1 <= 0x7F)
88
            return static_cast<char16_t>(ch1);
89

90
        uint32_t code;
91
        int      count;
92

93
        if ((ch1 & 0b11100000) == 0b11000000)
94
        {
95
            count = 2;
96
            code = (ch1 & 0b00011111);
97
        }
98
        else if ((ch1 & 0b11110000) == 0b11100000)
99
        {
100
            count = 3;
101
            code = (ch1 & 0b00001111);
102
        }
103
        else
104
        {
105
            count = 4;
106
            code = (ch1 & 0b00000111);
107
        }
108

109
        for(int i=1; i < count; ++i)
110
        {
111
            int ch = _in.get();
112

113
            if (ch == std::char_traits<char16_t>::eof())
114
                break;
115

116
            code = (code << 6) + (static_cast<uint32_t>(ch) & 0b00111111);
117
        }
118

119
        if (code <= 0xD7FF ||
120
        ((code >= 0xE000) && (code <= 0xFFFF)) )
121
        {
122
            return static_cast<char16_t>(code);
123
        }
124
        /// \attention PVS Studio: V560 A part of conditional expression is always true: (code >= 0xD800).
125
        else if ((code >= 0xD800) && (code <= 0xDFFF))
126
        {
127
            // unicode replacement character
128
            return 0xFFFD;
129
        }
130
        else
131
        {
132
            // surrogate pair
133
            code -= 0x010000;
134
            _surrogate_pair = 0xD800 + ((code >> 10) & 0x3FF);
135
            return 0xDC00 + (code & 0x3FF);
136
        }
137
    }
138

139
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.