ClickHouse

Форк
0
/
byteSwap.cpp 
106 строк · 2.8 Кб
1
#include <Functions/FunctionFactory.h>
2
#include <Functions/FunctionUnaryArithmetic.h>
3

4
namespace DB
5
{
6
namespace ErrorCodes
7
{
8
extern const int NOT_IMPLEMENTED;
9
}
10

11
namespace
12
{
13
template <typename T>
14
requires std::is_integral_v<T>
15
T byteSwap(T x)
16
{
17
    return std::byteswap(x);
18
}
19

20
template <typename T>
21
requires std::is_same_v<T, UInt128> || std::is_same_v<T, Int128> || std::is_same_v<T, UInt256> || std::is_same_v<T, Int256>
22
T byteSwap(T x)
23
{
24
    T dest;
25
    reverseMemcpy(&dest, &x, sizeof(T));
26
    return dest;
27
}
28

29
template <typename T>
30
T byteSwap(T)
31
{
32
    throw Exception(ErrorCodes::NOT_IMPLEMENTED, "byteSwap() is not implemented for {} datatype", demangle(typeid(T).name()));
33
}
34

35
template <typename T>
36
struct ByteSwapImpl
37
{
38
    using ResultType = T;
39
    static constexpr const bool allow_string_or_fixed_string = false;
40
    static T apply(T x) { return byteSwap<T>(x); }
41

42
#if USE_EMBEDDED_COMPILER
43
    static constexpr bool compilable = false;
44
#endif
45
};
46

47
struct NameByteSwap
48
{
49
    static constexpr auto name = "byteSwap";
50
};
51
using FunctionByteSwap = FunctionUnaryArithmetic<ByteSwapImpl, NameByteSwap, true>;
52

53
}
54

55
template <>
56
struct FunctionUnaryArithmeticMonotonicity<NameByteSwap>
57
{
58
    static bool has() { return false; }
59
    static IFunction::Monotonicity get(const Field &, const Field &) { return {}; }
60
};
61

62
REGISTER_FUNCTION(ByteSwap)
63
{
64
    factory.registerFunction<FunctionByteSwap>(
65
        FunctionDocumentation{
66
            .description = R"(
67
Reverses the bytes of an integer, i.e. changes its [endianness](https://en.wikipedia.org/wiki/Endianness).
68

69
**Example**
70

71
```sql
72
byteSwap(3351772109)
73
```
74

75
Result:
76

77
```result
78
┌─byteSwap(3351772109)─┐
79
│           3455829959 │
80
└──────────────────────┘
81
```
82

83
The above example can be worked out in the following manner:
84
1. Convert the base-10 integer to its equivalent hexadecimal format in big-endian format, i.e. 3351772109 -> C7 C7 FB CD (4 bytes)
85
2. Reverse the bytes, i.e. C7 C7 FB CD -> CD FB C7 C7
86
3. Convert the result back to an integer assuming big-endian, i.e. CD FB C7 C7  -> 3455829959
87

88
One use-case of this function is reversing IPv4s:
89

90
```result
91
┌─toIPv4(byteSwap(toUInt32(toIPv4('205.251.199.199'))))─┐
92
│ 199.199.251.205                                       │
93
└───────────────────────────────────────────────────────┘
94
```
95
)",
96
            .examples{
97
                {"8-bit", "SELECT byteSwap(54)", "54"},
98
                {"16-bit", "SELECT byteSwap(4135)", "10000"},
99
                {"32-bit", "SELECT byteSwap(3351772109)", "3455829959"},
100
                {"64-bit", "SELECT byteSwap(123294967295)", "18439412204227788800"},
101
            },
102
            .categories{"Mathematical", "Arithmetic"}},
103
        FunctionFactory::CaseInsensitive);
104
}
105

106
}
107

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

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

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

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