Files
doris/be/src/vec/common/format_ip.h

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