GetFEM++  5.3
dal_naming_system.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2017 Yves Renard
5 
6  This file is a part of GetFEM++
7 
8  GetFEM++ is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 #ifndef DAL_NAMING_SYSTEM_H
33 #define DAL_NAMING_SYSTEM_H
34 
35 #include <deque>
36 #include <map>
38 #include "getfem_omp.h"
39 
40 
41 namespace dal {
42 
43  /** @file dal_naming_system.h
44  @author Yves Renard <Yves.Renard@insa-lyon.fr>
45  @date August 17, 2002.
46  @brief Naming system.
47  */
48 
49 
50  /** Associate a name to a method descriptor and store method descriptors.
51  *
52  * Methods may have parameters such as integer or other methods.
53  * The class METHOD have to derive from dal::static_stored_object
54  */
55  template <class METHOD> class naming_system {
56 
57  public :
58 
59  typedef std::shared_ptr<const METHOD> pmethod;
60 
61  struct parameter {
62  int type_; // 0 = numeric value, 1 = pointer on another method.
63  double num_;
64  pmethod pm_;
65 
66  pmethod method(void) const { return pm_; }
67  double num(void) const { return num_; }
68  int type(void) const { return type_; }
69  parameter(double e) : type_(0), num_(e), pm_(0) {}
70  parameter(pmethod p) : type_(1), num_(0.), pm_(p) {}
71  };
72 
73  typedef std::deque<parameter> param_list;
74  typedef pmethod (* pfunction)(param_list &,
75  std::vector<pstatic_stored_object> &);
76  typedef pmethod (* pgenfunction)(std::string,
77  std::vector<pstatic_stored_object> &);
78  typedef size_t size_type;
79 
80  protected :
81 
82  std::string prefix;
83  std::map<std::string, size_type> suffixes;
84  std::vector<pfunction> functions;
85  std::vector<pgenfunction> genfunctions;
86  std::map<std::string, std::string> shorter_names;
87  std::map<std::string, std::string> aliases;
88 
89  struct method_key : virtual public static_stored_object_key {
90  std::string name;
91 
92  virtual bool compare(const static_stored_object_key &oo) const {
93  const method_key &o = dynamic_cast<const method_key &>(oo);
94  if (name < o.name) return true; else return false;
95  }
96  method_key(const std::string &name_) : name(name_) {}
97  };
98 
99  int mns_lexem(const std::string &s, size_type i, size_type &lenght);
100  pmethod method_(const std::string &name, size_type &i, bool throw_if_not_found);
101 
102 
103 
104 
105  public :
106 
107  void add_suffix(std::string name, pfunction pf);
108  void add_generic_function(pgenfunction pf);
109  std::string normative_name_of_method(pmethod pm) const;
110  std::string shorter_name_of_method(pmethod pm) const;
111  pmethod method(const std::string &name, size_type &i,
112  bool throw_if_not_found = true)
113  { gmm::standard_locale sl; return method_(name, i, throw_if_not_found); }
114  naming_system(std::string pr) : prefix(pr) {}
115  bool delete_method(std::string name);
116  };
117 
118  template <class METHOD>
119  void naming_system<METHOD>::add_suffix(std::string name,
120  typename naming_system<METHOD>::pfunction pf) {
121  std::string tname = prefix + '_' + name;
122  if (suffixes.find(tname) != suffixes.end()) {
123  functions[suffixes[tname]] = pf;
124  } else {
125  suffixes[tname] = functions.size();
126  functions.push_back(pf);
127  }
128 
129  }
130 
131  template <class METHOD>
132  void naming_system<METHOD>::add_generic_function(pgenfunction pf) {
133  genfunctions.push_back(pf);
134  }
135 
136  template <class METHOD>
138  naming_system<METHOD>::pmethod pm) const {
139  pstatic_stored_object_key k = key_of_stored_object(pm);
140  const method_key *p;
141  if (!k || !(p = dynamic_cast<const method_key *>(k.get())))
142  return prefix + "_UNKNOWN";
143  return p->name;
144  }
145 
146  template <class METHOD> std::string
148  naming_system<METHOD>::pmethod pm) const {
149  pstatic_stored_object_key k = key_of_stored_object(pm);
150  const method_key *p;
151  if (!k || !(p = dynamic_cast<const method_key *>(k.get())))
152  return prefix + "_UNKNOWN";
153  const std::string &name(p->name);
154  std::map<std::string, std::string>::const_iterator
155  it = shorter_names.find(name);
156  if (it != shorter_names.end()) return it->second;
157  return name;
158  }
159 
160  /* 0 = end of the string
161  1 = espace
162  2 = method name
163  3 = number
164  4 = '('
165  5 = ')'
166  6 = ','
167  */
168  template <class METHOD>
169  int naming_system<METHOD>::mns_lexem(const std::string &s, size_type i,
170  size_type &lenght) {
171  lenght = 1;
172  if (i >= s.size()) return 0;
173  char c = s[i++];
174  if (isspace(c)) return 1;
175  if (isalpha(c) || c == '_') {
176  while (i < s.size() && (isalpha(s[i]) || s[i] == '_' || isdigit(s[i])))
177  { ++i; ++lenght; }
178  return 2;
179  }
180  if (isdigit(c) || c == '-' || c == '+') {
181  while (i < s.size() && (isdigit(s[i]) || s[i] == 'e' || s[i] == 'E' ||
182  s[i] == '.' || s[i] == '-' || s[i] == '+'))
183  { ++i; ++lenght; }
184  return 3;
185  }
186  if (c == '(') return 4;
187  if (c == ')') return 5;
188  if (c == ',') return 6;
189  GMM_ASSERT1(false, "Invalid character on position " << i
190  << " of the string : " << s);
191  }
192 
193 
194  template <class METHOD>
195  typename naming_system<METHOD>::pmethod
196  naming_system<METHOD>::method_(const std::string &name, size_type &i,
197  bool throw_if_not_found) {
198  int state = 0;
199  bool error = false;
200  bool isend = false;
201  pmethod pm;
202  size_type ind_suff = size_type(-1);
203  size_type l;
204  param_list params;
205  std::string suff;
206 
207  for(;;) {
208  int lex = mns_lexem(name, i, l);
209  switch (state) {
210  case 0 :
211  switch (lex) {
212  case 1 : i += l; break;
213  case 2 :
214  suff = name.substr(i, l);
215  if (suffixes.find(suff) != suffixes.end())
216  ind_suff = suffixes[suff];
217  state = 1; i += l; break;
218  default : error = true;
219  }
220  break;
221  case 1 :
222  switch (lex) {
223  case 4 : state = 2; i += l; break;
224  default : isend = true; break;
225  }
226  break;
227  case 2 :
228  switch (lex) {
229  case 1 : i += l; break;
230  case 2 :
231  pm = method_(name, i, throw_if_not_found);
232  if (!(pm.get())) return pm;
233  params.push_back(parameter(pm));
234  state = 3; break;
235  case 3 : {
236  char *p;
238  params.push_back(parameter(strtod(&(name[i]), &p)));
239  i += l; if (p < &(name[i])) error = true;
240  state = 3; break;
241  }
242  case 5 : i += l; isend = true; break;
243  default : error = true;
244  }
245  break;
246  case 3 :
247  switch (lex) {
248  case 1 : i += l; break;
249  case 5 : i += l; isend = true; break;
250  case 6 : i += l; state = 2; break;
251  default : error = true;
252  }
253  break;
254  }
255  GMM_ASSERT1(!error, "Syntax error on position " << i
256  << " of the string : " << name);
257  if (isend) {
258  std::stringstream norm_name(suff); //norm_name.imbue(std::locale("C"));
260  norm_name << suff;
261  if (params.size() > 0) {
262  norm_name << '(';
263  typename param_list::const_iterator it = params.begin(),
264  ite = params.end();
265  for (; it != ite; ++it) {
266  if ((*it).type() == 0) norm_name << (*it).num();
267  if ((*it).type() == 1)
268  norm_name << normative_name_of_method((*it).method());
269  if (it+1 != ite) norm_name << ',';
270  }
271  norm_name << ')';
272  }
273  auto pnname = std::make_shared<method_key>(norm_name.str());
274  // method_key nname(norm_name.str());
275  if (aliases.find(norm_name.str()) != aliases.end())
276  pnname->name = aliases[norm_name.str()];
277  pstatic_stored_object o = search_stored_object(pnname);
278  if (o) return std::dynamic_pointer_cast<const METHOD>(o);
279  pm = pmethod();
280  std::vector<pstatic_stored_object> dependencies;
281  for (size_type k = 0; k < genfunctions.size() && pm.get() == 0; ++k) {
282  pm = (*(genfunctions[k]))(pnname->name, dependencies);
283  }
284  if (!(pm.get())) {
285  if (ind_suff == size_type(-1)) {
286  GMM_ASSERT1(!throw_if_not_found, "Unknown method: "<<pnname->name);
287  return 0;
288  }
289  pm = (*(functions[ind_suff]))(params, dependencies);
290  }
291  pstatic_stored_object_key k = key_of_stored_object(pm);
292  if (!k) {
293  add_stored_object(pnname, pm,
294  dal::PERMANENT_STATIC_OBJECT);
295  for (size_type j = 0; j < dependencies.size(); ++j)
296  add_dependency(pm, dependencies[j]);
297  }
298  else {
299  std::string normname((dynamic_cast<const method_key *>(k.get()))->name);
300  aliases[pnname->name] = normname;
301  if (pnname->name.size() < normname.size()) {
302  if (shorter_names.find(normname) != shorter_names.end()) {
303  if (pnname->name.size() < shorter_names[normname].size())
304  shorter_names[normname] = pnname->name;
305  }
306  else shorter_names[normname] = pnname->name;
307  }
308  }
309  return pm;
310  }
311  }
312 
313  }
314 
315  /**deletion of static_stored_object in the naming system*/
316  template <class METHOD>
317  bool naming_system<METHOD>::delete_method(std::string name) {
318  pmethod pm;
319  // method_key nname(name);
320  pstatic_stored_object_key pnname = std::make_shared<method_key>(name);
321  pstatic_stored_object o = search_stored_object(pnname);
322  if (!o) return false;
323  pm = std::dynamic_pointer_cast<const METHOD>(o);
324  pstatic_stored_object_key k = key_of_stored_object(pm);
325  dal::del_stored_object(pm, false);
326  return true;
327  }
328 
329 }
330 #endif
Stores interdependent getfem objects.
bool delete_method(std::string name)
deletion of static_stored_object in the naming system
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
Tools for multithreaded, OpenMP and Boost based parallelization.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
Associate a name to a method descriptor and store method descriptors.
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
this is the above solutions for linux, but it still needs to be tested.
Definition: gmm_std.h:238
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
Dynamic Array Library.