mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
Added new config system
Added emulator state class Added emulator events Minor improvements
This commit is contained in:
parent
bbfca3fc0d
commit
e4f6eb04e8
20 changed files with 1435 additions and 112 deletions
|
|
@ -208,6 +208,16 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
|
|||
return std::move(result);
|
||||
}
|
||||
|
||||
std::string fmt::trim(const std::string& source, const std::string& values)
|
||||
{
|
||||
std::size_t begin = source.find_first_not_of(values);
|
||||
|
||||
if (begin == source.npos)
|
||||
return{};
|
||||
|
||||
return source.substr(begin, source.find_last_not_of(values) + 1);
|
||||
}
|
||||
|
||||
std::string fmt::tolower(std::string source)
|
||||
{
|
||||
std::transform(source.begin(), source.end(), source.begin(), ::tolower);
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ namespace fmt
|
|||
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
|
||||
|
||||
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
|
||||
std::string trim(const std::string& source, const std::string& values = " \t");
|
||||
|
||||
template<typename T>
|
||||
std::string merge(const T& source, const std::string& separator)
|
||||
|
|
|
|||
146
Utilities/config_context.cpp
Normal file
146
Utilities/config_context.cpp
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#include "stdafx.h"
|
||||
#include "config_context.h"
|
||||
#include "convert.h"
|
||||
#include "StrFmt.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
void config_context_t::group::init()
|
||||
{
|
||||
m_cfg->m_groups[full_name()] = this;
|
||||
}
|
||||
|
||||
config_context_t::group::group(config_context_t* cfg, const std::string& name)
|
||||
: m_cfg(cfg)
|
||||
, m_name(name)
|
||||
, m_parent(nullptr)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
config_context_t::group::group(group* parent, const std::string& name)
|
||||
: m_cfg(parent->m_cfg)
|
||||
, m_name(name)
|
||||
, m_parent(parent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void config_context_t::group::set_parent(config_context_t* cfg)
|
||||
{
|
||||
m_cfg = cfg;
|
||||
init();
|
||||
}
|
||||
|
||||
std::string config_context_t::group::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string config_context_t::group::full_name() const
|
||||
{
|
||||
if (m_parent)
|
||||
return m_parent->full_name() + "/" + m_name;
|
||||
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void config_context_t::assign(const config_context_t& rhs)
|
||||
{
|
||||
for (auto &rhs_g : rhs.m_groups)
|
||||
{
|
||||
auto g = m_groups.at(rhs_g.first);
|
||||
|
||||
for (auto rhs_e : rhs_g.second->entries)
|
||||
{
|
||||
g->entries[rhs_e.first]->value_from(rhs_e.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void config_context_t::deserialize(std::istream& stream)
|
||||
{
|
||||
set_defaults();
|
||||
|
||||
uint line_index = 0;
|
||||
std::string line;
|
||||
group *current_group = nullptr;
|
||||
|
||||
while (std::getline(stream, line))
|
||||
{
|
||||
++line_index;
|
||||
line = fmt::trim(line);
|
||||
|
||||
if (line.empty())
|
||||
continue;
|
||||
|
||||
if (line.front() == '[' && line.back() == ']')
|
||||
{
|
||||
std::string group_name = line.substr(1, line.length() - 2);
|
||||
|
||||
auto found = m_groups.find(group_name);
|
||||
|
||||
if (found == m_groups.end())
|
||||
{
|
||||
std::cerr << line_index << ": group '" << group_name << "' not exists. ignored" << std::endl;
|
||||
current_group = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
current_group = found->second;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_group == nullptr)
|
||||
{
|
||||
std::cerr << line_index << ": line '" << line << "' ignored, no group." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto name_value = fmt::split(line, { "=" });
|
||||
switch (name_value.size())
|
||||
{
|
||||
case 1: current_group->entries[fmt::trim(name_value[0])]->string_value({}); break;
|
||||
|
||||
default:
|
||||
std::cerr << line_index << ": line '" << line << "' has more than one symbol '='. used only first" << std::endl;
|
||||
case 2: current_group->entries[fmt::trim(name_value[0])]->string_value(fmt::trim(name_value[1])); break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void config_context_t::serialize(std::ostream& stream) const
|
||||
{
|
||||
for (auto &g : m_groups)
|
||||
{
|
||||
stream << "[" + g.first + "]" << std::endl;
|
||||
|
||||
for (auto &e : g.second->entries)
|
||||
{
|
||||
stream << e.first << "=" << e.second->string_value() << std::endl;
|
||||
}
|
||||
|
||||
stream << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void config_context_t::set_defaults()
|
||||
{
|
||||
for (auto &g : m_groups)
|
||||
{
|
||||
for (auto &e : g.second->entries)
|
||||
{
|
||||
e.second->to_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string config_context_t::to_string() const
|
||||
{
|
||||
std::ostringstream result;
|
||||
|
||||
serialize(result);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
127
Utilities/config_context.h
Normal file
127
Utilities/config_context.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
class config_context_t
|
||||
{
|
||||
public:
|
||||
class entry_base;
|
||||
|
||||
protected:
|
||||
class group
|
||||
{
|
||||
group* m_parent;
|
||||
config_context_t* m_cfg;
|
||||
std::string m_name;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
std::unordered_map<std::string, entry_base *> entries;
|
||||
|
||||
group(config_context_t* cfg, const std::string& name);
|
||||
group(group* parent, const std::string& name);
|
||||
void set_parent(config_context_t* cfg);
|
||||
|
||||
std::string name() const;
|
||||
std::string full_name() const;
|
||||
|
||||
friend config_context_t;
|
||||
};
|
||||
|
||||
public:
|
||||
class entry_base
|
||||
{
|
||||
public:
|
||||
virtual std::string name() = 0;
|
||||
virtual void to_default() = 0;
|
||||
virtual std::string string_value() = 0;
|
||||
virtual void string_value(const std::string& value) = 0;
|
||||
virtual void value_from(const entry_base* rhs) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class entry : public entry_base
|
||||
{
|
||||
T m_default_value;
|
||||
T m_value;
|
||||
group* m_parent;
|
||||
std::string m_name;
|
||||
|
||||
public:
|
||||
entry(group* parent, const std::string& name, const T& default_value)
|
||||
: m_parent(parent)
|
||||
, m_name(name)
|
||||
, m_default_value(default_value)
|
||||
, m_value(default_value)
|
||||
{
|
||||
parent->entries[name] = this;
|
||||
}
|
||||
|
||||
T default_value() const
|
||||
{
|
||||
return m_default_value;
|
||||
}
|
||||
|
||||
T value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void value(const T& new_value)
|
||||
{
|
||||
m_value = new_value;
|
||||
}
|
||||
|
||||
std::string name() override
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void to_default() override
|
||||
{
|
||||
value(default_value());
|
||||
}
|
||||
|
||||
std::string string_value() override
|
||||
{
|
||||
return convert::to<std::string>(value());
|
||||
}
|
||||
|
||||
void string_value(const std::string &new_value) override
|
||||
{
|
||||
value(convert::to<T>(new_value));
|
||||
}
|
||||
|
||||
void value_from(const entry_base* rhs)
|
||||
{
|
||||
value(static_cast<const entry*>(rhs)->value());
|
||||
}
|
||||
|
||||
entry& operator = (const T& new_value)
|
||||
{
|
||||
value(new_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator const T&() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, group*> m_groups;
|
||||
|
||||
public:
|
||||
config_context_t() = default;
|
||||
|
||||
void assign(const config_context_t& rhs);
|
||||
|
||||
void serialize(std::ostream& stream) const;
|
||||
void deserialize(std::istream& stream);
|
||||
|
||||
void set_defaults();
|
||||
|
||||
std::string to_string() const;
|
||||
};
|
||||
240
Utilities/convert.h
Normal file
240
Utilities/convert.h
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace convert
|
||||
{
|
||||
template<typename ReturnType, typename FromType>
|
||||
struct to_impl_t;
|
||||
|
||||
template<typename Type>
|
||||
struct to_impl_t<Type, Type>
|
||||
{
|
||||
static Type func(const Type& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, bool>
|
||||
{
|
||||
static std::string func(bool value)
|
||||
{
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<bool, std::string>
|
||||
{
|
||||
static bool func(const std::string& value)
|
||||
{
|
||||
return value == "true" ? true : false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, char>
|
||||
{
|
||||
static std::string func(char value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, unsigned char>
|
||||
{
|
||||
static std::string func(unsigned char value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, short>
|
||||
{
|
||||
static std::string func(short value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, unsigned short>
|
||||
{
|
||||
static std::string func(unsigned short value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, int>
|
||||
{
|
||||
static std::string func(int value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, unsigned int>
|
||||
{
|
||||
static std::string func(unsigned int value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, long>
|
||||
{
|
||||
static std::string func(long value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, unsigned long>
|
||||
{
|
||||
static std::string func(unsigned long value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, long long>
|
||||
{
|
||||
static std::string func(long long value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, unsigned long long>
|
||||
{
|
||||
static std::string func(unsigned long long value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, float>
|
||||
{
|
||||
static std::string func(float value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, double>
|
||||
{
|
||||
static std::string func(double value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<std::string, long double>
|
||||
{
|
||||
static std::string func(long double value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<int, std::string>
|
||||
{
|
||||
static int func(const std::string& value)
|
||||
{
|
||||
return std::stoi(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<unsigned int, std::string>
|
||||
{
|
||||
static unsigned int func(const std::string& value)
|
||||
{
|
||||
return (unsigned long)std::stoul(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<long, std::string>
|
||||
{
|
||||
static long func(const std::string& value)
|
||||
{
|
||||
return std::stol(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<unsigned long, std::string>
|
||||
{
|
||||
static unsigned long func(const std::string& value)
|
||||
{
|
||||
return std::stoul(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<long long, std::string>
|
||||
{
|
||||
static long long func(const std::string& value)
|
||||
{
|
||||
return std::stoll(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<unsigned long long, std::string>
|
||||
{
|
||||
static unsigned long long func(const std::string& value)
|
||||
{
|
||||
return std::stoull(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<float, std::string>
|
||||
{
|
||||
static float func(const std::string& value)
|
||||
{
|
||||
return std::stof(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<double, std::string>
|
||||
{
|
||||
static double func(const std::string& value)
|
||||
{
|
||||
return std::stod(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_impl_t<long double, std::string>
|
||||
{
|
||||
static long double func(const std::string& value)
|
||||
{
|
||||
return std::stold(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ReturnType, typename FromType>
|
||||
ReturnType to(FromType value)
|
||||
{
|
||||
return to_impl_t<std::remove_all_extents_t<ReturnType>, std::remove_all_extents_t<FromType>>::func(value);
|
||||
}
|
||||
}
|
||||
420
Utilities/event.h
Normal file
420
Utilities/event.h
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
|
||||
enum class event_result
|
||||
{
|
||||
skip,
|
||||
handled
|
||||
};
|
||||
|
||||
class events_queue
|
||||
{
|
||||
std::deque<std::function<void()>> m_queue;
|
||||
|
||||
public:
|
||||
/*template<typename Type>
|
||||
events_queue& operator += (event<Type> &evt)
|
||||
{
|
||||
evt.set_queue(this);
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
void invoke(std::function<void()> function)
|
||||
{
|
||||
m_queue.push_back(function);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
while (!m_queue.empty())
|
||||
{
|
||||
std::function<void()> function = m_queue.front();
|
||||
function();
|
||||
m_queue.pop_front();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ...AT>
|
||||
class event
|
||||
{
|
||||
using func_t = std::function<event_result(AT...)>;
|
||||
using entry_t = typename std::list<func_t>::iterator;
|
||||
|
||||
std::list<func_t> handlers;
|
||||
events_queue& m_queue;
|
||||
|
||||
public:
|
||||
event(events_queue* queue = nullptr) : m_queue(*queue)
|
||||
{
|
||||
}
|
||||
|
||||
void invoke(AT... args)
|
||||
{
|
||||
m_queue.invoke(std::bind([&](AT... eargs)
|
||||
{
|
||||
for (auto &&handler : handlers)
|
||||
{
|
||||
if (handler(eargs...) == event_result::handled)
|
||||
break;
|
||||
}
|
||||
}, args...));
|
||||
}
|
||||
|
||||
void operator()(AT... args)
|
||||
{
|
||||
invoke(args...);
|
||||
}
|
||||
|
||||
entry_t bind(func_t func)
|
||||
{
|
||||
handlers.push_front(func);
|
||||
return handlers.begin();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
entry_t bind(T *caller, event_result(T::*callback)(AT...))
|
||||
{
|
||||
return bind([=](AT... args) { return (caller->*callback)(args...); });
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
entry_t bind(T *caller, void(T::*callback)(AT...))
|
||||
{
|
||||
return bind([=](AT... args) { (caller->*callback)(args...); return event_result::skip; });
|
||||
}
|
||||
|
||||
void unbind(entry_t entry)
|
||||
{
|
||||
handlers.erase(entry);
|
||||
}
|
||||
|
||||
entry_t operator +=(func_t func)
|
||||
{
|
||||
return bind(func);
|
||||
}
|
||||
|
||||
void operator -=(entry_t what)
|
||||
{
|
||||
return unbind(what);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class event<void>
|
||||
{
|
||||
using func_t = std::function<event_result()>;
|
||||
using entry_t = std::list<func_t>::iterator;
|
||||
|
||||
std::list<func_t> m_listeners;
|
||||
events_queue* m_queue;
|
||||
|
||||
void invoke_listeners()
|
||||
{
|
||||
for (auto &&listener : m_listeners)
|
||||
{
|
||||
if (listener() == event_result::handled)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
event(events_queue* queue = nullptr) : m_queue(queue)
|
||||
{
|
||||
}
|
||||
|
||||
void invoke()
|
||||
{
|
||||
if (m_queue)
|
||||
m_queue->invoke([=]() { invoke_listeners(); });
|
||||
else
|
||||
invoke_listeners();
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
invoke();
|
||||
}
|
||||
|
||||
entry_t bind(func_t func)
|
||||
{
|
||||
m_listeners.push_front(func);
|
||||
return m_listeners.begin();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
entry_t bind(T *caller, event_result(T::*callback)())
|
||||
{
|
||||
return bind([=]() { return (caller->*callback)(); });
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
entry_t bind(T *caller, void(T::*callback)())
|
||||
{
|
||||
return bind([=]() { (caller->*callback)(); return event_result::skip; });
|
||||
}
|
||||
|
||||
void unbind(entry_t what)
|
||||
{
|
||||
m_listeners.erase(what);
|
||||
}
|
||||
|
||||
entry_t operator +=(func_t func)
|
||||
{
|
||||
return bind(func);
|
||||
}
|
||||
|
||||
void operator -=(entry_t what)
|
||||
{
|
||||
return unbind(what);
|
||||
}
|
||||
};
|
||||
|
||||
class event_binder_t
|
||||
{
|
||||
template<typename Type>
|
||||
class binder_impl_t
|
||||
{
|
||||
event_binder_t *m_binder;
|
||||
event<Type> *m_event;
|
||||
|
||||
public:
|
||||
binder_impl_t(event_binder_t *binder, event<Type> *evt)
|
||||
: m_binder(binder)
|
||||
, m_event(evt)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename Type>
|
||||
binder_impl_t<Type> operator()(event<Type>& evt) const
|
||||
{
|
||||
return{ this, &evt };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class combined_data;
|
||||
|
||||
template<typename T>
|
||||
class local_data
|
||||
{
|
||||
public:
|
||||
using type = T;
|
||||
|
||||
protected:
|
||||
type m_data;
|
||||
|
||||
void set(type value)
|
||||
{
|
||||
m_data = value;
|
||||
}
|
||||
|
||||
type get() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
bool equals(T value) const
|
||||
{
|
||||
return get() == value;
|
||||
}
|
||||
|
||||
bool invoke_event(type value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
friend combined_data<T>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class combined_data
|
||||
{
|
||||
public:
|
||||
using type = T;
|
||||
|
||||
protected:
|
||||
local_data<type> m_local_data;
|
||||
std::function<void(type)> m_invoke_event_function;
|
||||
std::function<type()> m_get_function;
|
||||
|
||||
bool invoke_event(type value)
|
||||
{
|
||||
if (m_invoke_event_function)
|
||||
{
|
||||
m_invoke_event_function(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void set(type value)
|
||||
{
|
||||
m_local_data.set(value);
|
||||
}
|
||||
|
||||
type get() const
|
||||
{
|
||||
if (m_get_function)
|
||||
{
|
||||
return m_get_function();
|
||||
}
|
||||
|
||||
return m_local_data.get();
|
||||
}
|
||||
|
||||
type get_local() const
|
||||
{
|
||||
return m_local_data.get();
|
||||
}
|
||||
|
||||
bool equals(T value) const
|
||||
{
|
||||
return get_local() == value;
|
||||
}
|
||||
|
||||
public:
|
||||
void invoke_event_function(std::function<void(type)> function)
|
||||
{
|
||||
m_invoke_event_function = function;
|
||||
}
|
||||
|
||||
void get_function(std::function<type()> function)
|
||||
{
|
||||
m_get_function = function;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename base_type_ = local_data<T>>
|
||||
class data_event : public base_type_
|
||||
{
|
||||
public:
|
||||
using type = T;
|
||||
using base_type = base_type_;
|
||||
|
||||
protected:
|
||||
event_result dochange(type new_value)
|
||||
{
|
||||
auto old_value = get();
|
||||
base_type::set(new_value);
|
||||
onchanged(old_value);
|
||||
return event_result::handled;
|
||||
}
|
||||
|
||||
public:
|
||||
event<type> onchange;
|
||||
event<type> onchanged;
|
||||
|
||||
data_event(events_queue *queue = nullptr)
|
||||
: onchange(queue)
|
||||
, onchanged(queue)
|
||||
{
|
||||
onchange.bind(this, &data_event::dochange);
|
||||
base_type::set({});
|
||||
}
|
||||
|
||||
type get() const
|
||||
{
|
||||
return base_type::get();
|
||||
}
|
||||
|
||||
type operator()() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
void change(type value, bool use_custom_invoke_event = true)
|
||||
{
|
||||
if (!base_type::equals(value))
|
||||
{
|
||||
if (!use_custom_invoke_event || !base_type::invoke_event(value))
|
||||
{
|
||||
onchange(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator const type() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
operator type()
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
data_event& operator = (type value)
|
||||
{
|
||||
change(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename aType> auto operator + (aType value) const { return get() + value; }
|
||||
template<typename aType> auto operator - (aType value) const { return get() - value; }
|
||||
template<typename aType> auto operator * (aType value) const { return get() * value; }
|
||||
template<typename aType> auto operator / (aType value) const { return get() / value; }
|
||||
template<typename aType> auto operator % (aType value) const { return get() % value; }
|
||||
template<typename aType> auto operator & (aType value) const { return get() & value; }
|
||||
template<typename aType> auto operator | (aType value) const { return get() | value; }
|
||||
template<typename aType> auto operator ^ (aType value) const { return get() ^ value; }
|
||||
|
||||
template<typename aType> data_event& operator += (aType value) { return *this = get() + value; }
|
||||
template<typename aType> data_event& operator -= (aType value) { return *this = get() - value; }
|
||||
template<typename aType> data_event& operator *= (aType value) { return *this = get() * value; }
|
||||
template<typename aType> data_event& operator /= (aType value) { return *this = get() / value; }
|
||||
template<typename aType> data_event& operator %= (aType value) { return *this = get() % value; }
|
||||
template<typename aType> data_event& operator &= (aType value) { return *this = get() & value; }
|
||||
template<typename aType> data_event& operator |= (aType value) { return *this = get() | value; }
|
||||
template<typename aType> data_event& operator ^= (aType value) { return *this = get() ^ value; }
|
||||
|
||||
data_event& operator ++()
|
||||
{
|
||||
type value = get();
|
||||
return *this = ++value;
|
||||
}
|
||||
|
||||
type operator ++(int)
|
||||
{
|
||||
type value = get();
|
||||
type result = value;
|
||||
*this = value++;
|
||||
return result;
|
||||
}
|
||||
|
||||
data_event& operator --()
|
||||
{
|
||||
type value = get();
|
||||
return *this = --value;
|
||||
}
|
||||
|
||||
type operator --(int)
|
||||
{
|
||||
type value = get();
|
||||
type result = value;
|
||||
*this = value--;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct with_event_binder
|
||||
{
|
||||
event_binder_t event_binder;
|
||||
};
|
||||
|
||||
struct test_obj
|
||||
{
|
||||
void test(int)
|
||||
{
|
||||
event<int> i;
|
||||
auto it = i.bind(this, &test_obj::test);
|
||||
i(5);
|
||||
i.unbind(it);
|
||||
i(6);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue