Skip to content

Instantly share code, notes, and snippets.

@untodesu
Created January 22, 2020 09:47
Show Gist options
  • Save untodesu/164e5a28c7a4202ff7b21ca2f388550d to your computer and use it in GitHub Desktop.
Save untodesu/164e5a28c7a4202ff7b21ca2f388550d to your computer and use it in GitHub Desktop.
#include <cstdint> // uint32_t
#include <cstddef> // size_t
#include <cstring> // strcmp, strncpy
#include <cstdlib> // atoi, atof
#include <string> // std::to_string
#include "cvardef.h"
#include "cvar.h"
//-----------------------------------------------------------------------------
// s_cvars
// Global list head
//-----------------------------------------------------------------------------
static cvar_t *s_cvars = nullptr;
//-----------------------------------------------------------------------------
// CVar_FindVar
// Find and return the pointer to existing variable
// Returns null if not found
//-----------------------------------------------------------------------------
cvar_t * CVar_FindVar(const char *name)
{
for(cvar_t *cvar = s_cvars; cvar; cvar = cvar->next) {
if(!strcmp(cvar->name, name)) {
return cvar;
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
// CVar_Register
// Registers new variable
//-----------------------------------------------------------------------------
void CVar_Register(cvar_t *cvar, const char *value)
{
if(CVar_FindVar(cvar.name)) {
// Already defined?
return;
}
// todo: concommand checks - UNUSED: COMMANDS WRAP CVARS
// Registering will force heap allocation
// so we pick this values
const char *oldstr = cvar.value;
const size_t len = strlen(oldstr);
// Make cvar use heap for values
cvar.value = new char[len + 1];
cvar.value[len] = 0; // null terminator
strncpy(cvar.value, oldstr, len);
// Add new cvar to list
cvar.next = s_cvars;
s_cvars = &cvar;
}
//-----------------------------------------------------------------------------
// CVar_Unregister
// Revert CVar_Register
//-----------------------------------------------------------------------------
void CVar_Unregister(cvar_t &cvar)
{
cvar_t *prev = s_cvars;
for(cvar_t *node = s_cvars; node; node = node->next) {
if(node == &cvar) {
// If we have last added node,
// we don't have prev value, so we just move previous thing forward
if(node == s_cvars) {
s_cvars = s_cvars->next;
}
// else - we have valid prev value, so replace em
else {
prev->next = node->next;
}
delete[] cvar.value;
cvar.value = nullptr;
cvar.next = nullptr;
return;
}
prev = node;
}
}
//-----------------------------------------------------------------------------
// CVar_SetValue
// Sets string value of cvar
//-----------------------------------------------------------------------------
void CVar_SetValue(const char *name, const char *value)
{
cvar_t *cvar = CVar_FindVar(name);
if(!cvar) {
// we cannot set the empty variable
return;
}
// We can set variable only if the FCVAR_READONLY is not set
if(!(cvar->flags & FCVAR_READONLY)) {
const size_t len = strlen(value);
// Re-allocate
delete cvar->value;
cvar->value = new char[len + 1];
cvar->value[len] = 0; // null-terminator
strncpy(cvar->value, value, len);
// todo: Do some other stuff
}
}
//-----------------------------------------------------------------------------
// CVar_GetValue
//
//-----------------------------------------------------------------------------
const char * CVar_GetValue(const char *name)
{
static const char *s_defaultValue = "";
cvar_t *cvar = CVar_FindVar(name);
if(!cvar) {
return s_defaultValue;
}
return cvar->value;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CVar::CVar
// Constructor
//-----------------------------------------------------------------------------
CVar::CVar(const char *name, const char *value, uint32_t flags) : cvar_t(*this)
{
const size_t vlen = strlen(value);
char *dummy = new char[vlen];
strncpy(dummy, value, vlen);
// cvar_t inherited
this->name = name;
this->value = dummy;
this->flags = flags;
CVar_Register(*this);
delete[] dummy;
}
//-----------------------------------------------------------------------------
// CVar::~CVar
// Destructor
//-----------------------------------------------------------------------------
CVar::~CVar(void)
{
CVar_Unregister(*this);
}
//-----------------------------------------------------------------------------
// CVar::IsValid
//
//-----------------------------------------------------------------------------
bool CVar::IsValid(void) const
{
// we cannot use m_me here cuz reference
return !!CVar_FindVar(this->name);
}
//-----------------------------------------------------------------------------
// CVar::GetString
// Data accessor
//-----------------------------------------------------------------------------
const char * CVar::GetString(void) const
{
return this->value;
}
//-----------------------------------------------------------------------------
// CVar::GetInt
// Data accessor
//-----------------------------------------------------------------------------
int CVar::GetInt(void) const
{
if(IsValid()) {
return std::atoi(this->value);
}
return 0;
}
//-----------------------------------------------------------------------------
// CVar::GetFloat
// Data accessor
//-----------------------------------------------------------------------------
double CVar::GetFloat(void) const
{
if(IsValid()) {
return std::atof(this->value);
}
return 0.0;
}
//-----------------------------------------------------------------------------
// CVar::GetBool
// Data accessor
//-----------------------------------------------------------------------------
bool CVar::GetBool(void) const
{
return !!GetInt();
}
//-----------------------------------------------------------------------------
// CVar::SetValue <- const char *
// Data accessor
//-----------------------------------------------------------------------------
void CVar::SetValue(const char *value) const
{
if(IsValid()) {
// Now we have a different function to set value
// because cvar is reallocating memory in heap
CVar_SetValue(this->name, value);
}
}
//-----------------------------------------------------------------------------
// CVar::SetValue <- int
// Data accessor
//-----------------------------------------------------------------------------
void CVar::SetValue(const int value) const
{
SetValue(std::to_string(value).c_str());
}
//-----------------------------------------------------------------------------
// CVar::SetValue <- double
// Data accessor
//-----------------------------------------------------------------------------
void CVar::SetValue(const double value) const
{
SetValue(std::to_string(value).c_str());
}
//-----------------------------------------------------------------------------
// CVar::SetValue <- bool
// Data accessor
//-----------------------------------------------------------------------------
void CVar::SetValue(const bool value) const
{
SetValue(value ? 1 : 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment