00001 #ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66_PM 00002 #define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66_PM 00003 00004 #if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 00005 #pragma once 00006 #endif 00007 00008 00009 #include <memory> 00010 #include <vector> 00011 #include "yaml-cpp-pm/noncopyable.h" 00012 00013 namespace YAML_PM 00014 { 00015 class SettingChangeBase; 00016 00017 template <typename T> 00018 class Setting 00019 { 00020 public: 00021 Setting(): m_value() {} 00022 00023 const T get() const { return m_value; } 00024 std::auto_ptr <SettingChangeBase> set(const T& value); 00025 void restore(const Setting<T>& oldSetting) { 00026 m_value = oldSetting.get(); 00027 } 00028 00029 private: 00030 T m_value; 00031 }; 00032 00033 class SettingChangeBase 00034 { 00035 public: 00036 virtual ~SettingChangeBase() {} 00037 virtual void pop() = 0; 00038 }; 00039 00040 template <typename T> 00041 class SettingChange: public SettingChangeBase 00042 { 00043 public: 00044 SettingChange(Setting<T> *pSetting): m_pCurSetting(pSetting) { 00045 // copy old setting to save its state 00046 m_oldSetting = *pSetting; 00047 } 00048 00049 virtual void pop() { 00050 m_pCurSetting->restore(m_oldSetting); 00051 } 00052 00053 private: 00054 Setting<T> *m_pCurSetting; 00055 Setting<T> m_oldSetting; 00056 }; 00057 00058 template <typename T> 00059 inline std::auto_ptr <SettingChangeBase> Setting<T>::set(const T& value) { 00060 std::auto_ptr <SettingChangeBase> pChange(new SettingChange<T> (this)); 00061 m_value = value; 00062 return pChange; 00063 } 00064 00065 class SettingChanges: private noncopyable 00066 { 00067 public: 00068 SettingChanges() {} 00069 ~SettingChanges() { clear(); } 00070 00071 void clear() { 00072 restore(); 00073 00074 for(setting_changes::const_iterator it=m_settingChanges.begin();it!=m_settingChanges.end();++it) 00075 delete *it; 00076 m_settingChanges.clear(); 00077 } 00078 00079 void restore() { 00080 for(setting_changes::const_iterator it=m_settingChanges.begin();it!=m_settingChanges.end();++it) 00081 (*it)->pop(); 00082 } 00083 00084 void push(std::auto_ptr <SettingChangeBase> pSettingChange) { 00085 m_settingChanges.push_back(pSettingChange.release()); 00086 } 00087 00088 // like std::auto_ptr - assignment is transfer of ownership 00089 SettingChanges& operator = (SettingChanges& rhs) { 00090 if(this == &rhs) 00091 return *this; 00092 00093 clear(); 00094 m_settingChanges = rhs.m_settingChanges; 00095 rhs.m_settingChanges.clear(); 00096 return *this; 00097 } 00098 00099 private: 00100 typedef std::vector <SettingChangeBase *> setting_changes; 00101 setting_changes m_settingChanges; 00102 }; 00103 } 00104 00105 #endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66_PM