2012-06-15 19:32:25 +00:00
|
|
|
#pragma once
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/types.h>
|
2023-03-15 07:33:45 +00:00
|
|
|
#include <base/defines.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/ReadBuffer.h>
|
|
|
|
#include <IO/WriteBuffer.h>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2023-04-05 07:50:26 +00:00
|
|
|
/// Variable-Length Quantity (VLQ) Base-128 compression, also known as Variable Byte (VB) or Varint encoding.
|
2023-03-15 07:33:45 +00:00
|
|
|
|
2023-04-13 08:55:29 +00:00
|
|
|
[[noreturn]] void throwReadAfterEOF();
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void writeVarUInt(UInt64 x, WriteBuffer & ostr)
|
2011-03-22 20:36:01 +00:00
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
while (x > 0x7F)
|
2023-07-06 14:44:06 +00:00
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
uint8_t byte = 0x80 | (x & 0x7F);
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
ostr.nextIfAtEnd();
|
|
|
|
*ostr.position() = byte;
|
|
|
|
++ostr.position();
|
|
|
|
|
|
|
|
x >>= 7;
|
|
|
|
}
|
2023-07-06 14:56:05 +00:00
|
|
|
|
|
|
|
uint8_t final_byte = static_cast<uint8_t>(x);
|
|
|
|
|
|
|
|
ostr.nextIfAtEnd();
|
|
|
|
*ostr.position() = final_byte;
|
|
|
|
++ostr.position();
|
2010-03-01 16:59:51 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void writeVarUInt(UInt64 x, std::ostream & ostr)
|
2011-03-22 20:36:01 +00:00
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
while (x > 0x7F)
|
2023-07-06 14:44:06 +00:00
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
uint8_t byte = 0x80 | (x & 0x7F);
|
2023-07-06 14:44:06 +00:00
|
|
|
ostr.put(byte);
|
2012-06-15 19:32:25 +00:00
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
x >>= 7;
|
|
|
|
}
|
2023-07-06 14:56:05 +00:00
|
|
|
|
|
|
|
uint8_t final_byte = static_cast<uint8_t>(x);
|
|
|
|
ostr.put(final_byte);
|
2010-03-01 16:59:51 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline char * writeVarUInt(UInt64 x, char * ostr)
|
2012-06-15 19:32:25 +00:00
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
while (x > 0x7F)
|
2023-07-06 14:44:06 +00:00
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
uint8_t byte = 0x80 | (x & 0x7F);
|
2023-07-06 14:44:06 +00:00
|
|
|
|
|
|
|
*ostr = byte;
|
|
|
|
++ostr;
|
|
|
|
|
|
|
|
x >>= 7;
|
|
|
|
}
|
|
|
|
|
2023-07-06 14:56:05 +00:00
|
|
|
uint8_t final_byte = static_cast<uint8_t>(x);
|
|
|
|
|
|
|
|
*ostr = final_byte;
|
|
|
|
++ostr;
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
return ostr;
|
2012-06-15 19:32:25 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
template <typename Out>
|
|
|
|
inline void writeVarInt(Int64 x, Out & ostr)
|
2012-06-15 19:32:25 +00:00
|
|
|
{
|
2023-07-06 14:44:06 +00:00
|
|
|
writeVarUInt(static_cast<UInt64>((x << 1) ^ (x >> 63)), ostr);
|
2012-06-15 19:32:25 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline char * writeVarInt(Int64 x, char * ostr)
|
2012-06-15 19:32:25 +00:00
|
|
|
{
|
2023-07-06 14:44:06 +00:00
|
|
|
return writeVarUInt(static_cast<UInt64>((x << 1) ^ (x >> 63)), ostr);
|
2012-06-15 19:32:25 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
namespace impl
|
2017-10-14 01:03:35 +00:00
|
|
|
{
|
|
|
|
|
2023-07-06 14:47:40 +00:00
|
|
|
template <bool check_eof>
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void readVarUInt(UInt64 & x, ReadBuffer & istr)
|
2014-11-15 18:57:49 +00:00
|
|
|
{
|
2016-04-15 02:28:56 +00:00
|
|
|
x = 0;
|
2023-07-06 14:56:05 +00:00
|
|
|
for (size_t i = 0; i < 10; ++i)
|
2014-11-15 18:57:49 +00:00
|
|
|
{
|
2023-07-06 14:47:40 +00:00
|
|
|
if constexpr (check_eof)
|
2023-04-13 08:55:29 +00:00
|
|
|
if (istr.eof()) [[unlikely]]
|
2018-08-25 18:23:26 +00:00
|
|
|
throwReadAfterEOF();
|
2016-04-15 02:28:56 +00:00
|
|
|
|
2024-02-28 23:24:27 +00:00
|
|
|
UInt64 byte = static_cast<unsigned char>(*istr.position());
|
2016-04-15 02:28:56 +00:00
|
|
|
++istr.position();
|
2016-08-04 05:19:37 +00:00
|
|
|
x |= (byte & 0x7F) << (7 * i);
|
2016-04-15 02:28:56 +00:00
|
|
|
|
|
|
|
if (!(byte & 0x80))
|
|
|
|
return;
|
2014-11-15 18:57:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
}
|
|
|
|
|
2018-08-25 18:23:26 +00:00
|
|
|
inline void readVarUInt(UInt64 & x, ReadBuffer & istr)
|
|
|
|
{
|
2023-07-06 14:56:05 +00:00
|
|
|
if (istr.buffer().end() - istr.position() >= 10)
|
2023-07-06 14:47:40 +00:00
|
|
|
return impl::readVarUInt<false>(x, istr);
|
|
|
|
return impl::readVarUInt<true>(x, istr);
|
2018-08-25 18:23:26 +00:00
|
|
|
}
|
|
|
|
|
2014-11-15 18:57:49 +00:00
|
|
|
inline void readVarUInt(UInt64 & x, std::istream & istr)
|
|
|
|
{
|
2016-08-04 05:19:37 +00:00
|
|
|
x = 0;
|
2023-07-06 14:56:05 +00:00
|
|
|
for (size_t i = 0; i < 10; ++i)
|
2014-11-15 18:57:49 +00:00
|
|
|
{
|
2016-10-26 22:27:38 +00:00
|
|
|
UInt64 byte = istr.get();
|
2016-08-04 05:19:37 +00:00
|
|
|
x |= (byte & 0x7F) << (7 * i);
|
|
|
|
|
|
|
|
if (!(byte & 0x80))
|
|
|
|
return;
|
2014-11-15 18:57:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-04 05:32:58 +00:00
|
|
|
inline const char * readVarUInt(UInt64 & x, const char * istr, size_t size)
|
|
|
|
{
|
|
|
|
const char * end = istr + size;
|
|
|
|
|
|
|
|
x = 0;
|
2023-07-06 14:56:05 +00:00
|
|
|
for (size_t i = 0; i < 10; ++i)
|
2016-08-04 05:32:58 +00:00
|
|
|
{
|
2023-04-13 08:55:29 +00:00
|
|
|
if (istr == end) [[unlikely]]
|
2016-08-04 05:32:58 +00:00
|
|
|
throwReadAfterEOF();
|
|
|
|
|
2024-02-28 23:24:27 +00:00
|
|
|
UInt64 byte = static_cast<unsigned char>(*istr);
|
2016-08-04 05:32:58 +00:00
|
|
|
++istr;
|
|
|
|
x |= (byte & 0x7F) << (7 * i);
|
|
|
|
|
|
|
|
if (!(byte & 0x80))
|
|
|
|
return istr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return istr;
|
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
template <typename In>
|
|
|
|
inline void readVarInt(Int64 & x, In & istr)
|
2014-11-15 18:57:49 +00:00
|
|
|
{
|
2023-07-06 14:44:06 +00:00
|
|
|
readVarUInt(*reinterpret_cast<UInt64*>(&x), istr);
|
|
|
|
x = (static_cast<UInt64>(x) >> 1) ^ -(x & 1);
|
2014-11-15 18:57:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline const char * readVarInt(Int64 & x, const char * istr, size_t size)
|
2014-11-15 18:57:49 +00:00
|
|
|
{
|
2023-07-06 14:44:06 +00:00
|
|
|
const char * res = readVarUInt(*reinterpret_cast<UInt64*>(&x), istr, size);
|
|
|
|
x = (static_cast<UInt64>(x) >> 1) ^ -(x & 1);
|
|
|
|
return res;
|
2014-11-15 18:57:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void readVarUInt(UInt32 & x, ReadBuffer & istr)
|
2014-11-15 18:57:49 +00:00
|
|
|
{
|
2023-07-06 14:44:06 +00:00
|
|
|
UInt64 tmp;
|
|
|
|
readVarUInt(tmp, istr);
|
|
|
|
x = static_cast<UInt32>(tmp);
|
|
|
|
}
|
2016-08-04 05:19:37 +00:00
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void readVarInt(Int32 & x, ReadBuffer & istr)
|
|
|
|
{
|
|
|
|
Int64 tmp;
|
|
|
|
readVarInt(tmp, istr);
|
|
|
|
x = static_cast<Int32>(tmp);
|
|
|
|
}
|
2016-08-04 05:19:37 +00:00
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void readVarUInt(UInt16 & x, ReadBuffer & istr)
|
|
|
|
{
|
|
|
|
UInt64 tmp;
|
|
|
|
readVarUInt(tmp, istr);
|
|
|
|
x = tmp;
|
|
|
|
}
|
2014-11-15 18:57:49 +00:00
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
inline void readVarInt(Int16 & x, ReadBuffer & istr)
|
|
|
|
{
|
|
|
|
Int64 tmp;
|
|
|
|
readVarInt(tmp, istr);
|
|
|
|
x = tmp;
|
2014-11-15 18:57:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 14:44:06 +00:00
|
|
|
template <typename T>
|
|
|
|
requires (!std::is_same_v<T, UInt64>)
|
|
|
|
inline void readVarUInt(T & x, ReadBuffer & istr)
|
|
|
|
{
|
|
|
|
UInt64 tmp;
|
|
|
|
readVarUInt(tmp, istr);
|
|
|
|
x = tmp;
|
|
|
|
}
|
2014-11-15 18:57:49 +00:00
|
|
|
|
|
|
|
inline size_t getLengthOfVarUInt(UInt64 x)
|
|
|
|
{
|
|
|
|
return x < (1ULL << 7) ? 1
|
|
|
|
: (x < (1ULL << 14) ? 2
|
|
|
|
: (x < (1ULL << 21) ? 3
|
|
|
|
: (x < (1ULL << 28) ? 4
|
|
|
|
: (x < (1ULL << 35) ? 5
|
|
|
|
: (x < (1ULL << 42) ? 6
|
|
|
|
: (x < (1ULL << 49) ? 7
|
|
|
|
: (x < (1ULL << 56) ? 8
|
2023-07-06 14:56:05 +00:00
|
|
|
: (x < (1ULL << 63) ? 9
|
|
|
|
: 10))))))));
|
2014-11-15 18:57:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline size_t getLengthOfVarInt(Int64 x)
|
|
|
|
{
|
|
|
|
return getLengthOfVarUInt(static_cast<UInt64>((x << 1) ^ (x >> 63)));
|
|
|
|
}
|
|
|
|
|
2012-06-15 19:32:25 +00:00
|
|
|
}
|