1 | #include <Functions/IFunctionImpl.h> |
2 | #include <Functions/FunctionFactory.h> |
3 | #include <DataTypes/DataTypesNumber.h> |
4 | #include <Formats/FormatSettings.h> |
5 | #include <Columns/ColumnsNumber.h> |
6 | #include <IO/WriteBufferFromString.h> |
7 | #include <Common/UTF8Helpers.h> |
8 | #include <Common/assert_cast.h> |
9 | |
10 | |
11 | namespace DB |
12 | { |
13 | |
14 | /** visibleWidth(x) - calculates the approximate width when outputting the value in a text form to the console. |
15 | * In fact it calculate the number of Unicode code points. |
16 | * It does not support zero width and full width characters, combining characters, etc. |
17 | */ |
18 | class FunctionVisibleWidth : public IFunction |
19 | { |
20 | public: |
21 | static constexpr auto name = "visibleWidth" ; |
22 | static FunctionPtr create(const Context &) |
23 | { |
24 | return std::make_shared<FunctionVisibleWidth>(); |
25 | } |
26 | |
27 | bool useDefaultImplementationForNulls() const override { return false; } |
28 | ColumnNumbers getArgumentsThatDontImplyNullableReturnType(size_t /*number_of_arguments*/) const override { return {0}; } |
29 | |
30 | /// Get the name of the function. |
31 | String getName() const override |
32 | { |
33 | return name; |
34 | } |
35 | |
36 | size_t getNumberOfArguments() const override |
37 | { |
38 | return 1; |
39 | } |
40 | |
41 | DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override |
42 | { |
43 | return std::make_shared<DataTypeUInt64>(); |
44 | } |
45 | |
46 | bool useDefaultImplementationForConstants() const override { return true; } |
47 | |
48 | /// Execute the function on the block. |
49 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
50 | { |
51 | auto & src = block.getByPosition(arguments[0]); |
52 | size_t size = input_rows_count; |
53 | |
54 | auto res_col = ColumnUInt64::create(size); |
55 | auto & res_data = assert_cast<ColumnUInt64 &>(*res_col).getData(); |
56 | |
57 | /// For simplicity reasons, function is implemented by serializing into temporary buffer. |
58 | |
59 | String tmp; |
60 | FormatSettings format_settings; |
61 | for (size_t i = 0; i < size; ++i) |
62 | { |
63 | { |
64 | WriteBufferFromString out(tmp); |
65 | src.type->serializeAsText(*src.column, i, out, format_settings); |
66 | } |
67 | |
68 | res_data[i] = UTF8::countCodePoints(reinterpret_cast<const UInt8 *>(tmp.data()), tmp.size()); |
69 | } |
70 | |
71 | block.getByPosition(result).column = std::move(res_col); |
72 | } |
73 | }; |
74 | |
75 | |
76 | void registerFunctionVisibleWidth(FunctionFactory & factory) |
77 | { |
78 | factory.registerFunction<FunctionVisibleWidth>(); |
79 | } |
80 | |
81 | } |
82 | |