Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ofxAutoSaveParam.h
#pragma once
/*
USAGE:
ofxAutoSaveParam param;
class ofApp {
public:
float my_float;
ofVec3f my_vec;
void setup()
{
// param.setup("custom_filename.xml"); // option. default = params.xml
// attach to vars
param.attach("my_float", my_float);
param.attach("my_vec", my_vec);
// key access
param.setString("test", "my string");
cout << param.getString("test", "defalut value") << endl; // returns "my string"
}
};
*/
#include "ofMain.h"
#include "Poco/Util/XMLConfiguration.h"
class ofxAutoSaveParam
{
public:
ofxAutoSaveParam()
: config(new Poco::Util::XMLConfiguration)
{
setup("params.xml");
}
~ofxAutoSaveParam()
{
save();
}
void setup(const string& path)
{
this->path = path;
load();
}
bool load()
{
config->loadEmpty("root");
if (ofFile::doesFileExist(path))
{
config->load(ofToDataPath(path));
return true;
}
return false;
}
void save()
{
for (int i = 0; i < params.size(); i++)
params[i]->save(config);
config->save(ofToDataPath(path));
}
float getNumber(const string& key, float default_value = 0) const
{
if (config->has(key) == false)
return default_value;
return config->getDouble(key);
}
void setNumber(const string& key, float value)
{
config->setDouble(key, value);
}
string getString(const string& key, string default_value = "") const
{
if (config->has(key) == false)
return default_value;
return config->getString(key);
}
void setString(const string& key, const string& value)
{
config->setString(key, value);
}
template <typename T>
T get(const string& key, T default_value = T());
template <typename T>
void set(const string& key, const T& value);
template <typename T>
void attach(const string& key, T& value)
{
ofPtr<Parameter> param = ofPtr<Parameter>(new Parameter_<T>(key, value));
params.push_back(param);
try
{
param->load(config);
}
catch (Poco::NotFoundException& e)
{
value = T();
}
}
public:
struct Parameter
{
string key;
Parameter(const string& key)
: key(key)
{}
virtual ~Parameter() {}
virtual void load(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {}
virtual void save(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {}
};
template <typename T>
struct Parameter_ : public Parameter
{};
protected:
string path;
Poco::AutoPtr<Poco::Util::XMLConfiguration> config;
vector<ofPtr<Parameter> > params;
};
#define DEFINE_BASIC_PARAM_TYPE(TYPE, XML_TYPE) \
template <> \
struct ofxAutoSaveParam::Parameter_<TYPE> : public ofxAutoSaveParam::Parameter { \
TYPE* value; \
Parameter_(const string& key, TYPE& v) \
: Parameter(key) \
, value(&v) \
{} \
\
void load(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) { \
if (config->has(key) == false) return; \
*value = config->get ## XML_TYPE(key); \
} \
\
void save(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) { \
config->set ## XML_TYPE(key, *value); \
} \
};
DEFINE_BASIC_PARAM_TYPE(float, Double);
DEFINE_BASIC_PARAM_TYPE(double, Double);
DEFINE_BASIC_PARAM_TYPE(int, Int);
DEFINE_BASIC_PARAM_TYPE(unsigned int, Int);
DEFINE_BASIC_PARAM_TYPE(string, String);
DEFINE_BASIC_PARAM_TYPE(bool, Bool);
#undef DEFINE_PARAM_TYPE
#define DEFINE_LOAD_PARAM_ELEMENT(VAL, XML_TYPE) if (config->has(key)) { value->VAL = config->get ## XML_TYPE(key + "[@" #VAL "]"); }
#define DEFINE_SAVE_PARAM_ELEMENT(VAL, XML_TYPE) config->set ## XML_TYPE(key + "[@" #VAL "]" , value->VAL);
#define DEFINE_LOAD_PARAM_ELEMENT2(VAL, XML_NAME, XML_TYPE) if (config->has(key)) { value->VAL = config->get ## XML_TYPE(key + "[@" #XML_NAME "]"); }
#define DEFINE_SAVE_PARAM_ELEMENT2(VAL, XML_NAME, XML_TYPE) config->set ## XML_TYPE(key + "[@" #XML_NAME "]" , value->VAL);
template <>
struct ofxAutoSaveParam::Parameter_<ofVec3f> : public ofxAutoSaveParam::Parameter{
ofVec3f* value;
Parameter_(const string& key, ofVec3f& v)
: Parameter(key)
, value(&v)
{}
void load(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {
if (config->has(key) == false) return;
DEFINE_LOAD_PARAM_ELEMENT(x, Double);
DEFINE_LOAD_PARAM_ELEMENT(y, Double);
DEFINE_LOAD_PARAM_ELEMENT(z, Double);
}
void save(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {
DEFINE_SAVE_PARAM_ELEMENT(x, Double);
DEFINE_SAVE_PARAM_ELEMENT(y, Double);
DEFINE_SAVE_PARAM_ELEMENT(z, Double);
}
};
template <>
struct ofxAutoSaveParam::Parameter_<ofRectangle> : public ofxAutoSaveParam::Parameter{
ofRectangle* value;
Parameter_(const string& key, ofRectangle& v)
: Parameter(key)
, value(&v)
{}
void load(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {
if (config->has(key) == false) return;
DEFINE_LOAD_PARAM_ELEMENT(x, Double);
DEFINE_LOAD_PARAM_ELEMENT(y, Double);
DEFINE_LOAD_PARAM_ELEMENT(width, Double);
DEFINE_LOAD_PARAM_ELEMENT(height, Double);
}
void save(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {
DEFINE_SAVE_PARAM_ELEMENT(x, Double);
DEFINE_SAVE_PARAM_ELEMENT(y, Double);
DEFINE_SAVE_PARAM_ELEMENT(width, Double);
DEFINE_SAVE_PARAM_ELEMENT(height, Double);
}
};
template <>
struct ofxAutoSaveParam::Parameter_<ofMatrix4x4> : public ofxAutoSaveParam::Parameter {
ofMatrix4x4* value;
Parameter_(const string& key, ofMatrix4x4& v)
: Parameter(key)
, value(&v)
{}
void load(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {
if (config->has(key) == false) return;
DEFINE_LOAD_PARAM_ELEMENT2(_mat[0][0], m00, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[0][1], m01, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[0][2], m02, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[0][3], m03, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[1][0], m10, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[1][1], m11, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[1][2], m12, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[1][3], m13, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[2][0], m20, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[2][1], m21, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[2][2], m22, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[2][3], m23, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[3][0], m30, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[3][1], m31, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[3][2], m32, Double);
DEFINE_LOAD_PARAM_ELEMENT2(_mat[3][3], m33, Double);
}
void save(Poco::AutoPtr<Poco::Util::XMLConfiguration>& config) {
DEFINE_SAVE_PARAM_ELEMENT2(_mat[0][0], m00, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[0][1], m01, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[0][2], m02, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[0][3], m03, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[1][0], m10, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[1][1], m11, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[1][2], m12, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[1][3], m13, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[2][0], m20, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[2][1], m21, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[2][2], m22, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[2][3], m23, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[3][0], m30, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[3][1], m31, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[3][2], m32, Double);
DEFINE_SAVE_PARAM_ELEMENT2(_mat[3][3], m33, Double);
}
};
template <typename T>
inline T ofxAutoSaveParam::get(const string& key, T default_value)
{
T value;
Parameter_<T> param(key, value);
param.load(config);
return value;
}
template <typename T>
inline void ofxAutoSaveParam::set(const string& key, const T& value_)
{
T value = value_;
Parameter_<T> param(key, value);
param.save(config);
}
#undef DEFINE_SAVE_PARAM_ELEMENT
#undef DEFINE_LOAD_PARAM_ELEMENT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment