2024-04-04 17:19:15 +02:00
# include "meta.hpp"
# include <hyprlang.hpp>
# include <toml++/toml.hpp>
# include <filesystem>
2024-04-12 02:01:33 +02:00
# include <regex>
2024-04-04 17:19:15 +02:00
# include "VarList.hpp"
CMeta * currentMeta = nullptr ;
CMeta : : CMeta ( const std : : string & rawdata_ , bool hyprlang_ /* false for toml */ , bool dataIsPath ) : rawdata ( rawdata_ ) , hyprlang ( hyprlang_ ) , dataPath ( dataIsPath ) {
if ( ! dataIsPath )
return ;
rawdata = " " ;
try {
if ( std : : filesystem : : exists ( rawdata_ + " .hl " ) ) {
rawdata = rawdata_ + " .hl " ;
hyprlang = true ;
return ;
}
if ( std : : filesystem : : exists ( rawdata_ + " .toml " ) ) {
rawdata = rawdata_ + " .toml " ;
hyprlang = false ;
return ;
}
} catch ( . . . ) { }
}
std : : optional < std : : string > CMeta : : parse ( ) {
if ( rawdata . empty ( ) )
return " Invalid meta (missing?) " ;
std : : optional < std : : string > res ;
currentMeta = this ;
if ( hyprlang )
res = parseHL ( ) ;
else
res = parseTOML ( ) ;
currentMeta = nullptr ;
return res ;
}
static std : : string removeBeginEndSpacesTabs ( std : : string str ) {
if ( str . empty ( ) )
return str ;
int countBefore = 0 ;
while ( str [ countBefore ] = = ' ' | | str [ countBefore ] = = ' \t ' ) {
countBefore + + ;
}
int countAfter = 0 ;
while ( ( int ) str . length ( ) - countAfter - 1 > = 0 & & ( str [ str . length ( ) - countAfter - 1 ] = = ' ' | | str [ str . length ( ) - 1 - countAfter ] = = ' \t ' ) ) {
countAfter + + ;
}
str = str . substr ( countBefore , str . length ( ) - countBefore - countAfter ) ;
return str ;
}
static Hyprlang : : CParseResult parseDefineSize ( const char * C , const char * V ) {
Hyprlang : : CParseResult result ;
const std : : string VALUE = V ;
2024-10-11 20:02:14 +02:00
CVarList sizes ( VALUE , 0 , ' ; ' ) ;
2024-04-04 17:19:15 +02:00
2024-10-11 20:02:14 +02:00
for ( const auto & sizeStr : sizes ) {
if ( ! sizeStr . contains ( " , " ) ) {
result . setError ( " Invalid define_size " ) ;
2024-04-04 17:19:15 +02:00
return result ;
}
2024-10-11 20:02:14 +02:00
auto LHS = removeBeginEndSpacesTabs ( sizeStr . substr ( 0 , sizeStr . find_first_of ( " , " ) ) ) ;
auto RHS = removeBeginEndSpacesTabs ( sizeStr . substr ( sizeStr . find_first_of ( " , " ) + 1 ) ) ;
auto DELAY = 0 ;
2024-04-04 17:19:15 +02:00
2024-10-11 20:02:14 +02:00
CMeta : : SDefinedSize size ;
if ( RHS . contains ( " , " ) ) {
const auto LL = removeBeginEndSpacesTabs ( RHS . substr ( 0 , RHS . find ( " , " ) ) ) ;
const auto RR = removeBeginEndSpacesTabs ( RHS . substr ( RHS . find ( " , " ) + 1 ) ) ;
2024-04-12 02:01:33 +02:00
2024-10-11 20:02:14 +02:00
try {
size . delayMs = std : : stoull ( RR ) ;
} catch ( std : : exception & e ) {
result . setError ( e . what ( ) ) ;
return result ;
}
2024-04-04 17:19:15 +02:00
2024-10-11 20:02:14 +02:00
RHS = LL ;
}
if ( ! std : : regex_match ( RHS , std : : regex ( " ^[A-Za-z0-9_ \\ - \\ .]+$ " ) ) ) {
result . setError ( " Invalid cursor file name, characters must be within [A-Za-z0-9_ \\ - \\ .] (if this seems like a mistake, check for invisible characters) " ) ;
2024-04-04 17:19:15 +02:00
return result ;
}
2024-10-11 20:02:14 +02:00
size . file = RHS ;
if ( ! size . file . ends_with ( " .svg " ) ) {
try {
size . size = std : : stoull ( LHS ) ;
} catch ( std : : exception & e ) {
result . setError ( e . what ( ) ) ;
return result ;
}
} else
size . size = 0 ;
currentMeta - > parsedData . definedSizes . push_back ( size ) ;
}
2024-04-04 17:19:15 +02:00
return result ;
}
static Hyprlang : : CParseResult parseOverride ( const char * C , const char * V ) {
Hyprlang : : CParseResult result ;
const std : : string VALUE = V ;
2024-10-11 20:02:14 +02:00
CVarList overrides ( VALUE , 0 , ' ; ' ) ;
for ( const auto & o : overrides ) {
currentMeta - > parsedData . overrides . push_back ( VALUE ) ;
}
2024-04-04 17:19:15 +02:00
return result ;
}
std : : optional < std : : string > CMeta : : parseHL ( ) {
std : : unique_ptr < Hyprlang : : CConfig > meta ;
try {
meta = std : : make_unique < Hyprlang : : CConfig > ( rawdata . c_str ( ) , Hyprlang : : SConfigOptions { . pathIsStream = ! dataPath } ) ;
meta - > addConfigValue ( " hotspot_x " , Hyprlang : : FLOAT { 0.F } ) ;
meta - > addConfigValue ( " hotspot_y " , Hyprlang : : FLOAT { 0.F } ) ;
meta - > addConfigValue ( " resize_algorithm " , Hyprlang : : STRING { " nearest " } ) ;
meta - > registerHandler ( : : parseDefineSize , " define_size " , { . allowFlags = false } ) ;
meta - > registerHandler ( : : parseOverride , " define_override " , { . allowFlags = false } ) ;
meta - > commence ( ) ;
2024-04-12 02:01:33 +02:00
const auto RESULT = meta - > parse ( ) ;
if ( RESULT . error )
return RESULT . getError ( ) ;
2024-04-04 17:19:15 +02:00
} catch ( const char * err ) { return " failed parsing meta: " + std : : string { err } ; }
parsedData . hotspotX = std : : any_cast < Hyprlang : : FLOAT > ( meta - > getConfigValue ( " hotspot_x " ) ) ;
parsedData . hotspotY = std : : any_cast < Hyprlang : : FLOAT > ( meta - > getConfigValue ( " hotspot_y " ) ) ;
parsedData . resizeAlgo = std : : any_cast < Hyprlang : : STRING > ( meta - > getConfigValue ( " resize_algorithm " ) ) ;
return { } ;
}
std : : optional < std : : string > CMeta : : parseTOML ( ) {
try {
auto MANIFEST = dataPath ? toml : : parse_file ( rawdata ) : toml : : parse ( rawdata ) ;
parsedData . hotspotX = MANIFEST [ " General " ] [ " hotspot_x " ] . value_or ( 0.f ) ;
parsedData . hotspotY = MANIFEST [ " General " ] [ " hotspot_y " ] . value_or ( 0.f ) ;
const std : : string OVERRIDES = MANIFEST [ " General " ] [ " define_override " ] . value_or ( " " ) ;
const std : : string SIZES = MANIFEST [ " General " ] [ " define_size " ] . value_or ( " " ) ;
//
CVarList OVERRIDESLIST ( OVERRIDES , 0 , ' ; ' , true ) ;
for ( auto & o : OVERRIDESLIST ) {
const auto RESULT = : : parseOverride ( " define_override " , o . c_str ( ) ) ;
if ( RESULT . error )
throw ;
}
CVarList SIZESLIST ( SIZES , 0 , ' ; ' , true ) ;
for ( auto & s : SIZESLIST ) {
const auto RESULT = : : parseDefineSize ( " define_size " , s . c_str ( ) ) ;
if ( RESULT . error )
throw ;
}
parsedData . resizeAlgo = MANIFEST [ " General " ] [ " resize_algorithm " ] . value_or ( " " ) ;
} catch ( std : : exception & e ) { return std : : string { " Failed parsing toml: " } + e . what ( ) ; }
return { } ;
}