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

Return an error on invalid hex values. #54

Merged
merged 6 commits into from
Sep 1, 2024
Merged
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
32 changes: 22 additions & 10 deletions src/config.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "config.hpp"
#include <exception>
#include <filesystem>
#include <fstream>
#include <stdexcept>
#include <string>
#include <format>
#include <algorithm>
Expand Down Expand Up @@ -160,14 +162,18 @@ void CConfig::commence() {
}

static std::expected<int64_t, std::string> configStringToInt(const std::string& VALUE) {
auto parseHex = [](const std::string& value) -> std::expected<int64_t, std::string> {
try {
size_t position;
auto result = stoll(value, &position, 16);
if (position == value.size())
return result;
} catch (const std::exception&) {}
return std::unexpected("invalid hex " + value);
};
if (VALUE.starts_with("0x")) {
// Values with 0x are hex
size_t position;
auto result = stoll(VALUE, &position, 16);
if (position == VALUE.size())
return result;

return std::unexpected("invalid hex " + VALUE);
return parseHex(VALUE);
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6));

Expand All @@ -191,10 +197,13 @@ static std::expected<int64_t, std::string> configStringToInt(const std::string&

return a * (Hyprlang::INT)0x1000000 + r.value() * (Hyprlang::INT)0x10000 + g.value() * (Hyprlang::INT)0x100 + b.value();
} else if (VALUEWITHOUTFUNC.length() == 8) {
const auto RGBA = std::stoll(VALUEWITHOUTFUNC, nullptr, 16);
const auto RGBA = parseHex(VALUEWITHOUTFUNC);

if (!RGBA.has_value())
return RGBA;

// now we need to RGBA -> ARGB. The config holds ARGB only.
return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
return (RGBA.value() >> 8) + 0x1000000 * (RGBA.value() & 0xFF);
}

return std::unexpected("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values");
Expand All @@ -217,9 +226,12 @@ static std::expected<int64_t, std::string> configStringToInt(const std::string&

return (Hyprlang::INT)0xFF000000 + r.value() * (Hyprlang::INT)0x10000 + g.value() * (Hyprlang::INT)0x100 + b.value();
} else if (VALUEWITHOUTFUNC.length() == 6) {
const auto RGB = std::stoll(VALUEWITHOUTFUNC, nullptr, 16);
const auto RGB = parseHex(VALUEWITHOUTFUNC);

if (!RGB.has_value())
return RGB;

return RGB + 0xFF000000;
return RGB.value() + 0xFF000000;
}

return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values");
Expand Down
5 changes: 0 additions & 5 deletions tests/config/error2.conf

This file was deleted.

15 changes: 15 additions & 0 deletions tests/config/invalid-numbers.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Every number/color in this file is invalid

invalidHex = 0x1Q
emptyHex = 0x
hugeHex = 0xFFFFFFFFFFFFFFFF

invalidInt = 1A
emptyInt =

invalidColor = rgb(ABCDEQ)
invalidFirstCharColor = rgb(QABCDE)

invalidColorAlpha = rgba(9ABCDEFQ)
invalidFirstCharColorAlpha = rgba(Q9ABCDEF)

23 changes: 15 additions & 8 deletions tests/parse/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,17 +279,24 @@ int main(int argc, char** argv, char** envp) {
const auto ERRORSTR = std::string{ERRORS.getError()};
EXPECT(std::count(ERRORSTR.begin(), ERRORSTR.end(), '\n'), 1);

std::cout << " → Testing error2.conf\n";
Hyprlang::CConfig errorConfig2("./config/error2.conf", {.throwAllErrors = true});
errorConfig2.addConfigValue("invalidHex", (Hyprlang::INT)0);
errorConfig2.addConfigValue("emptyHex", (Hyprlang::INT)0);

errorConfig2.commence();
const auto ERRORS2 = errorConfig2.parse();
std::cout << " → Testing invalid-numbers.conf\n";
Hyprlang::CConfig invalidNumbersConfig("./config/invalid-numbers.conf", {.throwAllErrors = true});
invalidNumbersConfig.addConfigValue("invalidHex", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("emptyHex", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("hugeHex", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("invalidInt", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("emptyInt", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("invalidColor", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("invalidFirstCharColor", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("invalidColorAlpha", (Hyprlang::INT)0);
invalidNumbersConfig.addConfigValue("invalidFirstCharColorAlpha", (Hyprlang::INT)0);

invalidNumbersConfig.commence();
const auto ERRORS2 = invalidNumbersConfig.parse();

EXPECT(ERRORS2.error, true);
const auto ERRORSTR2 = std::string{ERRORS2.getError()};
EXPECT(std::count(ERRORSTR2.begin(), ERRORSTR2.end(), '\n'), 1);
EXPECT(std::count(ERRORSTR2.begin(), ERRORSTR2.end(), '\n'), 9 - 1);
} catch (const char* e) {
std::cout << Colors::RED << "Error: " << Colors::RESET << e << "\n";
return 1;
Expand Down
Loading