Skip to content

Commit

Permalink
Do print errors in some cases
Browse files Browse the repository at this point in the history
Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
  • Loading branch information
Caellian committed May 25, 2024
1 parent 6a39ebf commit ed24c95
Showing 1 changed file with 74 additions and 12 deletions.
86 changes: 74 additions & 12 deletions src/colours.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@

#include "logging.h"

#include <cstdarg>
#include <cstdio>
#include <optional>
#include <type_traits>
#include <variant>

Colour Colour::from_argb32(uint32_t argb) {
Colour out;
Expand All @@ -54,17 +58,63 @@ Colour Colour::from_argb32(uint32_t argb) {
#include "colour-names-stub.hh"
#endif /* BUILD_COLOUR_NAME_MAP */

std::optional<Colour> parse_color_name(const std::string &name) {
const rgb *value = color_name_hash::in_word_set(name.c_str(), name.length());
/// Parsing result can be either a `Colour`, a none variant, or an error
/// message.
class parse_result {
std::variant<Colour, std::monostate, std::string> value;

public:
parse_result(Colour c) : value(c) {}
parse_result() : value(std::monostate{}) {}
parse_result(std::string msg) : value(std::move(msg)) {}

static parse_result error(const char *format...) {
va_list args;
va_start(args, format);
size_t len = snprintf(nullptr, 0, format, args);
va_end(args);

char *buffer = new char[len + 1];
va_start(args, format);
snprintf(buffer, len, format, args);
va_end(args);

auto value = std::string(buffer);
delete[] buffer;
return parse_result(value);
}

if (value == nullptr) {
return std::nullopt;
} else {
const bool has_colour() const {
return std::holds_alternative<Colour>(value);
}
const std::optional<Colour> get_colour() const {
if (std::holds_alternative<Colour>(value)) {
return std::get<Colour>(std::move(value));
} else {
return std::nullopt;
}
}
const std::optional<std::string> get_error() const {
if (std::holds_alternative<std::string>(value)) {
return std::get<std::string>(std::move(value));
} else {
return std::nullopt;
}
}
};

parse_result none() { return parse_result(); }

parse_result 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 Colour{value->red, value->green, value->blue};
} else {
return none();
}
}

std::optional<Colour> parse_hex_color(const std::string &color) {
parse_result parse_hex_color(const std::string &color) {
const char *name = color.c_str();
size_t len = color.length();
// Skip a leading '#' if present.
Expand All @@ -89,7 +139,9 @@ std::optional<Colour> parse_hex_color(const std::string &color) {
bool skip_alpha = (len == 3);
for (size_t i = 0; i < len; i++) {
int nib = hex_nibble_value(name[i]);
if (nib < 0) return std::nullopt;
if (nib < 0)
return parse_result::error("invalid hex color: '%s' (%d)",
color.c_str(), color.length());
// Duplicate the nibble, so "#abc" -> 0xaa, 0xbb, 0xcc
int val = (nib << 4) + nib;

Expand All @@ -100,13 +152,15 @@ 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 std::nullopt;
if (nib1 < 0 || nib2 < 0)
return parse_result::error("invalid hex color: '%s' (%d)",
color.c_str(), color.length());
int val = (nib1 << 4) + nib2;

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

return Colour(argb[1], argb[2], argb[3], argb[0]);
Expand All @@ -115,9 +169,17 @@ std::optional<Colour> parse_hex_color(const std::string &color) {
Colour parse_color(const std::string &color) {
std::optional<Colour> result;

#define TRY_PARSER(name) \
std::optional<Colour> value_##name = name(color); \
if (value_##name.has_value()) { return value_##name.value(); }
#define TRY_PARSER(name) \
parse_result value_##name = name(color); \
if (value_##name.has_colour()) { \
return value_##name.get_colour().value(); \
} else { \
auto err = value_##name.get_error(); \
if (err.has_value()) { \
NORM_ERR(err.value().c_str()); \
return ERROR_COLOUR; \
} \
}

TRY_PARSER(parse_color_name)
TRY_PARSER(parse_hex_color)
Expand Down

0 comments on commit ed24c95

Please sign in to comment.