Refactor color.h/color.cpp

* Use `uint8_t` instead of `unsigned char`
* Statically assert the sort order for `named_colors`
* Use constexpr for array lengths
This commit is contained in:
Mahmoud Al-Qudsi 2021-02-08 14:40:34 -06:00
parent 5fda1e05dc
commit 5d4c24bae1
2 changed files with 28 additions and 26 deletions

View file

@ -24,14 +24,12 @@ bool rgb_color_t::try_parse_special(const wcstring &special) {
// Take advantage of the fact that std::string length is O(1) to speed things up, and perform
// what amounts to a simple memcmp before needing to access the invariant case lookup tables.
static auto normal_len = wcslen(L"normal");
static auto reset_len = wcslen(L"reset");
this->type = type_none;
if (special.size() == normal_len) {
if (special.size() == const_strlen(L"normal")) {
if (!wcscmp(name, L"normal") || !wcscasecmp(name, L"normal")) {
this->type = type_normal;
}
} else if (special.size() == reset_len) {
} else if (special.size() == const_strlen(L"reset")) {
if (!wcscmp(name, L"reset") || !wcscasecmp(name, L"reset")) {
this->type = type_reset;
}
@ -106,11 +104,11 @@ static unsigned long squared_difference(long p1, long p2) {
return diff * diff;
}
static unsigned char convert_color(const unsigned char rgb[3], const uint32_t *colors,
static uint8_t convert_color(const uint8_t rgb[3], const uint32_t *colors,
size_t color_count) {
long r = rgb[0], g = rgb[1], b = rgb[2];
auto best_distance = static_cast<unsigned long>(-1);
auto best_index = static_cast<unsigned char>(-1);
auto best_index = static_cast<uint8_t>(-1);
for (size_t idx = 0; idx < color_count; idx++) {
uint32_t color = colors[idx];
long test_r = (color >> 16) & 0xFF, test_g = (color >> 8) & 0xFF,
@ -166,12 +164,12 @@ bool rgb_color_t::try_parse_rgb(const wcstring &name) {
struct named_color_t {
const wchar_t *name;
uint8_t idx;
unsigned char rgb[3];
uint8_t rgb[3];
bool hidden;
};
// Keep this sorted alphabetically
static const std::vector<named_color_t> named_colors{
static constexpr named_color_t named_colors[] = {
{L"black", 0, {0x00, 0x00, 0x00}, false}, {L"blue", 4, {0x00, 0x00, 0x80}, false},
{L"brblack", 8, {0x80, 0x80, 0x80}, false}, {L"brblue", 12, {0x00, 0x00, 0xFF}, false},
{L"brbrown", 11, {0xFF, 0xFF, 0x00}, true}, {L"brcyan", 14, {0x00, 0xFF, 0xFF}, false},
@ -184,10 +182,12 @@ static const std::vector<named_color_t> named_colors{
{L"purple", 5, {0x80, 0x00, 0x80}, true}, {L"red", 1, {0x80, 0x00, 0x00}, false},
{L"white", 7, {0xC0, 0xC0, 0xC0}, false}, {L"yellow", 3, {0x80, 0x80, 0x00}, false},
};
ASSERT_SORT_ORDER(named_colors, .name);
wcstring_list_t rgb_color_t::named_color_names() {
wcstring_list_t result;
result.reserve(1 + named_colors.size());
constexpr size_t colors_count = sizeof(named_colors) / sizeof(named_colors[0]);
result.reserve(1 + colors_count);
for (const auto &named_color : named_colors) {
if (!named_color.hidden) {
result.push_back(named_color.name);
@ -203,8 +203,9 @@ wcstring_list_t rgb_color_t::named_color_names() {
}
bool rgb_color_t::try_parse_named(const wcstring &str) {
static auto named_colors_begin = named_colors.begin();
static auto named_colors_end = named_colors.end();
constexpr size_t colors_count = sizeof(named_colors) / sizeof(named_colors[0]);
constexpr const named_color_t *named_colors_begin = &named_colors[0];
constexpr const named_color_t *named_colors_end = &named_colors[0] + colors_count;
std::memset(&data, 0, sizeof data);
if (str.size() == 0) {
@ -246,8 +247,9 @@ bool rgb_color_t::try_parse_named(const wcstring &str) {
return false;
}
static const wchar_t *name_for_color_idx(unsigned char idx) {
if (idx < named_colors.size()) {
static const wchar_t *name_for_color_idx(uint8_t idx) {
constexpr size_t colors_count = sizeof(named_colors) / sizeof(named_colors[0]);
if (idx < colors_count) {
for (auto &color : named_colors) {
if (idx == color.idx) {
return color.name;
@ -257,7 +259,7 @@ static const wchar_t *name_for_color_idx(unsigned char idx) {
return L"unknown";
}
rgb_color_t::rgb_color_t(unsigned char t, unsigned char i) : type(t), flags(), data() {
rgb_color_t::rgb_color_t(uint8_t t, uint8_t i) : type(t), flags(), data() {
data.name_idx = i;
}
@ -271,7 +273,7 @@ rgb_color_t rgb_color_t::white() { return rgb_color_t(type_named, 7); }
rgb_color_t rgb_color_t::black() { return rgb_color_t(type_named, 0); }
static unsigned char term16_color_for_rgb(const unsigned char rgb[3]) {
static uint8_t term16_color_for_rgb(const uint8_t rgb[3]) {
const uint32_t kColors[] = {
0x000000, // Black
0x800000, // Red
@ -293,7 +295,7 @@ static unsigned char term16_color_for_rgb(const unsigned char rgb[3]) {
return convert_color(rgb, kColors, sizeof kColors / sizeof *kColors);
}
static unsigned char term256_color_for_rgb(const unsigned char rgb[3]) {
static uint8_t term256_color_for_rgb(const uint8_t rgb[3]) {
const uint32_t kColors[240] = {
0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, 0x005f87,
0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af, 0x0087d7, 0x0087ff,
@ -325,7 +327,7 @@ static unsigned char term256_color_for_rgb(const unsigned char rgb[3]) {
return 16 + convert_color(rgb, kColors, sizeof kColors / sizeof *kColors);
}
unsigned char rgb_color_t::to_term256_index() const {
uint8_t rgb_color_t::to_term256_index() const {
assert(type == type_rgb);
return term256_color_for_rgb(data.color.rgb);
}
@ -335,12 +337,12 @@ color24_t rgb_color_t::to_color24() const {
return data.color;
}
unsigned char rgb_color_t::to_name_index() const {
uint8_t rgb_color_t::to_name_index() const {
// TODO: This should look for the nearest color.
assert(type == type_named || type == type_rgb);
if (type == type_named) return data.name_idx;
if (type == type_rgb) return term16_color_for_rgb(data.color.rgb);
return static_cast<unsigned char>(-1); // this is an error
return static_cast<uint8_t>(-1); // this is an error
}
void rgb_color_t::parse(const wcstring &str) {

View file

@ -9,7 +9,7 @@
// 24-bit color.
struct color24_t {
unsigned char rgb[3];
uint8_t rgb[3];
};
/// A type that represents a color. We work hard to keep it at a size of 4 bytes and verify with
@ -17,7 +17,7 @@ struct color24_t {
class rgb_color_t {
// Types
enum { type_none, type_named, type_rgb, type_normal, type_reset };
unsigned char type : 3;
uint8_t type : 3;
// Flags
enum {
@ -27,10 +27,10 @@ class rgb_color_t {
flag_dim = 1 << 3,
flag_reverse = 1 << 4
};
unsigned char flags : 5;
uint8_t flags : 5;
union {
unsigned char name_idx; // 0-10
uint8_t name_idx; // 0-10
color24_t color;
} data;
@ -47,7 +47,7 @@ class rgb_color_t {
void parse(const wcstring &str);
/// Private constructor.
explicit rgb_color_t(unsigned char t, unsigned char i = 0);
explicit rgb_color_t(uint8_t t, uint8_t i = 0);
public:
/// Default constructor of type none.
@ -94,10 +94,10 @@ class rgb_color_t {
wcstring description() const;
/// Returns the name index for the given color. Requires that the color be named or RGB.
unsigned char to_name_index() const;
uint8_t to_name_index() const;
/// Returns the term256 index for the given color. Requires that the color be RGB.
unsigned char to_term256_index() const;
uint8_t to_term256_index() const;
/// Returns the 24 bit color for the given color. Requires that the color be RGB.
color24_t to_color24() const;