mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-16 10:05:22 +00:00
More refactoring and (hopefully) simplification
The idea was to avoid passing the data_source factory function through two std::binds.
This commit is contained in:
parent
56266e9476
commit
ad6707fac9
@ -26,7 +26,6 @@
|
|||||||
#include "data-source.hh"
|
#include "data-source.hh"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace conky {
|
namespace conky {
|
||||||
@ -46,7 +45,46 @@ namespace conky {
|
|||||||
*/
|
*/
|
||||||
data_sources_t *data_sources;
|
data_sources_t *data_sources;
|
||||||
|
|
||||||
void register_data_source_(const std::string &name, const data_source_factory &factory_func)
|
data_source_base& get_data_source(lua::state *l)
|
||||||
|
{
|
||||||
|
if(l->gettop() != 1)
|
||||||
|
throw std::runtime_error("Wrong number of parameters");
|
||||||
|
|
||||||
|
l->rawgetfield(lua::REGISTRYINDEX, priv::data_source_metatable);
|
||||||
|
if(not l->getmetatable(-2) or not l->rawequal(-1, -2))
|
||||||
|
throw std::runtime_error("Invalid parameter");
|
||||||
|
|
||||||
|
return *static_cast<data_source_base *>(l->touserdata(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int data_source_asnumber(lua::state *l)
|
||||||
|
{
|
||||||
|
double x = get_data_source(l).get_number();
|
||||||
|
l->pushnumber(x);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int data_source_astext(lua::state *l)
|
||||||
|
{
|
||||||
|
std::string x = get_data_source(l).get_text();
|
||||||
|
l->pushstring(x.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char data_source__index[] =
|
||||||
|
"local table, key = ...;\n"
|
||||||
|
"if key == 'num' then\n"
|
||||||
|
" return conky.asnumber(table);\n"
|
||||||
|
"elseif key == 'text' then\n"
|
||||||
|
" return conky.astext(table);\n"
|
||||||
|
"else\n"
|
||||||
|
" print(string.format([[Invalid data source operation: '%s']], key));\n"
|
||||||
|
" return 0/0;\n"
|
||||||
|
"end\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace priv {
|
||||||
|
void do_register_data_source(const std::string &name, const lua::cpp_function &fn)
|
||||||
{
|
{
|
||||||
struct data_source_constructor {
|
struct data_source_constructor {
|
||||||
data_source_constructor() { data_sources = new data_sources_t(); }
|
data_source_constructor() { data_sources = new data_sources_t(); }
|
||||||
@ -54,20 +92,19 @@ namespace conky {
|
|||||||
};
|
};
|
||||||
static data_source_constructor constructor;
|
static data_source_constructor constructor;
|
||||||
|
|
||||||
bool inserted = data_sources->insert({name, factory_func}).second;
|
bool inserted = data_sources->insert({name, fn}).second;
|
||||||
if(not inserted)
|
if(not inserted)
|
||||||
throw std::logic_error("Data source with name '" + name + "' already registered");
|
throw std::logic_error("Data source with name '" + name + "' already registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
disabled_data_source::disabled_data_source(lua::state *l, const std::string &name,
|
||||||
disabled_source_factory(lua::state &l, const std::string &name, const std::string &setting)
|
const std::string &setting)
|
||||||
|
: simple_numeric_source<float>(l, name, &NaN)
|
||||||
{
|
{
|
||||||
// XXX some generic way of reporting errors? NORM_ERR?
|
// XXX some generic way of reporting errors? NORM_ERR?
|
||||||
std::cerr << "Support for variable '" << name
|
std::cerr << "Support for variable '" << name
|
||||||
<< "' has been disabled during compilation. Please recompile with '"
|
<< "' has been disabled during compilation. Please recompile with '"
|
||||||
<< setting << "'" << std::endl;
|
<< setting << "'" << std::endl;
|
||||||
|
|
||||||
simple_numeric_source<float>::factory(l, name, &NaN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,37 +118,45 @@ namespace conky {
|
|||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void
|
|
||||||
simple_numeric_source<T>::factory(lua::state &l, const std::string &name, const T *source)
|
|
||||||
{
|
|
||||||
l.pop();
|
|
||||||
l.createuserdata<simple_numeric_source<T>>(name, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
register_data_source::register_data_source(const std::string &name,
|
|
||||||
const data_source_factory &factory_func)
|
|
||||||
{ register_data_source_(name, factory_func); }
|
|
||||||
|
|
||||||
register_disabled_data_source::register_disabled_data_source(const std::string &name,
|
register_disabled_data_source::register_disabled_data_source(const std::string &name,
|
||||||
const std::string &setting)
|
const std::string &setting)
|
||||||
{
|
: register_data_source<priv::disabled_data_source>(name, setting)
|
||||||
register_data_source_(name,
|
{}
|
||||||
std::bind(disabled_source_factory,
|
|
||||||
std::placeholders::_1, std::placeholders::_2, setting)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// at least one data source should always be registered, so the pointer will not be null
|
// at least one data source should always be registered, so data_sources will not be null
|
||||||
const data_sources_t& get_data_sources()
|
void export_data_sources(lua::state &l)
|
||||||
{ return *data_sources; }
|
{
|
||||||
|
lua::stack_sentry s(l);
|
||||||
|
l.checkstack(2);
|
||||||
|
|
||||||
|
l.newmetatable(priv::data_source_metatable); ++s; {
|
||||||
|
l.pushboolean(false); ++s;
|
||||||
|
l.rawsetfield(-2, "__metatable"); --s;
|
||||||
|
|
||||||
|
l.pushdestructor<data_source_base>(); ++s;
|
||||||
|
l.rawsetfield(-2, "__gc"); --s;
|
||||||
|
|
||||||
|
l.loadstring(data_source__index); ++s;
|
||||||
|
l.rawsetfield(-2, "__index"); --s;
|
||||||
|
} l.pop(); --s;
|
||||||
|
|
||||||
|
l.newtable(); ++s; {
|
||||||
|
for(auto i = data_sources->begin(); i != data_sources->end(); ++i) {
|
||||||
|
l.pushfunction(i->second); ++s;
|
||||||
|
l.rawsetfield(-2, i->first.c_str()); --s;
|
||||||
|
}
|
||||||
|
} l.rawsetfield(-2, "variables"); --s;
|
||||||
|
|
||||||
|
l.pushfunction(data_source_asnumber); ++s;
|
||||||
|
l.rawsetfield(-2, "asnumber"); --s;
|
||||||
|
|
||||||
|
l.pushfunction(data_source_astext); ++s;
|
||||||
|
l.rawsetfield(-2, "astext"); --s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// example data sources, remove after real data sources are available ///////
|
/////////// example data sources, remove after real data sources are available ///////
|
||||||
int asdf_ = 47;
|
int asdf_ = 47;
|
||||||
conky::register_data_source asdf("asdf", std::bind(
|
conky::register_data_source<conky::simple_numeric_source<int>> asdf("asdf", &asdf_);
|
||||||
conky::simple_numeric_source<int>::factory,
|
|
||||||
std::placeholders::_1, std::placeholders::_2, &asdf_)
|
|
||||||
);
|
|
||||||
|
|
||||||
conky::register_disabled_data_source zxcv("zxcv", "BUILD_ZXCV");
|
conky::register_disabled_data_source zxcv("zxcv", "BUILD_ZXCV");
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#ifndef DATA_SOURCE_HH
|
#ifndef DATA_SOURCE_HH
|
||||||
#define DATA_SOURCE_HH
|
#define DATA_SOURCE_HH
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -34,13 +35,6 @@
|
|||||||
|
|
||||||
namespace conky {
|
namespace conky {
|
||||||
|
|
||||||
/*
|
|
||||||
* Recieves a lua table on the stack and the name the object was registered with. It should
|
|
||||||
* pop the table after consuming it. The result should be pushed on the stack as lua userdata
|
|
||||||
* containing (a subclass of) data_source_base.
|
|
||||||
*/
|
|
||||||
typedef std::function<void (lua::state &l, const std::string &name)> data_source_factory;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A base class for all data sources.
|
* A base class for all data sources.
|
||||||
* API consists of two functions:
|
* API consists of two functions:
|
||||||
@ -74,38 +68,69 @@ namespace conky {
|
|||||||
|
|
||||||
const T *source;
|
const T *source;
|
||||||
public:
|
public:
|
||||||
simple_numeric_source(const std::string &name_, const T *source_)
|
simple_numeric_source(lua::state *, const std::string &name_, const T *source_)
|
||||||
: data_source_base(name_), source(source_)
|
: data_source_base(name_), source(source_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static void factory(lua::state &l, const std::string &name, const T *source);
|
|
||||||
|
|
||||||
virtual double get_number() const
|
virtual double get_number() const
|
||||||
{ return *source; }
|
{ return *source; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace priv {
|
||||||
|
const char data_source_metatable[] = "conky::data_source_metatable";
|
||||||
|
|
||||||
|
void do_register_data_source(const std::string &name, const lua::cpp_function &fn);
|
||||||
|
|
||||||
|
class disabled_data_source: public simple_numeric_source<float> {
|
||||||
|
public:
|
||||||
|
disabled_data_source(lua::state *l, const std::string &name,
|
||||||
|
const std::string &setting);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Declaring an object of this type at global scope will register a data source with the give
|
* Declaring an object of this type at global scope will register a data source with the give
|
||||||
* name and factory function.
|
* name and factory function.
|
||||||
*/
|
*/
|
||||||
|
template<typename T>
|
||||||
class register_data_source {
|
class register_data_source {
|
||||||
|
template<typename... Args>
|
||||||
|
static int factory(lua::state *l, const std::string &name, Args&&... args)
|
||||||
|
{
|
||||||
|
T *t = static_cast<T *>(l->newuserdata(sizeof(T)));
|
||||||
|
l->insert(1);
|
||||||
|
new(t) T(l, name, std::forward<Args>(args)...);
|
||||||
|
l->settop(1);
|
||||||
|
l->rawgetfield(lua::REGISTRYINDEX, priv::data_source_metatable);
|
||||||
|
l->setmetatable(-2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
register_data_source(const std::string &name, const data_source_factory &factory_func);
|
template<typename... Args>
|
||||||
|
register_data_source(const std::string &name, Args&&... args)
|
||||||
|
{
|
||||||
|
priv::do_register_data_source( name, std::bind(&factory<Args...>,
|
||||||
|
std::placeholders::_1,
|
||||||
|
name,
|
||||||
|
std::forward<Args>(args)...
|
||||||
|
));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use this to declare a data source that has been disabled during compilation. We can then
|
* Use this to declare a data source that has been disabled during compilation. We can then
|
||||||
* print a nice error message telling the used which setting to enable.
|
* print a nice error message telling the used which setting to enable.
|
||||||
*/
|
*/
|
||||||
class register_disabled_data_source {
|
class register_disabled_data_source: public register_data_source<priv::disabled_data_source> {
|
||||||
public:
|
public:
|
||||||
register_disabled_data_source(const std::string &name, const std::string &setting);
|
register_disabled_data_source(const std::string &name, const std::string &setting);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<std::string, data_source_factory> data_sources_t;
|
typedef std::unordered_map<std::string, lua::cpp_function> data_sources_t;
|
||||||
|
|
||||||
// returns the list of registered data sources
|
void export_data_sources(lua::state &l);
|
||||||
const data_sources_t& get_data_sources();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DATA_SOURCE_HH */
|
#endif /* DATA_SOURCE_HH */
|
||||||
|
@ -28,87 +28,13 @@
|
|||||||
#include "data-source.hh"
|
#include "data-source.hh"
|
||||||
|
|
||||||
namespace conky {
|
namespace conky {
|
||||||
namespace {
|
|
||||||
const char data_source_metatable[] = "conky::data_source_metatable";
|
|
||||||
|
|
||||||
data_source_base& get_data_source(lua::state *l)
|
|
||||||
{
|
|
||||||
if(l->gettop() != 1)
|
|
||||||
throw std::runtime_error("Wrong number of parameters");
|
|
||||||
|
|
||||||
l->rawgetfield(lua::REGISTRYINDEX, data_source_metatable);
|
|
||||||
if(not l->getmetatable(-2) or not l->rawequal(-1, -2))
|
|
||||||
throw std::runtime_error("Invalid parameter");
|
|
||||||
|
|
||||||
return *static_cast<data_source_base *>(l->touserdata(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
int data_source_asnumber(lua::state *l)
|
|
||||||
{
|
|
||||||
double x = get_data_source(l).get_number();
|
|
||||||
l->pushnumber(x);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int data_source_astext(lua::state *l)
|
|
||||||
{
|
|
||||||
std::string x = get_data_source(l).get_text();
|
|
||||||
l->pushstring(x.c_str());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int create_data_source(lua::state *l, const data_sources_t::value_type &v)
|
|
||||||
{
|
|
||||||
v.second(*l, v.first);
|
|
||||||
l->rawgetfield(lua::REGISTRYINDEX, data_source_metatable);
|
|
||||||
l->setmetatable(-2);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char data_source__index[] =
|
|
||||||
"local table, key = ...;\n"
|
|
||||||
"if key == 'num' then\n"
|
|
||||||
" return conky.asnumber(table);\n"
|
|
||||||
"elseif key == 'text' then\n"
|
|
||||||
" return conky.astext(table);\n"
|
|
||||||
"else\n"
|
|
||||||
" print(string.format([[Invalid data source operation: '%s']], key));\n"
|
|
||||||
" return 0/0;\n"
|
|
||||||
"end\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void export_symbols(lua::state &l)
|
void export_symbols(lua::state &l)
|
||||||
{
|
{
|
||||||
lua::stack_sentry s(l);
|
lua::stack_sentry s(l);
|
||||||
l.checkstack(3);
|
l.checkstack(3);
|
||||||
|
|
||||||
l.newmetatable(data_source_metatable); ++s; {
|
|
||||||
l.pushboolean(false); ++s;
|
|
||||||
l.rawsetfield(-2, "__metatable"); --s;
|
|
||||||
|
|
||||||
l.pushdestructor<std::shared_ptr<data_source_base>>(); ++s;
|
|
||||||
l.rawsetfield(-2, "__gc"); --s;
|
|
||||||
|
|
||||||
l.loadstring(data_source__index); ++s;
|
|
||||||
l.rawsetfield(-2, "__index"); --s;
|
|
||||||
} l.pop(); --s;
|
|
||||||
|
|
||||||
l.newtable(); ++s; {
|
l.newtable(); ++s; {
|
||||||
l.newtable(); ++s; {
|
export_data_sources(l);
|
||||||
const data_sources_t &ds = get_data_sources();
|
|
||||||
for(auto i = ds.begin(); i != ds.end(); ++i) {
|
|
||||||
l.pushfunction(std::bind(create_data_source,
|
|
||||||
std::placeholders::_1, std::cref(*i)
|
|
||||||
)); ++s;
|
|
||||||
l.rawsetfield(-2, i->first.c_str()); --s;
|
|
||||||
}
|
|
||||||
} l.rawsetfield(-2, "variables"); --s;
|
|
||||||
|
|
||||||
l.pushfunction(data_source_asnumber); ++s;
|
|
||||||
l.rawsetfield(-2, "asnumber"); --s;
|
|
||||||
|
|
||||||
l.pushfunction(data_source_astext); ++s;
|
|
||||||
l.rawsetfield(-2, "astext"); --s;
|
|
||||||
} l.setglobal("conky"); --s;
|
} l.setglobal("conky"); --s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user