ClickHouse

Форк
0
119 строк · 3.4 Кб
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

17
struct TrimModeLeft
18
{
19
    static constexpr auto name = "trimLeft";
20
    static constexpr bool trim_left = true;
21
    static constexpr bool trim_right = false;
22
};
23

24
struct TrimModeRight
25
{
26
    static constexpr auto name = "trimRight";
27
    static constexpr bool trim_left = false;
28
    static constexpr bool trim_right = true;
29
};
30

31
struct TrimModeBoth
32
{
33
    static constexpr auto name = "trimBoth";
34
    static constexpr bool trim_left = true;
35
    static constexpr bool trim_right = true;
36
};
37

38
template <typename Mode>
39
class FunctionTrimImpl
40
{
41
public:
42
    static void vector(
43
        const ColumnString::Chars & data,
44
        const ColumnString::Offsets & offsets,
45
        ColumnString::Chars & res_data,
46
        ColumnString::Offsets & res_offsets)
47
    {
48
        size_t size = offsets.size();
49
        res_offsets.resize(size);
50
        res_data.reserve(data.size());
51

52
        size_t prev_offset = 0;
53
        size_t res_offset = 0;
54

55
        const UInt8 * start;
56
        size_t length;
57

58
        for (size_t i = 0; i < size; ++i)
59
        {
60
            execute(reinterpret_cast<const UInt8 *>(&data[prev_offset]), offsets[i] - prev_offset - 1, start, length);
61

62
            res_data.resize(res_data.size() + length + 1);
63
            memcpySmallAllowReadWriteOverflow15(&res_data[res_offset], start, length);
64
            res_offset += length + 1;
65
            res_data[res_offset - 1] = '\0';
66

67
            res_offsets[i] = res_offset;
68
            prev_offset = offsets[i];
69
        }
70
    }
71

72
    static void vectorFixed(const ColumnString::Chars &, size_t, ColumnString::Chars &)
73
    {
74
        throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Functions trimLeft, trimRight and trimBoth cannot work with FixedString argument");
75
    }
76

77
private:
78
    static void execute(const UInt8 * data, size_t size, const UInt8 *& res_data, size_t & res_size)
79
    {
80
        const char * char_data = reinterpret_cast<const char *>(data);
81
        const char * char_end = char_data + size;
82

83
        if constexpr (Mode::trim_left)
84
        { // NOLINT
85
            const char * found = find_first_not_symbols<' '>(char_data, char_end);
86
            size_t num_chars = found - char_data;
87
            char_data += num_chars;
88
        }
89

90
        if constexpr (Mode::trim_right)
91
        { // NOLINT
92
            const char * found = find_last_not_symbols_or_null<' '>(char_data, char_end);
93
            if (found)
94
                char_end = found + 1;
95
            else
96
                char_end = char_data;
97
        }
98

99
        res_data = reinterpret_cast<const UInt8 *>(char_data);
100
        res_size = char_end - char_data;
101
    }
102
};
103

104
using FunctionTrimLeft = FunctionStringToString<FunctionTrimImpl<TrimModeLeft>, TrimModeLeft>;
105
using FunctionTrimRight = FunctionStringToString<FunctionTrimImpl<TrimModeRight>, TrimModeRight>;
106
using FunctionTrimBoth = FunctionStringToString<FunctionTrimImpl<TrimModeBoth>, TrimModeBoth>;
107

108
}
109

110
REGISTER_FUNCTION(Trim)
111
{
112
    factory.registerFunction<FunctionTrimLeft>();
113
    factory.registerFunction<FunctionTrimRight>();
114
    factory.registerFunction<FunctionTrimBoth>();
115
    factory.registerAlias("ltrim", FunctionTrimLeft::name);
116
    factory.registerAlias("rtrim", FunctionTrimRight::name);
117
    factory.registerAlias("trim", FunctionTrimBoth::name);
118
}
119
}
120

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

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

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

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