mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +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>
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int LOGICAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace UnicodeBar
|
namespace UnicodeBar
|
||||||
{
|
{
|
||||||
@ -26,36 +33,61 @@ namespace UnicodeBar
|
|||||||
return (x - min) / (max - min) * max_width;
|
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)
|
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)
|
for (size_t i = 0; i < floor_width; ++i)
|
||||||
{
|
{
|
||||||
memcpy(dst, "█", UNICODE_BAR_CHAR_SIZE);
|
dst = checkedCopy(FULL_BAR, UNICODE_BAR_CHAR_SIZE, dst, dst_end);
|
||||||
dst += UNICODE_BAR_CHAR_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t remainder = static_cast<size_t>(floor((width - floor_width) * 8));
|
size_t remainder = int_width % GRADES_IN_FULL_BAR;
|
||||||
|
|
||||||
if (remainder)
|
if (remainder)
|
||||||
{
|
{
|
||||||
memcpy(dst, &"▏▎▍▌▋▋▊▉"[(remainder - 1) * UNICODE_BAR_CHAR_SIZE], UNICODE_BAR_CHAR_SIZE);
|
dst = checkedCopy(&FRACTIONAL_BARS[(remainder - 1) * UNICODE_BAR_CHAR_SIZE], UNICODE_BAR_CHAR_SIZE, dst, dst_end);
|
||||||
dst += UNICODE_BAR_CHAR_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst = 0;
|
dst = checkedCopy("\0", 1, dst, dst_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string render(double width)
|
std::string render(double width)
|
||||||
{
|
{
|
||||||
std::string res(getWidthInBytes(width), '\0');
|
std::string res(getWidthInBytes(width) + 1, '\0');
|
||||||
render(width, res.data());
|
render(width, res.data(), res.data() + res.size());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,6 @@ namespace UnicodeBar
|
|||||||
size_t getWidthInBytes(double width);
|
size_t getWidthInBytes(double width);
|
||||||
|
|
||||||
/// In `dst` there must be a space for barWidthInBytes(width) characters and a trailing zero.
|
/// 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);
|
std::string render(double width);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ public:
|
|||||||
|
|
||||||
size_t next_size = current_offset + UnicodeBar::getWidthInBytes(width) + 1;
|
size_t next_size = current_offset + UnicodeBar::getWidthInBytes(width) + 1;
|
||||||
dst_chars.resize(next_size);
|
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;
|
current_offset = next_size;
|
||||||
dst_offsets[i] = current_offset;
|
dst_offsets[i] = current_offset;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user