persist_context.hpp

Go to the documentation of this file.
00001 /* $Id: persist_context.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2010 - 2012 by Jody Northup
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #ifndef PERSIST_CONTEXT_H_INCLUDED
00017 #define PERSIST_CONTEXT_H_INCLUDED
00018 #include "config.hpp"
00019 #include "log.hpp"
00020 static lg::log_domain log_persist("engine/persistence");
00021 
00022 #define LOG_PERSIST LOG_STREAM(info, log_persist)
00023 #define ERR_PERSist LOG_STREAM(err, log_persist)
00024 config pack_scalar(const std::string &,const t_string &);
00025 class persist_context {
00026 public:
00027 
00028     virtual ~persist_context() {}
00029 
00030     struct name_space {
00031         std::string namespace_;
00032         std::string root_;
00033         std::string node_;
00034         std::string lineage_;
00035         std::string descendants_;
00036         bool valid_;
00037 
00038         bool valid() const {
00039             return valid_;
00040         }
00041         void parse() {
00042             while (namespace_.find_first_of("^") < namespace_.size()) {
00043                 if (namespace_[0] == '^') {
00044                     //TODO: Throw a WML error
00045                     namespace_ = "";
00046                     break;
00047                 }
00048                 std::string infix = namespace_.substr(namespace_.find_first_of("^"));
00049                 size_t end = infix.find_first_not_of("^");
00050                 if (!((end >= infix.length()) || (infix[end] == '.'))) {
00051                     //TODO: Throw a WML error
00052                     namespace_ = "";
00053                     break;
00054                 }
00055                 infix = infix.substr(0,end);
00056                 std::string suffix = namespace_.substr(namespace_.find_first_of("^") + infix.length());
00057                 while (!infix.empty())
00058                 {
00059                     std::string body = namespace_.substr(0,namespace_.find_first_of("^"));
00060                     body = body.substr(0,body.find_last_of("."));
00061                     infix = infix.substr(1);
00062                     namespace_ = body + infix + suffix;
00063                 }
00064             }
00065         }
00066         name_space next() const {
00067             return name_space(descendants_);
00068         }
00069         name_space prev() const {
00070             return name_space(lineage_);
00071         }
00072         operator bool () const { return valid_; }
00073         name_space()
00074             : namespace_()
00075             , root_()
00076             , node_()
00077             , lineage_()
00078             , descendants_()
00079             , valid_(false)
00080         {
00081         }
00082 
00083         name_space(const std::string &ns, bool doParse = false)
00084             : namespace_(ns)
00085             , root_()
00086             , node_()
00087             , lineage_()
00088             , descendants_()
00089             , valid_(false)
00090         {
00091             if (doParse)
00092                 parse();
00093             valid_ = ((namespace_.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.") > namespace_.length()) && !namespace_.empty());
00094             root_ = namespace_.substr(0,namespace_.find_first_of("."));
00095             node_ = namespace_.substr(namespace_.find_last_of(".") + 1);
00096             if (namespace_.find_last_of(".") <= namespace_.length())
00097                 lineage_ = namespace_.substr(0,namespace_.find_last_of("."));
00098             if (namespace_.find_first_of(".") <= namespace_.length())
00099                 descendants_ = namespace_.substr(namespace_.find_first_of(".") + 1);
00100         }
00101     };
00102 protected:
00103     struct node {
00104         typedef std::map<std::string,node*> child_map;
00105 
00106         std::string name_;
00107         persist_context *root_;
00108         node *parent_;
00109         child_map children_;
00110         config &cfg_;
00111 
00112         node(std::string name, persist_context *root, config & cfg, node *parent = NULL)
00113             : name_(name)
00114             , root_(root)
00115             , parent_(parent)
00116             , children_()
00117             , cfg_(cfg)
00118         {
00119         }
00120 
00121         ~node() {
00122             for (child_map::iterator i = children_.begin(); i != children_.end(); ++i)
00123                 delete (i->second);
00124         }
00125         config &cfg() { return cfg_; }
00126         node &add_child(const std::string &name) {
00127             children_[name] = new node(name,root_,cfg_.child_or_add(name),this);
00128             return *(children_[name]);
00129         }
00130         bool remove_child(const std::string &name) {
00131             bool ret = false;
00132             if (children_.find(name) != children_.end()) {
00133                 cfg_.clear_children(name);
00134                 cfg_.remove_attribute(name);
00135                 if (cfg_.child("variables").empty()) {
00136                     cfg_.clear_children("variables");
00137                     cfg_.remove_attribute("variables");
00138                 }
00139                 delete children_[name];
00140                 children_.erase(name);
00141                 ret = true;
00142             }
00143             return ret;
00144         }
00145         node &child(const name_space &name) {
00146             if (name) {
00147                 if (children_.find(name.root_) == children_.end())
00148                     add_child(name.root_);
00149                 node &chld = *children_[name.root_];
00150                 return chld.child(name.next());
00151             }
00152             else return *this;
00153         }
00154         void init () {
00155             for (config::all_children_iterator i = cfg_.ordered_begin(); i != cfg_.ordered_end(); ++i) {
00156                 if (i->key != "variables") {
00157                     child(i->key).init();
00158                 }
00159             }
00160             if (!cfg_.child("variables"))
00161                 cfg_.add_child("variables");
00162         }
00163     };
00164 
00165     config cfg_;
00166     name_space namespace_;
00167     node root_node_;
00168     node *active_;
00169     bool valid_;
00170     bool in_transaction_;
00171 
00172     persist_context()
00173         : cfg_()
00174         , namespace_()
00175         , root_node_("",this,cfg_)
00176         , active_(&root_node_)
00177         , valid_(false)
00178         , in_transaction_(false)
00179     {};
00180 
00181     persist_context(const std::string &name_space)
00182         : cfg_()
00183         , namespace_(name_space,true)
00184         , root_node_(namespace_.root_,this,cfg_)
00185         , active_(&root_node_)
00186         , valid_(namespace_.valid())
00187         , in_transaction_(false)
00188     {};
00189 
00190 public:
00191     virtual bool clear_var(const std::string &, bool immediate = false) = 0;
00192     virtual config get_var(const std::string &) const = 0;
00193     virtual bool set_var(const std::string &, const config &, bool immediate = false) = 0;
00194     virtual bool start_transaction () = 0;
00195     virtual bool end_transaction () = 0;
00196     virtual bool cancel_transaction () = 0;
00197     std::string get_node() const;
00198     void set_node(const std::string &);
00199     bool valid() const { return valid_; };
00200     bool dirty() const {
00201         return true;
00202     };
00203     operator bool() const { return valid_; }
00204 };
00205 
00206 class persist_file_context : public persist_context {
00207 private:
00208     void load();
00209     void init();
00210     bool save_context();
00211 
00212 public:
00213     persist_file_context(const std::string &name_space);
00214     bool clear_var(const std::string &, bool immediate = false);
00215     config get_var(const std::string &) const;
00216     bool set_var(const std::string &, const config &, bool immediate = false);
00217 
00218     bool start_transaction () {
00219         if (in_transaction_)
00220             return false;
00221         in_transaction_ = true;
00222         return true;
00223     }
00224     bool end_transaction () {
00225         if (!in_transaction_)
00226             return false;
00227         in_transaction_ = false;
00228         save_context();
00229         return true;
00230     }
00231     bool cancel_transaction () {
00232         if (!in_transaction_)
00233             return false;
00234         load();
00235         root_node_.init();
00236         in_transaction_ = false;
00237         return true;
00238     }
00239 };
00240 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:07 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs