Skip to content

Commit

Permalink
convar: Add small convar system
Browse files Browse the repository at this point in the history
Co-authored-by: Alpyne <[email protected]>
  • Loading branch information
misyltoad and AlpyneDreams committed Feb 6, 2024
1 parent 332f348 commit d70530c
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/convar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "convar.h"

namespace gamescope
{
Dict<ConCommand *>& ConCommand::GetCommands()
{
static Dict<ConCommand *> s_Commands;
return s_Commands;
}
}
145 changes: 145 additions & 0 deletions src/convar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#pragma once

#include <span>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <optional>
#include <charconv>
#include <type_traits>
#include <cstdint>
#include <functional>
#include <cassert>

namespace gamescope
{
class ConCommand;

template <typename T>
inline std::optional<T> Parse( std::string_view chars )
{
T obj;
auto result = std::from_chars( chars.begin(), chars.end(), obj );
if ( result.ec == std::errc{} )
return obj;
else
return std::nullopt;
}

template <>
inline std::optional<bool> Parse( std::string_view chars )
{
std::optional<uint32_t> oNumber = Parse<uint32_t>( chars );
if ( oNumber )
return !!*oNumber;

if ( chars == "true" )
return true;
else
return false;
}

struct StringHash
{
using is_transparent = void;
[[nodiscard]] size_t operator()( const char *string ) const { return std::hash<std::string_view>{}( string ); }
[[nodiscard]] size_t operator()( std::string_view string ) const { return std::hash<std::string_view>{}( string ); }
[[nodiscard]] size_t operator()( const std::string &string ) const { return std::hash<std::string>{}( string ); }
};

template <typename T>
using Dict = std::unordered_map<std::string, T, StringHash, std::equal_to<>>;

class ConCommand
{
using ConCommandFunc = std::function<void( std::span<std::string_view> )>;

public:
ConCommand( std::string_view pszName, std::string_view pszDescription, ConCommandFunc func )
: m_pszName{ pszName }
, m_pszDescription{ pszDescription }
, m_Func{ func }
{
assert( !GetCommands().contains( pszName ) );
GetCommands()[ std::string( pszName ) ] = this;
}

~ConCommand()
{
GetCommands().erase( GetCommands().find( m_pszName ) );
}

void Invoke( std::span<std::string_view> args )
{
if ( m_Func )
m_Func( args );
}

static Dict<ConCommand *>& GetCommands();
protected:
std::string_view m_pszName;
std::string_view m_pszDescription;
ConCommandFunc m_Func;
};

template <typename T>
class ConVar : public ConCommand
{
using ConVarCallbackFunc = std::function<void()>;
public:
ConVar( std::string_view pszName, T defaultValue = T{}, std::string_view pszDescription = "", ConVarCallbackFunc func = nullptr )
: ConCommand( pszName, pszDescription, [this]( std::span<std::string_view> pArgs ){ this->InvokeFunc( pArgs ); } )
, m_Value{ defaultValue }
, m_Callback{ func }
{
}

const T& Get() const
{
return m_Value;
}

template <typename J>
void SetValue( const J &newValue )
{
m_Value = T{ newValue };

if ( !m_bInCallback && m_Callback )
{
m_bInCallback = true;
m_Callback();
m_bInCallback = false;
}
}

template <typename J>
ConVar<T>& operator =( const J &newValue ) { SetValue<J>( newValue ); return *this; }

operator T() const { return m_Value; }

template <typename J> bool operator == ( const J &other ) const { return m_Value == other; }
template <typename J> bool operator != ( const J &other ) const { return m_Value != other; }
template <typename J> bool operator <=>( const J &other ) const { return m_Value <=> other; }

void InvokeFunc( std::span<std::string_view> pArgs )
{
if ( pArgs.size() != 2 )
return;

if constexpr ( std::is_integral<T>::value )
{
std::optional<T> oResult = Parse<T>( pArgs[1] );
SetValue( oResult ? *oResult : T{} );
}
else
{
SetValue( pArgs[1] );
}
}
private:
T m_Value{};
ConVarCallbackFunc m_Callback;
bool m_bInCallback;
};
}
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ required_wlroots_features = ['xwayland']

src = [
'steamcompmgr.cpp',
'convar.cpp',
'color_helpers.cpp',
'main.cpp',
'edid.cpp',
Expand Down

0 comments on commit d70530c

Please sign in to comment.