100 lines
3.6 KiB
C++
100 lines
3.6 KiB
C++
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
// This file is copied from
|
|
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Common/formatIPv6.h
|
|
// and modified by Doris
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <bit>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <utility>
|
|
|
|
constexpr size_t IPV4_BINARY_LENGTH = 4;
|
|
constexpr size_t IPV4_MAX_TEXT_LENGTH = 15; /// Does not count tail zero byte.
|
|
constexpr size_t IPV6_MAX_TEXT_LENGTH = 39;
|
|
constexpr size_t IPV4_MIN_NUM_VALUE = 0; //num value of '0.0.0.0'
|
|
constexpr size_t IPV4_MAX_NUM_VALUE = 4294967295; //num value of '255.255.255.255'
|
|
|
|
namespace doris::vectorized {
|
|
|
|
extern const std::array<std::pair<const char*, size_t>, 256> one_byte_to_string_lookup_table;
|
|
|
|
/** Format 4-byte binary sequesnce as IPv4 text: 'aaa.bbb.ccc.ddd',
|
|
* expects in out to be in BE-format, that is 0x7f000001 => "127.0.0.1".
|
|
*
|
|
* Any number of the tail bytes can be masked with given mask string.
|
|
*
|
|
* Assumptions:
|
|
* src is IPV4_BINARY_LENGTH long,
|
|
* dst is IPV4_MAX_TEXT_LENGTH long,
|
|
* mask_tail_octets <= IPV4_BINARY_LENGTH
|
|
* mask_string is NON-NULL, if mask_tail_octets > 0.
|
|
*
|
|
* Examples:
|
|
* formatIPv4(&0x7f000001, dst, mask_tail_octets = 0, nullptr);
|
|
* > dst == "127.0.0.1"
|
|
* formatIPv4(&0x7f000001, dst, mask_tail_octets = 1, "xxx");
|
|
* > dst == "127.0.0.xxx"
|
|
* formatIPv4(&0x7f000001, dst, mask_tail_octets = 1, "0");
|
|
* > dst == "127.0.0.0"
|
|
*/
|
|
inline void formatIPv4(const unsigned char* src, size_t src_size, char*& dst,
|
|
uint8_t mask_tail_octets = 0, const char* mask_string = "xxx") {
|
|
const size_t mask_length = mask_string ? strlen(mask_string) : 0;
|
|
const size_t limit = std::min(IPV4_BINARY_LENGTH, IPV4_BINARY_LENGTH - mask_tail_octets);
|
|
const size_t padding = std::min(4 - src_size, limit);
|
|
for (size_t octet = 0; octet < padding; ++octet) {
|
|
*dst++ = '0';
|
|
*dst++ = '.';
|
|
}
|
|
|
|
for (size_t octet = 4 - src_size; octet < limit; ++octet) {
|
|
uint8_t value = 0;
|
|
if constexpr (std::endian::native == std::endian::little)
|
|
value = static_cast<uint8_t>(src[IPV4_BINARY_LENGTH - octet - 1]);
|
|
else
|
|
value = static_cast<uint8_t>(src[octet]);
|
|
const uint8_t len = one_byte_to_string_lookup_table[value].second;
|
|
const char* str = one_byte_to_string_lookup_table[value].first;
|
|
|
|
memcpy(dst, str, len);
|
|
dst += len;
|
|
|
|
*dst++ = '.';
|
|
}
|
|
|
|
for (size_t mask = 0; mask < mask_tail_octets; ++mask) {
|
|
memcpy(dst, mask_string, mask_length);
|
|
dst += mask_length;
|
|
|
|
*dst++ = '.';
|
|
}
|
|
|
|
dst--;
|
|
}
|
|
|
|
inline void formatIPv4(const unsigned char* src, char*& dst, uint8_t mask_tail_octets = 0,
|
|
const char* mask_string = "xxx") {
|
|
formatIPv4(src, 4, dst, mask_tail_octets, mask_string);
|
|
}
|
|
|
|
} // namespace doris::vectorized
|