YARP
Yet Another Robot Platform
ResourceFinder.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
8 
9 #include <yarp/conf/dirs.h>
10 #include <yarp/conf/environment.h>
11 #include <yarp/conf/filesystem.h>
12 
13 #include <yarp/os/Bottle.h>
14 #include <yarp/os/Network.h>
15 #include <yarp/os/Os.h>
16 #include <yarp/os/Property.h>
17 #include <yarp/os/SystemClock.h>
18 #include <yarp/os/Time.h>
22 
23 #include <cerrno>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <string>
27 
28 using namespace yarp::os;
29 using namespace yarp::os::impl;
30 namespace fs = yarp::conf::filesystem;
31 
32 #define RTARGET stderr
33 #define RESOURCE_FINDER_CACHE_TIME 10
34 
35 namespace {
36 #ifndef YARP_NO_DEPRECATED // since YARP 3.4
37 // The log component cannot be const because we still support setVerbose and
38 // setQuiet
39 YARP_OS_NON_CONST_LOG_COMPONENT(RESOURCEFINDER, "yarp.os.ResourceFinder")
40 #else
41 YARP_OS_LOG_COMPONENT(RESOURCEFINDER, "yarp.os.ResourceFinder")
42 #endif
43 
44 std::vector<std::string> bottle_to_vector(const Bottle& b)
45 {
46  std::vector<std::string> out;
47  for (size_t i = 0; i < b.size(); ++i) {
48  out.push_back(b.get(i).asString());
49  }
50  return out;
51 }
52 
53 Bottle vector_to_bottle(const std::vector<std::string>& v)
54 {
55  Bottle out;
56  for (const auto& s : v) {
57  out.addString(s);
58  }
59  return out;
60 }
61 
62 } // namespace
63 
64 static std::string getPwd()
65 {
66  std::string result;
67  int len = 5;
68  char* buf = nullptr;
69  while (true) {
70  delete[] buf;
71  buf = new char[len];
72  if (buf == nullptr) {
73  break;
74  }
75  char* dir = yarp::os::getcwd(buf, len);
76  if (dir != nullptr) {
77  result = dir;
78  break;
79  }
80  if (errno != ERANGE) {
81  break;
82  }
83  len *= 2;
84  }
85  delete[] buf;
86  buf = nullptr;
87  return result;
88 }
89 
90 
91 static void appendResourceType(std::string& path,
92  const std::string& resourceType)
93 {
94  if (resourceType.empty()) {
95  return;
96  }
97  std::string slash{fs::preferred_separator};
98  if (path.length() > 0) {
99  if (path[path.length() - 1] != slash[0]) {
100  path +=slash;
101  }
102  }
103  path += resourceType;
104 }
105 
106 static void prependResourceType(std::string& path,
107  const std::string& resourceType)
108 {
109  if (resourceType.empty()) {
110  return;
111  }
112  std::string slash{fs::preferred_separator};
113  path = resourceType + slash + path;
114 }
115 
116 static void appendResourceType(std::vector<std::string>& paths,
117  const std::string& resourceType)
118 {
119  for (auto& txt : paths) {
120  appendResourceType(txt, resourceType);
121  }
122 }
123 
124 
125 //---------------------------------------------------------------------------------------------------
127 {
128 private:
129  yarp::os::Bottle apps;
130  std::string configFilePath;
131  yarp::os::Property cache;
132  bool mainActive{false};
133  bool useNearMain{false};
134 
135 public:
136  bool addAppName(const std::string& appName)
137  {
138  apps.addString(appName);
139  return true;
140  }
141 
143  {
144  apps.clear();
145  return true;
146  }
147 
148  static std::string extractPath(const std::string& fname)
149  {
150  std::string s{fname};
151  auto n = s.rfind('/');
152 #if defined(_WIN32)
153  if (n == std::string::npos) {
154  n = s.rfind('\\');
155  }
156 #endif
157  if (n != std::string::npos) {
158  return s.substr(0, n);
159  }
160  return {};
161  }
162 
163  bool configureProp(Property& config, int argc, char* argv[], bool skip)
164  {
165  Property p;
166  p.fromCommand(argc, argv, skip);
167 
168  bool user_specified_from = p.check("from");
169 
170  if (p.check("verbose")) {
171  yCWarning(RESOURCEFINDER, "The 'verbose' option is deprecated.");
172  }
173 
174  yCDebug(RESOURCEFINDER, "configuring");
175 
176  bool configured_normally = true;
177 
178  if (p.check("context")) {
179  clearAppNames();
180  std::string c = p.check("context", Value("default")).asString();
181  addAppName(c.c_str());
182  yCDebug(RESOURCEFINDER, "added context %s", c.c_str());
183  }
184 
185  config.fromCommand(argc, argv, skip, false);
186  if (config.check("from")) {
187  std::string from = config.check("from", Value("config.ini")).toString();
188  yCDebug(RESOURCEFINDER, "default config file specified as %s", from.c_str());
189  mainActive = true;
190  std::string corrected = findFile(config, from, nullptr);
191  mainActive = false;
192  if (!corrected.empty()) {
193  from = corrected;
194  }
195  std::string fromPath = extractPath(from.c_str());
196  configFilePath = fromPath;
197  if (!config.fromConfigFile(from, false) && user_specified_from) {
198  configured_normally = false;
199  }
200  config.fromCommand(argc, argv, skip, false);
201  }
202  return configured_normally;
203  }
204 
205  bool setDefault(Property& config, const std::string& key, const yarp::os::Value& val)
206  {
207  if (!config.check(key)) {
208  config.put(key, val);
209  }
210  return true;
211  }
212 
213  bool isAbsolute(const std::string& str)
214  {
215  if (str.length() > 0 && (str[0] == '/' || str[0] == '\\')) {
216  return true;
217  }
218  if (str.length() > 1) {
219  if (str[1] == ':') {
220  return true;
221  }
222  }
223  return false;
224  }
225 
226  bool isRooted(const std::string& str)
227  {
228  if (isAbsolute(str)) {
229  return true;
230  }
231  if (str.length() >= 2) {
232  if (str[0] == '.' && (str[1] == '/' || str[1] == '\\')) {
233  return true;
234  }
235  } else if (str == ".") {
236  return true;
237  }
238  return false;
239  }
240 
241  std::string getPath(const std::string& base1,
242  const std::string& base2,
243  const std::string& base3,
244  const std::string& name)
245  {
246  if (isAbsolute(name)) {
247  return name;
248  }
249 
250  std::string s;
251  std::string slash{fs::preferred_separator};
252 
253  if (!base1.empty()) {
254  s = base1;
255  s = s + slash;
256  }
257 
258  if (isRooted(base2)) {
259  s = base2;
260  } else {
261  s = s + base2;
262  }
263  if (!base2.empty()) {
264  s = s + slash;
265  }
266 
267  if (isRooted(base3)) {
268  s = base3;
269  } else {
270  s = s + base3;
271  }
272  if (!base3.empty()) {
273  s = s + slash;
274  }
275 
276  s = s + name;
277 
278  return s;
279  }
280 
281  std::string check(const std::string& base1,
282  const std::string& base2,
283  const std::string& base3,
284  const std::string& name,
285  bool isDir,
286  const Bottle& doc,
287  const std::string& doc2)
288  {
289  std::string s = getPath(base1, base2, base3, name);
290 
291  // check cache first
292  Bottle* prev = cache.find(s).asList();
293  if (prev != nullptr) {
294  double t = prev->get(0).asFloat64();
295  int flag = prev->get(1).asInt32();
297  if (flag != 0) {
298  return s;
299  }
300  return {};
301  }
302  }
303 
304  std::string base = doc.toString();
305  yCDebug(RESOURCEFINDER, "checking [%s] (%s%s%s)", s.c_str(), base.c_str(), (base.length() == 0) ? "" : " ", doc2.c_str());
306 
307  bool ok = exists(s.c_str(), isDir);
308  Value status;
309  yCAssert(RESOURCEFINDER, status.asList());
311  status.asList()->addInt32(ok ? 1 : 0);
312  cache.put(s, status);
313  if (ok) {
314  yCDebug(RESOURCEFINDER, "found %s", s.c_str());
315  return s;
316  }
317  return {};
318  }
319 
320  std::string findPath(Property& config, const std::string& name, const ResourceFinderOptions* externalOptions)
321  {
322  std::string fname = config.check(name, Value(name)).asString();
323  std::string result = findFileBase(config, fname, true, externalOptions);
324  return result;
325  }
326 
327  std::vector<std::string> findPaths(Property& config, const std::string& name, const ResourceFinderOptions* externalOptions, bool enforcePlural = true)
328  {
329  std::string fname = config.check(name, Value(name)).asString();
330  std::vector<std::string> paths;
331  if (externalOptions != nullptr) {
332  if (externalOptions->duplicateFilesPolicy == ResourceFinderOptions::All) {
333  findFileBase(config, fname, true, paths, *externalOptions);
334  return paths;
335  }
336  }
338  if (externalOptions != nullptr) {
339  opts = *externalOptions;
340  }
341  if (enforcePlural) {
343  }
344  findFileBase(config, fname, true, paths, opts);
345  return paths;
346  }
347 
348  std::string findPath(Property& config)
349  {
350  std::string result = findFileBase(config, "", true, nullptr);
351  if (result.empty()) {
352  result = getPwd();
353  }
354  return result;
355  }
356 
357  std::string findFile(Property& config, const std::string& name, const ResourceFinderOptions* externalOptions)
358  {
359  std::string fname = config.check(name, Value(name)).asString();
360  std::string result = findFileBase(config, fname, false, externalOptions);
361  return result;
362  }
363 
364  std::string findFileByName(Property& config, const std::string& fname, const ResourceFinderOptions* externalOptions)
365  {
366  std::string result = findFileBase(config, fname, false, externalOptions);
367  return result;
368  }
369 
370  std::string findFileBase(Property& config, const std::string& name, bool isDir, const ResourceFinderOptions* externalOptions)
371  {
372  std::vector<std::string> output;
374  if (externalOptions == nullptr) {
375  externalOptions = &opts;
376  }
377  findFileBase(config, name, isDir, output, *externalOptions);
378  return output.empty() ? std::string{} : output.at(0);
379  }
380 
381  bool canShowErrors(const ResourceFinderOptions& opts) const
382  {
384  return false;
385  }
386  return true;
387  }
388 
389  void findFileBase(Property& config, const std::string& name, bool isDir, std::vector<std::string>& output, const ResourceFinderOptions& opts)
390  {
391  Bottle doc;
392  size_t prelen = output.size();
393  findFileBaseInner(config, name, isDir, true, output, opts, doc, {});
394  if (output.size() != prelen) {
395  return;
396  }
397  bool justTop = (opts.duplicateFilesPolicy == ResourceFinderOptions::First);
398  if (justTop) {
399  if (canShowErrors(opts)) {
400  yCDebug(RESOURCEFINDER, "did not find %s", name.c_str());
401  }
402  }
403  }
404 
405  static void addString(std::vector<std::string>& output, const std::string& txt)
406  {
407  for (const auto& str : output) {
408  if (txt == str) {
409  return;
410  }
411  }
412  output.push_back(txt);
413  }
414 
415  void findFileBaseInner(Property& config, const std::string& name, bool isDir, bool allowPathd, std::vector<std::string>& output, const ResourceFinderOptions& opts, const Bottle& predoc, const std::string& reason)
416  {
417  Bottle doc;
418  doc = predoc;
419  if (!reason.empty()) {
420  doc.addString(reason);
421  }
424  std::string resourceType = opts.resourceType;
425 
426  bool justTop = (opts.duplicateFilesPolicy == ResourceFinderOptions::First);
427 
428  // check current directory
429  if ((locs & ResourceFinderOptions::Directory) != 0) {
430  if (name.empty() && isDir) {
431  addString(output, getPwd());
432  if (justTop) {
433  return;
434  }
435  }
436  std::string str = check(getPwd(), resourceType, "", name, isDir, doc, "pwd");
437  if (!str.empty()) {
438  if (mainActive) {
439  useNearMain = true;
440  }
441  addString(output, str);
442  if (justTop) {
443  return;
444  }
445  }
446  }
447 
448  if (((locs & ResourceFinderOptions::NearMainConfig) != 0) && useNearMain) {
449  if (!configFilePath.empty()) {
450  std::string str = check(configFilePath, resourceType, "", name, isDir, doc, "defaultConfigFile path");
451  if (!str.empty()) {
452  addString(output, str);
453  if (justTop) {
454  return;
455  }
456  }
457  }
458  }
459 
460  if ((locs & ResourceFinderOptions::Robot) != 0) {
461  std::string slash{fs::preferred_separator};
462  bool found = false;
463  std::string robot = yarp::conf::environment::get_string("YARP_ROBOT_NAME", &found);
464  if (!found) {
465  robot = "default";
466  }
467 
468  // Nested search to locate robot directory
469  std::vector<std::string> paths;
470  ResourceFinderOptions opts2;
472  opts2.resourceType = "robots";
474  findFileBaseInner(config, robot, true, allowPathd, paths, opts2, doc, "robot");
475  appendResourceType(paths, resourceType);
476  for (const auto& path : paths) {
477  std::string str = check(path,
478  "",
479  "",
480  name,
481  isDir,
482  doc,
483  "robot");
484  if (!str.empty()) {
485  addString(output, str);
486  if (justTop) {
487  return;
488  }
489  }
490  }
491  }
492 
493  if (((locs & ResourceFinderOptions::Context) != 0) && !useNearMain) {
494  for (size_t i = 0; i < apps.size(); i++) {
495  std::string app = apps.get(i).asString();
496 
497  // New context still apparently applies only to "applications"
498  // which means we need to restrict our attention to "app"
499  // directories.
500 
501  // Nested search to locate context directory
502  std::vector<std::string> paths;
503  ResourceFinderOptions opts2;
504  prependResourceType(app, "contexts");
507  findFileBaseInner(config, app, true, allowPathd, paths, opts2, doc, "context");
508  appendResourceType(paths, resourceType);
509  for (const auto& path : paths) {
510  std::string str = check(path, "", "", name, isDir, doc, "context");
511  if (!str.empty()) {
512  addString(output, str);
513  if (justTop) {
514  return;
515  }
516  }
517  }
518  }
519  }
520 
521  // check YARP_CONFIG_HOME
522  if (((locs & ResourceFinderOptions::User) != 0) && ((flavor & ResourceFinderOptions::ConfigLike) != 0)) {
523  std::string home = yarp::conf::dirs::yarpconfighome();
524  if (!home.empty()) {
525  appendResourceType(home, resourceType);
526  std::string str = check(home, "", "", name, isDir, doc, "YARP_CONFIG_HOME");
527  if (!str.empty()) {
528  addString(output, str);
529  if (justTop) {
530  return;
531  }
532  }
533  }
534  }
535 
536  // check YARP_DATA_HOME
537  if (((locs & ResourceFinderOptions::User) != 0) && ((flavor & ResourceFinderOptions::DataLike) != 0)) {
538  std::string home = yarp::conf::dirs::yarpdatahome();
539  if (!home.empty()) {
540  appendResourceType(home, resourceType);
541  std::string str = check(home, "", "", name, isDir, doc, "YARP_DATA_HOME");
542  if (!str.empty()) {
543  addString(output, str);
544  if (justTop) {
545  return;
546  }
547  }
548  }
549  }
550 
551  // check YARP_CONFIG_DIRS
552  if ((locs & ResourceFinderOptions::Sysadmin) != 0) {
553  auto dirs = yarp::conf::dirs::yarpconfigdirs();
554  appendResourceType(dirs, resourceType);
555  for (const auto& dir : dirs) {
556  std::string str = check(dir,
557  "",
558  "",
559  name,
560  isDir,
561  doc,
562  "YARP_CONFIG_DIRS");
563  if (!str.empty()) {
564  addString(output, str);
565  if (justTop) {
566  return;
567  }
568  }
569  }
570  }
571 
572  // check YARP_DATA_DIRS
573  if ((locs & ResourceFinderOptions::Installed) != 0) {
574  auto dirs = yarp::conf::dirs::yarpdatadirs();
575  appendResourceType(dirs, resourceType);
576  for (const auto& dir : dirs) {
577  std::string str = check(dir,
578  "",
579  "",
580  name,
581  isDir,
582  doc,
583  "YARP_DATA_DIRS");
584  if (!str.empty()) {
585  addString(output, str);
586  if (justTop) {
587  return;
588  }
589  }
590  }
591  }
592 
593  if (allowPathd && ((locs & ResourceFinderOptions::Installed) != 0)) {
594  // Nested search to locate path.d directories
595  std::vector<std::string> pathd_paths;
596  ResourceFinderOptions opts2;
598  opts2.resourceType = "config";
599  findFileBaseInner(config, "path.d", true, false, pathd_paths, opts2, doc, "path.d");
600 
601  for (const auto& pathd_path : pathd_paths) {
602  // check /.../path.d/*
603  // this directory is expected to contain *.ini files like this:
604  // [search BUNDLE_NAME]
605  // path /PATH1 /PATH2
606  // for example:
607  // [search icub]
608  // path /usr/share/iCub
609  Property pathd;
610  pathd.fromConfigFile(pathd_path);
611  Bottle sections = pathd.findGroup("search").tail();
612  for (size_t i = 0; i < sections.size(); i++) {
613  std::string search_name = sections.get(i).asString();
614  Bottle group = pathd.findGroup(search_name);
615  auto paths_v = bottle_to_vector(group.findGroup("path").tail());
616  appendResourceType(paths_v, resourceType);
617  for (const auto& path : paths_v) {
618  std::string str = check(path, "", "", name, isDir, doc, "yarp.d");
619  if (!str.empty()) {
620  addString(output, str);
621  if (justTop) {
622  return;
623  }
624  }
625  }
626  }
627  }
628  }
629  }
630 
631  bool exists(const std::string& fname, bool isDir)
632  {
633  int result = yarp::os::stat(fname.c_str());
634  if (result != 0) {
635  return false;
636  }
637  if (!isDir) {
638  // if not required to be a directory, pass anything.
639  return true;
640  }
641 
642  // ACE doesn't seem to help us interpret the results of stat
643  // in a portable fashion.
644 
645  // ACE on Ubuntu 9.10 has issues.
646  // Suppressing check for file here since it isn't really needed
647  // and causes a lot of problems.
648  /*
649  YARP_DIR *dir = ACE_OS::opendir(fname);
650  if (dir!=nullptr) {
651  ACE_OS::closedir(dir);
652  dir = nullptr;
653  return true;
654  }
655  return false;
656  */
657  return true;
658  }
659 
660 
661  std::string getContext()
662  {
663  return apps.get(0).asString();
664  }
665 
667  {
668  return apps;
669  }
670 
671  std::string getHomeContextPath(Property& config, const std::string& context)
672  {
673  YARP_UNUSED(config);
674  if (useNearMain) {
675  return configFilePath;
676  }
677  std::string path = getPath(yarp::conf::dirs::yarpdatahome(), "contexts", context, "");
678 
679  std::string slash{fs::preferred_separator};
680  if (path.length() > 1) {
681  if (path[path.length() - 1] == slash[0]) {
682  path = path.substr(0, path.length() - slash.size());
683  }
684  }
685 
686  std::string parentPath = getPath(yarp::conf::dirs::yarpdatahome(), "contexts", "", "");
687  if (yarp::os::stat(parentPath.c_str()) != 0) {
688  yarp::os::mkdir(parentPath.c_str());
689  }
690 
691  if (yarp::os::mkdir(path.c_str()) < 0 && errno != EEXIST) {
692  yCWarning(RESOURCEFINDER, "Could not create %s directory", path.c_str());
693  }
694  return path;
695  }
696 
697  std::string getHomeRobotPath()
698  {
699  if (useNearMain) {
700  return configFilePath;
701  }
702  bool found = false;
703  std::string robot = yarp::conf::environment::get_string("YARP_ROBOT_NAME", &found);
704  if (!found) {
705  robot = "default";
706  }
707  std::string path = getPath(yarp::conf::dirs::yarpdatahome(), "robots", robot, "");
708 
709  std::string slash{fs::preferred_separator};
710  if (path.length() > 1) {
711  if (path[path.length() - 1] == slash[0]) {
712  path = path.substr(0, path.length() - slash.size());
713  }
714  }
715 
716  std::string parentPath = getPath(yarp::conf::dirs::yarpdatahome(), "robots", "", "");
717  if (yarp::os::stat(parentPath.c_str()) != 0) {
718  yarp::os::mkdir(parentPath.c_str());
719  }
720 
721  if (yarp::os::mkdir(path.c_str()) < 0 && errno != EEXIST) {
722  yCWarning(RESOURCEFINDER, "Could not create %s directory", path.c_str());
723  }
724  return path;
725  }
726 };
727 
728 
729 //---------------------------------------------------------------------------------------------------
731  Searchable(),
732  m_owned(true),
733  m_nullConfig(false),
734  m_isConfiguredFlag(false),
735  mPriv(nullptr)
736 {
738  mPriv = new Private();
739 }
740 
742  Searchable(alt),
743  m_owned(true),
744  m_nullConfig(false),
745  m_isConfiguredFlag(false),
746  mPriv(nullptr)
747 {
749  mPriv = new Private();
750  *this = alt;
751 }
752 
753 ResourceFinder::ResourceFinder(Searchable& data, Private* altPriv) :
754  Searchable(),
755  m_owned(false),
756  m_nullConfig(data.isNull()),
757  m_isConfiguredFlag(true),
758  mPriv(nullptr)
759 {
761  this->mPriv = altPriv;
762  if (!data.isNull()) {
763  m_configprop.fromString(data.toString());
764  }
765 }
766 
768 {
769  if (m_owned) {
770  delete mPriv;
771  }
772 }
773 
775 {
776  if (&alt != this) {
777  *(mPriv) = *(alt.mPriv);
778  m_owned = true;
779  m_nullConfig = alt.m_nullConfig;
780  m_isConfiguredFlag = alt.m_isConfiguredFlag;
781  m_configprop = alt.m_configprop;
782  }
783  return *this;
784 }
785 
786 bool ResourceFinder::configure(int argc, char* argv[], bool skipFirstArgument)
787 {
788  m_isConfiguredFlag = true;
789  return mPriv->configureProp(m_configprop, argc, argv, skipFirstArgument);
790 }
791 
792 
793 bool ResourceFinder::addContext(const std::string& appName)
794 {
795  if (appName[0] == '\0') {
796  return true;
797  }
798  yCDebug(RESOURCEFINDER, "adding context [%s]", appName.c_str());
799  return mPriv->addAppName(appName);
800 }
801 
802 bool ResourceFinder::clearContext()
803 {
804  yCDebug(RESOURCEFINDER, "clearing context");
805  return mPriv->clearAppNames();
806 }
807 
808 bool ResourceFinder::setDefault(const std::string& key, const std::string& val)
809 {
810  Value val2;
811  val2.fromString(val.c_str());
812  return mPriv->setDefault(m_configprop, key, val2);
813 }
814 
815 bool ResourceFinder::setDefault(const std::string& key, std::int32_t val)
816 {
817  return mPriv->setDefault(m_configprop, key, Value(val));
818 }
819 
820 bool ResourceFinder::setDefault(const std::string& key, yarp::conf::float64_t val)
821 {
822  return mPriv->setDefault(m_configprop, key, Value(val));
823 }
824 
825 bool ResourceFinder::setDefault(const std::string& key, const yarp::os::Value& val)
826 {
827  return mPriv->setDefault(m_configprop, key, val);
828 }
829 
830 std::string ResourceFinder::findFile(const std::string& name)
831 {
832  yCDebug(RESOURCEFINDER, "finding file [%s]", name.c_str());
833  return mPriv->findFile(m_configprop, name, nullptr);
834 }
835 
836 std::string ResourceFinder::findFile(const std::string& name,
837  const ResourceFinderOptions& options)
838 {
839  yCDebug(RESOURCEFINDER, "finding file [%s]", name.c_str());
840  return mPriv->findFile(m_configprop, name, &options);
841 }
842 
843 std::string ResourceFinder::findFileByName(const std::string& name)
844 {
845  yCDebug(RESOURCEFINDER, "finding file %s", name.c_str());
846  return mPriv->findFileByName(m_configprop, name, nullptr);
847 }
848 
849 std::string ResourceFinder::findFileByName(const std::string& name,
850  const ResourceFinderOptions& options)
851 {
852  yCDebug(RESOURCEFINDER, "finding file %s", name.c_str());
853  return mPriv->findFileByName(m_configprop, name, &options);
854 }
855 
856 
857 std::string ResourceFinder::findPath(const std::string& name)
858 {
859  yCDebug(RESOURCEFINDER, "finding path [%s]", name.c_str());
860  return mPriv->findPath(m_configprop, name, nullptr);
861 }
862 
863 std::string ResourceFinder::findPath(const std::string& name,
864  const ResourceFinderOptions& options)
865 {
866  yCDebug(RESOURCEFINDER, "finding path [%s]", name.c_str());
867  return mPriv->findPath(m_configprop, name, &options);
868 }
869 
871 {
872  yCDebug(RESOURCEFINDER, "finding paths [%s]", name.c_str());
873  return vector_to_bottle(mPriv->findPaths(m_configprop, name, nullptr));
874 }
875 
877  const ResourceFinderOptions& options)
878 {
879  yCDebug(RESOURCEFINDER, "finding paths [%s]", name.c_str());
880  return vector_to_bottle(mPriv->findPaths(m_configprop, name, &options));
881 }
882 
884 {
885  yCDebug(RESOURCEFINDER, "finding path");
886  return mPriv->findPath(m_configprop);
887 }
888 
889 #ifndef YARP_NO_DEPRECATED // Since YARP 3.4
890 bool ResourceFinder::setVerbose(bool verbose)
891 {
892  RESOURCEFINDER().setMinimumPrintLevel(verbose ? yarp::os::Log::DebugType : yarp::os::Log::InfoType);
893  return true;
894 }
895 
896 bool ResourceFinder::setQuiet(bool quiet)
897 {
898  RESOURCEFINDER().setMinimumPrintLevel(quiet ? yarp::os::Log::WarningType : yarp::os::Log::InfoType);
899  return true;
900 }
901 #endif
902 
903 bool ResourceFinder::check(const std::string& key) const
904 {
905  return m_configprop.check(key);
906 }
907 
908 
909 Value& ResourceFinder::find(const std::string& key) const
910 {
911  return m_configprop.find(key);
912 }
913 
914 
915 Bottle& ResourceFinder::findGroup(const std::string& key) const
916 {
917  return m_configprop.findGroup(key);
918 }
919 
920 
922 {
923  return m_nullConfig || m_configprop.isNull();
924 }
925 
926 
927 std::string ResourceFinder::toString() const
928 {
929  return m_configprop.toString();
930 }
931 
933 {
934  return mPriv->getContext();
935 }
936 
938 {
939  return mPriv->getHomeContextPath(m_configprop, mPriv->getContext());
940 }
941 
943 {
944  return mPriv->getHomeRobotPath();
945 }
946 
948 {
949  return mPriv->getContexts();
950 }
951 
952 
954 {
955  return ResourceFinder(findGroup(key), mPriv);
956 }
957 
958 
960 {
961  static ResourceFinder instance;
962  return instance;
963 }
964 
965 std::string ResourceFinder::createIfAbsent(bool mayCreate,
966  const std::string& path)
967 {
968  if (!mayCreate) {
969  return path;
970  }
971  yarp::os::mkdir_p(path.c_str(), 0);
972  return path;
973 }
974 
976  const std::string& key,
977  const ResourceFinderOptions& options)
978 {
979  std::vector<std::string> paths = mPriv->findPaths(config, key, &options, false);
980 
981  for (auto it = paths.rbegin(); it != paths.rend(); ++it) {
982  const auto& path = *it;
983  config.fromConfigFile(path, false);
984  }
985 
986  return !paths.empty();
987 }
988 
989 
990 #ifndef YARP_NO_DEPRECATED // Since YARP 3.5
991 
992 std::string ResourceFinder::getDataHomeWithPossibleCreation(bool mayCreate)
993 {
994  return createIfAbsent(mayCreate, yarp::conf::dirs::yarpdatahome());
995 }
996 
997 
998 std::string ResourceFinder::getConfigHomeWithPossibleCreation(bool mayCreate)
999 {
1000  return createIfAbsent(mayCreate, yarp::conf::dirs::yarpconfighome());
1001 }
1002 
1003 
1005 {
1006  Bottle result;
1007  for (const auto& dir : yarp::conf::dirs::yarpdatadirs()) {
1008  result.addString(dir);
1009  }
1010  return result;
1011 }
1012 
1013 
1015 {
1016  Bottle result;
1017  for (const auto& dir : yarp::conf::dirs::yarpconfigdirs()) {
1018  result.addString(dir);
1019  }
1020  return result;
1021 }
1022 
1023 #endif // YARP_NO_DEPRECATED
float t
static void appendResourceType(std::string &path, const std::string &resourceType)
static void prependResourceType(std::string &path, const std::string &resourceType)
#define RESOURCE_FINDER_CACHE_TIME
static std::string getPwd()
constexpr fs::value_type slash
Definition: Run.cpp:98
bool setDefault(Property &config, const std::string &key, const yarp::os::Value &val)
bool addAppName(const std::string &appName)
std::string getPath(const std::string &base1, const std::string &base2, const std::string &base3, const std::string &name)
static void addString(std::vector< std::string > &output, const std::string &txt)
bool exists(const std::string &fname, bool isDir)
bool isRooted(const std::string &str)
std::string findFileBase(Property &config, const std::string &name, bool isDir, const ResourceFinderOptions *externalOptions)
std::string getHomeContextPath(Property &config, const std::string &context)
std::vector< std::string > findPaths(Property &config, const std::string &name, const ResourceFinderOptions *externalOptions, bool enforcePlural=true)
bool configureProp(Property &config, int argc, char *argv[], bool skip)
void findFileBase(Property &config, const std::string &name, bool isDir, std::vector< std::string > &output, const ResourceFinderOptions &opts)
std::string findPath(Property &config)
std::string check(const std::string &base1, const std::string &base2, const std::string &base3, const std::string &name, bool isDir, const Bottle &doc, const std::string &doc2)
std::string findFileByName(Property &config, const std::string &fname, const ResourceFinderOptions *externalOptions)
void findFileBaseInner(Property &config, const std::string &name, bool isDir, bool allowPathd, std::vector< std::string > &output, const ResourceFinderOptions &opts, const Bottle &predoc, const std::string &reason)
bool canShowErrors(const ResourceFinderOptions &opts) const
std::string findPath(Property &config, const std::string &name, const ResourceFinderOptions *externalOptions)
bool isAbsolute(const std::string &str)
std::string findFile(Property &config, const std::string &name, const ResourceFinderOptions *externalOptions)
static std::string extractPath(const std::string &fname)
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
void addFloat64(yarp::conf::float64_t x)
Places a 64-bit floating point number in the bottle, at the end of the list.
Definition: Bottle.cpp:158
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
Definition: Bottle.cpp:302
Bottle tail() const
Get all but the first element of a bottle.
Definition: Bottle.cpp:388
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:121
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:140
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:211
@ DebugType
Definition: Log.h:75
@ InfoType
Definition: Log.h:76
@ WarningType
Definition: Log.h:77
static void autoInitMinimum()
Basic system initialization, not including plugins.
Definition: Network.cpp:857
A class for storing options and configuration information.
Definition: Property.h:34
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Property.cpp:1051
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Property.cpp:1069
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1063
bool fromConfigFile(const std::string &fname, bool wipe=true)
Interprets a file as a list of properties.
Definition: Property.cpp:1098
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:1015
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Property.cpp:1041
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
Definition: Property.cpp:1142
void fromCommand(int argc, char *argv[], bool skipFirst=true, bool wipe=true)
Interprets a list of command arguments as a list of properties.
Definition: Property.cpp:1074
These options are loosely based on http://wiki.icub.org/wiki/YARP_ResourceFinder.
DuplicateFilesPolicy duplicateFilesPolicy
Helper class for finding config files and other external resources.
bool configure(int argc, char *argv[], bool skipFirstArgument=true)
Sets up the ResourceFinder.
std::string getContext()
Return the default "context" or "application name" used in searching for configuration files.
virtual Bottle & findGroup(const std::string &key) const=0
Gets a list corresponding to a given keyword.
std::string getHomeRobotPath()
Return the path to the "user" robot directory.
static Bottle getConfigDirs()
Locations where system administrator data and config files are stored.
std::string findPath()
Find the first existing directory in the search path.
std::string toString() const override
Return a standard text representation of the content of the object.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
bool isNull() const override
Checks if the object is invalid.
static ResourceFinder & getResourceFinderSingleton()
Access a ResourceFinder singleton whose lifetime will match that of the YARP library.
yarp::os::Bottle findPaths(const std::string &name)
Expand a partial path to a list of paths.
bool setDefault(const std::string &key, const std::string &val)
Provide a default value for a given key.
std::string findFileByName(const std::string &name)
Find the full path to a file.
const ResourceFinder & operator=(const ResourceFinder &alt)
bool readConfig(Property &config, const std::string &key, const ResourceFinderOptions &options)
virtual bool check(const std::string &key) const=0
Check if there exists a property of the given name.
static Bottle getDataDirs()
Locations where packaged data and config files are stored.
std::string findFile(const std::string &name)
Find the full path to a file.
bool setQuiet(bool quiet=true)
Request that information be suppressed from the console.
bool setVerbose(bool verbose=true)
Request that information be printed to the console on how resources are being found.
std::string getHomeContextPath()
Return the path to the "user" context directory for the current context.
virtual ResourceFinder findNestedResourceFinder(const std::string &key)
Gets a section as a ResourceFinder object, retaining the context and configuration of the current Res...
yarp::os::Bottle getContexts()
Return the full stack of contexts used in searching for configuration files.
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual bool isNull() const
Checks if the object is invalid.
Definition: Searchable.cpp:107
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
static double nowSystem()
Definition: SystemClock.cpp:34
A single value (typically within a Bottle).
Definition: Value.h:45
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
void fromString(const char *str)
Set value to correspond to a textual representation.
Definition: Value.cpp:351
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
#define yCAssert(component, x)
Definition: LogComponent.h:169
#define yCWarning(component,...)
Definition: LogComponent.h:143
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:34
#define YARP_OS_NON_CONST_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:45
std::string yarpdatahome()
Returns the directory where user-specific YARP data files should be written.
Definition: dirs.h:256
std::vector< std::string > yarpconfigdirs()
Returns the directories where YARP configuration files should be searched.
Definition: dirs.h:322
std::string yarpconfighome()
Returns the directory where user-specific YARP configuration files should be written.
Definition: dirs.h:297
std::string home()
Returns the home directory for current user.
Definition: dirs.h:86
std::vector< std::string > yarpdatadirs()
Returns the directories where YARP data files should be searched.
Definition: dirs.h:276
std::string get_string(const std::string &key, bool *found=nullptr)
Read a string from an environment variable.
Definition: environment.h:68
static constexpr value_type preferred_separator
Definition: filesystem.h:23
double float64_t
Definition: numeric.h:77
The components from which ports and connections are built.
An interface to the operating system, including Port based communication.
int mkdir(const char *p)
Portable wrapper for the mkdir() function.
Definition: Os.cpp:37
char * getcwd(char *buf, size_t size)
Portable wrapper for the getcwd() function.
Definition: Os.cpp:112
int stat(const char *path)
Portable wrapper for the stat() function.
Definition: Os.cpp:85
@ YARP_CLOCK_SYSTEM
Definition: Time.h:29
int mkdir_p(const char *p, int ignoreLevels=0)
Create a directory and all parent directories needed.
Definition: Os.cpp:42
#define YARP_UNUSED(var)
Definition: api.h:162