[beast: 12/57] SFI: add Bse::Path namespace with the most commonly needed file path utilities
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 12/57] SFI: add Bse::Path namespace with the most commonly needed file path utilities
- Date: Sun, 23 Jul 2017 09:58:48 +0000 (UTC)
commit b516d8a987d7b2d695a3f959caae3f5f115e3fc0
Author: Tim Janik <timj gnu org>
Date: Fri Jul 14 03:06:21 2017 +0200
SFI: add Bse::Path namespace with the most commonly needed file path utilities
Signed-off-by: Tim Janik <timj gnu org>
sfi/path.cc | 691 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sfi/path.hh | 75 +++++++
2 files changed, 766 insertions(+), 0 deletions(-)
---
diff --git a/sfi/path.cc b/sfi/path.cc
new file mode 100644
index 0000000..19608d2
--- /dev/null
+++ b/sfi/path.cc
@@ -0,0 +1,691 @@
+// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
+#include "path.hh"
+#include "platform.hh"
+#include <unistd.h> // getuid
+#include <sys/stat.h> // lstat
+#include <cstring> // strchr
+#include <mutex>
+
+#define IS_DIRCHAR(c) ((c) == BSE_DIRCHAR || (c) == BSE_DIRCHAR2)
+#define IS_SEARCHPATH_SEPARATOR(c) ((c) == BSE_SEARCHPATH_SEPARATOR || (c) == ';') // make ';' work
under Windows and Unix
+
+// == CxxPasswd =
+namespace { // Anon
+struct CxxPasswd {
+ std::string pw_name, pw_passwd, pw_gecos, pw_dir, pw_shell;
+ uid_t pw_uid;
+ gid_t pw_gid;
+ CxxPasswd (std::string username = "");
+};
+} // Anon
+
+namespace Bse {
+
+namespace Path {
+
+/// Retrieve the directory part of the filename @ path.
+String
+dirname (const String &path)
+{
+ char *gdir = g_path_get_dirname (path.c_str());
+ String dname = gdir;
+ g_free (gdir);
+ return dname;
+}
+
+/// Strips all directory components from @a path and returns the resulting file name.
+String
+basename (const String &path)
+{
+ char *gbase = g_path_get_basename (path.c_str());
+ String bname = gbase;
+ g_free (gbase);
+ return bname;
+}
+
+/// Resolve links and directory references in @a path and provide a canonicalized absolute pathname.
+String
+realpath (const String &path)
+{
+ char *const cpath = ::realpath (path.c_str(), NULL);
+ if (cpath)
+ {
+ const String result = cpath;
+ free (cpath);
+ errno = 0;
+ return result;
+ }
+ // error case
+ return path;
+}
+
+/**
+ * @param path a filename path
+ * @param incwd optional current working directory
+ *
+ * Complete @a path to become an absolute file path. If neccessary, @a incwd or
+ * the real current working directory is prepended.
+ */
+String
+abspath (const String &path, const String &incwd)
+{
+ if (isabs (path))
+ return path;
+ if (!incwd.empty())
+ return abspath (join (incwd, path), "");
+ String pcwd = program_cwd();
+ if (!pcwd.empty())
+ return join (pcwd, path);
+ return join (cwd(), path);
+}
+
+/// Return wether @a path is an absolute pathname.
+bool
+isabs (const String &path)
+{
+ return g_path_is_absolute (path.c_str());
+}
+
+/// Return wether @a path is pointing to a directory component.
+bool
+isdirname (const String &path)
+{
+ uint l = path.size();
+ if (path == "." || path == "..")
+ return true;
+ if (l >= 1 && IS_DIRCHAR (path[l-1]))
+ return true;
+ if (l >= 2 && IS_DIRCHAR (path[l-2]) && path[l-1] == '.')
+ return true;
+ if (l >= 3 && IS_DIRCHAR (path[l-3]) && path[l-2] == '.' && path[l-1] == '.')
+ return true;
+ return false;
+}
+
+/// Get a @a user's home directory, uses $HOME if no @a username is given.
+String
+user_home (const String &username)
+{
+ if (username.empty())
+ {
+ // $HOME gets precedence over getpwnam(3), like '~/' vs '~username/' expansion
+ const char *homedir = getenv ("HOME");
+ if (homedir && isabs (homedir))
+ return homedir;
+ }
+ CxxPasswd pwn (username);
+ return pwn.pw_dir;
+}
+
+/// Get the $XDG_DATA_HOME directory, see: https://specifications.freedesktop.org/basedir-spec/latest
+String
+data_home ()
+{
+ const char *var = getenv ("XDG_DATA_HOME");
+ if (var && isabs (var))
+ return var;
+ return expand_tilde ("~/.local/share");
+}
+
+/// Get the $XDG_CONFIG_HOME directory, see: https://specifications.freedesktop.org/basedir-spec/latest
+String
+config_home ()
+{
+ const char *var = getenv ("XDG_CONFIG_HOME");
+ if (var && isabs (var))
+ return var;
+ return expand_tilde ("~/.config");
+}
+
+/// Get the $XDG_CACHE_HOME directory, see: https://specifications.freedesktop.org/basedir-spec/latest
+String
+cache_home ()
+{
+ const char *var = getenv ("XDG_CACHE_HOME");
+ if (var && isabs (var))
+ return var;
+ return expand_tilde ("~/.cache");
+}
+
+/// Get the $XDG_RUNTIME_DIR directory, see: https://specifications.freedesktop.org/basedir-spec/latest
+String
+runtime_dir ()
+{
+ const char *var = getenv ("XDG_RUNTIME_DIR");
+ if (var && isabs (var))
+ return var;
+ return string_format ("/run/user/%u", getuid());
+}
+
+/// Get the $XDG_CONFIG_DIRS directory list, see: https://specifications.freedesktop.org/basedir-spec/latest
+String
+config_dirs ()
+{
+ const char *var = getenv ("XDG_CONFIG_DIRS");
+ if (var && var[0])
+ return var;
+ else
+ return "/etc/xdg";
+}
+
+/// Get the $XDG_DATA_DIRS directory list, see: https://specifications.freedesktop.org/basedir-spec/latest
+String
+data_dirs ()
+{
+ const char *var = getenv ("XDG_DATA_DIRS");
+ if (var && var[0])
+ return var;
+ else
+ return "/usr/local/share:/usr/share";
+}
+
+static String
+access_config_names (const String *newval)
+{
+ static std::mutex mutex;
+ static std::lock_guard<std::mutex> locker (mutex);
+ static String cfg_names;
+ if (newval)
+ cfg_names = *newval;
+ if (cfg_names.empty())
+ {
+ String names = Path::basename (program_alias());
+ if (program_alias() != names)
+ names = searchpath_join (names, program_alias());
+ return names;
+ }
+ else
+ return cfg_names;
+}
+
+/// Get config names as set with config_names(), if unset defaults to program_alias().
+String
+config_names ()
+{
+ return access_config_names (NULL);
+}
+
+/// Set a colon separated list of names for this application to find configuration settings and files.
+void
+config_names (const String &names)
+{
+ access_config_names (&names);
+}
+
+/// Expand a "~/" or "~user/" @a path which refers to user home directories.
+String
+expand_tilde (const String &path)
+{
+ if (path[0] != '~')
+ return path;
+ const size_t dir1 = path.find (BSE_DIRCHAR);
+ const size_t dir2 = BSE_DIRCHAR == BSE_DIRCHAR2 ? String::npos : path.find (BSE_DIRCHAR2);
+ const size_t dir = MIN (dir1, dir2);
+ String username;
+ if (dir != String::npos)
+ username = path.substr (1, dir - 1);
+ else
+ username = path.substr (1);
+ const String userhome = user_home (username);
+ return join (userhome, dir == String::npos ? "" : path.substr (dir));
+}
+
+String
+skip_root (const String &path)
+{
+ const char *frag = g_path_skip_root (path.c_str());
+ return frag;
+}
+
+String
+join (const String &frag0, const String &frag1,
+ const String &frag2, const String &frag3,
+ const String &frag4, const String &frag5,
+ const String &frag6, const String &frag7,
+ const String &frag8, const String &frag9,
+ const String &frag10, const String &frag11,
+ const String &frag12, const String &frag13,
+ const String &frag14, const String &frag15)
+{
+ const char dirsep[2] = { BSE_DIRCHAR, 0 };
+ gchar *cpath = g_build_path (dirsep, frag0.c_str(),
+ frag1.c_str(), frag2.c_str(), frag3.c_str(), frag4.c_str(),
+ frag5.c_str(), frag6.c_str(), frag7.c_str(), frag8.c_str(),
+ frag9.c_str(), frag10.c_str(), frag11.c_str(), frag12.c_str(),
+ frag13.c_str(), frag14.c_str(), frag15.c_str(), NULL);
+ String path (cpath);
+ g_free (cpath);
+ return path;
+}
+
+static int
+errno_check_file (const char *file_name, const char *mode)
+{
+ uint access_mask = 0, nac = 0;
+
+ if (strchr (mode, 'e')) // exists
+ nac++, access_mask |= F_OK;
+ if (strchr (mode, 'r')) // readable
+ nac++, access_mask |= R_OK;
+ if (strchr (mode, 'w')) // writable
+ nac++, access_mask |= W_OK;
+ bool check_exec = strchr (mode, 'x') != NULL;
+ if (check_exec) // executable
+ nac++, access_mask |= X_OK;
+
+ /* on some POSIX systems, X_OK may succeed for root without any
+ * executable bits set, so we also check via stat() below.
+ */
+ if (nac && access (file_name, access_mask) < 0)
+ return -errno;
+
+ const bool check_file = strchr (mode, 'f') != NULL; // open as file
+ const bool check_dir = strchr (mode, 'd') != NULL; // open as directory
+ const bool check_link = strchr (mode, 'l') != NULL; // open as link
+ const bool check_char = strchr (mode, 'c') != NULL; // open as character device
+ const bool check_block = strchr (mode, 'b') != NULL; // open as block device
+ const bool check_pipe = strchr (mode, 'p') != NULL; // open as pipe
+ const bool check_socket = strchr (mode, 's') != NULL; // open as socket
+
+ if (check_exec || check_file || check_dir || check_link || check_char || check_block || check_pipe ||
check_socket)
+ {
+ struct stat st;
+
+ if (check_link)
+ {
+ if (lstat (file_name, &st) < 0)
+ return -errno;
+ }
+ else if (stat (file_name, &st) < 0)
+ return -errno;
+
+ if (0)
+ printerr ("file-check(\"%s\",\"%s\"): %s%s%s%s%s%s%s\n",
+ file_name, mode,
+ S_ISREG (st.st_mode) ? "f" : "",
+ S_ISDIR (st.st_mode) ? "d" : "",
+ S_ISLNK (st.st_mode) ? "l" : "",
+ S_ISCHR (st.st_mode) ? "c" : "",
+ S_ISBLK (st.st_mode) ? "b" : "",
+ S_ISFIFO (st.st_mode) ? "p" : "",
+ S_ISSOCK (st.st_mode) ? "s" : "");
+
+ if (S_ISDIR (st.st_mode) && (check_file || check_link || check_char || check_block || check_pipe))
+ return -EISDIR;
+ if (check_file && !S_ISREG (st.st_mode))
+ return -EINVAL;
+ if (check_dir && !S_ISDIR (st.st_mode))
+ return -ENOTDIR;
+ if (check_link && !S_ISLNK (st.st_mode))
+ return -EINVAL;
+ if (check_char && !S_ISCHR (st.st_mode))
+ return -ENODEV;
+ if (check_block && !S_ISBLK (st.st_mode))
+ return -ENOTBLK;
+ if (check_pipe && !S_ISFIFO (st.st_mode))
+ return -ENXIO;
+ if (check_socket && !S_ISSOCK (st.st_mode))
+ return -ENOTSOCK;
+ if (check_exec && !(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return -EACCES; // for root executable, any +x bit is good enough
+ }
+
+ return 0;
+}
+
+/**
+ * @param file possibly relative filename
+ * @param mode feature string
+ * @return true if @a file adhears to @a mode
+ *
+ * Perform various checks on @a file and return whether all
+ * checks passed. On failure, errno is set appropriately, and
+ * FALSE is returned. Available features to be checked for are:
+ * @li @c e - @a file must exist
+ * @li @c r - @a file must be readable
+ * @li @c w - @a file must be writable
+ * @li @c x - @a file must be executable
+ * @li @c f - @a file must be a regular file
+ * @li @c d - @a file must be a directory
+ * @li @c l - @a file must be a symbolic link
+ * @li @c c - @a file must be a character device
+ * @li @c b - @a file must be a block device
+ * @li @c p - @a file must be a named pipe
+ * @li @c s - @a file must be a socket.
+ */
+bool
+check (const String &file, const String &mode)
+{
+ int err = file.size() && mode.size() ? errno_check_file (file.c_str(), mode.c_str()) : -EFAULT;
+ errno = err < 0 ? -err : 0;
+ return errno == 0;
+}
+
+/**
+ * @param file1 possibly relative filename
+ * @param file2 possibly relative filename
+ * @return TRUE if @a file1 and @a file2 are equal
+ *
+ * Check whether @a file1 and @a file2 are pointing to the same inode
+ * in the same file system on the same device.
+ */
+bool
+equals (const String &file1, const String &file2)
+{
+ if (!file1.size() || !file2.size())
+ return file1.size() == file2.size();
+ struct stat st1 = { 0, }, st2 = { 0, };
+ int err1 = 0, err2 = 0;
+ errno = 0;
+ if (stat (file1.c_str(), &st1) < 0 && stat (file1.c_str(), &st1) < 0)
+ err1 = errno;
+ errno = 0;
+ if (stat (file2.c_str(), &st2) < 0 && stat (file2.c_str(), &st2) < 0)
+ err2 = errno;
+ if (err1 || err2)
+ return err1 == err2;
+ return (st1.st_dev == st2.st_dev &&
+ st1.st_ino == st2.st_ino &&
+ st1.st_rdev == st2.st_rdev);
+}
+
+/// Return the current working directoy, including symlinks used in $PWD if available.
+String
+cwd ()
+{
+#ifdef _GNU_SOURCE
+ {
+ char *dir = get_current_dir_name();
+ if (dir)
+ {
+ const String result = dir;
+ free (dir);
+ return result;
+ }
+ }
+#endif
+ size_t size = 512;
+ do
+ {
+ char *buf = (char*) malloc (size);
+ if (!buf)
+ break;
+ const char *const dir = getcwd (buf, size);
+ if (dir)
+ {
+ const String result = dir;
+ free (buf);
+ return result;
+ }
+ free (buf);
+ size *= 2;
+ }
+ while (errno == ERANGE);
+ // system must be in a bad shape if we get here...
+ return "./";
+}
+
+StringVector
+searchpath_split (const String &searchpath)
+{
+ StringVector sv;
+ uint i, l = 0;
+ for (i = 0; i < searchpath.size(); i++)
+ if (IS_SEARCHPATH_SEPARATOR (searchpath[i]))
+ {
+ if (i > l)
+ sv.push_back (searchpath.substr (l, i - l));
+ l = i + 1;
+ }
+ if (i > l)
+ sv.push_back (searchpath.substr (l, i - l));
+ return sv;
+}
+
+/// Check if @a searchpath contains @a element, a trailing slash searches for directories.
+bool
+searchpath_contains (const String &searchpath, const String &element)
+{
+ const bool dirsearch = element.size() > 0 && IS_DIRCHAR (element[element.size() - 1]);
+ const String needle = dirsearch && element.size() > 1 ? element.substr (0, element.size() - 1) : element;
// strip trailing slash
+ size_t pos = searchpath.find (needle);
+ while (pos != String::npos)
+ {
+ size_t end = pos + needle.size();
+ if (pos == 0 || IS_SEARCHPATH_SEPARATOR (searchpath[pos - 1]))
+ {
+ if (dirsearch && IS_DIRCHAR (searchpath[end]))
+ end++; // skip trailing slash in searchpath segment
+ if (searchpath[end] == 0 || IS_SEARCHPATH_SEPARATOR (searchpath[end]))
+ return true;
+ }
+ pos = searchpath.find (needle, end);
+ }
+ return false;
+}
+
+/// Find the first @a file in @a searchpath which matches @a mode (see check()).
+String
+searchpath_find (const String &searchpath, const String &file, const String &mode)
+{
+ if (isabs (file))
+ return check (file, mode) ? file : "";
+ StringVector sv = searchpath_split (searchpath);
+ for (size_t i = 0; i < sv.size(); i++)
+ if (check (join (sv[i], file), mode))
+ return join (sv[i], file);
+ return "";
+}
+
+/// Find all @a searchpath entries matching @a mode (see check()).
+StringVector
+searchpath_list (const String &searchpath, const String &mode)
+{
+ StringVector v;
+ for (const auto &file : searchpath_split (searchpath))
+ if (check (file, mode))
+ v.push_back (file);
+ return v;
+}
+
+static String
+searchpath_join1 (const String &a, const String &b)
+{
+ if (a.empty())
+ return b;
+ if (b.empty())
+ return a;
+ if (IS_SEARCHPATH_SEPARATOR (a[a.size()-1]) || IS_SEARCHPATH_SEPARATOR (b[0]))
+ return a + b;
+ const char searchsep[2] = { BSE_SEARCHPATH_SEPARATOR, 0 };
+ return a + String (searchsep) + b;
+}
+
+/// Yield a new searchpath by combining each element of @a searchpath with each element of @a postfixes.
+String
+searchpath_multiply (const String &searchpath, const String &postfixes)
+{
+ String newpath;
+ for (const auto &e : searchpath_split (searchpath))
+ for (const auto &p : searchpath_split (postfixes))
+ newpath = searchpath_join1 (newpath, join (e, p));
+ return newpath;
+}
+
+String
+searchpath_join (const String &frag0, const String &frag1, const String &frag2, const String &frag3,
+ const String &frag4, const String &frag5, const String &frag6, const String &frag7,
+ const String &frag8, const String &frag9, const String &frag10, const String &frag11,
+ const String &frag12, const String &frag13, const String &frag14, const String &frag15)
+{
+ String result = searchpath_join1 (frag0, frag1);
+ result = searchpath_join1 (result, frag2);
+ result = searchpath_join1 (result, frag3);
+ result = searchpath_join1 (result, frag4);
+ result = searchpath_join1 (result, frag5);
+ result = searchpath_join1 (result, frag6);
+ result = searchpath_join1 (result, frag7);
+ result = searchpath_join1 (result, frag8);
+ result = searchpath_join1 (result, frag9);
+ result = searchpath_join1 (result, frag10);
+ result = searchpath_join1 (result, frag11);
+ result = searchpath_join1 (result, frag12);
+ result = searchpath_join1 (result, frag13);
+ result = searchpath_join1 (result, frag14);
+ result = searchpath_join1 (result, frag15);
+ return result;
+}
+
+String
+vpath_find (const String &file, const String &mode)
+{
+ String result = searchpath_find (".", file, mode);
+ if (!result.empty())
+ return result;
+ const char *vpath = getenv ("VPATH");
+ if (vpath)
+ {
+ result = searchpath_find (vpath, file, mode);
+ if (!result.empty())
+ return result;
+ }
+ return file;
+}
+
+static char* // return malloc()-ed buffer containing a full read of FILE
+file_memread (FILE *stream,
+ size_t *lengthp)
+{
+ size_t sz = 256;
+ char *malloc_string = (char*) malloc (sz);
+ if (!malloc_string)
+ return NULL;
+ char *start = malloc_string;
+ errno = 0;
+ while (!feof (stream))
+ {
+ size_t bytes = fread (start, 1, sz - (start - malloc_string), stream);
+ if (bytes <= 0 && ferror (stream) && errno != EAGAIN)
+ {
+ start = malloc_string; // error/0-data
+ break;
+ }
+ start += bytes;
+ if (start == malloc_string + sz)
+ {
+ bytes = start - malloc_string;
+ sz *= 2;
+ char *newstring = (char*) realloc (malloc_string, sz);
+ if (!newstring)
+ {
+ start = malloc_string; // error/0-data
+ break;
+ }
+ malloc_string = newstring;
+ start = malloc_string + bytes;
+ }
+ }
+ int savederr = errno;
+ *lengthp = start - malloc_string;
+ if (!*lengthp)
+ {
+ free (malloc_string);
+ malloc_string = NULL;
+ }
+ errno = savederr;
+ return malloc_string;
+}
+
+char*
+memread (const String &filename,
+ size_t *lengthp)
+{
+ FILE *file = fopen (filename.c_str(), "r");
+ if (!file)
+ {
+ *lengthp = 0;
+ return strdup ("");
+ }
+ char *contents = file_memread (file, lengthp);
+ int savederr = errno;
+ fclose (file);
+ errno = savederr;
+ return contents;
+}
+
+void
+memfree (char *memread_mem)
+{
+ if (memread_mem)
+ free (memread_mem);
+}
+
+bool
+memwrite (const String &filename, size_t len, const uint8 *bytes)
+{
+ FILE *file = fopen (filename.c_str(), "w");
+ if (!file)
+ return false;
+ const size_t nbytes = fwrite (bytes, 1, len, file);
+ bool success = ferror (file) == 0 && nbytes == len;
+ success = fclose (file) == 0 && success;
+ if (!success)
+ unlink (filename.c_str());
+ return success;
+}
+
+} // Path
+} // Bse
+
+#include <pwd.h> // getpwuid
+
+// == CxxPasswd =
+namespace { // Anon
+CxxPasswd::CxxPasswd (std::string username) :
+ pw_uid (-1), pw_gid (-1)
+{
+ const int strbuf_size = 5 * 1024;
+ char strbuf[strbuf_size + 256]; // work around Darwin getpwnam_r overwriting buffer boundaries
+ struct passwd pwnambuf, *p = NULL;
+ if (username.empty())
+ {
+ int ret = 0;
+ errno = 0;
+ do
+ {
+ if (1) // HAVE_GETPWUID_R
+ ret = getpwuid_r (getuid(), &pwnambuf, strbuf, strbuf_size, &p);
+ else // HAVE_GETPWUID
+ p = getpwuid (getuid());
+ }
+ while ((ret != 0 || p == NULL) && errno == EINTR);
+ if (ret != 0)
+ p = NULL;
+ }
+ else // !username.empty()
+ {
+ int ret = 0;
+ errno = 0;
+ do
+ {
+ if (1) // HAVE_GETPWNAM_R
+ ret = getpwnam_r (username.c_str(), &pwnambuf, strbuf, strbuf_size, &p);
+ else // HAVE_GETPWNAM
+ p = getpwnam (username.c_str());
+ }
+ while ((ret != 0 || p == NULL) && errno == EINTR);
+ if (ret != 0)
+ p = NULL;
+ }
+ if (p)
+ {
+ pw_name = p->pw_name;
+ pw_passwd = p->pw_passwd;
+ pw_uid = p->pw_uid;
+ pw_gid = p->pw_gid;
+ pw_gecos = p->pw_gecos;
+ pw_dir = p->pw_dir;
+ pw_shell = p->pw_shell;
+ }
+}
+} // Anon
diff --git a/sfi/path.hh b/sfi/path.hh
new file mode 100644
index 0000000..f4fa24e
--- /dev/null
+++ b/sfi/path.hh
@@ -0,0 +1,75 @@
+// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
+#ifndef __BSE_PATH_HH__
+#define __BSE_PATH_HH__
+
+#include <sfi/bcore.hh>
+
+#ifdef _WIN32 // includes _WIN64
+#undef BSE_UNIX_PATHS ///< Undefined on _WIN32 and _WIN64, defined on Unix.
+#define BSE_DOS_PATHS 1 ///< Undefined on Unix-like systems, defined on _WIN32 and
_WIN64.
+#define BSE_DIRCHAR '\\'
+#define BSE_DIRCHAR2 '/'
+#define BSE_DIRSEPARATORS "/\\"
+#define BSE_SEARCHPATH_SEPARATOR ';'
+#define BSE_LIBEXT ".dll"
+#else // !_WIN32
+#define BSE_UNIX_PATHS 1 ///< Macro defined if Unix path syntax is used.
+#undef BSE_DOS_PATHS ///< Undefined on Unix-like systems, defined on _WIN32 and
_WIN64.
+#define BSE_DIRCHAR '/' ///< Platform directory separator character, '/' on
Unix-like systems, a '\\' on _WIN32.
+#define BSE_DIRCHAR2 '/' ///< Secondary directory separator character, '/' on
Unix-like systems.
+#define BSE_DIRSEPARATORS "/" ///< List of platform directory separator characters, "/" on
Unix-like systems, "/\\" on _WIN32.
+#define BSE_SEARCHPATH_SEPARATOR ':' ///< Platform searchpath separator, ':' on Unix-like
systems, ';' on _WIN32.
+#define BSE_LIBEXT ".so" ///< Dynamic library filename extension on this platform.
+#endif // !_WIN32
+
+namespace Bse {
+
+/// The Path namespace provides functions for file path manipulation and testing.
+namespace Path {
+
+String dirname (const String &path);
+String basename (const String &path);
+String realpath (const String &path);
+String abspath (const String &path, const String &incwd = "");
+bool isabs (const String &path);
+bool isdirname (const String &path);
+String expand_tilde (const String &path);
+String user_home (const String &username = "");
+String data_home ();
+String config_home ();
+String config_names ();
+void config_names (const String &names);
+String cache_home ();
+String runtime_dir ();
+String config_dirs ();
+String data_dirs ();
+String skip_root (const String &path);
+String join (const String &frag0, const String &frag1, const String &frag2 = "", const
String &frag3 = "",
+ const String &frag4 = "", const String &frag5 = "", const String &frag6 =
"", const String &frag7 = "",
+ const String &frag8 = "", const String &frag9 = "", const String &frag10 =
"", const String &frag11 = "",
+ const String &frag12 = "", const String &frag13 = "", const String &frag14
= "", const String &frag15 = "");
+bool check (const String &file,
+ const String &mode);
+bool equals (const String &file1,
+ const String &file2);
+char* memread (const String &filename,
+ size_t *lengthp);
+void memfree (char *memread_mem);
+bool memwrite (const String &filename, size_t len, const uint8 *bytes);
+String cwd ();
+String vpath_find (const String &file, const String &mode = "e");
+bool searchpath_contains (const String &searchpath, const String &element);
+String searchpath_find (const String &searchpath, const String &file, const String &mode = "e");
+StringVector searchpath_list (const String &searchpath, const String &mode = "e");
+String searchpath_multiply (const String &searchpath, const String &postfixes);
+StringVector searchpath_split (const String &searchpath);
+String searchpath_join (const String &frag0, const String &frag1, const String &frag2 = "", const
String &frag3 = "",
+ const String &frag4 = "", const String &frag5 = "", const String &frag6 =
"", const String &frag7 = "",
+ const String &frag8 = "", const String &frag9 = "", const String &frag10 =
"",
+ const String &frag11 = "", const String &frag12 = "", const String &frag13
= "",
+ const String &frag14 = "", const String &frag15 = "");
+
+} // Path
+} // Bse
+
+#endif // __BSE_PATH_HH__
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]