GetFEM  5.5
dal_naming_system.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2026 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, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 #ifndef DAL_NAMING_SYSTEM_H
32 #define DAL_NAMING_SYSTEM_H
33 
34 #include <deque>
35 #include <map>
36 
38 #include "getfem/getfem_locale.h"
39 #include "getfem_omp.h"
40 
41 namespace dal {
42 
43  /** @file dal_naming_system.h
44  @author Yves Renard <[email protected]>
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  bool compare(const static_stored_object_key &oo) const override{
93  auto &o = dynamic_cast<const method_key &>(oo);
94  return name < o.name;
95  }
96 
97  bool equal(const static_stored_object_key &oo) const override{
98  auto &o = dynamic_cast<const method_key &>(oo);
99  return name == o.name;
100  }
101 
102  method_key(const std::string &name_) : name(name_) {}
103  };
104 
105  int mns_lexem(const std::string &s, size_type i, size_type &lenght);
106  pmethod method_(const std::string &name, size_type &i, bool throw_if_not_found);
107 
108 
109 
110 
111  public :
112 
113  void add_suffix(std::string name, pfunction pf);
114  void add_generic_function(pgenfunction pf);
115  std::string normative_name_of_method(pmethod pm) const;
116  std::string shorter_name_of_method(pmethod pm) const;
117  pmethod method(const std::string &name, size_type &i,
118  bool throw_if_not_found = true)
119  { getfem::standard_locale sl; return method_(name, i, throw_if_not_found); }
120  naming_system(std::string pr) : prefix(pr) {}
121  bool delete_method(std::string name);
122  };
123 
124  template <class METHOD>
125  void naming_system<METHOD>::add_suffix(std::string name,
126  typename naming_system<METHOD>::pfunction pf) {
127  std::string tname = prefix + '_' + name;
128  if (suffixes.find(tname) != suffixes.end()) {
129  functions[suffixes[tname]] = pf;
130  } else {
131  suffixes[tname] = functions.size();
132  functions.push_back(pf);
133  }
134 
135  }
136 
137  template <class METHOD>
138  void naming_system<METHOD>::add_generic_function(pgenfunction pf) {
139  genfunctions.push_back(pf);
140  }
141 
142  template <class METHOD>
143  std::string naming_system<METHOD>::normative_name_of_method(typename
144  naming_system<METHOD>::pmethod pm) const {
145  pstatic_stored_object_key k = key_of_stored_object(pm);
146  const method_key *p;
147  if (!k || !(p = dynamic_cast<const method_key *>(k.get())))
148  return prefix + "_UNKNOWN";
149  return p->name;
150  }
151 
152  template <class METHOD> std::string
153  naming_system<METHOD>::shorter_name_of_method(typename
154  naming_system<METHOD>::pmethod pm) const {
155  pstatic_stored_object_key k = key_of_stored_object(pm);
156  const method_key *p;
157  if (!k || !(p = dynamic_cast<const method_key *>(k.get())))
158  return prefix + "_UNKNOWN";
159  const std::string &name(p->name);
160  std::map<std::string, std::string>::const_iterator
161  it = shorter_names.find(name);
162  if (it != shorter_names.end()) return it->second;
163  return name;
164  }
165 
166  /* 0 = end of the string
167  1 = espace
168  2 = method name
169  3 = number
170  4 = '('
171  5 = ')'
172  6 = ','
173  */
174  template <class METHOD>
175  int naming_system<METHOD>::mns_lexem(const std::string &s, size_type i,
176  size_type &lenght) {
177  lenght = 1;
178  if (i >= s.size()) return 0;
179  char c = s[i++];
180  if (isspace(c)) return 1;
181  if (isalpha(c) || c == '_') {
182  while (i < s.size() && (isalpha(s[i]) || s[i] == '_' || isdigit(s[i])))
183  { ++i; ++lenght; }
184  return 2;
185  }
186  if (isdigit(c) || c == '-' || c == '+') {
187  while (i < s.size() && (isdigit(s[i]) || s[i] == 'e' || s[i] == 'E' ||
188  s[i] == '.' || s[i] == '-' || s[i] == '+'))
189  { ++i; ++lenght; }
190  return 3;
191  }
192  if (c == '(') return 4;
193  if (c == ')') return 5;
194  if (c == ',') return 6;
195  GMM_ASSERT1(false, "Invalid character on position " << i
196  << " of the string : " << s);
197  }
198 
199 
200  template <class METHOD>
201  typename naming_system<METHOD>::pmethod
202  naming_system<METHOD>::method_(const std::string &name, size_type &i,
203  bool throw_if_not_found) {
204  int state = 0;
205  bool error = false;
206  bool isend = false;
207  pmethod pm;
208  size_type ind_suff = size_type(-1);
209  size_type l;
210  param_list params;
211  std::string suff;
212 
213  for(;;) {
214  int lex = mns_lexem(name, i, l);
215  switch (state) {
216  case 0 :
217  switch (lex) {
218  case 1 : i += l; break;
219  case 2 :
220  suff = name.substr(i, l);
221  if (suffixes.find(suff) != suffixes.end())
222  ind_suff = suffixes[suff];
223  state = 1; i += l; break;
224  default : error = true;
225  }
226  break;
227  case 1 :
228  switch (lex) {
229  case 4 : state = 2; i += l; break;
230  default : isend = true; break;
231  }
232  break;
233  case 2 :
234  switch (lex) {
235  case 1 : i += l; break;
236  case 2 :
237  pm = method_(name, i, throw_if_not_found);
238  if (!(pm.get())) return pm;
239  params.push_back(parameter(pm));
240  state = 3; break;
241  case 3 : {
242  char *p;
244  params.push_back(parameter(strtod(&(name[i]), &p)));
245  i += l; if (p < &(name[i])) error = true;
246  state = 3; break;
247  }
248  case 5 : i += l; isend = true; break;
249  default : error = true;
250  }
251  break;
252  case 3 :
253  switch (lex) {
254  case 1 : i += l; break;
255  case 5 : i += l; isend = true; break;
256  case 6 : i += l; state = 2; break;
257  default : error = true;
258  }
259  break;
260  }
261  GMM_ASSERT1(!error, "Syntax error on position " << i
262  << " of the string : " << name);
263  if (isend) {
264  std::stringstream norm_name(suff); //norm_name.imbue(std::locale("C"));
266  norm_name << suff;
267  if (params.size() > 0) {
268  norm_name << '(';
269  typename param_list::const_iterator it = params.begin(),
270  ite = params.end();
271  for (; it != ite; ++it) {
272  if ((*it).type() == 0) norm_name << (*it).num();
273  if ((*it).type() == 1)
274  norm_name << normative_name_of_method((*it).method());
275  if (it+1 != ite) norm_name << ',';
276  }
277  norm_name << ')';
278  }
279  auto pnname = std::make_shared<method_key>(norm_name.str());
280  // method_key nname(norm_name.str());
281  if (aliases.find(norm_name.str()) != aliases.end())
282  pnname->name = aliases[norm_name.str()];
283  pstatic_stored_object o = search_stored_object(pnname);
284  if (o) return std::dynamic_pointer_cast<const METHOD>(o);
285  pm = pmethod();
286  std::vector<pstatic_stored_object> dependencies;
287  for (size_type k = 0; k < genfunctions.size() && pm.get() == 0; ++k) {
288  pm = (*(genfunctions[k]))(pnname->name, dependencies);
289  }
290  if (!(pm.get())) {
291  if (ind_suff == size_type(-1)) {
292  GMM_ASSERT1(!throw_if_not_found, "Unknown method: "<<pnname->name);
293  return 0;
294  }
295  pm = (*(functions[ind_suff]))(params, dependencies);
296  }
297  pstatic_stored_object_key k = key_of_stored_object(pm);
298  if (!k) {
299  add_stored_object(pnname, pm,
300  dal::PERMANENT_STATIC_OBJECT);
301  for (size_type j = 0; j < dependencies.size(); ++j)
302  add_dependency(pm, dependencies[j]);
303  }
304  else {
305  std::string normname((dynamic_cast<const method_key *>(k.get()))->name);
306  aliases[pnname->name] = normname;
307  if (pnname->name.size() < normname.size()) {
308  if (shorter_names.find(normname) != shorter_names.end()) {
309  if (pnname->name.size() < shorter_names[normname].size())
310  shorter_names[normname] = pnname->name;
311  }
312  else shorter_names[normname] = pnname->name;
313  }
314  }
315  return pm;
316  }
317  }
318 
319  }
320 
321  /**deletion of static_stored_object in the naming system*/
322  template <class METHOD>
323  bool naming_system<METHOD>::delete_method(std::string name) {
324  pmethod pm;
325  // method_key nname(name);
326  pstatic_stored_object_key pnname = std::make_shared<method_key>(name);
327  pstatic_stored_object o = search_stored_object(pnname);
328  if (!o) return false;
329  pm = std::dynamic_pointer_cast<const METHOD>(o);
330  pstatic_stored_object_key k = key_of_stored_object(pm);
331  dal::del_stored_object(pm, false);
332  return true;
333  }
334 
335 }
336 #endif
Associate a name to a method descriptor and store method descriptors.
bool delete_method(std::string name)
deletion of static_stored_object in the naming system
Identical to gmm::standard_locale, but does not change std::locale in multi-threaded sections of the ...
Definition: getfem_locale.h:49
Stores interdependent getfem objects.
thread safe standard locale with RAII semantics
Tools for multithreaded, OpenMP and Boost based parallelization.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
Dynamic Array Library.
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.