summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-20 17:46:41 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-20 17:46:41 +0100
commit8755bbe309d2f00c7bc73a6a6304ed8860a9a94d (patch)
treea364d21db838a5a27eb76a1639ddbdb882b4aedd /src/plugins
parentb61de477f91e9f6ec68a7e7b9ab5d4bddc632843 (diff)
Implemented automatic generation of default search paths
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/filesystem/FileLocator.cpp128
-rw-r--r--src/plugins/filesystem/FileLocator.hpp51
-rw-r--r--src/plugins/filesystem/SpecialPaths.cpp67
-rw-r--r--src/plugins/filesystem/SpecialPaths.hpp83
4 files changed, 298 insertions, 31 deletions
diff --git a/src/plugins/filesystem/FileLocator.cpp b/src/plugins/filesystem/FileLocator.cpp
index 9ab398e..7bb3a58 100644
--- a/src/plugins/filesystem/FileLocator.cpp
+++ b/src/plugins/filesystem/FileLocator.cpp
@@ -16,64 +16,140 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "FileLocator.hpp"
+#ifndef NDEBUG
+#include <iostream>
+#endif
+
+#include <algorithm>
+#include <fstream>
#include <boost/filesystem.hpp>
-#include <fstream>
+#include "FileLocator.hpp"
+#include "SpecialPaths.hpp"
+
+namespace fs = boost::filesystem;
namespace ousia {
+void FileLocator::addPath(const std::string &path,
+ std::vector<std::string> &paths)
+{
+ auto it = std::find(paths.begin(), paths.end(), path);
+ if (it == paths.end()) {
+ paths.push_back(path);
+ }
+}
+
void FileLocator::addSearchPath(const std::string &path,
std::set<ResourceType> types)
{
- // Canonicalize the given path
- std::string canonicalPath =
- boost::filesystem::canonical(path).generic_string();
+ if (path.empty() || !fs::exists(path)) {
+ return;
+ }
+
+ // Canonicalize the given path, check whether it exists
+ std::string canonicalPath = fs::canonical(path).generic_string();
+
+#ifndef NDEBUG
+ std::cout << "FileLocator: Adding search path " << canonicalPath
+ << std::endl;
+#endif
// Insert the path for all given types.
for (auto &type : types) {
auto it = searchPaths.find(type);
if (it != searchPaths.end()) {
- it->second.push_back(canonicalPath);
+ addPath(canonicalPath, it->second);
} else {
searchPaths.insert({type, {canonicalPath}});
}
}
}
+void FileLocator::addSearchPath(const std::string &path, ResourceType type)
+{
+ addSearchPath(path, std::set<ResourceType>{type});
+}
+
+void FileLocator::addDefaultSearchPaths(const std::string &relativeTo)
+{
+ // Abort if the base directory is empty
+ if (relativeTo.empty()) {
+ return;
+ }
+
+ // Abort if the base directory does not exist or is not a directory
+ fs::path base(relativeTo);
+ if (!fs::exists(base) || !fs::is_directory(base)) {
+ return;
+ }
+
+ // Add the search paths
+ addSearchPath(base.generic_string(), ResourceType::UNKNOWN);
+ addSearchPath((base / "domain").generic_string(),
+ ResourceType::DOMAIN_DESC);
+ addSearchPath((base / "typesystem").generic_string(),
+ ResourceType::TYPESYSTEM);
+}
+
+void FileLocator::addDefaultSearchPaths()
+{
+ addDefaultSearchPaths(SpecialPaths::getGlobalDataDir());
+ addDefaultSearchPaths(SpecialPaths::getLocalDataDir());
+#ifndef NDEBUG
+ addDefaultSearchPaths(SpecialPaths::getDebugDataDir());
+ addDefaultSearchPaths(SpecialPaths::getDebugTestdataDir());
+#endif
+}
+
bool FileLocator::doLocate(Resource &resource, const std::string &path,
const ResourceType type,
const std::string &relativeTo) const
{
- boost::filesystem::path base(relativeTo);
- if (boost::filesystem::exists(base)) {
- // Look if 'relativeTo' is a directory already.
- if (!boost::filesystem::is_directory(base)) {
- // If not we use the parent directory.
- base = base.parent_path();
- }
+ if (!relativeTo.empty()) {
+ fs::path base(relativeTo);
+ if (fs::exists(base)) {
+ // Look if 'relativeTo' is a directory already.
+ if (!fs::is_directory(base)) {
+ // If not we use the parent directory.
+ base = base.parent_path();
+ }
- // Use the / operator to append the path.
- base /= path;
+ // Use the / operator to append the path.
+ base /= path;
- // If we already found a fitting resource there, use that.
- if (boost::filesystem::exists(base)) {
- std::string location =
- boost::filesystem::canonical(base).generic_string();
- resource = Resource(true, *this, type, location);
- return true;
+ // If we already found a fitting resource there, use that.
+ if (fs::exists(base)) {
+ std::string location = fs::canonical(base).generic_string();
+#ifndef NDEBUG
+ std::cout << "FileLocator: Found \"" << path << "\" at "
+ << location << std::endl;
+#endif
+ resource = Resource(true, *this, type, location);
+ return true;
+ }
}
}
- // Otherwise look in the search paths.
+ // Otherwise look in the search paths, search backwards, last defined search
+ // paths have a higher precedence
auto it = searchPaths.find(type);
if (it != searchPaths.end()) {
- for (boost::filesystem::path p : it->second) {
+ const auto &paths = it->second;
+ for (auto it = paths.rbegin(); it != paths.rend(); it++) {
+#ifndef NDEBUG
+ std::cout << "FileLocator: Searching for \"" << path << "\" in "
+ << *it << std::endl;
+#endif
+ fs::path p{*it};
p /= path;
- if (boost::filesystem::exists(p)) {
- std::string location =
- boost::filesystem::canonical(p).generic_string();
+ if (fs::exists(p)) {
+ std::string location = fs::canonical(p).generic_string();
+#ifndef NDEBUG
+ std::cout << "FileLocator: Found \"" << path << "\" at "
+ << location << std::endl;
+#endif
resource = Resource(true, *this, type, location);
return true;
}
diff --git a/src/plugins/filesystem/FileLocator.hpp b/src/plugins/filesystem/FileLocator.hpp
index ffe5c8f..6d3bbf0 100644
--- a/src/plugins/filesystem/FileLocator.hpp
+++ b/src/plugins/filesystem/FileLocator.hpp
@@ -16,6 +16,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * @file FileLocator.hpp
+ *
+ * Contains the FileLocator class which is used to locate resources and to
+ * canonicalize file system paths.
+ *
+ * @author Benjamin Paaßen (bpassen@techfak.uni-bielefeld.de)
+ */
+
#ifndef _OUSIA_FILE_LOCATOR_HPP_
#define _OUSIA_FILE_LOCATOR_HPP_
@@ -39,7 +48,7 @@ namespace ousia {
class FileLocator : public ResourceLocator {
public:
/**
- * Type alias representing a Res
+ * Type alias representing the internal search path list.
*/
using SearchPaths = std::map<ResourceType, std::vector<std::string>>;
@@ -49,6 +58,25 @@ private:
*/
SearchPaths searchPaths;
+ /**
+ * Internally used to add a search path to the given vector without
+ * duplications.
+ *
+ * @parm path is the path that should be added to the vector (must be
+ * canonicalized).
+ * @parm paths is the list to which the path should be added.
+ */
+ void addPath(const std::string &path, std::vector<std::string> &paths);
+
+ /**
+ * Internally used to add the default search paths for various resource
+ * types relative to a certain parent directory.
+ *
+ * @param relativeTo is the base directory relative to which the search
+ * paths ought to be setup.
+ */
+ void addDefaultSearchPaths(const std::string &relativeTo);
+
protected:
bool doLocate(Resource &resource, const std::string &path,
const ResourceType type,
@@ -74,11 +102,24 @@ public:
* Adds a search path. Implicitly adds the search path for the "unknown"
*
* @param path is a fully qualified/canonical path to a directory.
- * @param types is a set of Resource Types. The FileLocator will look for
- * resources of the specified types at the given path in the
- * future.
+ * @param type is a single type for which the path should be added.
+ */
+ void addSearchPath(const std::string &path,
+ ResourceType type = ResourceType::UNKNOWN);
+
+ /**
+ * Adds platform-specific default search paths. These include
+ * (in order of their precedence):
+ * <ul>
+ * <li>The user application data directory (~/.local/share/ousia/ on
+ * UNIX)</li>
+ * <li>The global application data directory used for make install
+ * (default is /usr/local/share on UNIX)</li>
+ * </ul>
+ * Resource type specific subdirectories (domain, typesytem, etc.)
+ * are automatically added to the aforementioned paths.
*/
- void addSearchPath(const std::string &path);
+ void addDefaultSearchPaths();
/**
* Returns the backing map containing all search paths for a given type.
diff --git a/src/plugins/filesystem/SpecialPaths.cpp b/src/plugins/filesystem/SpecialPaths.cpp
new file mode 100644
index 0000000..97bdb9c
--- /dev/null
+++ b/src/plugins/filesystem/SpecialPaths.cpp
@@ -0,0 +1,67 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <cstdlib>
+#include <boost/filesystem.hpp>
+
+#include <config.h>
+
+#include "SpecialPaths.hpp"
+
+namespace fs = boost::filesystem;
+
+namespace ousia {
+
+std::string SpecialPaths::getHomeDir()
+{
+ char *home = getenv("HOME");
+ if (home) {
+ return std::string{home};
+ }
+ return std::string{};
+}
+
+std::string SpecialPaths::getGlobalDataDir()
+{
+ return OUSIA_INSTALL_DATA_DIR;
+}
+
+std::string SpecialPaths::getLocalDataDir()
+{
+ std::string home = getHomeDir();
+ if (!home.empty()) {
+ fs::path homePath{home};
+ return (homePath / ".local/share/ousia").generic_string();
+ }
+ return std::string{};
+}
+
+std::string SpecialPaths::getDebugDataDir()
+{
+ fs::path debug{OUSIA_DEBUG_DIR};
+ return (debug / "data").generic_string();
+}
+
+std::string SpecialPaths::getDebugTestdataDir()
+{
+ fs::path debug{OUSIA_DEBUG_DIR};
+ return (debug / "testdata").generic_string();
+}
+
+}
+
diff --git a/src/plugins/filesystem/SpecialPaths.hpp b/src/plugins/filesystem/SpecialPaths.hpp
new file mode 100644
index 0000000..84524fe
--- /dev/null
+++ b/src/plugins/filesystem/SpecialPaths.hpp
@@ -0,0 +1,83 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file SpecialPaths.hpp
+ *
+ * Access to platform specific special paths.
+ *
+ * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
+ */
+
+#ifndef _OUSIA_SPECIAL_PATHS_HPP_
+#define _OUSIA_SPECIAL_PATHS_HPP_
+
+#include <string>
+
+namespace ousia {
+
+/**
+ * Class containing static functions providing access to special paths.
+ */
+class SpecialPaths {
+public:
+ /**
+ * Returns the home directory of the current user or an empty string if the
+ * functionality is not available.
+ *
+ * @return path to the home director or empty string on failure.
+ */
+ static std::string getHomeDir();
+
+ /**
+ * Returns the global application data directory (e.g. /usr/share/ousia on
+ * unix).
+ *
+ * @return path to the installation data directory, empty string on failure.
+ */
+ static std::string getGlobalDataDir();
+
+ /**
+ * Returns the local application data directory (e.g.
+ * /home/usre/.local/share/ousia on unix).
+ *
+ * @return path to the local data directory, empty string on failure.
+ */
+ static std::string getLocalDataDir();
+
+ /**
+ * Returns the path to the application data when running a debug build.
+ *
+ * @return path to the application data when running a debug build. Returns
+ * an empty string otherwise.
+ */
+ static std::string getDebugDataDir();
+
+ /**
+ * Returns the path to the test data when running a debug build with enabled
+ * tests.
+ *
+ * @return path to the test data when running a debug build, Returns an
+ * empty string otherwise.
+ */
+ static std::string getDebugTestdataDir();
+};
+}
+
+#endif /* _OUSIA_SPECIAL_PATHS_HPP_ */
+