diff --git a/src/common.cpp b/src/common.cpp index 837ad7a..01788f2 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -32,6 +32,12 @@ CConfigValue::CConfigValue(const float value) { m_eType = CONFIGDATATYPE_FLOAT; } +CConfigValue::CConfigValue(const SVector2D value) { + m_pData = calloc(1, sizeof(SVector2D)); + *reinterpret_cast(m_pData) = value; + m_eType = CONFIGDATATYPE_VEC2; +} + CConfigValue::CConfigValue(const char* value) { m_pData = calloc(1, strlen(value) + 1); strncpy((char*)m_pData, value, strlen(value)); @@ -51,6 +57,11 @@ CConfigValue::CConfigValue(const CConfigValue& ref) { *reinterpret_cast(m_pData) = std::any_cast(ref.getValue()); break; } + case eDataType::CONFIGDATATYPE_VEC2: { + m_pData = calloc(1, sizeof(SVector2D)); + *reinterpret_cast(m_pData) = std::any_cast(ref.getValue()); + break; + } case eDataType::CONFIGDATATYPE_STR: { auto str = std::any_cast(ref.getValue()); m_pData = calloc(1, strlen(str) + 1); @@ -73,6 +84,11 @@ void CConfigValue::operator=(const CConfigValue& ref) { *reinterpret_cast(m_pData) = std::any_cast(ref.getValue()); break; } + case eDataType::CONFIGDATATYPE_VEC2: { + m_pData = calloc(1, sizeof(SVector2D)); + *reinterpret_cast(m_pData) = std::any_cast(ref.getValue()); + break; + } case eDataType::CONFIGDATATYPE_STR: { auto str = std::any_cast(ref.getValue()); m_pData = calloc(1, strlen(str) + 1); diff --git a/src/config.cpp b/src/config.cpp index 591ad93..cd8edf5 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -151,6 +151,24 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std:: } break; } + case CConfigValue::eDataType::CONFIGDATATYPE_VEC2: { + try { + const auto SPACEPOS = value.find(' '); + if (SPACEPOS == std::string::npos) + throw std::runtime_error("no space"); + const auto LHS = value.substr(0, SPACEPOS); + const auto RHS = value.substr(SPACEPOS + 1); + + if (LHS.contains(" ") || RHS.contains(" ")) + throw std::runtime_error("too many args"); + + VALUEIT->second = {SVector2D{std::stof(LHS), std::stof(RHS)}}; + } catch (std::exception& e) { + result.setError(std::format("failed parsing a vec2: {}", e.what())); + return result; + } + break; + } case CConfigValue::eDataType::CONFIGDATATYPE_STR: { VALUEIT->second = {value.c_str()}; break; diff --git a/src/public.hpp b/src/public.hpp index bfe15b6..57993ce 100644 --- a/src/public.hpp +++ b/src/public.hpp @@ -2,11 +2,26 @@ #include #include #include +#include class CConfigImpl; namespace Hyprlang { + /* types */ + struct SVector2D { + float x = 0, y = 0; + + // + bool operator==(const SVector2D& rhs) const { + return x == rhs.x && y == rhs.y; + } + + friend std::ostream& operator<<(std::ostream& os, const SVector2D& rhs) { + return os << "[" << rhs.x << ", " << rhs.y << "]"; + } + }; + struct SConfigValueImpl; /* Container for a config value */ class CConfigValue { @@ -15,6 +30,7 @@ namespace Hyprlang { CConfigValue(const int64_t value); CConfigValue(const float value); CConfigValue(const char* value); + CConfigValue(const SVector2D value); CConfigValue(const CConfigValue&); CConfigValue(CConfigValue&&); void operator=(const CConfigValue&); @@ -27,6 +43,7 @@ namespace Hyprlang { case CONFIGDATATYPE_INT: return std::any(*reinterpret_cast(m_pData)); case CONFIGDATATYPE_FLOAT: return std::any(*reinterpret_cast(m_pData)); case CONFIGDATATYPE_STR: return std::any(reinterpret_cast(m_pData)); + case CONFIGDATATYPE_VEC2: return std::any(*reinterpret_cast(m_pData)); default: throw; } return {}; // unreachable @@ -38,6 +55,7 @@ namespace Hyprlang { CONFIGDATATYPE_INT, CONFIGDATATYPE_FLOAT, CONFIGDATATYPE_STR, + CONFIGDATATYPE_VEC2, }; eDataType m_eType = eDataType::CONFIGDATATYPE_EMPTY; void* m_pData = nullptr; diff --git a/tests/main.cpp b/tests/main.cpp index f55bd1e..e7c026f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -7,7 +7,7 @@ std::cout << "Failed: " << #expr << ", expected " << #val << " but got " << RESULT << "\n"; \ ret = 1; \ } else { \ - std::cout << "Passed " << #expr << ". Got " << #val << "\n"; \ + std::cout << "Passed " << #expr << ". Got " << val << "\n"; \ } int main(int argc, char** argv, char** envp) { @@ -21,6 +21,7 @@ int main(int argc, char** argv, char** envp) { // setup config config.addConfigValue("testInt", 0L); config.addConfigValue("testFloat", 0.F); + config.addConfigValue("testVec", Hyprlang::SVector2D{69, 420}); config.addConfigValue("testString", ""); config.addConfigValue("testStringQuotes", ""); config.addConfigValue("testCategory:testValueInt", 0L); @@ -42,6 +43,8 @@ int main(int argc, char** argv, char** envp) { // test values EXPECT(std::any_cast(config.getConfigValue("testInt")), 123); EXPECT(std::any_cast(config.getConfigValue("testFloat")), 123.456f); + auto EXP = Hyprlang::SVector2D{69, 420}; + EXPECT(std::any_cast(config.getConfigValue("testVec")), EXP); EXPECT(std::any_cast(config.getConfigValue("testString")), std::string{"Hello World! ## This is not a comment!"}); EXPECT(std::any_cast(config.getConfigValue("testStringQuotes")), std::string{"\"Hello World!\""}); EXPECT(std::any_cast(config.getConfigValue("testCategory:testValueInt")), 123456L);