32 #define RTARGET stderr
33 #define RESOURCE_FINDER_CACHE_TIME 10
36 #ifndef YARP_NO_DEPRECATED
44 std::vector<std::string> bottle_to_vector(
const Bottle& b)
46 std::vector<std::string> out;
47 for (
size_t i = 0; i < b.
size(); ++i) {
53 Bottle vector_to_bottle(
const std::vector<std::string>& v)
56 for (
const auto& s : v) {
80 if (errno != ERANGE) {
92 const std::string& resourceType)
94 if (resourceType.empty()) {
98 if (path.length() > 0) {
99 if (path[path.length() - 1] !=
slash[0]) {
103 path += resourceType;
107 const std::string& resourceType)
109 if (resourceType.empty()) {
113 path = resourceType +
slash + path;
117 const std::string& resourceType)
119 for (
auto& txt : paths) {
130 std::string configFilePath;
132 bool mainActive{
false};
133 bool useNearMain{
false};
150 std::string s{fname};
151 auto n = s.rfind(
'/');
153 if (n == std::string::npos) {
157 if (n != std::string::npos) {
158 return s.substr(0, n);
168 bool user_specified_from = p.
check(
"from");
170 if (p.
check(
"verbose")) {
171 yCWarning(RESOURCEFINDER,
"The 'verbose' option is deprecated.");
174 yCDebug(RESOURCEFINDER,
"configuring");
176 bool configured_normally =
true;
178 if (p.
check(
"context")) {
180 std::string c = p.
check(
"context",
Value(
"default")).asString();
181 addAppName(c.c_str());
182 yCDebug(RESOURCEFINDER,
"added context %s", c.c_str());
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());
190 std::string corrected = findFile(config, from,
nullptr);
192 if (!corrected.empty()) {
195 std::string fromPath = extractPath(from.c_str());
196 configFilePath = fromPath;
198 configured_normally =
false;
202 return configured_normally;
207 if (!config.
check(key)) {
208 config.
put(key, val);
215 if (str.length() > 0 && (str[0] ==
'/' || str[0] ==
'\\')) {
218 if (str.length() > 1) {
228 if (isAbsolute(str)) {
231 if (str.length() >= 2) {
232 if (str[0] ==
'.' && (str[1] ==
'/' || str[1] ==
'\\')) {
235 }
else if (str ==
".") {
242 const std::string& base2,
243 const std::string& base3,
244 const std::string& name)
246 if (isAbsolute(name)) {
253 if (!base1.empty()) {
258 if (isRooted(base2)) {
263 if (!base2.empty()) {
267 if (isRooted(base3)) {
272 if (!base3.empty()) {
281 std::string
check(
const std::string& base1,
282 const std::string& base2,
283 const std::string& base3,
284 const std::string& name,
287 const std::string& doc2)
289 std::string s = getPath(base1, base2, base3, name);
293 if (prev !=
nullptr) {
305 yCDebug(RESOURCEFINDER,
"checking [%s] (%s%s%s)", s.c_str(), base.c_str(), (base.length() == 0) ?
"" :
" ", doc2.c_str());
307 bool ok = exists(s.c_str(), isDir);
312 cache.
put(s, status);
314 yCDebug(RESOURCEFINDER,
"found %s", s.c_str());
322 std::string fname = config.
check(name,
Value(name)).asString();
323 std::string result = findFileBase(config, fname,
true, externalOptions);
329 std::string fname = config.
check(name,
Value(name)).asString();
330 std::vector<std::string> paths;
331 if (externalOptions !=
nullptr) {
333 findFileBase(config, fname,
true, paths, *externalOptions);
338 if (externalOptions !=
nullptr) {
339 opts = *externalOptions;
344 findFileBase(config, fname,
true, paths, opts);
350 std::string result = findFileBase(config,
"",
true,
nullptr);
351 if (result.empty()) {
359 std::string fname = config.
check(name,
Value(name)).asString();
360 std::string result = findFileBase(config, fname,
false, externalOptions);
366 std::string result = findFileBase(config, fname,
false, externalOptions);
372 std::vector<std::string> output;
374 if (externalOptions ==
nullptr) {
375 externalOptions = &opts;
377 findFileBase(config, name, isDir, output, *externalOptions);
378 return output.empty() ? std::string{} : output.at(0);
392 size_t prelen = output.
size();
393 findFileBaseInner(config, name, isDir,
true, output, opts, doc, {});
394 if (output.size() != prelen) {
399 if (canShowErrors(opts)) {
400 yCDebug(RESOURCEFINDER,
"did not find %s", name.c_str());
405 static void addString(std::vector<std::string>& output,
const std::string& txt)
407 for (
const auto& str : output) {
412 output.push_back(txt);
419 if (!reason.empty()) {
430 if (name.empty() && isDir) {
431 addString(output,
getPwd());
436 std::string str = check(
getPwd(), resourceType,
"", name, isDir, doc,
"pwd");
441 addString(output, str);
449 if (!configFilePath.empty()) {
450 std::string str = check(configFilePath, resourceType,
"", name, isDir, doc,
"defaultConfigFile path");
452 addString(output, str);
469 std::vector<std::string> paths;
474 findFileBaseInner(config, robot,
true, allowPathd, paths, opts2, doc,
"robot");
476 for (
const auto& path : paths) {
477 std::string str = check(path,
485 addString(output, str);
494 for (
size_t i = 0; i < apps.
size(); i++) {
502 std::vector<std::string> paths;
507 findFileBaseInner(config, app,
true, allowPathd, paths, opts2, doc,
"context");
509 for (
const auto& path : paths) {
510 std::string str = check(path,
"",
"", name, isDir, doc,
"context");
512 addString(output, str);
526 std::string str = check(
home,
"",
"", name, isDir, doc,
"YARP_CONFIG_HOME");
528 addString(output, str);
541 std::string str = check(
home,
"",
"", name, isDir, doc,
"YARP_DATA_HOME");
543 addString(output, str);
555 for (
const auto& dir : dirs) {
556 std::string str = check(dir,
564 addString(output, str);
576 for (
const auto& dir : dirs) {
577 std::string str = check(dir,
585 addString(output, str);
595 std::vector<std::string> pathd_paths;
599 findFileBaseInner(config,
"path.d",
true,
false, pathd_paths, opts2, doc,
"path.d");
601 for (
const auto& pathd_path : pathd_paths) {
612 for (
size_t i = 0; i < sections.
size(); i++) {
613 std::string search_name = sections.
get(i).
asString();
615 auto paths_v = bottle_to_vector(group.
findGroup(
"path").
tail());
617 for (
const auto& path : paths_v) {
618 std::string str = check(path,
"",
"", name, isDir, doc,
"yarp.d");
620 addString(output, str);
631 bool exists(
const std::string& fname,
bool isDir)
675 return configFilePath;
680 if (path.length() > 1) {
681 if (path[path.length() - 1] ==
slash[0]) {
682 path = path.substr(0, path.length() -
slash.size());
692 yCWarning(RESOURCEFINDER,
"Could not create %s directory", path.c_str());
700 return configFilePath;
710 if (path.length() > 1) {
711 if (path[path.length() - 1] ==
slash[0]) {
712 path = path.substr(0, path.length() -
slash.size());
722 yCWarning(RESOURCEFINDER,
"Could not create %s directory", path.c_str());
734 m_isConfiguredFlag(false),
745 m_isConfiguredFlag(false),
756 m_nullConfig(data.isNull()),
757 m_isConfiguredFlag(true),
761 this->mPriv = altPriv;
777 *(mPriv) = *(alt.mPriv);
779 m_nullConfig = alt.m_nullConfig;
780 m_isConfiguredFlag = alt.m_isConfiguredFlag;
781 m_configprop = alt.m_configprop;
788 m_isConfiguredFlag =
true;
789 return mPriv->configureProp(m_configprop, argc, argv, skipFirstArgument);
793 bool ResourceFinder::addContext(
const std::string& appName)
795 if (appName[0] ==
'\0') {
798 yCDebug(RESOURCEFINDER,
"adding context [%s]", appName.c_str());
799 return mPriv->addAppName(appName);
802 bool ResourceFinder::clearContext()
804 yCDebug(RESOURCEFINDER,
"clearing context");
805 return mPriv->clearAppNames();
812 return mPriv->setDefault(m_configprop, key, val2);
817 return mPriv->setDefault(m_configprop, key,
Value(val));
822 return mPriv->setDefault(m_configprop, key,
Value(val));
827 return mPriv->setDefault(m_configprop, key, val);
832 yCDebug(RESOURCEFINDER,
"finding file [%s]", name.c_str());
833 return mPriv->findFile(m_configprop, name,
nullptr);
839 yCDebug(RESOURCEFINDER,
"finding file [%s]", name.c_str());
840 return mPriv->findFile(m_configprop, name, &options);
845 yCDebug(RESOURCEFINDER,
"finding file %s", name.c_str());
846 return mPriv->findFileByName(m_configprop, name,
nullptr);
852 yCDebug(RESOURCEFINDER,
"finding file %s", name.c_str());
853 return mPriv->findFileByName(m_configprop, name, &options);
859 yCDebug(RESOURCEFINDER,
"finding path [%s]", name.c_str());
860 return mPriv->findPath(m_configprop, name,
nullptr);
866 yCDebug(RESOURCEFINDER,
"finding path [%s]", name.c_str());
867 return mPriv->findPath(m_configprop, name, &options);
872 yCDebug(RESOURCEFINDER,
"finding paths [%s]", name.c_str());
873 return vector_to_bottle(mPriv->findPaths(m_configprop, name,
nullptr));
879 yCDebug(RESOURCEFINDER,
"finding paths [%s]", name.c_str());
880 return vector_to_bottle(mPriv->findPaths(m_configprop, name, &options));
885 yCDebug(RESOURCEFINDER,
"finding path");
886 return mPriv->findPath(m_configprop);
889 #ifndef YARP_NO_DEPRECATED
905 return m_configprop.
check(key);
911 return m_configprop.
find(key);
923 return m_nullConfig || m_configprop.
isNull();
934 return mPriv->getContext();
939 return mPriv->getHomeContextPath(m_configprop, mPriv->getContext());
944 return mPriv->getHomeRobotPath();
949 return mPriv->getContexts();
965 std::string ResourceFinder::createIfAbsent(
bool mayCreate,
966 const std::string& path)
976 const std::string& key,
979 std::vector<std::string> paths = mPriv->findPaths(config, key, &options,
false);
981 for (
auto it = paths.rbegin(); it != paths.rend(); ++it) {
982 const auto& path = *it;
986 return !paths.empty();
990 #ifndef YARP_NO_DEPRECATED
992 std::string ResourceFinder::getDataHomeWithPossibleCreation(
bool mayCreate)
998 std::string ResourceFinder::getConfigHomeWithPossibleCreation(
bool mayCreate)
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
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 getHomeRobotPath()
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.
size_type size() const
Gets the number of elements in the bottle.
void addFloat64(yarp::conf::float64_t x)
Places a 64-bit floating point number in the bottle, at the end of the list.
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
Bottle tail() const
Get all but the first element of a bottle.
void clear()
Empties the bottle of any objects it contains.
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
std::string toString() const override
Gives a human-readable textual representation of the bottle.
static void autoInitMinimum()
Basic system initialization, not including plugins.
A class for storing options and configuration information.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
std::string toString() const override
Return a standard text representation of the content of the object.
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
bool fromConfigFile(const std::string &fname, bool wipe=true)
Interprets a file as a list of properties.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
void fromCommand(int argc, char *argv[], bool skipFirst=true, bool wipe=true)
Interprets a list of command arguments as a list of properties.
These options are loosely based on http://wiki.icub.org/wiki/YARP_ResourceFinder.
SearchFlavor searchFlavor
DuplicateFilesPolicy duplicateFilesPolicy
MessageFilter messageFilter
SearchLocations searchLocations
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.
virtual ~ResourceFinder()
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.
virtual bool isNull() const
Checks if the object is invalid.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
static double nowSystem()
A single value (typically within a Bottle).
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
virtual std::int32_t asInt32() const
Get 32-bit integer value.
virtual Bottle * asList() const
Get list value.
void fromString(const char *str)
Set value to correspond to a textual representation.
virtual std::string asString() const
Get string value.
#define yCAssert(component, x)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_OS_LOG_COMPONENT(name, name_string)
#define YARP_OS_NON_CONST_LOG_COMPONENT(name, name_string)
std::string yarpdatahome()
Returns the directory where user-specific YARP data files should be written.
std::vector< std::string > yarpconfigdirs()
Returns the directories where YARP configuration files should be searched.
std::string yarpconfighome()
Returns the directory where user-specific YARP configuration files should be written.
std::string home()
Returns the home directory for current user.
std::vector< std::string > yarpdatadirs()
Returns the directories where YARP data files should be searched.
std::string get_string(const std::string &key, bool *found=nullptr)
Read a string from an environment variable.
static constexpr value_type preferred_separator
The components from which ports and connections are built.
An interface to the operating system, including Port based communication.
char * getcwd(char *buf, size_t size)
Portable wrapper for the getcwd() function.
int stat(const char *path)
Portable wrapper for the stat() function.
int mkdir_p(const char *p, int ignoreLevels=0)
Create a directory and all parent directories needed.