The Battle for Wesnoth  1.15.1+dev
persist_context.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2018 by Jody Northup
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "config.hpp"
18 #include "log.hpp"
19 static lg::log_domain log_persist("engine/persistence");
20 
21 #define LOG_PERSIST LOG_STREAM(info, log_persist)
22 #define ERR_PERSist LOG_STREAM(err, log_persist)
23 config pack_scalar(const std::string &,const t_string &);
25 public:
26 
27  virtual ~persist_context() {}
28 
29  struct name_space {
30  std::string namespace_;
31  std::string root_;
32  std::string node_;
33  std::string lineage_;
34  std::string descendants_;
35  bool valid_;
36 
37  bool valid() const {
38  return valid_;
39  }
40  void parse() {
41  while (namespace_.find_first_of("^") < namespace_.size()) {
42  if (namespace_[0] == '^') {
43  //TODO: Throw a WML error
44  namespace_ = "";
45  break;
46  }
47  std::string infix = namespace_.substr(namespace_.find_first_of("^"));
48  std::size_t end = infix.find_first_not_of("^");
49  if (!((end >= infix.length()) || (infix[end] == '.'))) {
50  //TODO: Throw a WML error
51  namespace_ = "";
52  break;
53  }
54  infix = infix.substr(0,end);
55  std::string suffix = namespace_.substr(namespace_.find_first_of("^") + infix.length());
56  while (!infix.empty())
57  {
58  std::string body = namespace_.substr(0,namespace_.find_first_of("^"));
59  body = body.substr(0,body.find_last_of("."));
60  infix = infix.substr(1);
61  namespace_ = body + infix + suffix;
62  }
63  }
64  }
65  name_space next() const {
66  return name_space(descendants_);
67  }
68  name_space prev() const {
69  return name_space(lineage_);
70  }
71  operator bool () const { return valid_; }
73  : namespace_()
74  , root_()
75  , node_()
76  , lineage_()
77  , descendants_()
78  , valid_(false)
79  {
80  }
81 
82  name_space(const std::string &ns, bool doParse = false)
83  : namespace_(ns)
84  , root_()
85  , node_()
86  , lineage_()
87  , descendants_()
88  , valid_(false)
89  {
90  if (doParse)
91  parse();
92  valid_ = ((namespace_.find_first_not_of("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.") > namespace_.length()) && !namespace_.empty());
93  root_ = namespace_.substr(0,namespace_.find_first_of("."));
94  node_ = namespace_.substr(namespace_.find_last_of(".") + 1);
95  if (namespace_.find_last_of(".") <= namespace_.length())
96  lineage_ = namespace_.substr(0,namespace_.find_last_of("."));
97  if (namespace_.find_first_of(".") <= namespace_.length())
98  descendants_ = namespace_.substr(namespace_.find_first_of(".") + 1);
99  }
100  };
101 protected:
104  bool valid_;
106 
108  : cfg_()
109  , namespace_()
110  , valid_(false)
111  , in_transaction_(false)
112  {}
113 
114  persist_context(const std::string &name_space)
115  : cfg_()
116  , namespace_(name_space,true)
117  , valid_(namespace_.valid())
118  , in_transaction_(false)
119  {}
120 
121  config *get_node(config &cfg, name_space &ns, bool force = false) {
122  name_space next = ns.next();
123  if (next) {
124  if (force)
125  return get_node(cfg.child_or_add(next.root_), next, true);
126  else if (cfg.has_child(next.root_))
127  return get_node(cfg.child(next.root_), next);
128  else
129  return nullptr;
130  }
131  else
132  return &cfg;
133  }
134 
135  const config *get_node(const config &cfg, const name_space &ns) const {
136  name_space next = ns.next();
137  if (next) {
138  if (cfg.has_child(next.root_))
139  return get_node(cfg.child(next.root_), next);
140  else
141  return nullptr;
142  }
143  else
144  return &cfg;
145  }
146 
147 public:
148  virtual bool clear_var(const std::string &, bool immediate = false) = 0;
149  virtual config get_var(const std::string &) const = 0;
150  virtual bool set_var(const std::string &, const config &, bool immediate = false) = 0;
151  virtual bool start_transaction () = 0;
152  virtual bool end_transaction () = 0;
153  virtual bool cancel_transaction () = 0;
154  std::string get_node() const;
155  void set_node(const std::string &);
156  bool valid() const { return valid_; }
157  bool dirty() const {
158  return true;
159  }
160  operator bool() const { return valid_; }
161 };
162 
164 private:
165  void load();
166  void init();
167  bool save_context();
168 
169 public:
170  persist_file_context(const std::string &name_space);
171  bool clear_var(const std::string &, bool immediate = false);
172  config get_var(const std::string &) const;
173  bool set_var(const std::string &, const config &, bool immediate = false);
174 
176  if (in_transaction_)
177  return false;
178  in_transaction_ = true;
179  return true;
180  }
181  bool end_transaction () {
182  if (!in_transaction_)
183  return false;
184  in_transaction_ = false;
185  save_context();
186  return true;
187  }
189  if (!in_transaction_)
190  return false;
191  load();
192  in_transaction_ = false;
193  return true;
194  }
195 };
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:420
virtual bool start_transaction()=0
static lg::log_domain log_persist("engine/persistence")
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
Definition: tips.cpp:35
const config * get_node(const config &cfg, const name_space &ns) const
virtual bool cancel_transaction()=0
virtual ~persist_context()
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
Definition: config.cpp:412
static void body(LexState *ls, expdesc *e, int ismethod, int line)
Definition: lparser.cpp:782
config & child_or_add(config_key_type key)
Definition: config.cpp:466
virtual bool set_var(const std::string &, const config &, bool immediate=false)=0
Definitions for the interface to Wesnoth Markup Language (WML).
bool valid() const
struct utils::detail::formula_initer init
virtual config get_var(const std::string &) const =0
config pack_scalar(const std::string &, const t_string &)
virtual bool clear_var(const std::string &, bool immediate=false)=0
persist_context(const std::string &name_space)
virtual bool end_transaction()=0
void set_node(const std::string &)
std::string get_node() const
config * get_node(config &cfg, name_space &ns, bool force=false)
Standard logging facilities (interface).
name_space(const std::string &ns, bool doParse=false)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
bool dirty() const