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 // 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. // 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; 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")) { if (!wcscmp(name, L"normal") || !wcscasecmp(name, L"normal")) {
this->type = type_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")) { if (!wcscmp(name, L"reset") || !wcscasecmp(name, L"reset")) {
this->type = type_reset; this->type = type_reset;
} }
@ -106,11 +104,11 @@ static unsigned long squared_difference(long p1, long p2) {
return diff * diff; 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) { size_t color_count) {
long r = rgb[0], g = rgb[1], b = rgb[2]; long r = rgb[0], g = rgb[1], b = rgb[2];
auto best_distance = static_cast<unsigned long>(-1); 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++) { for (size_t idx = 0; idx < color_count; idx++) {
uint32_t color = colors[idx]; uint32_t color = colors[idx];
long test_r = (color >> 16) & 0xFF, test_g = (color >> 8) & 0xFF, 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 { struct named_color_t {
const wchar_t *name; const wchar_t *name;
uint8_t idx; uint8_t idx;
unsigned char rgb[3]; uint8_t rgb[3];
bool hidden; bool hidden;
}; };
// Keep this sorted alphabetically // 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"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"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}, {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"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}, {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 rgb_color_t::named_color_names() {
wcstring_list_t result; 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) { for (const auto &named_color : named_colors) {
if (!named_color.hidden) { if (!named_color.hidden) {
result.push_back(named_color.name); 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) { bool rgb_color_t::try_parse_named(const wcstring &str) {
static auto named_colors_begin = named_colors.begin(); constexpr size_t colors_count = sizeof(named_colors) / sizeof(named_colors[0]);
static auto named_colors_end = named_colors.end(); 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); std::memset(&data, 0, sizeof data);
if (str.size() == 0) { if (str.size() == 0) {
@ -246,8 +247,9 @@ bool rgb_color_t::try_parse_named(const wcstring &str) {
return false; return false;
} }
static const wchar_t *name_for_color_idx(unsigned char idx) { static const wchar_t *name_for_color_idx(uint8_t idx) {
if (idx < named_colors.size()) { constexpr size_t colors_count = sizeof(named_colors) / sizeof(named_colors[0]);
if (idx < colors_count) {
for (auto &color : named_colors) { for (auto &color : named_colors) {
if (idx == color.idx) { if (idx == color.idx) {
return color.name; return color.name;
@ -257,7 +259,7 @@ static const wchar_t *name_for_color_idx(unsigned char idx) {
return L"unknown"; 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; 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); } 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[] = { const uint32_t kColors[] = {
0x000000, // Black 0x000000, // Black
0x800000, // Red 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); 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] = { const uint32_t kColors[240] = {
0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, 0x005f87, 0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, 0x005f87,
0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af, 0x0087d7, 0x0087ff, 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); 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); assert(type == type_rgb);
return term256_color_for_rgb(data.color.rgb); return term256_color_for_rgb(data.color.rgb);
} }
@ -335,12 +337,12 @@ color24_t rgb_color_t::to_color24() const {
return data.color; 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. // TODO: This should look for the nearest color.
assert(type == type_named || type == type_rgb); assert(type == type_named || type == type_rgb);
if (type == type_named) return data.name_idx; if (type == type_named) return data.name_idx;
if (type == type_rgb) return term16_color_for_rgb(data.color.rgb); 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) { void rgb_color_t::parse(const wcstring &str) {

View file

@ -9,7 +9,7 @@
// 24-bit color. // 24-bit color.
struct color24_t { 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 /// 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 { class rgb_color_t {
// Types // Types
enum { type_none, type_named, type_rgb, type_normal, type_reset }; enum { type_none, type_named, type_rgb, type_normal, type_reset };
unsigned char type : 3; uint8_t type : 3;
// Flags // Flags
enum { enum {
@ -27,10 +27,10 @@ class rgb_color_t {
flag_dim = 1 << 3, flag_dim = 1 << 3,
flag_reverse = 1 << 4 flag_reverse = 1 << 4
}; };
unsigned char flags : 5; uint8_t flags : 5;
union { union {
unsigned char name_idx; // 0-10 uint8_t name_idx; // 0-10
color24_t color; color24_t color;
} data; } data;
@ -47,7 +47,7 @@ class rgb_color_t {
void parse(const wcstring &str); void parse(const wcstring &str);
/// Private constructor. /// 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: public:
/// Default constructor of type none. /// Default constructor of type none.
@ -94,10 +94,10 @@ class rgb_color_t {
wcstring description() const; wcstring description() const;
/// Returns the name index for the given color. Requires that the color be named or RGB. /// 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. /// 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. /// Returns the 24 bit color for the given color. Requires that the color be RGB.
color24_t to_color24() const; color24_t to_color24() const;