Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move color parse error message out of hex parser #1937

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,4 @@ jobs:
run: cmake --build build
- name: Test
working-directory: build
run: ctest
run: ctest --output-on-failure
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-macos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ jobs:
run: cmake --build build
- name: Test
working-directory: build
run: ctest
run: ctest --output-on-failure
37 changes: 28 additions & 9 deletions src/colours.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "logging.h"

#include <cstdio>
#include <optional>

Colour Colour::from_argb32(uint32_t argb) {
Expand All @@ -54,11 +55,32 @@ Colour Colour::from_argb32(uint32_t argb) {
#include "colour-names-stub.hh"
#endif /* BUILD_COLOUR_NAME_MAP */

std::optional<Colour> inline no_colour() { return std::nullopt; }
template <typename... Args>
std::optional<Colour> parse_error(const std::string &color_str,
const char *format, Args... args) {
size_t len = snprintf(nullptr, 0, format, args...);

char *reason = new char[len + 1];
snprintf(reason, len + 1, format, args...);

CRIT_ERR("can't parse color '%s' (len: %d): %s", color_str.c_str(),
color_str.length(), reason);
delete[] reason;

return ERROR_COLOUR;
}
std::optional<Colour> parse_error(const std::string &color_str,
const char *reason) {
CRIT_ERR("can't parse color '%s' (len: %d): %s", color_str.c_str(),
color_str.length(), reason);
return ERROR_COLOUR;
}

std::optional<Colour> parse_color_name(const std::string &name) {
const rgb *value = color_name_hash::in_word_set(name.c_str(), name.length());

if (value == nullptr) {
return std::nullopt;
return no_colour();
} else {
return Colour{value->red, value->green, value->blue};
}
Expand All @@ -83,17 +105,13 @@ std::optional<Colour> parse_hex_color(const std::string &color) {
}
return -1;
};
const auto none = [&]() {
NORM_ERR("can't parse hex color '%s' (%d)", name, len);
return std::nullopt;
};

uint8_t argb[4] = {0xff, 0, 0, 0};
if (len == 3 || len == 4) {
bool skip_alpha = (len == 3);
for (size_t i = 0; i < len; i++) {
int nib = hex_nibble_value(name[i]);
if (nib < 0) { return none(); }
if (nib < 0) return parse_error(color, "invalid hex value");
// Duplicate the nibble, so "#abc" -> 0xaa, 0xbb, 0xcc
int val = (nib << 4) + nib;

Expand All @@ -104,13 +122,13 @@ std::optional<Colour> parse_hex_color(const std::string &color) {
for (size_t i = 0; i + 1 < len; i += 2) {
int nib1 = hex_nibble_value(name[i]);
int nib2 = hex_nibble_value(name[i + 1]);
if (nib1 < 0 || nib2 < 0) { return none(); }
if (nib1 < 0 || nib2 < 0) return parse_error(color, "invalid hex value");
int val = (nib1 << 4) + nib2;

argb[skip_alpha + i / 2] = val;
}
} else {
return none();
return no_colour();
}

return Colour(argb[1], argb[2], argb[3], argb[0]);
Expand All @@ -128,6 +146,7 @@ Colour parse_color(const std::string &color) {

#undef TRY_PARSER

NORM_ERR("can't parse color '%s'", color.c_str());
return ERROR_COLOUR;
}

Expand Down
Loading