Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "global.hpp"
00017
00018 #include "filesystem.hpp"
00019 #include "log.hpp"
00020 #include "persist_context.hpp"
00021 #include "persist_manager.hpp"
00022 #include "serialization/binary_or_text.hpp"
00023 #include "serialization/parser.hpp"
00024 #include "util.hpp"
00025
00026 config pack_scalar(const std::string &name, const t_string &val)
00027 {
00028 config cfg;
00029 cfg[name] = val;
00030 return cfg;
00031 }
00032
00033 static std::string get_persist_cfg_name(const std::string &name_space) {
00034 return (get_dir(get_user_data_dir() + "/persist/") + name_space + ".cfg");
00035 }
00036
00037 void persist_file_context::load() {
00038 std::string cfg_dir = get_dir(get_user_data_dir() + "/persist");
00039 create_directory_if_missing(cfg_dir);
00040
00041 std::string cfg_name = get_persist_cfg_name(namespace_.root_);
00042 if (file_exists(cfg_name) && !is_directory(cfg_name)) {
00043 scoped_istream file_stream = istream_file(cfg_name);
00044 if (!(file_stream->fail())) {
00045 try {
00046 read(cfg_,*file_stream);
00047 } catch (config::error &err) {
00048 LOG_PERSIST << err.message;
00049 }
00050 }
00051 }
00052 }
00053
00054 persist_file_context::persist_file_context(const std::string &name_space)
00055 : persist_context(name_space)
00056 {
00057 load();
00058 root_node_.init();
00059 active_ = &(root_node_.child(namespace_.next()));
00060 }
00061
00062 bool persist_file_context::clear_var(const std::string &global, bool immediate)
00063 {
00064
00065
00066
00067
00068 config bak;
00069 config bactive;
00070 if (immediate) {
00071 bak = cfg_;
00072 bactive = active_->cfg_.child_or_add("variables");
00073 load();
00074 root_node_.init();
00075 }
00076 config &cfg = active_->cfg_.child_or_add("variables");
00077 bool ret(cfg);
00078 if (ret) {
00079 bool exists = cfg.has_attribute(global);
00080 if (!exists) {
00081 if (cfg.child(global)) {
00082 exists = true;
00083 std::string::const_iterator index_start = std::find(global.begin(),global.end(),'[');
00084 if (index_start != global.end())
00085 {
00086 const std::string::const_iterator index_end = std::find(global.begin(),global.end(),']');
00087 const std::string index_str(index_start+1,index_end);
00088 size_t index = static_cast<size_t>(lexical_cast_default<int>(index_str));
00089 cfg.remove_child(global,index);
00090 if (immediate) bactive.remove_child(global,index);
00091 } else {
00092 cfg.clear_children(global);
00093 if (immediate) bactive.clear_children(global);
00094 }
00095 }
00096 }
00097 if (exists) {
00098 cfg.remove_attribute(global);
00099 if (immediate) bactive.remove_attribute(global);
00100 if (cfg.empty()) {
00101 active_->cfg_.clear_children("variables");
00102 active_->cfg_.remove_attribute("variables");
00103 while ((active_->cfg_.empty()) && (active_->parent_ != NULL)) {
00104 active_ = active_->parent_;
00105 active_->remove_child(namespace_.node_);
00106 namespace_ = namespace_.prev();
00107 }
00108 }
00109
00110 if (!in_transaction_)
00111 ret = save_context();
00112 else if (immediate) {
00113 ret = save_context();
00114 cfg_ = bak;
00115 root_node_.init();
00116 active_->cfg_.clear_children("variables");
00117 active_->cfg_.remove_attribute("variables");
00118 active_->cfg_.add_child("variables",bactive);
00119 config &cfg = active_->cfg_.child("variables");
00120 if (cfg.empty()) {
00121 active_->cfg_.clear_children("variables");
00122 active_->cfg_.remove_attribute("variables");
00123 while ((active_->cfg_.empty()) && (active_->parent_ != NULL)) {
00124 active_ = active_->parent_;
00125 active_->remove_child(namespace_.node_);
00126 namespace_ = namespace_.prev();
00127 }
00128 }
00129 } else
00130 ret = true;
00131 } else {
00132 ret = exists;
00133 }
00134 }
00135 return ret;
00136 }
00137
00138 config persist_file_context::get_var(const std::string &global) const
00139 {
00140 config ret;
00141
00142
00143
00144
00145 config &cfg = active_->cfg_.child("variables");
00146 if (cfg) {
00147 size_t arrsize = cfg.child_count(global);
00148 if (arrsize > 0) {
00149 for (size_t i = 0; i < arrsize; i++)
00150 ret.add_child(global,cfg.child(global,i));
00151 } else {
00152 ret = pack_scalar(global,cfg[global]);
00153 }
00154 } else {
00155 ret = pack_scalar(global,"");
00156 }
00157 return ret;
00158 }
00159 bool persist_file_context::save_context() {
00160 bool success = false;
00161
00162 std::string cfg_name = get_persist_cfg_name(namespace_.root_);
00163 if (!cfg_name.empty()) {
00164 if (cfg_.empty()) {
00165 success = delete_directory(cfg_name);
00166 } else {
00167 scoped_ostream out = ostream_file(cfg_name);
00168 if (!out->fail())
00169 {
00170 config_writer writer(*out,false);
00171 try {
00172 writer.write(cfg_);
00173 success = true;
00174 } catch(config::error &err) {
00175 LOG_PERSIST << err.message;
00176 success = false;
00177 }
00178 }
00179 }
00180 }
00181 return success;
00182 }
00183 bool persist_file_context::set_var(const std::string &global,const config &val, bool immediate)
00184 {
00185
00186
00187
00188 config bak;
00189 config bactive;
00190 if (immediate) {
00191 bak = cfg_;
00192 bactive = active_->cfg_.child_or_add("variables");
00193 load();
00194 root_node_.init();
00195 }
00196
00197 config &cfg = active_->cfg_.child_or_add("variables");
00198 if (val.has_attribute(global)) {
00199 if (val[global].empty()) {
00200 clear_var(global,immediate);
00201 } else {
00202 cfg[global] = val[global];
00203 if (immediate) bactive[global] = val[global];
00204 }
00205 } else {
00206 cfg.clear_children(global);
00207 cfg.append(val);
00208 if (immediate) {
00209 bactive.clear_children(global);
00210 bactive.append(val);
00211 }
00212 }
00213
00214 if (!in_transaction_)
00215 return save_context();
00216 else if (immediate) {
00217 bool ret = save_context();
00218 cfg_ = bak;
00219 root_node_.init();
00220 active_->cfg_.clear_children("variables");
00221 active_->cfg_.remove_attribute("variables");
00222 active_->cfg_.add_child("variables",bactive);
00223 return ret;
00224 } else
00225 return true;
00226 }
00227 void persist_context::set_node(const std::string &name) {
00228 active_ = &(root_node_.child(name));
00229 namespace_ = name_space(namespace_.namespace_ + "." + name);
00230 }
00231
00232 std::string persist_context::get_node() const
00233 {
00234 return namespace_.namespace_;
00235 }
00236