blob: 2d2b4d378418b5eb7791dc92391352f9af56b09e [file]
// Copyright 2023 Google LLC
//
// Licensed 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.
#ifndef RIEGELI_BYTES_WRITE_INT_INTERNAL_H_
#define RIEGELI_BYTES_WRITE_INT_INTERNAL_H_
#include <stddef.h>
#include <stdint.h>
#include <limits>
#include <type_traits>
#include "absl/numeric/int128.h"
#include "riegeli/base/arithmetic.h"
namespace riegeli::write_int_internal {
template <typename T, typename Target, typename Enable = void>
struct FitsIn;
template <typename T, typename Target>
struct FitsIn<T, Target,
std::enable_if_t<std::disjunction_v<
std::conjunction<IsUnsignedInt<T>, IsUnsignedInt<Target>>,
std::conjunction<IsSignedInt<T>, IsSignedInt<Target>>>>>
: std::bool_constant<(std::numeric_limits<T>::max() <=
std::numeric_limits<Target>::max())> {};
// `WriteDec()` with no width parameter writes no leading zeros, except for 0
// itself.
char* WriteDec(uint32_t src, char* dest);
char* WriteDec(uint64_t src, char* dest);
char* WriteDec(absl::uint128 src, char* dest);
char* WriteDec(int32_t src, char* dest);
char* WriteDec(int64_t src, char* dest);
char* WriteDec(absl::int128 src, char* dest);
// `WriteDecUnsigned()` with no width parameter writes no leading zeros, except
// for 0 itself.
template <typename T, std::enable_if_t<FitsIn<T, uint32_t>::value, int> = 0>
inline char* WriteDecUnsigned(T src, char* dest) {
return WriteDec(IntCast<uint32_t>(src), dest);
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint32_t>>,
FitsIn<T, uint64_t>>,
int> = 0>
inline char* WriteDecUnsigned(T src, char* dest) {
return WriteDec(IntCast<uint64_t>(src), dest);
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint64_t>>,
FitsIn<T, absl::uint128>>,
int> = 0>
inline char* WriteDecUnsigned(T src, char* dest) {
return WriteDec(IntCast<absl::uint128>(src), dest);
}
// `WriteDecSigned()` with no width parameter writes no leading zeros, except
// for 0 itself.
template <typename T, std::enable_if_t<FitsIn<T, int32_t>::value, int> = 0>
inline char* WriteDecSigned(T src, char* dest) {
return WriteDec(IntCast<int32_t>(src), dest);
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int32_t>>,
FitsIn<T, int64_t>>,
int> = 0>
inline char* WriteDecSigned(T src, char* dest) {
return WriteDec(IntCast<int64_t>(src), dest);
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int64_t>>,
FitsIn<T, absl::int128>>,
int> = 0>
inline char* WriteDecSigned(T src, char* dest) {
return WriteDec(IntCast<absl::int128>(src), dest);
}
// `WriteDec()` with a width parameter writes at least `width` characters.
char* WriteDec(uint32_t src, char* dest, size_t width);
char* WriteDec(uint64_t src, char* dest, size_t width);
char* WriteDec(absl::uint128 src, char* dest, size_t width);
char* WriteDec(int32_t src, char* dest, size_t width);
char* WriteDec(int64_t src, char* dest, size_t width);
char* WriteDec(absl::int128 src, char* dest, size_t width);
// `WriteDecUnsigned()` with a width parameter writes at least `width`
// characters.
template <typename T, std::enable_if_t<FitsIn<T, uint32_t>::value, int> = 0>
inline char* WriteDecUnsigned(T src, char* dest, size_t width) {
return width <= 1 ? WriteDec(IntCast<uint32_t>(src), dest)
: WriteDec(IntCast<uint32_t>(src), dest, width);
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint32_t>>,
FitsIn<T, uint64_t>>,
int> = 0>
inline char* WriteDecUnsigned(T src, char* dest, size_t width) {
return width <= 1 ? WriteDec(IntCast<uint64_t>(src), dest)
: WriteDec(IntCast<uint64_t>(src), dest, width);
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint64_t>>,
FitsIn<T, absl::uint128>>,
int> = 0>
inline char* WriteDecUnsigned(T src, char* dest, size_t width) {
return width <= 1 ? WriteDec(IntCast<absl::uint128>(src), dest)
: WriteDec(IntCast<absl::uint128>(src), dest, width);
}
// `WriteDecSigned()` with a width parameter writes at least `width` characters.
template <typename T, std::enable_if_t<FitsIn<T, int32_t>::value, int> = 0>
inline char* WriteDecSigned(T src, char* dest, size_t width) {
return width <= 1 ? WriteDec(IntCast<int32_t>(src), dest)
: WriteDec(IntCast<int32_t>(src), dest, width);
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int32_t>>,
FitsIn<T, int64_t>>,
int> = 0>
inline char* WriteDecSigned(T src, char* dest, size_t width) {
return width <= 1 ? WriteDec(IntCast<int64_t>(src), dest)
: WriteDec(IntCast<int64_t>(src), dest, width);
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int64_t>>,
FitsIn<T, absl::int128>>,
int> = 0>
inline char* WriteDecSigned(T src, char* dest, size_t width) {
return width <= 1 ? WriteDec(IntCast<absl::int128>(src), dest)
: WriteDec(IntCast<absl::int128>(src), dest, width);
}
// `WriteDecBackward()` writes no leading zeros, except for 0 itself.
char* WriteDecBackward(uint32_t src, char* dest);
char* WriteDecBackward(uint64_t src, char* dest);
char* WriteDecBackward(absl::uint128 src, char* dest);
char* WriteDecBackward(int32_t src, char* dest);
char* WriteDecBackward(int64_t src, char* dest);
char* WriteDecBackward(absl::int128 src, char* dest);
// `WriteDecUnsignedBackward()` writes no leading zeros, except for 0 itself.
template <typename T, std::enable_if_t<FitsIn<T, uint32_t>::value, int> = 0>
inline char* WriteDecUnsignedBackward(T src, char* dest) {
return WriteDecBackward(IntCast<uint32_t>(src), dest);
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint32_t>>,
FitsIn<T, uint64_t>>,
int> = 0>
inline char* WriteDecUnsignedBackward(T src, char* dest) {
return WriteDecBackward(IntCast<uint64_t>(src), dest);
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint64_t>>,
FitsIn<T, absl::uint128>>,
int> = 0>
inline char* WriteDecUnsignedBackward(T src, char* dest) {
return WriteDecBackward(IntCast<absl::uint128>(src), dest);
}
// `WriteDecSignedBackward()` writes no leading zeros, except for 0 itself.
template <typename T, std::enable_if_t<FitsIn<T, int32_t>::value, int> = 0>
inline char* WriteDecSignedBackward(T src, char* dest) {
return WriteDecBackward(IntCast<int32_t>(src), dest);
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int32_t>>,
FitsIn<T, int64_t>>,
int> = 0>
inline char* WriteDecSignedBackward(T src, char* dest) {
return WriteDecBackward(IntCast<int64_t>(src), dest);
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int64_t>>,
FitsIn<T, absl::int128>>,
int> = 0>
inline char* WriteDecSignedBackward(T src, char* dest) {
return WriteDecBackward(IntCast<absl::int128>(src), dest);
}
size_t StringifiedSize(uint32_t src);
size_t StringifiedSize(uint64_t src);
size_t StringifiedSize(absl::uint128 src);
size_t StringifiedSize(int32_t src);
size_t StringifiedSize(int64_t src);
size_t StringifiedSize(absl::int128 src);
template <typename T, std::enable_if_t<FitsIn<T, uint32_t>::value, int> = 0>
inline size_t StringifiedSizeUnsigned(T src) {
return StringifiedSize(IntCast<uint32_t>(src));
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint32_t>>,
FitsIn<T, uint64_t>>,
int> = 0>
inline size_t StringifiedSizeUnsigned(T src) {
return StringifiedSize(IntCast<uint64_t>(src));
}
template <typename T, std::enable_if_t<
std::conjunction_v<std::negation<FitsIn<T, uint64_t>>,
FitsIn<T, absl::uint128>>,
int> = 0>
inline size_t StringifiedSizeUnsigned(T src) {
return StringifiedSize(IntCast<absl::uint128>(src));
}
template <typename T, std::enable_if_t<FitsIn<T, int32_t>::value, int> = 0>
inline size_t StringifiedSizeSigned(T src) {
return StringifiedSize(IntCast<int32_t>(src));
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int32_t>>,
FitsIn<T, int64_t>>,
int> = 0>
inline size_t StringifiedSizeSigned(T src) {
return StringifiedSize(IntCast<int64_t>(src));
}
template <typename T,
std::enable_if_t<std::conjunction_v<std::negation<FitsIn<T, int64_t>>,
FitsIn<T, absl::int128>>,
int> = 0>
inline size_t StringifiedSizeSigned(T src) {
return StringifiedSize(IntCast<absl::int128>(src));
}
} // namespace riegeli::write_int_internal
#endif // RIEGELI_BYTES_WRITE_INT_INTERNAL_H_