GetFEM  5.4.2
dal_naming_system.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2020 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>
37 
39 #include "getfem/getfem_locale.h"
40 #include "getfem_omp.h"
41 
42 namespace dal {
43 
44  /** @file dal_naming_system.h
45  @author Yves Renard <[email protected]>
46  @date August 17, 2002.
47  @brief Naming system.
48  */
49 
50 
51  /** Associate a name to a method descriptor and store method descriptors.
52  *
53  * Methods may have parameters such as integer or other methods.
54  * The class METHOD have to derive from dal::static_stored_object
55  */
56  template <class METHOD> class naming_system {
57 
58  public :
59 
60  typedef std::shared_ptr<const METHOD> pmethod;
61 
62  struct parameter {
63  int type_; // 0 = numeric value, 1 = pointer on another method.
64  double num_;
65  pmethod pm_;
66 
67  pmethod method(void) const { return pm_; }
68  double num(void) const { return num_; }
69  int type(void) const { return type_; }
70  parameter(double e) : type_(0), num_(e), pm_(0) {}
71  parameter(pmethod p) : type_(1), num_(0.), pm_(p) {}
72  };
73 
74  typedef std::deque<parameter> param_list;
75  typedef pmethod (* pfunction)(param_list &,
76  std::vector<pstatic_stored_object> &);
77  typedef pmethod (* pgenfunction)(std::string,
78  std::vector<pstatic_stored_object> &);
79  typedef size_t size_type;
80 
81  protected :
82 
83  std::string prefix;
84  std::map<std::string, size_type> suffixes;
85  std::vector<pfunction> functions;
86  std::vector<pgenfunction> genfunctions;
87  std::map<std::string, std::string> shorter_names;
88  std::map<std::string, std::string> aliases;
89 
90  struct method_key : virtual public static_stored_object_key {
91  std::string name;
92 
93  bool compare(const static_stored_object_key &oo) const override{
94  auto &o = dynamic_cast<const method_key &>(oo);
95  return name < o.name;
96  }
97 
98  bool equal(const static_stored_object_key &oo) const override{
99  auto &o = dynamic_cast<const method_key &>(oo);
100  return name == o.name;
101  }
102 
103  method_key(const std::string &name_) : name(name_) {}
104  };
105 
106  int mns_lexem(const std::string &s, size_type i, size_type &lenght);
107  pmethod method_(const std::string &name, size_type &i, bool throw_if_not_found);
108 
109 
110 
111 
112  public :
113 
114  void add_suffix(std::string name, pfunction pf);
115  void add_generic_function(pgenfunction pf);
116  std::string normative_name_of_method(pmethod pm) const;
117  std::string shorter_name_of_method(pmethod pm) const;
118  pmethod method(const std::string &name, size_type &i,
119  bool throw_if_not_found = true)
120  { getfem::standard_locale sl; return method_(name, i, throw_if_not_found); }
121  naming_system(std::string pr) : prefix(pr) {}
122  bool delete_method(std::string name);
123  };
124 
125  template <class METHOD>
126  void naming_system<METHOD>::add_suffix(std::string name,
127  typename naming_system<METHOD>::pfunction pf) {
128  std::string tname = prefix + '_' + name;
129  if (suffixes.find(tname) != suffixes.end()) {
130  functions[suffixes[tname]] = pf;
131  } else {
132  suffixes[tname] = functions.size();
133  functions.push_back(pf);
134  }
135 
136  }
137 
138  template <class METHOD>
139  void naming_system<METHOD>::add_generic_function(pgenfunction pf) {
140  genfunctions.push_back(pf);
141  }
142 
143  template <class METHOD>
144  std::string naming_system<METHOD>::normative_name_of_method(typename
145  naming_system<METHOD>::pmethod pm) const {
146  pstatic_stored_object_key k = key_of_stored_object(pm);
147  const method_key *p;
148  if (!k || !(p = dynamic_cast<const method_key *>(k.get())))
149  return prefix + "_UNKNOWN";
150  return p->name;
151  }
152 
153  template <class METHOD> std::string
154  naming_system<METHOD>::shorter_name_of_method(typename
155  naming_system<METHOD>::pmethod pm) const {
156  pstatic_stored_object_key k = key_of_stored_object(pm);
157  const method_key *p;
158  if (!k || !(p = dynamic_cast<const method_key *>(k.get())))
159  return prefix + "_UNKNOWN";
160  const std::string &name(p->name);
161  std::map<std::string, std::string>::const_iterator
162  it = shorter_names.find(name);
163  if (it != shorter_names.end()) return it->second;
164  return name;
165  }
166 
167  /* 0 = end of the string
168  1 = espace
169  2 = method name
170  3 = number
171  4 = '('
172  5 = ')'
173  6 = ','
174  */
175  template <class METHOD>
176  int naming_system<METHOD>::mns_lexem(const std::string &s, size_type i,
177  size_type &lenght) {
178  lenght = 1;
179  if (i >= s.size()) return 0;
180  char c = s[i++];
181  if (isspace(c)) return 1;
182  if (isalpha(c) || c == '_') {
183  while (i < s.size() && (isalpha(s[i]) || s[i] == '_' || isdigit(s[i])))
184  { ++i; ++lenght; }
185  return 2;
186  }
187  if (isdigit(c) || c == '-' || c == '+') {
188  while (i < s.size() && (isdigit(s[i]) || s[i] == 'e' || s[i] == 'E' ||
189  s[i] == '.' || s[i] == '-' || s[i] == '+'))
190  { ++i; ++lenght; }
191  return 3;
192  }
193  if (c == '(') return 4;
194  if (c == ')') return 5;
195  if (c == ',') return 6;
196  GMM_ASSERT1(false, "Invalid character on position " << i
197  << " of the string : " << s);
198  }
199 
200 
201  template <class METHOD>
202  typename naming_system<METHOD>::pmethod
203  naming_system<METHOD>::method_(const std::string &name, size_type &i,
204  bool throw_if_not_found) {
205  int state = 0;
206  bool error = false;
207  bool isend = false;
208  pmethod pm;
209  size_type ind_suff = size_type(-1);
210  size_type l;
211  param_list params;
212  std::string suff;
213 
214  for(;;) {
215  int lex = mns_lexem(name, i, l);
216  switch (state) {
217  case 0 :
218  switch (lex) {
219  case 1 : i += l; break;
220  case 2 :
221  suff = name.substr(i, l);
222  if (suffixes.find(suff) != suffixes.end())
223  ind_suff = suffixes[suff];
224  state = 1; i += l; break;
225  default : error = true;
226  }
227  break;
228  case 1 :
229  switch (lex) {
230  case 4 : state = 2; i += l; break;
231  default : isend = true; break;
232  }
233  break;
234  case 2 :
235  switch (lex) {
236  case 1 : i += l; break;
237  case 2 :
238  pm = method_(name, i, throw_if_not_found);
239  if (!(pm.get())) return pm;
240  params.push_back(parameter(pm));
241  state = 3; break;
242  case 3 : {
243  char *p;
245  params.push_back(parameter(strtod(&(name[i]), &p)));
246  i += l; if (p < &(name[i])) error = true;
247  state = 3; break;
248  }
249  case 5 : i += l; isend = true; break;
250  default : error = true;
251  }
252  break;
253  case 3 :
254  switch (lex) {
255  case 1 : i += l; break;
256  case 5 : i += l; isend = true; break;
257  case 6 : i += l; state = 2; break;
258  default : error = true;
259  }
260  break;
261  }
262  GMM_ASSERT1(!error, "Syntax error on position " << i
263  << " of the string : " << name);
264  if (isend) {
265  std::stringstream norm_name(suff); //norm_name.imbue(std::locale("C"));
267  norm_name << suff;
268  if (params.size() > 0) {
269  norm_name << '(';
270  typename param_list::const_iterator it = params.begin(),
271  ite = params.end();
272  for (; it != ite; ++it) {
273  if ((*it).type() == 0) norm_name << (*it).num();
274  if ((*it).type() == 1)
275  norm_name << normative_name_of_method((*it).method());
276  if (it+1 != ite) norm_name << ',';
277  }
278  norm_name << ')';
279  }
280  auto pnname = std::make_shared<method_key>(norm_name.str());
281  // method_key nname(norm_name.str());
282  if (aliases.find(norm_name.str()) != aliases.end())
283  pnname->name = aliases[norm_name.str()];
284  pstatic_stored_object o = search_stored_object(pnname);
285  if (o) return std::dynamic_pointer_cast<const METHOD>(o);
286  pm = pmethod();
287  std::vector<pstatic_stored_object> dependencies;
288  for (size_type k = 0; k < genfunctions.size() && pm.get() == 0; ++k) {
289  pm = (*(genfunctions[k]))(pnname->name, dependencies);
290  }
291  if (!(pm.get())) {
292  if (ind_suff == size_type(-1)) {
293  GMM_ASSERT1(!throw_if_not_found, "Unknown method: "<<pnname->name);
294  return 0;
295  }
296  pm = (*(functions[ind_suff]))(params, dependencies);
297  }
298  pstatic_stored_object_key k = key_of_stored_object(pm);
299  if (!k) {
300  add_stored_object(pnname, pm,
301  dal::PERMANENT_STATIC_OBJECT);
302  for (size_type j = 0; j < dependencies.size(); ++j)
303  add_dependency(pm, dependencies[j]);
304  }
305  else {
306  std::string normname((dynamic_cast<const method_key *>(k.get()))->name);
307  aliases[pnname->name] = normname;
308  if (pnname->name.size() < normname.size()) {
309  if (shorter_names.find(normname) != shorter_names.end()) {
310  if (pnname->name.size() < shorter_names[normname].size())
311  shorter_names[normname] = pnname->name;
312  }
313  else shorter_names[normname] = pnname->name;
314  }
315  }
316  return pm;
317  }
318  }
319 
320  }
321 
322  /**deletion of static_stored_object in the naming system*/
323  template <class METHOD>
324  bool naming_system<METHOD>::delete_method(std::string name) {
325  pmethod pm;
326  // method_key nname(name);
327  pstatic_stored_object_key pnname = std::make_shared<method_key>(name);
328  pstatic_stored_object o = search_stored_object(pnname);
329  if (!o) return false;
330  pm = std::dynamic_pointer_cast<const METHOD>(o);
331  pstatic_stored_object_key k = key_of_stored_object(pm);
332  dal::del_stored_object(pm, false);
333  return true;
334  }
335 
336 }
337 #endif
bgeot::size_type
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
dal::naming_system::delete_method
bool delete_method(std::string name)
deletion of static_stored_object in the naming system
Definition: dal_naming_system.h:324
dal
Dynamic Array Library.
Definition: dal_backtrace.cc:29
dal::naming_system
Associate a name to a method descriptor and store method descriptors.
Definition: dal_naming_system.h:56
dal::del_stored_object
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
Definition: dal_static_stored_objects.cc:369
getfem::standard_locale
Identical to gmm::standard_locale, but does not change std::locale in multi-threaded sections of the ...
Definition: getfem_locale.h:50
dal::search_stored_object
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
Definition: dal_static_stored_objects.cc:177
getfem_omp.h
Tools for multithreaded, OpenMP and Boost based parallelization.
getfem_locale.h
thread safe standard locale with RAII semantics
dal_static_stored_objects.h
Stores interdependent getfem objects.
dal::add_stored_object
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
Definition: dal_static_stored_objects.cc:284
dal::add_dependency
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
Definition: dal_static_stored_objects.cc:230