mirror of
https://github.com/hyprwm/hyprlang.git
synced 2024-11-16 18:25:57 +01:00
config: Return an error on invalid hex values. (#54)
* config.cpp: fix parsing invalid hex Instead of crashing on an invalid hex, return an error. * config: return an error on an invalid hex value * cleanup * style: add references for catching exceptions * style: ignore `std::out_of_range`
This commit is contained in:
parent
c12ab785ce
commit
5b175c9704
4 changed files with 51 additions and 22 deletions
|
@ -1,6 +1,8 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include <exception>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -160,14 +162,18 @@ void CConfig::commence() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::expected<int64_t, std::string> configStringToInt(const std::string& VALUE) {
|
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")) {
|
if (VALUE.starts_with("0x")) {
|
||||||
// Values with 0x are hex
|
// Values with 0x are hex
|
||||||
size_t position;
|
return parseHex(VALUE);
|
||||||
auto result = stoll(VALUE, &position, 16);
|
|
||||||
if (position == VALUE.size())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return std::unexpected("invalid hex " + VALUE);
|
|
||||||
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
|
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
|
||||||
const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6));
|
const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6));
|
||||||
|
|
||||||
|
@ -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();
|
return a * (Hyprlang::INT)0x1000000 + r.value() * (Hyprlang::INT)0x10000 + g.value() * (Hyprlang::INT)0x100 + b.value();
|
||||||
} else if (VALUEWITHOUTFUNC.length() == 8) {
|
} 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.
|
// 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");
|
return std::unexpected("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values");
|
||||||
|
@ -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();
|
return (Hyprlang::INT)0xFF000000 + r.value() * (Hyprlang::INT)0x10000 + g.value() * (Hyprlang::INT)0x100 + b.value();
|
||||||
} else if (VALUEWITHOUTFUNC.length() == 6) {
|
} else if (VALUEWITHOUTFUNC.length() == 6) {
|
||||||
const auto RGB = std::stoll(VALUEWITHOUTFUNC, nullptr, 16);
|
const auto RGB = parseHex(VALUEWITHOUTFUNC);
|
||||||
|
|
||||||
return RGB + 0xFF000000;
|
if (!RGB.has_value())
|
||||||
|
return RGB;
|
||||||
|
|
||||||
|
return RGB.value() + 0xFF000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values");
|
return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values");
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
# This config houses two errors
|
|
||||||
|
|
||||||
invalidHex = 0xQQ
|
|
||||||
emptyHex = 0x
|
|
||||||
|
|
15
tests/config/invalid-numbers.conf
Normal file
15
tests/config/invalid-numbers.conf
Normal file
|
@ -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)
|
||||||
|
|
|
@ -279,17 +279,24 @@ int main(int argc, char** argv, char** envp) {
|
||||||
const auto ERRORSTR = std::string{ERRORS.getError()};
|
const auto ERRORSTR = std::string{ERRORS.getError()};
|
||||||
EXPECT(std::count(ERRORSTR.begin(), ERRORSTR.end(), '\n'), 1);
|
EXPECT(std::count(ERRORSTR.begin(), ERRORSTR.end(), '\n'), 1);
|
||||||
|
|
||||||
std::cout << " → Testing error2.conf\n";
|
std::cout << " → Testing invalid-numbers.conf\n";
|
||||||
Hyprlang::CConfig errorConfig2("./config/error2.conf", {.throwAllErrors = true});
|
Hyprlang::CConfig invalidNumbersConfig("./config/invalid-numbers.conf", {.throwAllErrors = true});
|
||||||
errorConfig2.addConfigValue("invalidHex", (Hyprlang::INT)0);
|
invalidNumbersConfig.addConfigValue("invalidHex", (Hyprlang::INT)0);
|
||||||
errorConfig2.addConfigValue("emptyHex", (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);
|
||||||
|
|
||||||
errorConfig2.commence();
|
invalidNumbersConfig.commence();
|
||||||
const auto ERRORS2 = errorConfig2.parse();
|
const auto ERRORS2 = invalidNumbersConfig.parse();
|
||||||
|
|
||||||
EXPECT(ERRORS2.error, true);
|
EXPECT(ERRORS2.error, true);
|
||||||
const auto ERRORSTR2 = std::string{ERRORS2.getError()};
|
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) {
|
} catch (const char* e) {
|
||||||
std::cout << Colors::RED << "Error: " << Colors::RESET << e << "\n";
|
std::cout << Colors::RED << "Error: " << Colors::RESET << e << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in a new issue