Gyoto
GyotoRegister.h
Go to the documentation of this file.
1 /*
2  Copyright 2011-2025 Thibaut Paumard
3 
4  This file is part of Gyoto.
5 
6  Gyoto is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Gyoto is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Gyoto. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef __GyotoRegister_H_
21 #define __GyotoRegister_H_
22 
23 #include <string>
24 #include <glob.h>
25 #include <filesystem>
26 #include "GyotoSmartPointer.h"
27 
37 namespace Gyoto {
46  namespace Register {
47 
48  /* Documented below */
49  class Entry;
50 
65  void init( char const * pluglist = NULL );
66 
70  void list();
71  }
72 
92  void * loadPlugin( char const * const plugname, int nofail = 0);
93 
99  bool havePlugin(std::string plugname);
100 
112  void requirePlugin(std::string plugname, int nofail = 0);
113 
117  std::vector<std::string> pluginPath();
118 
122  void pluginPath(const std::vector<std::string> &v);
123 
124 }
125 
136  friend void Gyoto::Register::list();
137 protected:
138  std::string name_;
144  const std::string plugin_;
146 public:
150  Entry(std::string name,
152  Entry* next);
153  ~Entry();
154 
181  getSubcontractor(std::string name, std::string &plugin, int errmode=0);
182 
186  std::string name();
187 
191  std::string plugin();
192 
197 
201  void pluginsSlashNames(std::vector<std::string> &retval) const;
202 };
203 
204 
212 #define GYOTO_REGISTEREDPLUGINSSLASHKINDS(space) \
213  std::vector<std::string> \
214  Gyoto::space::Generic::registeredPluginsSlashKinds() { \
215  std::vector<std::string> retval; \
216  if (Gyoto::space::Register_) \
217  Gyoto::space::Register_->pluginsSlashNames(retval); \
218  return retval; \
219  }
220 
269 #define GYOTO_GETSUBCONTRACTOR(space) \
270  Gyoto::space::Subcontractor_t* \
271  Gyoto::space::getSubcontractor(std::string name, \
272  std::vector<std::string> &plugin, \
273  int errmode) { \
274  std::vector<std::string> mandatory; \
275  std::vector<std::string> fallback; \
276  std::vector<std::string> plug_path(Gyoto::pluginPath()); \
277  GYOTO_DEBUG << "loading non-fallback plug-ins..." << std::endl; \
278  for (const auto &plg : plugin) { \
279  GYOTO_DEBUG_EXPR(plg); \
280  if (plg.rfind("fallback:", 0) != 0) { \
281  Gyoto::requirePlugin(plg); \
282  mandatory.emplace_back(plg); \
283  } \
284  else fallback.emplace_back(plg.substr(9)); \
285  } \
286  GYOTO_DEBUG << "found " << mandatory.size() \
287  << " mandatory plg-ins and "<< fallback.size() \
288  << " fallback plug-ins" << std::endl; \
289  GYOTO_DEBUG << \
290  "loading fallback plug-ins until the Register is not empty" \
291  << std::endl; \
292  for (const auto plg : fallback) { \
293  if (Gyoto::space::Register_) break; \
294  GYOTO_DEBUG_EXPR(plg); \
295  Gyoto::requirePlugin(plg, 2); \
296  } \
297  for (const auto &plg : fallback) { \
298  if (Gyoto::space::Register_) break; \
299  GYOTO_DEBUG_EXPR(plg); \
300  for (const auto &path : plug_path) { \
301  std::string pattern = (path + "libgyoto-" + plg) \
302  + "." GYOTO_PLUGIN_SFX; \
303  std::vector<std::string> files = \
304  Gyoto::glob(pattern); \
305  for (const auto &file : files) { \
306  GYOTO_DEBUG << "Trying " << file << std::endl; \
307  Gyoto::requirePlugin(file, 2); \
308  } \
309  } \
310  } \
311  if (!Gyoto::space::Register_) \
312  throwError("No " GYOTO_STRINGIFY(space) " kind registered!"); \
313  Gyoto::space::Subcontractor_t* sctr= NULL; \
314  GYOTO_DEBUG << "looking for " << name \
315  << " in non-fallback plug-ins..." << std::endl; \
316  for (auto & plg : mandatory) { \
317  GYOTO_DEBUG_EXPR(plg); \
318  sctr=(Gyoto::space::Subcontractor_t*)Gyoto::space::Register_ \
319  -> getSubcontractor(name, plg, 2); \
320  if (sctr) { \
321  GYOTO_DEBUG << "found " << name << " in plug-in " \
322  << plg << std::endl; \
323  return sctr; \
324  } \
325  } \
326  if (!mandatory.size()) { \
327  GYOTO_DEBUG << "looking for " << name \
328  << " in registered plug-ins..." << std::endl; \
329  std::string plg(""); \
330  sctr = (Gyoto::space::Subcontractor_t*)Gyoto::space::Register_ \
331  -> getSubcontractor(name, plg, 2); \
332  if (sctr){ \
333  GYOTO_DEBUG << "found " << name << " in plug-in " \
334  << plg << std::endl; \
335  plugin.emplace(plugin.begin(), plg); \
336  GYOTO_DEBUG << "added '" << plugin[0] \
337  << "' as item 0 of pluglist" << std::endl; \
338  return sctr; \
339  } else if (!fallback.size() && !errmode) \
340  throwError ("Kind not found in any plug-in: "+name); \
341  } \
342  GYOTO_DEBUG << "looking for " << name \
343  << " in fallback plug-ins..." << std::endl; \
344  /* try to load fallbacks directly */ \
345  for (auto &plg : fallback) { \
346  GYOTO_DEBUG_EXPR(plg); \
347  Gyoto::requirePlugin(plg, 2); \
348  sctr = (Gyoto::space::Subcontractor_t*)Gyoto::space::Register_ \
349  -> getSubcontractor(name, plg, 2); \
350  if (sctr) { \
351  GYOTO_DEBUG << "found " << name << " in plug-in " \
352  << plg << std::endl; \
353  return sctr; \
354  } \
355  } \
356  GYOTO_DEBUG << "looking for " << name \
357  << " in fallback plug-ins, " \
358  << "allowing for glob expansion..." << std::endl; \
359  for (const auto &plg : fallback) { \
360  /* try glob expansion on plg itself, may it is already a path \
361  with wildcards */ \
362  GYOTO_DEBUG_EXPR(plg); \
363  std::vector<std::string> files = Gyoto::glob(plg); \
364  for (auto &file : files) { \
365  GYOTO_DEBUG << "Trying " << file << std::endl; \
366  if (!std::filesystem::exists(file)) continue; \
367  Gyoto::requirePlugin(file, 2); \
368  sctr = (Gyoto::space::Subcontractor_t*)Gyoto::space::Register_ \
369  -> getSubcontractor(name, file, 2); \
370  if (sctr) { \
371  GYOTO_DEBUG << "found " << name << " in plug-in " \
372  << file << std::endl; \
373  return sctr; \
374  } \
375  } \
376  /* try glob expansion on <directory>/libgyoto-<plg>.so for every \
377  directory in the plug-in path */ \
378  for (const auto &path : plug_path) { \
379  std::string pattern = (path + "libgyoto-" + plg) \
380  + "." GYOTO_PLUGIN_SFX; \
381  files = Gyoto::glob(pattern); \
382  for (auto &file : files) { \
383  GYOTO_DEBUG << "Trying " << file << std::endl; \
384  if (!std::filesystem::exists(file)) continue; \
385  Gyoto::requirePlugin(file, 2); \
386  sctr=(Gyoto::space::Subcontractor_t*)Gyoto::space::Register_ \
387  -> getSubcontractor(name, file, 2); \
388  if (sctr) { \
389  GYOTO_DEBUG << "found " << name << " in plug-in " \
390  << file << std::endl; \
391  return sctr; \
392  } \
393  } \
394  } \
395  } \
396  GYOTO_DEBUG << name << " not found anywhere, error?" \
397  << std::endl; \
398  if (!errmode) \
399  throwError("Kind not found in the specified plug-ins: "+name); \
400  return sctr; \
401  }
402 
403 #endif
void * loadPlugin(char const *const plugname, int nofail=0)
Load a plugin by name.
Entry(std::string name, Gyoto::SmartPointee::Subcontractor_t *subcontractor, Entry *next)
Constructor.
Gyoto::SmartPointee::Subcontractor_t * getSubcontractor(std::string name, std::string &plugin, int errmode=0)
Get subcontractor for a given name.
std::string name_
Kind name for the entry, as found in the "kind" XML attribute.
Definition: GyotoRegister.h:138
Reference-counting pointers.
void Register(std::string name, Gyoto::Astrobj::Subcontractor_t *scp)
Make an Astrobj kind known to the Factory.
void init(char const *pluglist=NULL)
Initialise the various registers.
std::string plugin()
Get plugin.
void list()
List the various registers.
void pluginsSlashNames(std::vector< std::string > &retval) const
Get "plugin/name" for this and all subsequent entries.
Gyoto::SmartPointer< Gyoto::SmartPointee > Subcontractor_t(Gyoto::FactoryMessenger *, std::vector< std::string > const &)
A subcontractor builds an object upon order from the Factory.
Definition: GyotoSmartPointer.h:115
Register::Entry * next_
Next entry in the register, or NULL.
Definition: GyotoRegister.h:142
Namespace for the Gyoto library.
Definition: GyotoAstrobj.h:46
std::string name()
Get name.
~Entry()
Destructor.
const std::string plugin_
Plug-in from which this Entry was loaded.
Definition: GyotoRegister.h:144
std::vector< std::string > pluginPath()
Get a copy of the plug-in path.
Gyoto::SmartPointee::Subcontractor_t * subcontractor_
Pointer to the Gyoto::SmartPointee::Subcontractor_t function that produces an object of this kind...
Definition: GyotoRegister.h:140
bool havePlugin(std::string plugname)
Check whether a given plug-in has already been loaded.
void requirePlugin(std::string plugname, int nofail=0)
Load a plugin by name, only if not loaded yet.
Register::Entry * next()
Get next.
Entry in a register (or a full register)
Definition: GyotoRegister.h:132