fs/Path: add separator constants/functions
This commit is contained in:
		| @@ -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(); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann