Traits.hxx 7.28 KB
Newer Older
1
/*
2
 * Copyright 2003-2018 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * http://www.musicpd.org
 *
 * 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 2 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, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_FS_TRAITS_HXX
#define MPD_FS_TRAITS_HXX

23
#include "util/Compiler.h"
24
#include "util/StringPointer.hxx"
25
#include "util/StringAPI.hxx"
26

27
#ifdef _WIN32
28
#include "util/CharUtil.hxx"
29
#include <tchar.h>
30 31
#endif

Max Kellermann's avatar
Max Kellermann committed
32 33
#include <string>

34 35
#include <assert.h>

36
#ifdef _WIN32
37 38
#define PATH_LITERAL(s) _T(s)
#else
39
#define PATH_LITERAL(s) (s)
40
#endif
41

42
/**
43
 * This class describes the nature of a native filesystem path.
44
 */
45
struct PathTraitsFS {
46
#ifdef _WIN32
47 48
	typedef std::wstring string;
#else
49
	typedef std::string string;
50
#endif
51 52
	typedef string::traits_type char_traits;
	typedef char_traits::char_type value_type;
53
	typedef StringPointer<value_type> Pointer;
54 55
	typedef Pointer::pointer_type pointer_type;
	typedef Pointer::const_pointer_type const_pointer_type;
56

57
#ifdef _WIN32
58
	static constexpr value_type SEPARATOR = '\\';
59
#else
60
	static constexpr value_type SEPARATOR = '/';
61 62
#endif

63
	static constexpr const_pointer_type CURRENT_DIRECTORY = PATH_LITERAL(".");
64

65
	static constexpr bool IsSeparator(value_type ch) noexcept {
66
		return
67
#ifdef _WIN32
68 69
			ch == '/' ||
#endif
70
			ch == SEPARATOR;
71 72
	}

73
	gcc_pure gcc_nonnull_all
74
	static const_pointer_type FindLastSeparator(const_pointer_type p) noexcept {
75 76
#if !CLANG_CHECK_VERSION(3,6)
		/* disabled on clang due to -Wtautological-pointer-compare */
77
		assert(p != nullptr);
78 79
#endif

80
#ifdef _WIN32
81
		const_pointer_type pos = p + GetLength(p);
82 83 84 85
		while (p != pos && !IsSeparator(*pos))
			--pos;
		return IsSeparator(*pos) ? pos : nullptr;
#else
86
		return StringFindLast(p, SEPARATOR);
87 88 89
#endif
	}

90
#ifdef _WIN32
91
	gcc_pure gcc_nonnull_all
92
	static constexpr bool IsDrive(const_pointer_type p) noexcept {
93 94 95 96
		return IsAlphaASCII(p[0]) && p[1] == ':';
	}
#endif

97
	gcc_pure gcc_nonnull_all
98
	static bool IsAbsolute(const_pointer_type p) noexcept {
99 100
#if !CLANG_CHECK_VERSION(3,6)
		/* disabled on clang due to -Wtautological-pointer-compare */
101
		assert(p != nullptr);
102 103
#endif

104
#ifdef _WIN32
105
		if (IsDrive(p) && IsSeparator(p[2]))
106
			return true;
107
#endif
108
		return IsSeparator(*p);
109
	}
Max Kellermann's avatar
Max Kellermann committed
110

111
	gcc_pure gcc_nonnull_all
112
	static size_t GetLength(const_pointer_type p) noexcept {
113
		return StringLength(p);
Max Kellermann's avatar
Max Kellermann committed
114 115 116
	}

	gcc_pure gcc_nonnull_all
117
	static const_pointer_type Find(const_pointer_type p, value_type ch) noexcept {
118
		return StringFind(p, ch);
Max Kellermann's avatar
Max Kellermann committed
119 120
	}

121 122 123 124 125
	/**
	 * Determine the "base" file name of the given native path.
	 * The return value points inside the given string.
	 */
	gcc_pure gcc_nonnull_all
126
	static const_pointer_type GetBase(const_pointer_type p) noexcept;
127 128 129 130 131 132 133

	/**
	 * Determine the "parent" file name of the given native path.
	 * As a special case, returns the string "." if there is no
	 * separator in the given input string.
	 */
	gcc_pure gcc_nonnull_all
134
	static string GetParent(const_pointer_type p) noexcept;
135

136 137 138 139 140 141 142
	/**
	 * Determine the relative part of the given path to this
	 * object, not including the directory separator.  Returns an
	 * empty string if the given path equals this object or
	 * nullptr on mismatch.
	 */
	gcc_pure gcc_nonnull_all
143
	static const_pointer_type Relative(const_pointer_type base,
144
					   const_pointer_type other) noexcept;
145

146 147 148 149 150 151 152
	/**
	 * Constructs the path from the given components.
	 * If either of the components is empty string,
	 * remaining component is returned unchanged.
	 * If both components are empty strings, empty string is returned.
	 */
	gcc_pure gcc_nonnull_all
153
	static string Build(const_pointer_type a, size_t a_size,
154
			    const_pointer_type b, size_t b_size) noexcept;
155 156

