Schnek
block.hpp
1 /*
2  * block.hpp
3  *
4  * Created on: 1 May 2012
5  * Author: Holger Schmitz
6  * Email: holger@notjustphysics.com
7  *
8  * Copyright 2012 Holger Schmitz
9  *
10  * This file is part of Schnek.
11  *
12  * Schnek is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Schnek is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Schnek. If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef SCHNEK_BLOCK_HPP_
28 #define SCHNEK_BLOCK_HPP_
29 
30 #include "blockparameters.hpp"
31 #include "blockdata.hpp"
32 #include "../util/unique.hpp"
33 
34 #include <memory>
35 #include <boost/algorithm/string.hpp>
36 
37 #include <stack>
38 
39 namespace schnek {
40 
41 class Block;
42 typedef std::shared_ptr<Block> pBlock;
43 typedef std::list<pBlock> BlockList;
44 typedef std::shared_ptr<BlockList> pBlockList;
45 
46 class BlockTree
47 {
48  private:
49  pBlock root;
50  pBlock cursor;
51  std::stack<int> depth;
52  public:
53  BlockTree();
54  void addChild(pBlock);
55  void moveDown();
56  void moveUp();
57  pBlock getRoot() {return root; }
58 };
59 
60 typedef std::shared_ptr<BlockTree> pBlockTree;
61 
65 class Block : public Unique<Block>
66 {
67  private:
68  BlockParameters blockParameters;
69  pBlock parent;
70  BlockList children;
71  std::string name;
72 
73  template<typename T>
74  bool getData(std::string key, T* &data, bool upward);
75 
76  void registerHierarchy();
77  void preInitHierarchy();
78  void initHierarchy();
79  void postInitHierarchy();
80 
81  void setParent(pBlock parent_) { parent=parent_; }
82  friend class BlockTree;
83  protected:
84  virtual void initParameters(BlockParameters&) {}
85  virtual void registerData() {}
86  virtual void preInit() {}
87  virtual void init() {}
88  virtual void postInit() {}
89  BlockList getChildren() { return BlockList(children); }
90  public:
91  Block(pBlock parent_ = pBlock()) : parent(parent_) {}
92  virtual ~Block() {}
93 
94  void setContext(pBlockVariables context)
95  {
96  blockParameters.setContext(context);
97  }
98 
99  pBlockVariables getLocalVariables()
100  {
101  return blockParameters.getContext();
102  }
103 
104  pBlockVariables getVariables()
105  {
106  pBlockVariables vars = blockParameters.getContext();
107  while (vars->getParent()) vars = vars->getParent();
108  return vars;
109  }
110 
111 
112  void setup();
113  void addChild(pBlock child);
114  void evaluateParameters();
115 
116  pBlock getParent() { return parent; }
117 
118  template<typename T>
119  void addData(std::string key, T &data);
120 
121  template<typename T>
122  void retrieveData(std::string key, T* &data);
123 
124  template<typename T>
125  void retrieveData(std::string key, T &data);
126 
127  void initAll();
128 
129  void setName(const std::string &name_) { name = name_; }
130  std::string getName() { return name; }
131 };
132 
133 // template functions
134 
135 template<typename T>
136 bool Block::getData(std::string key, T* &data, bool upward)
137 {
138  if (BlockData<T>::instance().exists(this->getId(), key))
139  {
140  data = BlockData<T>::instance().get(this->getId(), key);
141  return true;
142  }
143 
144  boost::iterator_range<std::string::iterator> dot = boost::find_first(key,".");
145  if (!dot.empty())
146  {
147  std::string head = std::string(key.begin(), dot.begin());
148  std::string tail = std::string(dot.end(), key.end());
149  int count = 0;
150  for(pBlock child: children)
151  {
152  if ((child->getName()==head) && child->getData(tail, data, false)) ++count;
153  }
154 
155  if (count>1) throw DuplicateVariableException();
156  else if (count==1) return true;
157  }
158 
159  if (upward && parent)
160  return parent->getData(key, data, true);
161 
162  int count = 0;
163  for(pBlock child: children)
164  {
165  if (child->getData(key,data, false)) ++count;
166  }
167 
168  if (count>1) throw DuplicateVariableException();
169  return (count!=0);
170 }
171 
172 template<typename T>
173 void Block::addData(std::string key, T &data)
174 {
175  BlockData<T>::instance().add(this->getId(), key, data);
176 }
177 
178 template<typename T>
179 void Block::retrieveData(std::string key, T* &data)
180 {
181  T **datap;
182  if (getData(key, datap, true)) {
183  data = *datap;
184  }
185  else if (!getData(key, data, true))
186  throw VariableNotFoundException("Could not find Block variable "+key);
187 }
188 
189 template<typename T>
190 void Block::retrieveData(std::string key, T &data)
191 {
192  T *datap;
193  if (!getData(key, datap, true))
194  throw VariableNotFoundException("Could not find Block variable "+key);
195  data = *datap;
196 }
197 
198 
199 } // namespace
200 
201 #endif // SCHNEK_BLOCK_HPP_
Definition: unique.hpp:36
Definition: types.hpp:89
Definition: algo.hpp:30
Definition: blockdata.hpp:42
Definition: block.hpp:46
Definition: types.hpp:59
static BlockData< T > & instance()
Definition: logger.hpp:90
Definition: block.hpp:65
Definition: blockparameters.hpp:149