mirror of
https://github.com/hyprwm/hyprlang.git
synced 2024-11-17 02:25:59 +01:00
core: add custom data types
This commit is contained in:
parent
8d538588ff
commit
a081d90b19
6 changed files with 217 additions and 83 deletions
|
@ -9,6 +9,8 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
class CConfigImpl;
|
class CConfigImpl;
|
||||||
|
struct SConfigDefaultValue;
|
||||||
|
struct SSpecialCategory;
|
||||||
|
|
||||||
namespace Hyprlang {
|
namespace Hyprlang {
|
||||||
|
|
||||||
|
@ -66,8 +68,30 @@ namespace Hyprlang {
|
||||||
|
|
||||||
/* typedefs */
|
/* typedefs */
|
||||||
typedef CParseResult (*PCONFIGHANDLERFUNC)(const char* COMMAND, const char* VALUE);
|
typedef CParseResult (*PCONFIGHANDLERFUNC)(const char* COMMAND, const char* VALUE);
|
||||||
|
typedef CParseResult (*PCONFIGCUSTOMVALUEHANDLERFUNC)(const char* VALUE, void** data);
|
||||||
|
typedef void (*PCONFIGCUSTOMVALUEDESTRUCTOR)(void** data);
|
||||||
|
|
||||||
|
/* Container for a custom config value type
|
||||||
|
When creating, pass your handler.
|
||||||
|
Handler will receive a void** that points to a void* that you can set to your own
|
||||||
|
thing. Pass a dtor to free whatever you allocated when the custom value type is being released.
|
||||||
|
data may always be pointing to a nullptr.
|
||||||
|
*/
|
||||||
|
class CConfigCustomValueType {
|
||||||
|
public:
|
||||||
|
CConfigCustomValueType(PCONFIGCUSTOMVALUEHANDLERFUNC handler_, PCONFIGCUSTOMVALUEDESTRUCTOR dtor_, const char* defaultValue);
|
||||||
|
~CConfigCustomValueType();
|
||||||
|
|
||||||
|
private:
|
||||||
|
PCONFIGCUSTOMVALUEHANDLERFUNC handler = nullptr;
|
||||||
|
PCONFIGCUSTOMVALUEDESTRUCTOR dtor = nullptr;
|
||||||
|
void* data = nullptr;
|
||||||
|
std::string defaultVal = "";
|
||||||
|
|
||||||
|
friend class CConfigValue;
|
||||||
|
friend class CConfig;
|
||||||
|
};
|
||||||
|
|
||||||
struct SConfigValueImpl;
|
|
||||||
/* Container for a config value */
|
/* Container for a config value */
|
||||||
class CConfigValue {
|
class CConfigValue {
|
||||||
public:
|
public:
|
||||||
|
@ -76,9 +100,11 @@ namespace Hyprlang {
|
||||||
CConfigValue(const float value);
|
CConfigValue(const float value);
|
||||||
CConfigValue(const char* value);
|
CConfigValue(const char* value);
|
||||||
CConfigValue(const SVector2D value);
|
CConfigValue(const SVector2D value);
|
||||||
CConfigValue(const CConfigValue&);
|
CConfigValue(CConfigCustomValueType&& value);
|
||||||
CConfigValue(CConfigValue&&);
|
CConfigValue(const CConfigValue&) = delete;
|
||||||
void operator=(const CConfigValue&);
|
CConfigValue(CConfigValue&&) = delete;
|
||||||
|
CConfigValue(const CConfigValue&&) = delete;
|
||||||
|
CConfigValue(CConfigValue&) = delete;
|
||||||
~CConfigValue();
|
~CConfigValue();
|
||||||
|
|
||||||
void* dataPtr() const;
|
void* dataPtr() const;
|
||||||
|
@ -89,21 +115,26 @@ namespace Hyprlang {
|
||||||
case CONFIGDATATYPE_FLOAT: return std::any(*reinterpret_cast<float*>(m_pData));
|
case CONFIGDATATYPE_FLOAT: return std::any(*reinterpret_cast<float*>(m_pData));
|
||||||
case CONFIGDATATYPE_STR: return std::any(reinterpret_cast<const char*>(m_pData));
|
case CONFIGDATATYPE_STR: return std::any(reinterpret_cast<const char*>(m_pData));
|
||||||
case CONFIGDATATYPE_VEC2: return std::any(*reinterpret_cast<SVector2D*>(m_pData));
|
case CONFIGDATATYPE_VEC2: return std::any(*reinterpret_cast<SVector2D*>(m_pData));
|
||||||
|
case CONFIGDATATYPE_CUSTOM: return std::any(reinterpret_cast<CConfigCustomValueType*>(m_pData)->data);
|
||||||
default: throw;
|
default: throw;
|
||||||
}
|
}
|
||||||
return {}; // unreachable
|
return {}; // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// remember to also edit config.hpp if editing
|
||||||
enum eDataType {
|
enum eDataType {
|
||||||
CONFIGDATATYPE_EMPTY,
|
CONFIGDATATYPE_EMPTY,
|
||||||
CONFIGDATATYPE_INT,
|
CONFIGDATATYPE_INT,
|
||||||
CONFIGDATATYPE_FLOAT,
|
CONFIGDATATYPE_FLOAT,
|
||||||
CONFIGDATATYPE_STR,
|
CONFIGDATATYPE_STR,
|
||||||
CONFIGDATATYPE_VEC2,
|
CONFIGDATATYPE_VEC2,
|
||||||
|
CONFIGDATATYPE_CUSTOM,
|
||||||
};
|
};
|
||||||
eDataType m_eType = eDataType::CONFIGDATATYPE_EMPTY;
|
eDataType m_eType = eDataType::CONFIGDATATYPE_EMPTY;
|
||||||
void* m_pData = nullptr;
|
void* m_pData = nullptr;
|
||||||
|
void defaultFrom(SConfigDefaultValue& ref);
|
||||||
|
void setFrom(std::any value);
|
||||||
|
|
||||||
friend class CConfig;
|
friend class CConfig;
|
||||||
};
|
};
|
||||||
|
@ -117,7 +148,7 @@ namespace Hyprlang {
|
||||||
/* Add a config value, for example myCategory:myValue.
|
/* Add a config value, for example myCategory:myValue.
|
||||||
This has to be done before commence()
|
This has to be done before commence()
|
||||||
Value provided becomes default */
|
Value provided becomes default */
|
||||||
void addConfigValue(const char* name, const CConfigValue value);
|
void addConfigValue(const char* name, const CConfigValue& value);
|
||||||
|
|
||||||
/* Register a handler. Can be called anytime, though not recommended
|
/* Register a handler. Can be called anytime, though not recommended
|
||||||
to do this dynamically */
|
to do this dynamically */
|
||||||
|
@ -181,6 +212,7 @@ namespace Hyprlang {
|
||||||
CParseResult configSetValueSafe(const std::string& command, const std::string& value);
|
CParseResult configSetValueSafe(const std::string& command, const std::string& value);
|
||||||
CParseResult parseVariable(const std::string& lhs, const std::string& rhs, bool dynamic = false);
|
CParseResult parseVariable(const std::string& lhs, const std::string& rhs, bool dynamic = false);
|
||||||
void clearState();
|
void clearState();
|
||||||
|
void applyDefaultsToCat(SSpecialCategory& cat);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
155
src/common.cpp
155
src/common.cpp
|
@ -1,4 +1,5 @@
|
||||||
#include "public.hpp"
|
#include "public.hpp"
|
||||||
|
#include "config.hpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
using namespace Hyprlang;
|
using namespace Hyprlang;
|
||||||
|
@ -16,6 +17,9 @@ void CParseResult::setError(const char* err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CConfigValue::~CConfigValue() {
|
CConfigValue::~CConfigValue() {
|
||||||
|
if (m_eType == CONFIGDATATYPE_CUSTOM)
|
||||||
|
reinterpret_cast<CConfigCustomValueType*>(m_pData)->dtor(&reinterpret_cast<CConfigCustomValueType*>(m_pData)->data);
|
||||||
|
|
||||||
if (m_pData)
|
if (m_pData)
|
||||||
free(m_pData);
|
free(m_pData);
|
||||||
}
|
}
|
||||||
|
@ -44,65 +48,10 @@ CConfigValue::CConfigValue(const char* value) {
|
||||||
m_eType = CONFIGDATATYPE_STR;
|
m_eType = CONFIGDATATYPE_STR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CConfigValue::CConfigValue(const CConfigValue& ref) {
|
CConfigValue::CConfigValue(CConfigCustomValueType&& value) {
|
||||||
m_eType = ref.m_eType;
|
m_pData = calloc(1, sizeof(CConfigCustomValueType));
|
||||||
switch (ref.m_eType) {
|
new (m_pData) CConfigCustomValueType(value);
|
||||||
case eDataType::CONFIGDATATYPE_INT: {
|
m_eType = CONFIGDATATYPE_CUSTOM;
|
||||||
m_pData = calloc(1, sizeof(int64_t));
|
|
||||||
*reinterpret_cast<int64_t*>(m_pData) = std::any_cast<int64_t>(ref.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eDataType::CONFIGDATATYPE_FLOAT: {
|
|
||||||
m_pData = calloc(1, sizeof(float));
|
|
||||||
*reinterpret_cast<float*>(m_pData) = std::any_cast<float>(ref.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eDataType::CONFIGDATATYPE_VEC2: {
|
|
||||||
m_pData = calloc(1, sizeof(SVector2D));
|
|
||||||
*reinterpret_cast<SVector2D*>(m_pData) = std::any_cast<SVector2D>(ref.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eDataType::CONFIGDATATYPE_STR: {
|
|
||||||
auto str = std::any_cast<const char*>(ref.getValue());
|
|
||||||
m_pData = calloc(1, strlen(str) + 1);
|
|
||||||
strncpy((char*)m_pData, str, strlen(str));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConfigValue::operator=(const CConfigValue& ref) {
|
|
||||||
m_eType = ref.m_eType;
|
|
||||||
switch (ref.m_eType) {
|
|
||||||
case eDataType::CONFIGDATATYPE_INT: {
|
|
||||||
m_pData = calloc(1, sizeof(int64_t));
|
|
||||||
*reinterpret_cast<int64_t*>(m_pData) = std::any_cast<int64_t>(ref.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eDataType::CONFIGDATATYPE_FLOAT: {
|
|
||||||
m_pData = calloc(1, sizeof(float));
|
|
||||||
*reinterpret_cast<float*>(m_pData) = std::any_cast<float>(ref.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eDataType::CONFIGDATATYPE_VEC2: {
|
|
||||||
m_pData = calloc(1, sizeof(SVector2D));
|
|
||||||
*reinterpret_cast<SVector2D*>(m_pData) = std::any_cast<SVector2D>(ref.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eDataType::CONFIGDATATYPE_STR: {
|
|
||||||
auto str = std::any_cast<const char*>(ref.getValue());
|
|
||||||
m_pData = calloc(1, strlen(str) + 1);
|
|
||||||
strncpy((char*)m_pData, str, strlen(str));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CConfigValue::CConfigValue(CConfigValue&& ref) {
|
|
||||||
m_pData = ref.dataPtr();
|
|
||||||
m_eType = ref.m_eType;
|
|
||||||
ref.m_eType = eDataType::CONFIGDATATYPE_EMPTY;
|
|
||||||
ref.m_pData = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CConfigValue::CConfigValue() {
|
CConfigValue::CConfigValue() {
|
||||||
|
@ -112,3 +61,91 @@ CConfigValue::CConfigValue() {
|
||||||
void* CConfigValue::dataPtr() const {
|
void* CConfigValue::dataPtr() const {
|
||||||
return m_pData;
|
return m_pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CConfigCustomValueType::CConfigCustomValueType(PCONFIGCUSTOMVALUEHANDLERFUNC handler_, PCONFIGCUSTOMVALUEDESTRUCTOR dtor_, const char* def) {
|
||||||
|
handler = handler_;
|
||||||
|
dtor = dtor_;
|
||||||
|
defaultVal = def;
|
||||||
|
}
|
||||||
|
|
||||||
|
CConfigCustomValueType::~CConfigCustomValueType() {
|
||||||
|
dtor(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigValue::defaultFrom(SConfigDefaultValue& ref) {
|
||||||
|
m_eType = (CConfigValue::eDataType)ref.type;
|
||||||
|
switch (m_eType) {
|
||||||
|
case CONFIGDATATYPE_FLOAT: {
|
||||||
|
if (!m_pData)
|
||||||
|
m_pData = calloc(1, sizeof(float));
|
||||||
|
*reinterpret_cast<float*>(m_pData) = std::any_cast<float>(ref.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_INT: {
|
||||||
|
if (!m_pData)
|
||||||
|
m_pData = calloc(1, sizeof(int64_t));
|
||||||
|
*reinterpret_cast<int64_t*>(m_pData) = std::any_cast<int64_t>(ref.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_STR: {
|
||||||
|
if (!m_pData)
|
||||||
|
free(m_pData);
|
||||||
|
std::string str = std::any_cast<std::string>(ref.data);
|
||||||
|
m_pData = calloc(1, str.length() + 1);
|
||||||
|
strncpy((char*)m_pData, str.c_str(), str.length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_VEC2: {
|
||||||
|
if (!m_pData)
|
||||||
|
m_pData = calloc(1, sizeof(SVector2D));
|
||||||
|
*reinterpret_cast<SVector2D*>(m_pData) = std::any_cast<SVector2D>(ref.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_CUSTOM: {
|
||||||
|
if (!m_pData)
|
||||||
|
m_pData = calloc(1, sizeof(CConfigCustomValueType));
|
||||||
|
CConfigCustomValueType* type = reinterpret_cast<CConfigCustomValueType*>(m_pData);
|
||||||
|
type->handler = ref.handler;
|
||||||
|
type->dtor = ref.dtor;
|
||||||
|
type->handler(std::any_cast<std::string>(ref.data).c_str(), &type->data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw "bad defaultFrom type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigValue::setFrom(std::any value) {
|
||||||
|
switch (m_eType) {
|
||||||
|
case CONFIGDATATYPE_FLOAT: {
|
||||||
|
*reinterpret_cast<float*>(m_pData) = std::any_cast<float>(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_INT: {
|
||||||
|
*reinterpret_cast<int64_t*>(m_pData) = std::any_cast<int64_t>(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_STR: {
|
||||||
|
free(m_pData);
|
||||||
|
std::string str = std::any_cast<std::string>(value);
|
||||||
|
m_pData = calloc(1, str.length() + 1);
|
||||||
|
strncpy((char*)m_pData, str.c_str(), str.length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIGDATATYPE_VEC2: {
|
||||||
|
*reinterpret_cast<SVector2D*>(m_pData) = std::any_cast<SVector2D>(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// case CONFIGDATATYPE_CUSTOM: {
|
||||||
|
// CConfigCustomValueType* type = reinterpret_cast<CConfigCustomValueType*>(m_pData);
|
||||||
|
// type->handler = ref.handler;
|
||||||
|
// type->dtor = ref.dtor;
|
||||||
|
// type->handler(std::any_cast<std::string>(ref.data).c_str(), &type->data);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
default: {
|
||||||
|
throw "bad defaultFrom type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,11 +52,19 @@ CConfig::~CConfig() {
|
||||||
delete impl;
|
delete impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfig::addConfigValue(const char* name, const CConfigValue value) {
|
void CConfig::addConfigValue(const char* name, const CConfigValue& value) {
|
||||||
if (m_bCommenced)
|
if (m_bCommenced)
|
||||||
throw "Cannot addConfigValue after commence()";
|
throw "Cannot addConfigValue after commence()";
|
||||||
|
|
||||||
impl->defaultValues[std::string{name}] = value;
|
if ((eDataType)value.m_eType != CONFIGDATATYPE_CUSTOM && (eDataType)value.m_eType != CONFIGDATATYPE_STR)
|
||||||
|
impl->defaultValues.emplace(name, SConfigDefaultValue{value.getValue(), (eDataType)value.m_eType});
|
||||||
|
else if ((eDataType)value.m_eType == CONFIGDATATYPE_STR)
|
||||||
|
impl->defaultValues.emplace(name, SConfigDefaultValue{std::string{std::any_cast<const char*>(value.getValue())}, (eDataType)value.m_eType});
|
||||||
|
else
|
||||||
|
impl->defaultValues.emplace(name,
|
||||||
|
SConfigDefaultValue{reinterpret_cast<CConfigCustomValueType*>(value.m_pData)->defaultVal, (eDataType)value.m_eType,
|
||||||
|
reinterpret_cast<CConfigCustomValueType*>(value.m_pData)->handler,
|
||||||
|
reinterpret_cast<CConfigCustomValueType*>(value.m_pData)->dtor});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfig::addSpecialConfigValue(const char* cat, const char* name, const CConfigValue value) {
|
void CConfig::addSpecialConfigValue(const char* cat, const char* name, const CConfigValue value) {
|
||||||
|
@ -65,7 +73,15 @@ void CConfig::addSpecialConfigValue(const char* cat, const char* name, const CCo
|
||||||
if (IT == impl->specialCategoryDescriptors.end())
|
if (IT == impl->specialCategoryDescriptors.end())
|
||||||
throw "No such category";
|
throw "No such category";
|
||||||
|
|
||||||
IT->get()->defaultValues[std::string{name}] = value;
|
if ((eDataType)value.m_eType != CONFIGDATATYPE_CUSTOM && (eDataType)value.m_eType != CONFIGDATATYPE_STR)
|
||||||
|
IT->get()->defaultValues.emplace(name, SConfigDefaultValue{value.getValue(), (eDataType)value.m_eType});
|
||||||
|
else if ((eDataType)value.m_eType == CONFIGDATATYPE_STR)
|
||||||
|
IT->get()->defaultValues.emplace(name, SConfigDefaultValue{std::string{std::any_cast<const char*>(value.getValue())}, (eDataType)value.m_eType});
|
||||||
|
else
|
||||||
|
IT->get()->defaultValues.emplace(name,
|
||||||
|
SConfigDefaultValue{reinterpret_cast<CConfigCustomValueType*>(value.m_pData)->defaultVal, (eDataType)value.m_eType,
|
||||||
|
reinterpret_cast<CConfigCustomValueType*>(value.m_pData)->handler,
|
||||||
|
reinterpret_cast<CConfigCustomValueType*>(value.m_pData)->dtor});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfig::addSpecialCategory(const char* name, SSpecialCategoryOptions options) {
|
void CConfig::addSpecialCategory(const char* name, SSpecialCategoryOptions options) {
|
||||||
|
@ -85,16 +101,16 @@ void CConfig::addSpecialCategory(const char* name, SSpecialCategoryOptions optio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSpecialCategory::applyDefaults() {
|
void CConfig::applyDefaultsToCat(SSpecialCategory& cat) {
|
||||||
for (auto& [k, v] : descriptor->defaultValues) {
|
for (auto& [k, v] : cat.descriptor->defaultValues) {
|
||||||
values[k] = v;
|
cat.values[k].defaultFrom(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfig::commence() {
|
void CConfig::commence() {
|
||||||
m_bCommenced = true;
|
m_bCommenced = true;
|
||||||
for (auto& [k, v] : impl->defaultValues) {
|
for (auto& [k, v] : impl->defaultValues) {
|
||||||
impl->values[k] = v;
|
impl->values[k].defaultFrom(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +256,7 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
|
||||||
PCAT->key = sc->key;
|
PCAT->key = sc->key;
|
||||||
addSpecialConfigValue(sc->name.c_str(), sc->key.c_str(), CConfigValue("0"));
|
addSpecialConfigValue(sc->name.c_str(), sc->key.c_str(), CConfigValue("0"));
|
||||||
|
|
||||||
PCAT->applyDefaults();
|
applyDefaultsToCat(*PCAT);
|
||||||
|
|
||||||
VALUEIT = PCAT->values.find(valueName.substr(sc->name.length() + 1));
|
VALUEIT = PCAT->values.find(valueName.substr(sc->name.length() + 1));
|
||||||
|
|
||||||
|
@ -267,7 +283,7 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
|
||||||
switch (VALUEIT->second.m_eType) {
|
switch (VALUEIT->second.m_eType) {
|
||||||
case CConfigValue::eDataType::CONFIGDATATYPE_INT: {
|
case CConfigValue::eDataType::CONFIGDATATYPE_INT: {
|
||||||
try {
|
try {
|
||||||
VALUEIT->second = {configStringToInt(value)};
|
VALUEIT->second.setFrom(configStringToInt(value));
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
result.setError(std::format("failed parsing an int: {}", e.what()));
|
result.setError(std::format("failed parsing an int: {}", e.what()));
|
||||||
return result;
|
return result;
|
||||||
|
@ -276,7 +292,7 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
|
||||||
}
|
}
|
||||||
case CConfigValue::eDataType::CONFIGDATATYPE_FLOAT: {
|
case CConfigValue::eDataType::CONFIGDATATYPE_FLOAT: {
|
||||||
try {
|
try {
|
||||||
VALUEIT->second = {std::stof(value)};
|
VALUEIT->second.setFrom(std::stof(value));
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
result.setError(std::format("failed parsing a float: {}", e.what()));
|
result.setError(std::format("failed parsing a float: {}", e.what()));
|
||||||
return result;
|
return result;
|
||||||
|
@ -294,7 +310,7 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
|
||||||
if (LHS.contains(" ") || RHS.contains(" "))
|
if (LHS.contains(" ") || RHS.contains(" "))
|
||||||
throw std::runtime_error("too many args");
|
throw std::runtime_error("too many args");
|
||||||
|
|
||||||
VALUEIT->second = {SVector2D{std::stof(LHS), std::stof(RHS)}};
|
VALUEIT->second.setFrom(SVector2D{std::stof(LHS), std::stof(RHS)});
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
result.setError(std::format("failed parsing a vec2: {}", e.what()));
|
result.setError(std::format("failed parsing a vec2: {}", e.what()));
|
||||||
return result;
|
return result;
|
||||||
|
@ -302,7 +318,11 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CConfigValue::eDataType::CONFIGDATATYPE_STR: {
|
case CConfigValue::eDataType::CONFIGDATATYPE_STR: {
|
||||||
VALUEIT->second = {value.c_str()};
|
VALUEIT->second.setFrom(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CConfigValue::eDataType::CONFIGDATATYPE_CUSTOM: {
|
||||||
|
reinterpret_cast<CConfigCustomValueType*>(VALUEIT->second.m_pData)->handler(value.c_str(), &reinterpret_cast<CConfigCustomValueType*>(VALUEIT->second.m_pData)->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -468,10 +488,10 @@ CParseResult CConfig::parse() {
|
||||||
clearState();
|
clearState();
|
||||||
|
|
||||||
for (auto& [k, v] : impl->defaultValues) {
|
for (auto& [k, v] : impl->defaultValues) {
|
||||||
impl->values.at(k) = v;
|
impl->values.at(k).defaultFrom(v);
|
||||||
}
|
}
|
||||||
for (auto& sc : impl->specialCategories) {
|
for (auto& sc : impl->specialCategories) {
|
||||||
sc->applyDefaults();
|
applyDefaultsToCat(*sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
CParseResult fileParseResult = parseFile(impl->path);
|
CParseResult fileParseResult = parseFile(impl->path);
|
||||||
|
|
|
@ -16,10 +16,30 @@ struct SVariable {
|
||||||
std::vector<std::string> linesContainingVar; // for dynamic updates
|
std::vector<std::string> linesContainingVar; // for dynamic updates
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// remember to also edit CConfigValue if editing
|
||||||
|
enum eDataType {
|
||||||
|
CONFIGDATATYPE_EMPTY,
|
||||||
|
CONFIGDATATYPE_INT,
|
||||||
|
CONFIGDATATYPE_FLOAT,
|
||||||
|
CONFIGDATATYPE_STR,
|
||||||
|
CONFIGDATATYPE_VEC2,
|
||||||
|
CONFIGDATATYPE_CUSTOM,
|
||||||
|
};
|
||||||
|
|
||||||
|
// CUSTOM is stored as STR!!
|
||||||
|
struct SConfigDefaultValue {
|
||||||
|
std::any data;
|
||||||
|
eDataType type = CONFIGDATATYPE_EMPTY;
|
||||||
|
|
||||||
|
// this sucks but I have no better idea
|
||||||
|
Hyprlang::PCONFIGCUSTOMVALUEHANDLERFUNC handler = nullptr;
|
||||||
|
Hyprlang::PCONFIGCUSTOMVALUEDESTRUCTOR dtor = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct SSpecialCategoryDescriptor {
|
struct SSpecialCategoryDescriptor {
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
std::string key = "";
|
std::string key = "";
|
||||||
std::unordered_map<std::string, Hyprlang::CConfigValue> defaultValues;
|
std::unordered_map<std::string, SConfigDefaultValue> defaultValues;
|
||||||
bool dontErrorOnMissing = false;
|
bool dontErrorOnMissing = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,7 +58,7 @@ class CConfigImpl {
|
||||||
std::string path = "";
|
std::string path = "";
|
||||||
|
|
||||||
std::unordered_map<std::string, Hyprlang::CConfigValue> values;
|
std::unordered_map<std::string, Hyprlang::CConfigValue> values;
|
||||||
std::unordered_map<std::string, Hyprlang::CConfigValue> defaultValues;
|
std::unordered_map<std::string, SConfigDefaultValue> defaultValues;
|
||||||
std::vector<SHandler> handlers;
|
std::vector<SHandler> handlers;
|
||||||
std::vector<SVariable> variables;
|
std::vector<SVariable> variables;
|
||||||
std::vector<SVariable> envVariables;
|
std::vector<SVariable> envVariables;
|
||||||
|
|
|
@ -13,6 +13,8 @@ testEnv = $SHELL
|
||||||
|
|
||||||
source = ./colors.conf
|
source = ./colors.conf
|
||||||
|
|
||||||
|
customType = abc
|
||||||
|
|
||||||
testCategory {
|
testCategory {
|
||||||
testValueInt = 123456
|
testValueInt = 123456
|
||||||
testValueHex = 0xF
|
testValueHex = 0xF
|
||||||
|
|
|
@ -48,6 +48,24 @@ static Hyprlang::CParseResult handleSource(const char* COMMAND, const char* VALU
|
||||||
return pConfig->parseFile(PATH);
|
return pConfig->parseFile(PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Hyprlang::CParseResult handleCustomValueSet(const char* VALUE, void** data) {
|
||||||
|
if (!*data)
|
||||||
|
*data = calloc(1, sizeof(int64_t));
|
||||||
|
std::string V = VALUE;
|
||||||
|
if (V == "abc")
|
||||||
|
*reinterpret_cast<int64_t*>(*data) = 1;
|
||||||
|
else
|
||||||
|
*reinterpret_cast<int64_t*>(*data) = 2;
|
||||||
|
|
||||||
|
Hyprlang::CParseResult result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleCustomValueDestroy(void** data) {
|
||||||
|
if (*data)
|
||||||
|
free(*data);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv, char** envp) {
|
int main(int argc, char** argv, char** envp) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -80,6 +98,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
config.addConfigValue("myColors:pink", 0L);
|
config.addConfigValue("myColors:pink", 0L);
|
||||||
config.addConfigValue("myColors:green", 0L);
|
config.addConfigValue("myColors:green", 0L);
|
||||||
config.addConfigValue("myColors:random", 0L);
|
config.addConfigValue("myColors:random", 0L);
|
||||||
|
config.addConfigValue("customType", {Hyprlang::CConfigCustomValueType{&handleCustomValueSet, &handleCustomValueDestroy, "def"}});
|
||||||
|
|
||||||
config.registerHandler(&handleDoABarrelRoll, "doABarrelRoll", {false});
|
config.registerHandler(&handleDoABarrelRoll, "doABarrelRoll", {false});
|
||||||
config.registerHandler(&handleFlagsTest, "flags", {true});
|
config.registerHandler(&handleFlagsTest, "flags", {true});
|
||||||
|
@ -159,6 +178,10 @@ int main(int argc, char** argv, char** envp) {
|
||||||
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:green")), 0xFF14f014L);
|
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:green")), 0xFF14f014L);
|
||||||
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:random")), 0xFFFF1337L);
|
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:random")), 0xFFFF1337L);
|
||||||
|
|
||||||
|
// test custom type
|
||||||
|
std::cout << " → Testing custom types\n";
|
||||||
|
EXPECT(*reinterpret_cast<int64_t*>(std::any_cast<void*>(config.getConfigValue("customType"))), 1L);
|
||||||
|
|
||||||
} 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