	gcc_pure gcc_nonnull_all
157
	static string Build(const_pointer_type a, const_pointer_type b) noexcept {
158 159
		return Build(a, GetLength(a), b, GetLength(b));
	}
160 161 162 163 164 165 166 167

	/**
	 * Interpret the given path as being relative to the given
	 * base, and return the concatenated path.
	 */
	gcc_pure
	static string Apply(const_pointer_type base,
			    const_pointer_type path) noexcept;
168 169 170 171 172 173
};

/**
 * This class describes the nature of a MPD internal filesystem path.
 */
struct PathTraitsUTF8 {
174
	typedef std::string string;
175 176
	typedef string::traits_type char_traits;
	typedef char_traits::char_type value_type;
177 178
	typedef value_type *pointer_type;
	typedef const value_type *const_pointer_type;
179

180 181
	static constexpr value_type SEPARATOR = '/';

182
	static constexpr const_pointer_type CURRENT_DIRECTORY = ".";
183

184
	static constexpr bool IsSeparator(value_type ch) {
185 186 187
		return ch == SEPARATOR;
	}

188
	gcc_pure gcc_nonnull_all
189
	static const_pointer_type FindLastSeparator(const_pointer_type p) noexcept {
190 191
#if !CLANG_CHECK_VERSION(3,6)
		/* disabled on clang due to -Wtautological-pointer-compare */
192
		assert(p != nullptr);
193 194
#endif

195 196 197
		return strrchr(p, SEPARATOR);
	}

198
#ifdef _WIN32
199
	gcc_pure gcc_nonnull_all
200
	static constexpr bool IsDrive(const_pointer_type p) noexcept {
201 202 203 204
		return IsAlphaASCII(p[0]) && p[1] == ':';
	}
#endif

205
	gcc_pure gcc_nonnull_all
206
	static bool IsAbsolute(const_pointer_type p) noexcept {
207 208
#if !CLANG_CHECK_VERSION(3,6)
		/* disabled on clang due to -Wtautological-pointer-compare */
209
		assert(p != nullptr);
210 211
#endif

212
#ifdef _WIN32
213
		if (IsDrive(p) && IsSeparator(p[2]))
214 215 216 217
			return true;
#endif
		return IsSeparator(*p);
	}
218

219
	gcc_pure gcc_nonnull_all
220
	static size_t GetLength(const_pointer_type p) noexcept {
221
		return StringLength(p);
Max Kellermann's avatar
Max Kellermann committed
222 223 224
	}

	gcc_pure gcc_nonnull_all
225
	static const_pointer_type Find(const_pointer_type p, value_type ch) noexcept {
226
		return StringFind(p, ch);
Max Kellermann's avatar
Max Kellermann committed
227 228
	}

Max Kellermann's avatar
Max Kellermann committed
229 230 231 232 233
	/**
	 * Determine the "base" file name of the given UTF-8 path.
	 * The return value points inside the given string.
	 */
	gcc_pure gcc_nonnull_all
234
	static const_pointer_type GetBase(const_pointer_type p) noexcept;
Max Kellermann's avatar
Max Kellermann committed
235 236 237 238 239 240 241

	/**
	 * Determine the "parent" file name of the given UTF-8 path.
	 * As a special case, returns the string "." if there is no
	 * separator in the given input string.
	 */
	gcc_pure gcc_nonnull_all
242
	static string GetParent(const_pointer_type p) noexcept;
243

244 245 246 247 248 249 250
	/**
	 * Determine the relative part of the given path to this
	 * object, not including the directory separator.  Returns an
	 * empty string if the given path equals this object or
	 * nullptr on mismatch.
	 */
	gcc_pure gcc_nonnull_all
251
	static const_pointer_type Relative(const_pointer_type base,
252
					   const_pointer_type other) noexcept;
253

254 255 256 257 258 259 260
	/**
	 * Constructs the path from the given components.
	 * If either of the components is empty string,
	 * remaining component is returned unchanged.
	 * If both components are empty strings, empty string is returned.
	 */
	gcc_pure gcc_nonnull_all
261
	static string Build(const_pointer_type a, size_t a_size,
262
			    const_pointer_type b, size_t b_size) noexcept;
263 264

	gcc_pure gcc_nonnull_all
265
	static string Build(const_pointer_type a, const_pointer_type b) noexcept {
266 267
		return Build(a, GetLength(a), b, GetLength(b));
	}
268 269 270
};

#endif