ClickHouse

Форк
0
/
encodeXMLComponent.cpp 
144 строки · 5.0 Кб
1
#include <Columns/ColumnString.h>
2
#include <Functions/FunctionFactory.h>
3
#include <Functions/FunctionStringToString.h>
4
#include <base/find_symbols.h>
5

6

7
namespace DB
8
{
9
namespace ErrorCodes
10
{
11
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
12
}
13

14
namespace
15
{
16
    struct EncodeXMLComponentName
17
    {
18
        static constexpr auto name = "encodeXMLComponent";
19
    };
20

21
    class FunctionEncodeXMLComponentImpl
22
    {
23
    public:
24
        static void vector(
25
            const ColumnString::Chars & data,
26
            const ColumnString::Offsets & offsets,
27
            ColumnString::Chars & res_data,
28
            ColumnString::Offsets & res_offsets)
29
        {
30
            /// 6 is the maximum size amplification (the maximum length of encoded entity: &quot;)
31
            res_data.resize(data.size() * 6);
32
            size_t size = offsets.size();
33
            res_offsets.resize(size);
34

35
            size_t prev_offset = 0;
36
            size_t res_offset = 0;
37

38
            for (size_t i = 0; i < size; ++i)
39
            {
40
                const char * src_data = reinterpret_cast<const char *>(&data[prev_offset]);
41
                size_t src_size = offsets[i] - prev_offset;
42
                size_t dst_size = execute(src_data, src_size, reinterpret_cast<char *>(res_data.data() + res_offset));
43

44
                res_offset += dst_size;
45
                res_offsets[i] = res_offset;
46
                prev_offset = offsets[i];
47
            }
48

49
            res_data.resize(res_offset);
50
        }
51

52
        [[noreturn]] static void vectorFixed(const ColumnString::Chars &, size_t, ColumnString::Chars &)
53
        {
54
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Function encodeXML cannot work with FixedString argument");
55
        }
56

57
    private:
58
        static size_t execute(const char * src, size_t src_size, char * dst)
59
        {
60
            const char * src_prev_pos = src;
61
            const char * src_curr_pos = src;
62
            const char * src_end = src + src_size;
63
            char * dst_pos = dst;
64

65
            while (true)
66
            {
67
                src_curr_pos = find_first_symbols<'<', '&', '>', '"', '\''>(src_curr_pos, src_end);
68

69
                if (src_curr_pos == src_end)
70
                {
71
                    break;
72
                }
73
                else if (*src_curr_pos == '<')
74
                {
75
                    size_t bytes_to_copy = src_curr_pos - src_prev_pos;
76
                    memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
77
                    dst_pos += bytes_to_copy;
78
                    memcpy(dst_pos, "&lt;", 4);
79
                    dst_pos += 4;
80
                    src_prev_pos = src_curr_pos + 1;
81
                    ++src_curr_pos;
82
                }
83
                else if (*src_curr_pos == '&')
84
                {
85
                    size_t bytes_to_copy = src_curr_pos - src_prev_pos;
86
                    memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
87
                    dst_pos += bytes_to_copy;
88
                    memcpy(dst_pos, "&amp;", 5);
89
                    dst_pos += 5;
90
                    src_prev_pos = src_curr_pos + 1;
91
                    ++src_curr_pos;
92
                }
93
                else if (*src_curr_pos == '>')
94
                {
95
                    size_t bytes_to_copy = src_curr_pos - src_prev_pos;
96
                    memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
97
                    dst_pos += bytes_to_copy;
98
                    memcpy(dst_pos, "&gt;", 4);
99
                    dst_pos += 4;
100
                    src_prev_pos = src_curr_pos + 1;
101
                    ++src_curr_pos;
102
                }
103
                else if (*src_curr_pos == '"')
104
                {
105
                    size_t bytes_to_copy = src_curr_pos - src_prev_pos;
106
                    memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
107
                    dst_pos += bytes_to_copy;
108
                    memcpy(dst_pos, "&quot;", 6);
109
                    dst_pos += 6;
110
                    src_prev_pos = src_curr_pos + 1;
111
                    ++src_curr_pos;
112
                }
113
                else if (*src_curr_pos == '\'')
114
                {
115
                    size_t bytes_to_copy = src_curr_pos - src_prev_pos;
116
                    memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
117
                    dst_pos += bytes_to_copy;
118
                    memcpy(dst_pos, "&apos;", 6);
119
                    dst_pos += 6;
120
                    src_prev_pos = src_curr_pos + 1;
121
                    ++src_curr_pos;
122
                }
123
            }
124

125
            if (src_prev_pos < src_curr_pos)
126
            {
127
                size_t bytes_to_copy = src_curr_pos - src_prev_pos;
128
                memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
129
                dst_pos += bytes_to_copy;
130
            }
131

132
            return dst_pos - dst;
133
        }
134
    };
135

136
    using FunctionEncodeXMLComponent = FunctionStringToString<FunctionEncodeXMLComponentImpl, EncodeXMLComponentName>;
137

138
}
139

140
REGISTER_FUNCTION(EncodeXMLComponent)
141
{
142
    factory.registerFunction<FunctionEncodeXMLComponent>();
143
}
144
}
145

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

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

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

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