ClickHouse

Форк
0
/
initcapUTF8.cpp 
114 строк · 3.2 Кб
1
#include <DataTypes/DataTypeString.h>
2
#include <Functions/FunctionStringToString.h>
3
#include <Functions/LowerUpperUTF8Impl.h>
4
#include <Functions/FunctionFactory.h>
5
#include <Poco/Unicode.h>
6

7

8
namespace DB
9
{
10

11
namespace ErrorCodes
12
{
13
    extern const int BAD_ARGUMENTS;
14
}
15

16
namespace
17
{
18

19
struct InitcapUTF8Impl
20
{
21
    static void vector(
22
        const ColumnString::Chars & data,
23
        const ColumnString::Offsets & offsets,
24
        ColumnString::Chars & res_data,
25
        ColumnString::Offsets & res_offsets)
26
    {
27
        if (data.empty())
28
            return;
29
        res_data.resize(data.size());
30
        res_offsets.assign(offsets);
31
        array(data.data(), data.data() + data.size(), offsets, res_data.data());
32
    }
33

34
    [[noreturn]] static void vectorFixed(const ColumnString::Chars &, size_t, ColumnString::Chars &)
35
    {
36
        throw Exception(ErrorCodes::BAD_ARGUMENTS, "Function initcapUTF8 cannot work with FixedString argument");
37
    }
38

39
    static void processCodePoint(const UInt8 *& src, const UInt8 * src_end, UInt8 *& dst, bool& prev_alphanum)
40
    {
41
        size_t src_sequence_length = UTF8::seqLength(*src);
42
        auto src_code_point = UTF8::convertUTF8ToCodePoint(src, src_end - src);
43

44
        if (src_code_point)
45
        {
46
            bool alpha = Poco::Unicode::isAlpha(*src_code_point);
47
            bool alphanum = alpha || Poco::Unicode::isDigit(*src_code_point);
48

49
            int dst_code_point = *src_code_point;
50
            if (alphanum && !prev_alphanum)
51
            {
52
                if (alpha)
53
                    dst_code_point = Poco::Unicode::toUpper(*src_code_point);
54
            }
55
            else if (alpha)
56
            {
57
                dst_code_point = Poco::Unicode::toLower(*src_code_point);
58
            }
59
            prev_alphanum = alphanum;
60
            if (dst_code_point > 0)
61
            {
62
                size_t dst_sequence_length = UTF8::convertCodePointToUTF8(dst_code_point, dst, src_end - src);
63
                assert(dst_sequence_length <= 4);
64

65
                if (dst_sequence_length == src_sequence_length)
66
                {
67
                    src += dst_sequence_length;
68
                    dst += dst_sequence_length;
69
                    return;
70
                }
71
            }
72
        }
73

74
        *dst = *src;
75
        ++dst;
76
        ++src;
77
        prev_alphanum = false;
78
    }
79

80
private:
81

82
    static void array(const UInt8 * src, const UInt8 * src_end, const ColumnString::Offsets & offsets, UInt8 * dst)
83
    {
84
        const auto * offset_it = offsets.begin();
85
        const UInt8 * begin = src;
86

87
        /// handle remaining symbols, row by row (to avoid influence of bad UTF8 symbols from one row, to another)
88
        while (src < src_end)
89
        {
90
            const UInt8 * row_end = begin + *offset_it;
91
            chassert(row_end >= src);
92
            bool prev_alphanum = false;
93
            while (src < row_end)
94
                processCodePoint(src, row_end, dst, prev_alphanum);
95
            ++offset_it;
96
        }
97
    }
98
};
99

100
struct NameInitcapUTF8
101
{
102
    static constexpr auto name = "initcapUTF8";
103
};
104

105
using FunctionInitcapUTF8 = FunctionStringToString<InitcapUTF8Impl, NameInitcapUTF8>;
106

107
}
108

109
REGISTER_FUNCTION(InitcapUTF8)
110
{
111
    factory.registerFunction<FunctionInitcapUTF8>();
112
}
113

114
}
115

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

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

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

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