ClickHouse
106 строк · 2.8 Кб
1#include <Functions/FunctionFactory.h>2#include <Functions/FunctionUnaryArithmetic.h>3
4namespace DB5{
6namespace ErrorCodes7{
8extern const int NOT_IMPLEMENTED;9}
10
11namespace
12{
13template <typename T>14requires std::is_integral_v<T>15T byteSwap(T x)16{
17return std::byteswap(x);18}
19
20template <typename T>21requires std::is_same_v<T, UInt128> || std::is_same_v<T, Int128> || std::is_same_v<T, UInt256> || std::is_same_v<T, Int256>22T byteSwap(T x)23{
24T dest;25reverseMemcpy(&dest, &x, sizeof(T));26return dest;27}
28
29template <typename T>30T byteSwap(T)31{
32throw Exception(ErrorCodes::NOT_IMPLEMENTED, "byteSwap() is not implemented for {} datatype", demangle(typeid(T).name()));33}
34
35template <typename T>36struct ByteSwapImpl37{
38using ResultType = T;39static constexpr const bool allow_string_or_fixed_string = false;40static T apply(T x) { return byteSwap<T>(x); }41
42#if USE_EMBEDDED_COMPILER43static constexpr bool compilable = false;44#endif45};46
47struct NameByteSwap48{
49static constexpr auto name = "byteSwap";50};51using FunctionByteSwap = FunctionUnaryArithmetic<ByteSwapImpl, NameByteSwap, true>;52
53}
54
55template <>56struct FunctionUnaryArithmeticMonotonicity<NameByteSwap>57{
58static bool has() { return false; }59static IFunction::Monotonicity get(const Field &, const Field &) { return {}; }60};61
62REGISTER_FUNCTION(ByteSwap)63{
64factory.registerFunction<FunctionByteSwap>(65FunctionDocumentation{66.description = R"(67Reverses the bytes of an integer, i.e. changes its [endianness](https://en.wikipedia.org/wiki/Endianness).
68
69**Example**
70
71```sql
72byteSwap(3351772109)
73```
74
75Result:
76
77```result
78┌─byteSwap(3351772109)─┐
79│ 3455829959 │
80└──────────────────────┘
81```
82
83The above example can be worked out in the following manner:
841. Convert the base-10 integer to its equivalent hexadecimal format in big-endian format, i.e. 3351772109 -> C7 C7 FB CD (4 bytes)
852. Reverse the bytes, i.e. C7 C7 FB CD -> CD FB C7 C7
863. Convert the result back to an integer assuming big-endian, i.e. CD FB C7 C7 -> 3455829959
87
88One 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"}},103FunctionFactory::CaseInsensitive);104}
105
106}
107