diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index aae03c85c..8251b6dc6 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2619,6 +2619,9 @@ backgroundFillSolid color:int32 = BackgroundFill; //@rotation_angle Clockwise rotation angle of the gradient, in degrees; 0-359. Should be always divisible by 45 backgroundFillGradient top_color:int32 bottom_color:int32 rotation_angle:int32 = BackgroundFill; +//@description Describes a freeform gradient fill of a background @colors A list of 3 or 4 colors of the freeform gradients in the RGB24 format +backgroundFillFreeformGradient colors:vector = BackgroundFill; + //@class BackgroundType @description Describes the type of a background diff --git a/td/telegram/BackgroundManager.cpp b/td/telegram/BackgroundManager.cpp index 09f6398d0..c76477de1 100644 --- a/td/telegram/BackgroundManager.cpp +++ b/td/telegram/BackgroundManager.cpp @@ -28,6 +28,7 @@ #include "td/db/SqliteKeyValueAsync.h" #include "td/utils/algorithm.h" +#include "td/utils/base64.h" #include "td/utils/buffer.h" #include "td/utils/common.h" #include "td/utils/format.h" @@ -393,7 +394,7 @@ void BackgroundManager::reload_background(BackgroundId background_id, int64 acce } static bool is_background_name_local(Slice name) { - return name.size() <= 6 || name.find('?') <= 13u; + return name.size() <= 13u || name.find('?') <= 13u || !is_base64url_characters(name.substr(0, name.find('?'))); } BackgroundId BackgroundManager::search_background(const string &name, Promise &&promise) { @@ -409,49 +410,12 @@ BackgroundId BackgroundManager::search_background(const string &name, Promise 6 || i + 7 < fill_colors.size()) { - promise.set_error(Status::Error(400, "WALLPAPER_INVALID")); - return BackgroundId(); - } - have_hyphen = true; - hyphen_pos = i; - } - } - - BackgroundFill fill; - if (have_hyphen) { - int32 top_color = static_cast(hex_to_integer(fill_colors.substr(0, hyphen_pos))); - int32 bottom_color = static_cast(hex_to_integer(fill_colors.substr(hyphen_pos + 1))); - int32 rotation_angle = 0; - - Slice prefix("rotation="); - if (begins_with(parameters, prefix)) { - rotation_angle = to_integer(parameters.substr(prefix.size())); - if (!BackgroundFill::is_valid_rotation_angle(rotation_angle)) { - rotation_angle = 0; - } - } - - fill = BackgroundFill(top_color, bottom_color, rotation_angle); - } else { - int32 color = static_cast(hex_to_integer(fill_colors)); - fill = BackgroundFill(color); - } - auto background_id = add_fill_background(fill); + auto background_id = add_fill_background(r_fill.ok()); promise.set_value(Unit()); return background_id; } @@ -538,7 +502,7 @@ Result BackgroundManager::prepare_input_file(const tl_object_ptrflags_ & telegram_api::wallPaperSettings::BACKGROUND_COLOR_MASK) != 0; - auto color = has_color ? settings->background_color_ : 0; auto is_default = (wallpaper->flags_ & telegram_api::wallPaperNoFile::DEFAULT_MASK) != 0; auto is_dark = (wallpaper->flags_ & telegram_api::wallPaperNoFile::DARK_MASK) != 0; - BackgroundFill fill = BackgroundFill(color); - if ((settings->flags_ & telegram_api::wallPaperSettings::SECOND_BACKGROUND_COLOR_MASK) != 0) { - fill = BackgroundFill(color, settings->second_background_color_, settings->rotation_); - } - return add_fill_background(fill, is_default, is_dark); + return add_fill_background(BackgroundFill(settings.get()), is_default, is_dark); } auto wallpaper = move_tl_object_as(wallpaper_ptr); @@ -994,8 +952,9 @@ BackgroundId BackgroundManager::on_get_background(BackgroundId expected_backgrou name_to_background_id_.emplace(expected_background_name, id); } - if (G()->parameters().use_file_db && !is_background_name_local(background.name)) { + if (G()->parameters().use_file_db) { LOG(INFO) << "Save " << id << " to database with name " << background.name; + CHECK(!is_background_name_local(background.name)); G()->td_db()->get_sqlite_pmc()->set(get_background_name_database_key(background.name), log_event_store(background).as_slice().str(), Auto()); } diff --git a/td/telegram/BackgroundType.cpp b/td/telegram/BackgroundType.cpp index 5a30eba33..9c6039373 100644 --- a/td/telegram/BackgroundType.cpp +++ b/td/telegram/BackgroundType.cpp @@ -7,6 +7,7 @@ #include "td/telegram/BackgroundType.h" #include "td/utils/logging.h" +#include "td/utils/misc.h" #include "td/utils/Slice.h" #include "td/utils/SliceBuilder.h" @@ -15,7 +16,7 @@ namespace td { static string get_color_hex_string(int32 color) { string result; for (int i = 20; i >= 0; i -= 4) { - result += "0123456789abcdef"[(color >> i) & 0xf]; + result += "0123456789abcdef"[(color >> i) & 0xF]; } return result; } @@ -24,6 +25,57 @@ static bool is_valid_color(int32 color) { return 0 <= color && color <= 0xFFFFFF; } +static bool is_valid_rotation_angle(int32 rotation_angle) { + return 0 <= rotation_angle && rotation_angle < 360 && rotation_angle % 45 == 0; +} + +BackgroundFill::BackgroundFill(const telegram_api::wallPaperSettings *settings) { + if (settings == nullptr) { + return; + } + + auto flags = settings->flags_; + if ((flags & telegram_api::wallPaperSettings::BACKGROUND_COLOR_MASK) != 0) { + top_color = settings->background_color_; + if (!is_valid_color(top_color)) { + LOG(ERROR) << "Receive " << to_string(*settings); + top_color = 0; + } + } + if ((flags & telegram_api::wallPaperSettings::FOURTH_BACKGROUND_COLOR_MASK) != 0 || + (flags & telegram_api::wallPaperSettings::THIRD_BACKGROUND_COLOR_MASK) != 0) { + bottom_color = settings->second_background_color_; + if (!is_valid_color(bottom_color)) { + LOG(ERROR) << "Receive " << to_string(*settings); + bottom_color = 0; + } + third_color = settings->third_background_color_; + if (!is_valid_color(third_color)) { + LOG(ERROR) << "Receive " << to_string(*settings); + third_color = 0; + } + if ((flags & telegram_api::wallPaperSettings::FOURTH_BACKGROUND_COLOR_MASK) != 0) { + fourth_color = settings->fourth_background_color_; + if (!is_valid_color(fourth_color)) { + LOG(ERROR) << "Receive " << to_string(*settings); + fourth_color = 0; + } + } + } else if ((flags & telegram_api::wallPaperSettings::SECOND_BACKGROUND_COLOR_MASK) != 0) { + bottom_color = settings->second_background_color_; + if (!is_valid_color(bottom_color)) { + LOG(ERROR) << "Receive " << to_string(*settings); + bottom_color = 0; + } + + rotation_angle = settings->rotation_; + if (!is_valid_rotation_angle(rotation_angle)) { + LOG(ERROR) << "Receive " << to_string(*settings); + rotation_angle = 0; + } + } +} + static Result get_background_fill(const td_api::BackgroundFill *fill) { if (fill == nullptr) { return Status::Error(400, "Background fill info must be non-empty"); @@ -44,17 +96,85 @@ static Result get_background_fill(const td_api::BackgroundFill * if (!is_valid_color(gradient->bottom_color_)) { return Status::Error(400, "Invalid bottom gradient color value"); } - if (!BackgroundFill::is_valid_rotation_angle(gradient->rotation_angle_)) { + if (!is_valid_rotation_angle(gradient->rotation_angle_)) { return Status::Error(400, "Invalid rotation angle value"); } return BackgroundFill(gradient->top_color_, gradient->bottom_color_, gradient->rotation_angle_); } + case td_api::backgroundFillFreeformGradient::ID: { + auto freeform = static_cast(fill); + if (freeform->colors_.size() != 3 && freeform->colors_.size() != 4) { + return Status::Error(400, "Wrong number of gradient colors"); + } + for (auto &color : freeform->colors_) { + if (!is_valid_color(color)) { + return Status::Error(400, "Invalid freeform gradient color value"); + } + } + return BackgroundFill(freeform->colors_[0], freeform->colors_[1], freeform->colors_[2], + freeform->colors_.size() == 3 ? -1 : freeform->colors_[3]); + } default: UNREACHABLE(); return {}; } } +Result BackgroundFill::get_background_fill(Slice name) { + name = name.substr(0, name.find('#')); + + Slice parameters; + auto parameters_pos = name.find('?'); + if (parameters_pos != Slice::npos) { + parameters = name.substr(parameters_pos + 1); + name = name.substr(0, parameters_pos); + } + + auto get_color = [](Slice color_string) -> Result { + auto r_color = hex_to_integer_safe(color_string); + if (r_color.is_error() || color_string.size() > 6) { + return Status::Error(400, "WALLPAPER_INVALID"); + } + return static_cast(r_color.ok()); + }; + + if (name.find('~') < name.size()) { + vector color_strings = full_split(name, '~'); + if (color_strings.size() != 4 && color_strings.size() != 3) { + return Status::Error(400, "WALLPAPER_INVALID"); + } + + TRY_RESULT(first_color, get_color(color_strings[0])); + TRY_RESULT(second_color, get_color(color_strings[1])); + TRY_RESULT(third_color, get_color(color_strings[2])); + int32 fourth_color = -1; + if (color_strings.size() == 4) { + TRY_RESULT_ASSIGN(fourth_color, get_color(color_strings[3])); + } + return BackgroundFill(first_color, second_color, third_color, fourth_color); + } + + size_t hyphen_pos = name.find('-'); + if (hyphen_pos < name.size()) { + TRY_RESULT(top_color, get_color(name.substr(0, hyphen_pos))); + TRY_RESULT(bottom_color, get_color(name.substr(hyphen_pos + 1))); + int32 rotation_angle = 0; + + Slice prefix("rotation="); + if (begins_with(parameters, prefix)) { + rotation_angle = to_integer(parameters.substr(prefix.size())); + if (!is_valid_rotation_angle(rotation_angle)) { + rotation_angle = 0; + } + } + + return BackgroundFill(top_color, bottom_color, rotation_angle); + } + + TRY_RESULT(color, get_color(name)); + return BackgroundFill(color); +} + static string get_background_fill_color_hex_string(const BackgroundFill &fill, bool is_first) { switch (fill.get_type()) { case BackgroundFill::Type::Solid: @@ -67,6 +187,15 @@ static string get_background_fill_color_hex_string(const BackgroundFill &fill, b } return colors; } + case BackgroundFill::Type::FreeformGradient: { + SliceBuilder sb; + sb << get_color_hex_string(fill.top_color) << '~' << get_color_hex_string(fill.bottom_color) << '~' + << get_color_hex_string(fill.third_color); + if (fill.fourth_color != -1) { + sb << '~' << get_color_hex_string(fill.fourth_color); + } + return sb.as_cslice().str(); + } default: UNREACHABLE(); return string(); @@ -80,13 +209,38 @@ static bool is_valid_intensity(int32 intensity) { int64 BackgroundFill::get_id() const { CHECK(is_valid_color(top_color)); CHECK(is_valid_color(bottom_color)); - CHECK(is_valid_rotation_angle(rotation_angle)); switch (get_type()) { case Type::Solid: return static_cast(top_color) + 1; case Type::Gradient: + CHECK(is_valid_rotation_angle(rotation_angle)); return (rotation_angle / 45) * 0x1000001000001 + (static_cast(top_color) << 24) + bottom_color + (1 << 24) + 1; + case Type::FreeformGradient: { + CHECK(is_valid_color(third_color)); + CHECK(fourth_color == -1 || is_valid_color(fourth_color)); + const uint64 mul = 123456789; + uint64 result = static_cast(top_color); + result = result * mul + static_cast(bottom_color); + result = result * mul + static_cast(third_color); + result = result * mul + static_cast(fourth_color); + return 0x8000008000008 + static_cast(result % 0x8000008000008); + } + default: + UNREACHABLE(); + return 0; + } +} + +bool BackgroundFill::is_dark() const { + switch (get_type()) { + case Type::Solid: + return (top_color & 0x808080) == 0; + case Type::Gradient: + return (top_color & 0x808080) == 0 && (bottom_color & 0x808080) == 0; + case Type::FreeformGradient: + return (top_color & 0x808080) == 0 && (bottom_color & 0x808080) == 0 && (third_color & 0x808080) == 0 && + (fourth_color == -1 || (fourth_color & 0x808080) == 0); default: UNREACHABLE(); return 0; @@ -94,12 +248,13 @@ int64 BackgroundFill::get_id() const { } bool BackgroundFill::is_valid_id(int64 id) { - return 0 < id && id < 0x8000008000008; + return 0 < id && id < 0x8000008000008 * 2; } bool operator==(const BackgroundFill &lhs, const BackgroundFill &rhs) { return lhs.top_color == rhs.top_color && lhs.bottom_color == rhs.bottom_color && - lhs.rotation_angle == rhs.rotation_angle; + lhs.rotation_angle == rhs.rotation_angle && lhs.third_color == rhs.third_color && + lhs.fourth_color == rhs.fourth_color; } string BackgroundType::get_link() const { @@ -198,39 +353,13 @@ BackgroundType get_background_type(bool is_pattern, telegram_api::object_ptr settings) { bool is_blurred = false; bool is_moving = false; - BackgroundFill fill; + BackgroundFill fill(settings.get()); int32 intensity = 0; if (settings) { auto flags = settings->flags_; is_blurred = (flags & telegram_api::wallPaperSettings::BLUR_MASK) != 0; is_moving = (flags & telegram_api::wallPaperSettings::MOTION_MASK) != 0; - int32 color = 0; - if ((flags & telegram_api::wallPaperSettings::BACKGROUND_COLOR_MASK) != 0) { - color = settings->background_color_; - if (!is_valid_color(color)) { - LOG(ERROR) << "Receive " << to_string(settings); - color = 0; - } - } - if ((flags & telegram_api::wallPaperSettings::SECOND_BACKGROUND_COLOR_MASK) != 0) { - int32 second_color = settings->second_background_color_; - if (!is_valid_color(second_color)) { - LOG(ERROR) << "Receive " << to_string(settings); - second_color = 0; - } - - int32 rotation_angle = settings->rotation_; - if (!BackgroundFill::is_valid_rotation_angle(rotation_angle)) { - LOG(ERROR) << "Receive " << to_string(settings); - rotation_angle = 0; - } - - fill = BackgroundFill(color, second_color, rotation_angle); - } else { - fill = BackgroundFill(color); - } - if ((flags & telegram_api::wallPaperSettings::INTENSITY_MASK) != 0) { intensity = settings->intensity_; if (!is_valid_intensity(intensity)) { @@ -253,6 +382,13 @@ static td_api::object_ptr get_background_fill_object(con case BackgroundFill::Type::Gradient: return td_api::make_object(fill.top_color, fill.bottom_color, fill.rotation_angle); + case BackgroundFill::Type::FreeformGradient: { + vector colors{fill.top_color, fill.bottom_color, fill.third_color, fill.fourth_color}; + if (colors.back() == -1) { + colors.pop_back(); + } + return td_api::make_object(std::move(colors)); + } default: UNREACHABLE(); return nullptr; @@ -285,6 +421,12 @@ telegram_api::object_ptr get_input_wallpaper_se flags |= telegram_api::wallPaperSettings::MOTION_MASK; } switch (type.fill.get_type()) { + case BackgroundFill::Type::FreeformGradient: + if (type.fill.fourth_color != -1) { + flags |= telegram_api::wallPaperSettings::FOURTH_BACKGROUND_COLOR_MASK; + } + flags |= telegram_api::wallPaperSettings::THIRD_BACKGROUND_COLOR_MASK; + // fallthrough case BackgroundFill::Type::Gradient: flags |= telegram_api::wallPaperSettings::SECOND_BACKGROUND_COLOR_MASK; // fallthrough @@ -297,9 +439,9 @@ telegram_api::object_ptr get_input_wallpaper_se if (type.intensity != 0) { flags |= telegram_api::wallPaperSettings::INTENSITY_MASK; } - return telegram_api::make_object(flags, false /*ignored*/, false /*ignored*/, - type.fill.top_color, type.fill.bottom_color, 0, 0, - type.intensity, type.fill.rotation_angle); + return telegram_api::make_object( + flags, false /*ignored*/, false /*ignored*/, type.fill.top_color, type.fill.bottom_color, type.fill.third_color, + type.fill.fourth_color, type.intensity, type.fill.rotation_angle); } } // namespace td diff --git a/td/telegram/BackgroundType.h b/td/telegram/BackgroundType.h index a41a01bdb..fc7c4a1f8 100644 --- a/td/telegram/BackgroundType.h +++ b/td/telegram/BackgroundType.h @@ -19,6 +19,8 @@ struct BackgroundFill { int32 top_color = 0; int32 bottom_color = 0; int32 rotation_angle = 0; + int32 third_color = -1; + int32 fourth_color = -1; BackgroundFill() = default; explicit BackgroundFill(int32 solid_color) : top_color(solid_color), bottom_color(solid_color) { @@ -26,9 +28,19 @@ struct BackgroundFill { BackgroundFill(int32 top_color, int32 bottom_color, int32 rotation_angle) : top_color(top_color), bottom_color(bottom_color), rotation_angle(rotation_angle) { } + BackgroundFill(int32 first_color, int32 second_color, int32 third_color, int32 fourth_color) + : top_color(first_color), bottom_color(second_color), third_color(third_color), fourth_color(fourth_color) { + } - enum class Type : int32 { Solid, Gradient }; + explicit BackgroundFill(const telegram_api::wallPaperSettings *settings); + + static Result get_background_fill(Slice name); + + enum class Type : int32 { Solid, Gradient, FreeformGradient }; Type get_type() const { + if (third_color != -1) { + return Type::FreeformGradient; + } if (top_color == bottom_color) { return Type::Solid; } @@ -37,11 +49,9 @@ struct BackgroundFill { int64 get_id() const; - static bool is_valid_id(int64 id); + bool is_dark() const; - static bool is_valid_rotation_angle(int32 rotation_angle) { - return 0 <= rotation_angle && rotation_angle < 360 && rotation_angle % 45 == 0; - } + static bool is_valid_id(int64 id); }; bool operator==(const BackgroundFill &lhs, const BackgroundFill &rhs); diff --git a/td/telegram/BackgroundType.hpp b/td/telegram/BackgroundType.hpp index c8b008b47..81fa3c777 100644 --- a/td/telegram/BackgroundType.hpp +++ b/td/telegram/BackgroundType.hpp @@ -18,15 +18,22 @@ void store(const BackgroundType &type, StorerT &storer) { bool has_intensity = type.intensity != 0; auto fill_type = type.fill.get_type(); bool is_gradient = fill_type == BackgroundFill::Type::Gradient; + bool is_freeform_gradient = fill_type == BackgroundFill::Type::FreeformGradient; BEGIN_STORE_FLAGS(); STORE_FLAG(type.is_blurred); STORE_FLAG(type.is_moving); STORE_FLAG(has_fill); STORE_FLAG(has_intensity); STORE_FLAG(is_gradient); + STORE_FLAG(is_freeform_gradient); END_STORE_FLAGS(); store(type.type, storer); - if (has_fill) { + if (is_freeform_gradient) { + store(type.fill.top_color, storer); + store(type.fill.bottom_color, storer); + store(type.fill.third_color, storer); + store(type.fill.fourth_color, storer); + } else if (has_fill) { store(type.fill.top_color, storer); if (is_gradient) { store(type.fill.bottom_color, storer); @@ -43,15 +50,22 @@ void parse(BackgroundType &type, ParserT &parser) { bool has_fill; bool has_intensity; bool is_gradient; + bool is_freeform_gradient; BEGIN_PARSE_FLAGS(); PARSE_FLAG(type.is_blurred); PARSE_FLAG(type.is_moving); PARSE_FLAG(has_fill); PARSE_FLAG(has_intensity); PARSE_FLAG(is_gradient); + PARSE_FLAG(is_freeform_gradient); END_PARSE_FLAGS(); parse(type.type, parser); - if (has_fill) { + if (is_freeform_gradient) { + parse(type.fill.top_color, parser); + parse(type.fill.bottom_color, parser); + parse(type.fill.third_color, parser); + parse(type.fill.fourth_color, parser); + } else if (has_fill) { parse(type.fill.top_color, parser); if (is_gradient) { parse(type.fill.bottom_color, parser); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 6a2fd89d7..eb37f2e29 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1535,6 +1535,10 @@ class CliClient final : public Actor { return td_api::make_object(top_color, bottom_color, Random::fast(0, 7) * 45); } + static td_api::object_ptr get_background_fill(vector colors) { + return td_api::make_object(std::move(colors)); + } + static td_api::object_ptr get_solid_pattern_background(int32 color, int32 intensity, bool is_moving) { return get_gradient_pattern_background(color, color, intensity, is_moving); @@ -1546,6 +1550,13 @@ class CliClient final : public Actor { is_moving); } + static td_api::object_ptr get_freeform_gradient_pattern_background(vector colors, + int32 intensity, + bool is_moving) { + return td_api::make_object(get_background_fill(std::move(colors)), intensity, + is_moving); + } + static td_api::object_ptr get_solid_background(int32 color) { return td_api::make_object(get_background_fill(color)); } @@ -1554,6 +1565,10 @@ class CliClient final : public Actor { return td_api::make_object(get_background_fill(top_color, bottom_color)); } + static td_api::object_ptr get_freeform_gradient_background(vector colors) { + return td_api::make_object(get_background_fill(std::move(colors))); + } + static td_api::object_ptr execute(td_api::object_ptr f) { if (combined_log.get_first_verbosity_level() < VERBOSITY_NAME(td_requests)) { LOG(ERROR) << "Execute request: " << to_string(f); @@ -2206,12 +2221,19 @@ class CliClient final : public Actor { send_get_background_url(get_gradient_pattern_background(0xFFFFFF, 0, 100, true)); send_get_background_url(get_gradient_pattern_background(0xABCDEF, 0xFEDCBA, 49, true)); send_get_background_url(get_gradient_pattern_background(0, 0x1000000, 49, true)); + send_get_background_url(get_freeform_gradient_pattern_background({0xABCDEF, 0xFEDCBA}, 49, true)); + send_get_background_url(get_freeform_gradient_pattern_background({0xABCDEF, 0x111111, 0x222222}, 49, true)); + send_get_background_url( + get_freeform_gradient_pattern_background({0xABCDEF, 0xFEDCBA, 0x111111, 0x222222}, 49, true)); send_get_background_url(get_solid_background(-1)); send_get_background_url(get_solid_background(0xABCDEF)); send_get_background_url(get_solid_background(0x1000000)); send_get_background_url(get_gradient_background(0xABCDEF, 0xFEDCBA)); send_get_background_url(get_gradient_background(0, 0)); send_get_background_url(get_gradient_background(-1, -1)); + send_get_background_url(get_freeform_gradient_background({0xFEDCBA, 0x222222})); + send_get_background_url(get_freeform_gradient_background({0xFEDCBA, 0x111111, 0x222222})); + send_get_background_url(get_freeform_gradient_background({0xABCDEF, 0xFEDCBA, 0x111111, 0x222222})); } else if (op == "sbg") { send_request(td_api::make_object(args)); } else if (op == "sbgd") { @@ -2237,6 +2259,9 @@ class CliClient final : public Actor { get_args(args, top_color, bottom_color); auto background_type = get_gradient_background(top_color, bottom_color); send_request(td_api::make_object(nullptr, std::move(background_type), op == "sbggd")); + } else if (op == "sbgfg" || op == "sbgfgd") { + auto background_type = get_freeform_gradient_background(to_integers(args)); + send_request(td_api::make_object(nullptr, std::move(background_type), op == "sbgfgd")); } else if (op == "sbgwid" || op == "sbgwidd") { send_request(td_api::make_object( td_api::make_object(to_integer(args)), diff --git a/tdutils/td/utils/misc.h b/tdutils/td/utils/misc.h index d26e689f7..14b77cba3 100644 --- a/tdutils/td/utils/misc.h +++ b/tdutils/td/utils/misc.h @@ -226,13 +226,16 @@ Result::value, T>::type> hex_to_inte T integer_value = 0; auto begin = str.begin(); auto end = str.end(); + if (begin == end) { + return Status::Error("String is empty"); + } while (begin != end) { T digit = hex_to_int(*begin++); if (digit == 16) { - return Status::Error("Not a hex digit"); + return Status::Error("String contains non-hex digit"); } if (integer_value > std::numeric_limits::max() / 16) { - return Status::Error("Hex number overflow"); + return Status::Error("String hex number overflows"); } integer_value = integer_value * 16 + digit; }