From 47d655ea7f0ed9c26ceba4767ef6aa82e434d129 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 14 Oct 2013 22:26:23 +0200 Subject: [PATCH] fs/Path: add separator constants/functions --- src/Mapper.cxx | 21 ++++----------------- src/UpdateWalk.cxx | 4 ++-- src/fs/Path.cxx | 21 +++++++++++++++++++-- src/fs/Path.hxx | 29 +++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/Mapper.cxx b/src/Mapper.cxx index 2ccc36961..0b808a7ea 100644 --- a/src/Mapper.cxx +++ b/src/Mapper.cxx @@ -61,20 +61,6 @@ static size_t music_dir_fs_length; */ static Path playlist_dir_fs = Path::Null(); -/** - * Duplicate a string, chop all trailing slashes. - */ -static char * -strdup_chop_slash(const char *path_fs) -{ - size_t length = strlen(path_fs); - - while (length > 0 && path_fs[length - 1] == G_DIR_SEPARATOR) - --length; - - return g_strndup(path_fs, length); -} - static void check_directory(const char *path_utf8, const Path &path_fs) { @@ -112,10 +98,11 @@ mapper_set_music_dir(Path &&path) assert(!path.IsNull()); music_dir_fs = std::move(path); + music_dir_fs.ChopSeparators(); music_dir_fs_length = music_dir_fs.length(); const auto utf8 = music_dir_fs.ToUTF8(); - music_dir_utf8 = strdup_chop_slash(utf8.c_str()); + music_dir_utf8 = g_strdup(utf8.c_str()); music_dir_utf8_length = strlen(music_dir_utf8); check_directory(music_dir_utf8, music_dir_fs); @@ -165,7 +152,7 @@ map_to_relative_path(const char *path_utf8) return music_dir_utf8 != NULL && memcmp(path_utf8, music_dir_utf8, music_dir_utf8_length) == 0 && - G_IS_DIR_SEPARATOR(path_utf8[music_dir_utf8_length]) + Path::IsSeparatorUTF8(path_utf8[music_dir_utf8_length]) ? path_utf8 + music_dir_utf8_length + 1 : path_utf8; } @@ -251,7 +238,7 @@ map_song_fs(const Song *song) std::string map_fs_to_utf8(const char *path_fs) { - if (G_IS_DIR_SEPARATOR(path_fs[0])) { + if (Path::IsSeparatorFS(path_fs[0])) { path_fs = music_dir_fs.RelativeFS(path_fs); if (path_fs == nullptr || *path_fs == 0) return std::string(); diff --git a/src/UpdateWalk.cxx b/src/UpdateWalk.cxx index cfa68dcf4..d7dfd3015 100644 --- a/src/UpdateWalk.cxx +++ b/src/UpdateWalk.cxx @@ -306,7 +306,7 @@ skip_symlink(const Directory *directory, const char *utf8_name) const char *p = target_str; while (*p == '.') { - if (p[1] == '.' && G_IS_DIR_SEPARATOR(p[2])) { + if (p[1] == '.' && Path::IsSeparatorFS(p[2])) { /* "../" moves to parent directory */ directory = directory->parent; if (directory == NULL) { @@ -316,7 +316,7 @@ skip_symlink(const Directory *directory, const char *utf8_name) return !follow_outside_symlinks; } p += 3; - } else if (G_IS_DIR_SEPARATOR(p[1])) + } else if (Path::IsSeparatorFS(p[1])) /* eliminate "./" */ p += 2; else diff --git a/src/fs/Path.cxx b/src/fs/Path.cxx index 1a1f133d0..8f31f45f7 100644 --- a/src/fs/Path.cxx +++ b/src/fs/Path.cxx @@ -194,15 +194,32 @@ Path::RelativeFS(const char *other_fs) const other_fs += l; if (*other_fs != 0) { - if (!G_IS_DIR_SEPARATOR(*other_fs)) + if (!IsSeparatorFS(*other_fs)) /* mismatch */ return nullptr; /* skip remaining path separators */ do { ++other_fs; - } while (G_IS_DIR_SEPARATOR(*other_fs)); + } while (IsSeparatorFS(*other_fs)); } return other_fs; } + +void +Path::ChopSeparators() +{ + size_t l = length(); + const char *p = data(); + + while (l >= 2 && IsSeparatorFS(p[l - 1])) { + --l; + +#if GCC_CHECK_VERSION(4,7) && !defined(__clang__) + value.pop_back(); +#else + value.erase(value.end() - 1, value.end()); +#endif + } +} diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx index 52a62ae76..bd3f3a94e 100644 --- a/src/fs/Path.hxx +++ b/src/fs/Path.hxx @@ -57,6 +57,14 @@ public: typedef string::pointer pointer; typedef string::const_pointer const_pointer; +#ifdef WIN32 + static constexpr value_type SEPARATOR_FS = '\\'; + static constexpr char SEPARATOR_UTF8 = '/'; +#else + static constexpr value_type SEPARATOR_FS = '/'; + static constexpr char SEPARATOR_UTF8 = '/'; +#endif + private: string value; @@ -232,6 +240,27 @@ public: */ gcc_pure const char *RelativeFS(const char *other_fs) const; + + /** + * Chop trailing directory separators. + */ + void ChopSeparators(); + + static constexpr bool IsSeparatorFS(value_type ch) { + return +#ifdef WIN32 + ch == '/' || +#endif + ch == SEPARATOR_FS; + } + + static constexpr bool IsSeparatorUTF8(char ch) { + return +#ifdef WIN32 + ch == '/' || +#endif + ch == SEPARATOR_UTF8; + } }; #endif