mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Added a function "computeBytesBeforeWidth"
This commit is contained in:
parent
ad14025b5e
commit
eb0e28b26d
@ -89,7 +89,18 @@ static int wcwidth(wchar_t wc)
|
||||
}
|
||||
}
|
||||
|
||||
size_t computeWidth(const UInt8 * data, size_t size, size_t prefix) noexcept
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
enum ComputeWidthMode
|
||||
{
|
||||
Width, /// Calcualte and return visible width
|
||||
BytesBeforLimit /// Calculate and return the maximum number of bytes when substring fits in visible width.
|
||||
};
|
||||
|
||||
template <ComputeWidthMode mode>
|
||||
static size_t computeWidthImpl(const UInt8 * data, size_t size, size_t prefix, size_t limit) noexcept
|
||||
{
|
||||
UTF8Decoder decoder;
|
||||
size_t width = 0;
|
||||
@ -132,16 +143,22 @@ size_t computeWidth(const UInt8 * data, size_t size, size_t prefix) noexcept
|
||||
++i;
|
||||
}
|
||||
|
||||
if (mode == BytesBeforLimit && width >= limit)
|
||||
return i - (width - limit);
|
||||
|
||||
switch (decoder.decode(data[i]))
|
||||
{
|
||||
case UTF8Decoder::REJECT:
|
||||
{
|
||||
decoder.reset();
|
||||
// invalid sequences seem to have zero width in modern terminals
|
||||
// tested in libvte-based, alacritty, urxvt and xterm
|
||||
i -= rollback;
|
||||
rollback = 0;
|
||||
break;
|
||||
}
|
||||
case UTF8Decoder::ACCEPT:
|
||||
{
|
||||
// there are special control characters that manipulate the terminal output.
|
||||
// (`0x08`, `0x09`, `0x0a`, `0x0b`, `0x0c`, `0x0d`, `0x1b`)
|
||||
// Since we don't touch the original column data, there is no easy way to escape them.
|
||||
@ -149,12 +166,19 @@ size_t computeWidth(const UInt8 * data, size_t size, size_t prefix) noexcept
|
||||
// TODO: multiline support for '\n'
|
||||
|
||||
// special treatment for '\t'
|
||||
size_t next_width = width;
|
||||
if (decoder.codepoint == '\t')
|
||||
width += 8 - (prefix + width) % 8;
|
||||
next_width += 8 - (prefix + width) % 8;
|
||||
else
|
||||
width += wcwidth(decoder.codepoint);
|
||||
next_width += wcwidth(decoder.codepoint);
|
||||
|
||||
if (mode == BytesBeforLimit && next_width >= limit)
|
||||
return i - rollback;
|
||||
width = next_width;
|
||||
|
||||
rollback = 0;
|
||||
break;
|
||||
}
|
||||
// continue if we meet other values here
|
||||
default:
|
||||
++rollback;
|
||||
@ -162,7 +186,21 @@ size_t computeWidth(const UInt8 * data, size_t size, size_t prefix) noexcept
|
||||
}
|
||||
|
||||
// no need to handle trailing sequence as they have zero width
|
||||
return width;
|
||||
}
|
||||
return (mode == BytesBeforLimit) ? size : width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
size_t computeWidth(const UInt8 * data, size_t size, size_t prefix) noexcept
|
||||
{
|
||||
return computeWidthImpl<Width>(data, size, prefix, 0);
|
||||
}
|
||||
|
||||
size_t computeBytesBeforeWidth(const UInt8 * data, size_t size, size_t prefix, size_t limit) noexcept
|
||||
{
|
||||
return computeWidthImpl<BytesBeforLimit>(data, size, prefix, limit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user