diff options
author | Max Kellermann <max@duempel.org> | 2013-01-17 00:56:57 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-01-17 00:56:57 +0100 |
commit | 2cca3ed6ad118b58365ec2a87e71536f03055cf8 (patch) | |
tree | a511887a2b7a38a98969e04f6501dcbb711f1236 /src/Path.hxx | |
parent | 21fe376d1d9ffa6064cf89faab7860d443d9f7fd (diff) | |
download | mpd-path.tar.gz mpd-path.tar.xz mpd-path.zip |
Path: new class "Path" wraps filesystem path stringspath
Diffstat (limited to '')
-rw-r--r-- | src/Path.hxx | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/Path.hxx b/src/Path.hxx index db3f95961..ad40fa551 100644 --- a/src/Path.hxx +++ b/src/Path.hxx @@ -21,7 +21,14 @@ #define MPD_PATH_HXX #include "check.h" +#include "gcc.h" +#include <glib.h> + +#include <algorithm> + +#include <assert.h> +#include <string.h> #include <limits.h> #if !defined(MPD_PATH_MAX) @@ -54,4 +61,122 @@ utf8_to_fs_charset(const char *path_utf8); const char *path_get_fs_charset(); +/** + * A path name in the native file system character set. + */ +class Path { + char *value; + + struct Donate {}; + + Path(Donate, char *_value):value(_value) {} + +public: + Path(Path &&other):value(other.value) { + other.value = nullptr; + } + + Path(const Path &other) = delete; + +#if 0 + /* this is the correct implementation, but unfortunately it + disables compiler optimizations */ + Path(const Path &other) + :value(g_strdup(other.value)) {} +#endif + + + ~Path() { + /* free() can be optimized by gcc, while g_free() can + not: when the compiler knows that the value is + nullptr, it will not emit a free() call in the + inlined destructor; however on Windows, we need to + call g_free(), because the value has been allocated + by GLib, and on Windows, this matters */ +#ifdef WIN32 + g_free(value); +#else + free(value); +#endif + } + + gcc_const + static Path Null() { + return Path(Donate(), nullptr); + } + + gcc_pure + static Path Build(const char *a, const char *b) { + return Path(Donate(), g_build_filename(a, b, nullptr)); + } + + static Path Build(const char *a, const Path &b) { + return Build(a, b.c_str()); + } + + static Path Build(const Path &a, const Path &b) { + return Build(a.c_str(), b.c_str()); + } + + gcc_pure + static Path FromFS(const char *fs) { + return Path(Donate(), g_strdup(fs)); + } + + gcc_pure + static Path FromUTF8(const char *utf8) { + return Path(Donate(), utf8_to_fs_charset(utf8)); + } + + Path &operator=(const Path &other) { + value = g_strdup(other.value); + return *this; + } + + Path &operator=(Path &&other) { + std::swap(value, other.value); + return *this; + } + + char *Steal() { + char *result = value; + value = nullptr; + return result; + } + + bool IsNull() const { + return value == nullptr; + } + + void SetNull() { + g_free(value); + value = nullptr; + } + + gcc_pure + size_t length() const { + assert(value != nullptr); + + return strlen(value); + } + + gcc_pure + const char *c_str() const { + assert(value != nullptr); + + return value; + } + + /** + * Convert the path to UTF-8. The caller is responsible for + * freeing the return value with g_free(). Returns nullptr on + * error. + */ + char *ToUTF8() const { + return value != nullptr + ? fs_charset_to_utf8(value) + : nullptr; + } +}; + #endif |