mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Check remaining space to avoid buffer overruns; some cleanups
This commit is contained in:
parent
4cd91b1ec6
commit
2ab6b7d033
@ -9,6 +9,13 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
namespace UnicodeBar
|
||||
{
|
||||
@ -26,36 +33,61 @@ namespace UnicodeBar
|
||||
return (x - min) / (max - min) * max_width;
|
||||
}
|
||||
|
||||
/// We use the following Unicode characters to draw the bar:
|
||||
/// U+2588 "█" Full block
|
||||
/// U+2589 "▉" Left seven eighths block
|
||||
/// U+258A "▊" Left three quarters block
|
||||
/// U+258B "▋" Left five eighths block
|
||||
/// U+258C "▌" Left half block
|
||||
/// U+258D "▍" Left three eighths block
|
||||
/// U+258E "▎" Left one quarter block
|
||||
/// U+258F "▏" Left one eighth block
|
||||
constexpr size_t GRADES_IN_FULL_BAR = 8;
|
||||
constexpr char FULL_BAR[] = "█";
|
||||
constexpr char FRACTIONAL_BARS[] = "▏▎▍▌▋▊▉"; /// 7 elements: 1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8
|
||||
|
||||
size_t getWidthInBytes(double width)
|
||||
{
|
||||
return static_cast<size_t>(ceil(width - 1.0 / 8) * UNICODE_BAR_CHAR_SIZE);
|
||||
Int64 int_width = Int64(width * GRADES_IN_FULL_BAR);
|
||||
return (int_width / GRADES_IN_FULL_BAR) * UNICODE_BAR_CHAR_SIZE + (int_width % GRADES_IN_FULL_BAR ? UNICODE_BAR_CHAR_SIZE : 0);
|
||||
}
|
||||
|
||||
void render(double width, char * dst)
|
||||
static char* checkedCopy(const char * src, size_t src_size, char * dst, const char * dst_end)
|
||||
{
|
||||
size_t floor_width = static_cast<size_t>(floor(width));
|
||||
if (dst + src_size > dst_end)
|
||||
throw DB::Exception(
|
||||
DB::ErrorCodes::LOGICAL_ERROR,
|
||||
"Not enough space in buffer for UnicodeBar::render, required: {}, got: {}",
|
||||
src_size, dst_end - dst);
|
||||
|
||||
memcpy(dst, src, src_size);
|
||||
return dst + src_size;
|
||||
}
|
||||
|
||||
void render(double width, char * dst, const char * dst_end)
|
||||
{
|
||||
Int64 int_width = Int64(width * GRADES_IN_FULL_BAR);
|
||||
size_t floor_width = (int_width / GRADES_IN_FULL_BAR);
|
||||
|
||||
for (size_t i = 0; i < floor_width; ++i)
|
||||
{
|
||||
memcpy(dst, "█", UNICODE_BAR_CHAR_SIZE);
|
||||
dst += UNICODE_BAR_CHAR_SIZE;
|
||||
dst = checkedCopy(FULL_BAR, UNICODE_BAR_CHAR_SIZE, dst, dst_end);
|
||||
}
|
||||
|
||||
size_t remainder = static_cast<size_t>(floor((width - floor_width) * 8));
|
||||
size_t remainder = int_width % GRADES_IN_FULL_BAR;
|
||||
|
||||
if (remainder)
|
||||
{
|
||||
memcpy(dst, &"▏▎▍▌▋▋▊▉"[(remainder - 1) * UNICODE_BAR_CHAR_SIZE], UNICODE_BAR_CHAR_SIZE);
|
||||
dst += UNICODE_BAR_CHAR_SIZE;
|
||||
dst = checkedCopy(&FRACTIONAL_BARS[(remainder - 1) * UNICODE_BAR_CHAR_SIZE], UNICODE_BAR_CHAR_SIZE, dst, dst_end);
|
||||
}
|
||||
|
||||
*dst = 0;
|
||||
dst = checkedCopy("\0", 1, dst, dst_end);
|
||||
}
|
||||
|
||||
std::string render(double width)
|
||||
{
|
||||
std::string res(getWidthInBytes(width), '\0');
|
||||
render(width, res.data());
|
||||
std::string res(getWidthInBytes(width) + 1, '\0');
|
||||
render(width, res.data(), res.data() + res.size());
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,6 @@ namespace UnicodeBar
|
||||
size_t getWidthInBytes(double width);
|
||||
|
||||
/// In `dst` there must be a space for barWidthInBytes(width) characters and a trailing zero.
|
||||
void render(double width, char * dst);
|
||||
void render(double width, char * dst, const char * dst_end);
|
||||
std::string render(double width);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public:
|
||||
|
||||
size_t next_size = current_offset + UnicodeBar::getWidthInBytes(width) + 1;
|
||||
dst_chars.resize(next_size);
|
||||
UnicodeBar::render(width, reinterpret_cast<char *>(&dst_chars[current_offset]));
|
||||
UnicodeBar::render(width, reinterpret_cast<char *>(&dst_chars[current_offset]), reinterpret_cast<char *>(&dst_chars[next_size]));
|
||||
current_offset = next_size;
|
||||
dst_offsets[i] = current_offset;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user