summaryrefslogtreecommitdiffstats
path: root/ingen
diff options
context:
space:
mode:
Diffstat (limited to 'ingen')
-rw-r--r--ingen/Configuration.hpp15
-rw-r--r--ingen/FilePath.hpp126
-rw-r--r--ingen/Node.hpp3
-rw-r--r--ingen/Parser.hpp11
-rw-r--r--ingen/URI.hpp6
-rw-r--r--ingen/filesystem.hpp84
-rw-r--r--ingen/runtime_paths.hpp13
7 files changed, 242 insertions, 16 deletions
diff --git a/ingen/Configuration.hpp b/ingen/Configuration.hpp
index ae5e4909..67104422 100644
--- a/ingen/Configuration.hpp
+++ b/ingen/Configuration.hpp
@@ -30,6 +30,7 @@
namespace Ingen {
+class FilePath;
class Forge;
class URIMap;
@@ -81,7 +82,7 @@ public:
void parse(int argc, char** argv) throw (OptionError);
/** Load a specific file. */
- bool load(const std::string& path);
+ bool load(const FilePath& path);
/** Save configuration to a file.
*
@@ -98,10 +99,10 @@ public:
*
* @return The absolute path of the saved configuration file.
*/
- std::string save(URIMap& uri_map,
- const std::string& app,
- const std::string& filename,
- unsigned scopes) throw (FileError);
+ FilePath save(URIMap& uri_map,
+ const std::string& app,
+ const FilePath& filename,
+ unsigned scopes) throw (FileError);
/** Load files from the standard configuration directories for the app.
*
@@ -109,8 +110,8 @@ public:
* will be loaded before the user's, e.g. ~/.config/appname/filename,
* so the user options will override the system options.
*/
- std::list<std::string> load_default(const std::string& app,
- const std::string& filename);
+ std::list<FilePath> load_default(const std::string& app,
+ const FilePath& filename);
const Atom& option(const std::string& long_name) const;
bool set(const std::string& long_name, const Atom& value);
diff --git a/ingen/FilePath.hpp b/ingen/FilePath.hpp
new file mode 100644
index 00000000..7ad341e0
--- /dev/null
+++ b/ingen/FilePath.hpp
@@ -0,0 +1,126 @@
+/*
+ This file is part of Ingen.
+ Copyright 2018 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen 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 Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INGEN_FILE_PATH_HPP
+#define INGEN_FILE_PATH_HPP
+
+#include <iosfwd>
+#include <type_traits>
+#include <utility>
+
+#include <boost/utility/string_view.hpp>
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define USE_WINDOWS_FILE_PATHS 1
+#endif
+
+namespace Ingen {
+
+/** A path to a file.
+ *
+ * This is a minimal subset of the std::filesystem::path interface in C++17.
+ * Support for Windows paths is only partial and there is no support for
+ * character encoding conversion at all.
+ */
+class FilePath
+{
+public:
+#ifdef USE_WINDOWS_FILE_PATHS
+ typedef wchar_t value_type;
+ static constexpr value_type preferred_separator = L'\\';
+#else
+ typedef char value_type;
+ static constexpr value_type preferred_separator = '/';
+#endif
+
+ typedef std::basic_string<value_type> string_type;
+
+ FilePath() noexcept = default;
+ FilePath(const FilePath&) = default;
+
+ FilePath(FilePath&& path) noexcept
+ : _str(std::move(path._str))
+ {
+ path.clear();
+ }
+
+ FilePath(string_type&& str) : _str(std::move(str)) {}
+ FilePath(const string_type& str) : _str(str) {}
+ FilePath(const value_type* str) : _str(str) {}
+ FilePath(const boost::basic_string_view<value_type>& sv) : _str(sv) {}
+
+ ~FilePath() = default;
+
+ FilePath& operator=(const FilePath& path) = default;
+ FilePath& operator=(FilePath&& path) noexcept;
+ FilePath& operator=(string_type&& str);
+
+ FilePath& operator/=(const FilePath& path);
+
+ FilePath& operator+=(const FilePath& path);
+ FilePath& operator+=(const string_type& str);
+ FilePath& operator+=(const value_type* str);
+ FilePath& operator+=(value_type chr);
+ FilePath& operator+=(boost::basic_string_view<value_type> sv);
+
+ void clear() noexcept { _str.clear(); }
+
+ const string_type& native() const noexcept { return _str; }
+ const string_type& string() const noexcept { return _str; }
+ const value_type* c_str() const noexcept { return _str.c_str(); }
+
+ operator string_type() const { return _str; }
+
+ FilePath root_name() const;
+ FilePath root_directory() const;
+ FilePath root_path() const;
+ FilePath relative_path() const;
+ FilePath parent_path() const;
+ FilePath filename() const;
+ FilePath stem() const;
+ FilePath extension() const;
+
+ bool empty() const noexcept { return _str.empty(); }
+
+ bool is_absolute() const;
+ bool is_relative() const { return !is_absolute(); }
+
+private:
+ std::size_t find_first_sep() const;
+ std::size_t find_last_sep() const;
+
+ string_type _str;
+};
+
+bool operator==(const FilePath& lhs, const FilePath& rhs) noexcept;
+bool operator!=(const FilePath& lhs, const FilePath& rhs) noexcept;
+bool operator<(const FilePath& lhs, const FilePath& rhs) noexcept;
+bool operator<=(const FilePath& lhs, const FilePath& rhs) noexcept;
+bool operator>(const FilePath& lhs, const FilePath& rhs) noexcept;
+bool operator>=(const FilePath& lhs, const FilePath& rhs) noexcept;
+
+FilePath operator/(const FilePath& lhs, const FilePath& rhs);
+
+template <typename Char, typename Traits>
+std::basic_ostream<Char, Traits>&
+operator<<(std::basic_ostream<Char, Traits>& os, const FilePath& path)
+{
+ return os << path.string();
+}
+
+} // namespace Ingen
+
+#endif // INGEN_FILE_PATH_HPP
diff --git a/ingen/Node.hpp b/ingen/Node.hpp
index e023e9e2..ca78aa3d 100644
--- a/ingen/Node.hpp
+++ b/ingen/Node.hpp
@@ -36,6 +36,7 @@ class Symbol;
namespace Ingen {
class Arc;
+class FilePath;
class Store;
class URIs;
@@ -74,7 +75,7 @@ public:
// Plugin blocks only
virtual LilvInstance* instance() { return nullptr; }
- virtual bool save_state(const std::string& dir) const { return false; }
+ virtual bool save_state(const FilePath& dir) const { return false; }
// All objects
virtual GraphType graph_type() const = 0;
diff --git a/ingen/Parser.hpp b/ingen/Parser.hpp
index ac9d8320..96e21c51 100644
--- a/ingen/Parser.hpp
+++ b/ingen/Parser.hpp
@@ -23,6 +23,7 @@
#include <boost/optional/optional.hpp>
+#include "ingen/FilePath.hpp"
#include "ingen/Properties.hpp"
#include "ingen/URI.hpp"
#include "ingen/ingen.h"
@@ -50,7 +51,7 @@ public:
/** Record of a resource listed in a bundle manifest. */
struct ResourceRecord {
- inline ResourceRecord(URI u, std::string f)
+ inline ResourceRecord(URI u, FilePath f)
: uri(std::move(u)), filename(std::move(f))
{}
@@ -58,8 +59,8 @@ public:
return uri < r.uri;
}
- URI uri; ///< URI of resource (e.g. a Graph)
- std::string filename; ///< Path of describing file (seeAlso)
+ URI uri; ///< URI of resource (e.g. a Graph)
+ FilePath filename; ///< Path of describing file (seeAlso)
};
/** Find all resources of a given type listed in a manifest file. */
@@ -79,7 +80,7 @@ public:
virtual bool parse_file(
World* world,
Interface* target,
- const std::string& path,
+ const FilePath& path,
boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(),
boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(),
boost::optional<Properties> data = boost::optional<Properties>());
@@ -88,7 +89,7 @@ public:
World* world,
Interface* target,
const std::string& str,
- const std::string& base_uri,
+ const URI& base_uri,
boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(),
boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(),
boost::optional<Properties> data = boost::optional<Properties>());
diff --git a/ingen/URI.hpp b/ingen/URI.hpp
index 6b2adff4..30aeb7cc 100644
--- a/ingen/URI.hpp
+++ b/ingen/URI.hpp
@@ -22,6 +22,7 @@
#include <boost/utility/string_view.hpp>
+#include "ingen/FilePath.hpp"
#include "ingen/ingen.h"
#include "serd/serd.h"
#include "sord/sordmm.hpp"
@@ -38,6 +39,7 @@ public:
explicit URI(const char* str);
URI(const std::string& str, const URI& base);
explicit URI(const Sord::Node& node);
+ explicit URI(const FilePath& path);
URI(const URI& uri);
URI& operator=(const URI& uri);
@@ -53,6 +55,10 @@ public:
size_t length() const { return _node.n_bytes; }
const char* c_str() const { return (const char*)_node.buf; }
+ FilePath file_path() const {
+ return scheme() == "file" ? FilePath(path()) : FilePath();
+ }
+
operator std::string() const { return string(); }
const char* begin() const { return (const char*)_node.buf; }
diff --git a/ingen/filesystem.hpp b/ingen/filesystem.hpp
new file mode 100644
index 00000000..19fa74b2
--- /dev/null
+++ b/ingen/filesystem.hpp
@@ -0,0 +1,84 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2017 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen 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 Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INGEN_FILESYSTEM_HPP
+#define INGEN_FILESYSTEM_HPP
+
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+
+#include <cerrno>
+#include <climits>
+#include <cstdlib>
+#include <memory>
+#include <vector>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+# include <windows.h>
+# include <io.h>
+# define F_OK 0
+# define mkdir(path, flags) _mkdir(path)
+#endif
+
+#include "ingen/FilePath.hpp"
+
+/* A minimal subset of the std::filesystem API from C++17. */
+
+namespace Ingen {
+namespace filesystem {
+
+inline bool exists(const FilePath& path)
+{
+ return !access(path.c_str(), F_OK);
+}
+
+inline bool is_directory(const FilePath& path)
+{
+ struct stat info;
+ stat(path.c_str(), &info);
+ return S_ISDIR(info.st_mode);
+}
+
+inline bool create_directories(const FilePath& path)
+{
+ std::vector<FilePath> paths;
+ for (FilePath p = path; p != path.root_directory(); p = p.parent_path()) {
+ paths.emplace_back(p);
+ }
+
+ for (auto p = paths.rbegin(); p != paths.rend(); ++p) {
+ if (mkdir(p->c_str(), 0755) && errno != EEXIST) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+inline FilePath current_path()
+{
+ std::unique_ptr<char> cpath(realpath(".", NULL));
+ const FilePath path(cpath.get());
+ return path;
+}
+
+} // namespace filesystem
+} // namespace Ingen
+
+#endif // INGEN_FILESYSTEM_HPP
diff --git a/ingen/runtime_paths.hpp b/ingen/runtime_paths.hpp
index 747bc9b7..1a8bc2c2 100644
--- a/ingen/runtime_paths.hpp
+++ b/ingen/runtime_paths.hpp
@@ -18,17 +18,24 @@
#define INGEN_RUNTIME_PATHS_HPP
#include <string>
+#include <vector>
#include "ingen/ingen.h"
+#include "ingen/FilePath.hpp"
namespace Ingen {
+extern const char search_path_separator;
+
INGEN_API void set_bundle_path(const char* path);
INGEN_API void set_bundle_path_from_code(void* function);
-INGEN_API std::string bundle_file_path(const std::string& name);
-INGEN_API std::string data_file_path(const std::string& name);
-INGEN_API std::string module_path(const std::string& name, std::string dir="");
+INGEN_API FilePath bundle_file_path(const std::string& name);
+INGEN_API FilePath data_file_path(const std::string& name);
+INGEN_API FilePath ingen_module_path(const std::string& name, FilePath dir={});
+
+INGEN_API FilePath user_config_dir();
+INGEN_API std::vector<FilePath> system_config_dirs();
} // namespace Ingen