diff options
Diffstat (limited to 'src/fs')
-rw-r--r-- | src/fs/AllocatedPath.cxx | 25 | ||||
-rw-r--r-- | src/fs/AllocatedPath.hxx | 7 | ||||
-rw-r--r-- | src/fs/Charset.cxx | 95 | ||||
-rw-r--r-- | src/fs/Charset.hxx | 19 | ||||
-rw-r--r-- | src/fs/Config.cxx | 34 | ||||
-rw-r--r-- | src/fs/Config.hxx | 7 | ||||
-rw-r--r-- | src/fs/Path.hxx | 18 | ||||
-rw-r--r-- | src/fs/Path2.cxx | 28 | ||||
-rw-r--r-- | src/fs/io/TextFile.cxx | 6 | ||||
-rw-r--r-- | src/fs/io/TextFile.hxx | 2 |
10 files changed, 127 insertions, 114 deletions
diff --git a/src/fs/AllocatedPath.cxx b/src/fs/AllocatedPath.cxx index ceaad73ea..bd026db74 100644 --- a/src/fs/AllocatedPath.cxx +++ b/src/fs/AllocatedPath.cxx @@ -24,33 +24,14 @@ #include "util/Error.hxx" #include "Compiler.h" -#ifdef HAVE_GLIB -#include <glib.h> -#endif - -#include <string.h> - -#ifdef HAVE_GLIB - -inline AllocatedPath::AllocatedPath(Donate, pointer _value) - :value(_value) { - g_free(_value); -} - -#endif - /* no inlining, please */ AllocatedPath::~AllocatedPath() {} AllocatedPath AllocatedPath::FromUTF8(const char *path_utf8) { -#ifdef HAVE_GLIB - char *path = ::PathFromUTF8(path_utf8); - if (path == nullptr) - return AllocatedPath::Null(); - - return AllocatedPath(Donate(), path); +#ifdef HAVE_FS_CHARSET + return AllocatedPath(::PathFromUTF8(path_utf8)); #else return FromFS(path_utf8); #endif @@ -111,7 +92,7 @@ AllocatedPath::ChopSeparators() while (l >= 2 && PathTraitsFS::IsSeparator(p[l - 1])) { --l; -#if GCC_CHECK_VERSION(4,7) && !defined(__clang__) +#if GCC_CHECK_VERSION(4,7) value.pop_back(); #else value.erase(value.end() - 1, value.end()); diff --git a/src/fs/AllocatedPath.hxx b/src/fs/AllocatedPath.hxx index c345470c8..73b6891ad 100644 --- a/src/fs/AllocatedPath.hxx +++ b/src/fs/AllocatedPath.hxx @@ -44,13 +44,6 @@ class AllocatedPath { string value; - struct Donate {}; - - /** - * Donate the allocated pointer to a new #AllocatedPath object. - */ - AllocatedPath(Donate, pointer _value); - AllocatedPath(const_pointer _value):value(_value) {} AllocatedPath(string &&_value):value(std::move(_value)) {} diff --git a/src/fs/Charset.cxx b/src/fs/Charset.cxx index abf4d8287..453962c1f 100644 --- a/src/fs/Charset.cxx +++ b/src/fs/Charset.cxx @@ -21,66 +21,52 @@ #include "Charset.hxx" #include "Domain.hxx" #include "Limits.hxx" -#include "system/FatalError.hxx" #include "Log.hxx" #include "Traits.hxx" - -#ifdef HAVE_GLIB -#include <glib.h> -#endif +#include "lib/icu/Converter.hxx" +#include "util/Error.hxx" #include <algorithm> #include <assert.h> #include <string.h> -#ifdef HAVE_GLIB - -/** - * Maximal number of bytes required to represent path name in UTF-8 - * (including nul-terminator). - * This value is a rought estimate of upper bound. - * It's based on path name limit in bytes (MPD_PATH_MAX) - * and assumption that some weird encoding could represent some UTF-8 4 byte - * sequences with single byte. - */ -static constexpr size_t MPD_PATH_MAX_UTF8 = (MPD_PATH_MAX - 1) * 4 + 1; +#ifdef HAVE_FS_CHARSET static std::string fs_charset; -gcc_pure -static bool -IsSupportedCharset(const char *charset) -{ - /* convert a space to check if the charset is valid */ - char *test = g_convert(" ", 1, charset, "UTF-8", nullptr, nullptr, nullptr); - if (test == nullptr) - return false; - - g_free(test); - return true; -} +static IcuConverter *fs_converter; -void -SetFSCharset(const char *charset) +bool +SetFSCharset(const char *charset, Error &error) { assert(charset != nullptr); + assert(fs_converter == nullptr); - if (!IsSupportedCharset(charset)) - FormatFatalError("invalid filesystem charset: %s", charset); - - fs_charset = charset; + fs_converter = IcuConverter::Create(charset, error); + if (fs_converter == nullptr) + return false; FormatDebug(path_domain, "SetFSCharset: fs charset is: %s", fs_charset.c_str()); + return true; } #endif +void +DeinitFSCharset() +{ +#ifdef HAVE_ICU_CONVERTER + delete fs_converter; + fs_converter = nullptr; +#endif +} + const char * GetFSCharset() { -#ifdef HAVE_GLIB +#ifdef HAVE_FS_CHARSET return fs_charset.empty() ? "UTF-8" : fs_charset.c_str(); #else return "UTF-8"; @@ -105,53 +91,32 @@ PathToUTF8(const char *path_fs) { assert(path_fs != nullptr); -#ifdef HAVE_GLIB - if (fs_charset.empty()) { +#ifdef HAVE_FS_CHARSET + if (fs_converter == nullptr) { #endif auto result = std::string(path_fs); FixSeparators(result); return result; -#ifdef HAVE_GLIB +#ifdef HAVE_FS_CHARSET } - GIConv conv = g_iconv_open("utf-8", fs_charset.c_str()); - if (conv == reinterpret_cast<GIConv>(-1)) - return std::string(); - - // g_iconv() does not need nul-terminator, - // std::string could be created without it too. - char path_utf8[MPD_PATH_MAX_UTF8 - 1]; - char *in = const_cast<char *>(path_fs); - char *out = path_utf8; - size_t in_left = strlen(path_fs); - size_t out_left = sizeof(path_utf8); - - size_t ret = g_iconv(conv, &in, &in_left, &out, &out_left); - - g_iconv_close(conv); - - if (ret == static_cast<size_t>(-1) || in_left > 0) - return std::string(); - - auto result_path = std::string(path_utf8, sizeof(path_utf8) - out_left); + auto result_path = fs_converter->ToUTF8(path_fs); FixSeparators(result_path); return result_path; #endif } -#ifdef HAVE_GLIB +#ifdef HAVE_FS_CHARSET -char * +std::string PathFromUTF8(const char *path_utf8) { assert(path_utf8 != nullptr); - if (fs_charset.empty()) - return g_strdup(path_utf8); + if (fs_converter == nullptr) + return path_utf8; - return g_convert(path_utf8, -1, - fs_charset.c_str(), "utf-8", - nullptr, nullptr, nullptr); + return fs_converter->FromUTF8(path_utf8); } #endif diff --git a/src/fs/Charset.hxx b/src/fs/Charset.hxx index 0a71d7c58..f1d5f3bbf 100644 --- a/src/fs/Charset.hxx +++ b/src/fs/Charset.hxx @@ -25,6 +25,12 @@ #include <string> +#if defined(HAVE_ICU) || defined(HAVE_GLIB) +#define HAVE_FS_CHARSET +#endif + +class Error; + /** * Gets file system character set name. */ @@ -32,8 +38,11 @@ gcc_const const char * GetFSCharset(); +bool +SetFSCharset(const char *charset, Error &error); + void -SetFSCharset(const char *charset); +DeinitFSCharset(); /** * Convert the path to UTF-8. @@ -43,8 +52,12 @@ gcc_pure gcc_nonnull_all std::string PathToUTF8(const char *path_fs); -gcc_malloc gcc_nonnull_all -char * +/** + * Convert the path from UTF-8. + * Returns empty string on error. + */ +gcc_pure gcc_nonnull_all +std::string PathFromUTF8(const char *path_utf8); #endif diff --git a/src/fs/Config.cxx b/src/fs/Config.cxx index 6aa23005c..7b0da061a 100644 --- a/src/fs/Config.cxx +++ b/src/fs/Config.cxx @@ -29,21 +29,15 @@ #include <glib.h> #endif -void -ConfigureFS() +bool +ConfigureFS(Error &error) { -#if defined(HAVE_GLIB) || defined(WIN32) +#ifdef HAVE_FS_CHARSET const char *charset = nullptr; charset = config_get_string(CONF_FS_CHARSET, nullptr); if (charset == nullptr) { -#ifndef WIN32 - const gchar **encodings; - g_get_filename_charsets(&encodings); - - if (encodings[0] != nullptr && *encodings[0] != '\0') - charset = encodings[0]; -#else +#ifdef WIN32 /* Glib claims that file system encoding is always utf-8 * on native Win32 (i.e. not Cygwin). * However this is true only if <gstdio.h> helpers are used. @@ -52,10 +46,26 @@ ConfigureFS() static char win_charset[13]; sprintf(win_charset, "cp%u", GetACP()); charset = win_charset; +#elif defined(HAVE_GLIB) + const gchar **encodings; + g_get_filename_charsets(&encodings); + + if (encodings[0] != nullptr && *encodings[0] != '\0') + charset = encodings[0]; #endif } - if (charset != nullptr) - SetFSCharset(charset); + return charset == nullptr || SetFSCharset(charset, error); +#else + (void)error; + return true; +#endif +} + +void +DeinitFS() +{ +#ifdef HAVE_FS_CHARSET + DeinitFSCharset(); #endif } diff --git a/src/fs/Config.hxx b/src/fs/Config.hxx index d4f1709f5..403c07685 100644 --- a/src/fs/Config.hxx +++ b/src/fs/Config.hxx @@ -22,10 +22,15 @@ #include "check.h" +class Error; + /** * Performs global one-time initialization of this class. */ +bool +ConfigureFS(Error &error); + void -ConfigureFS(); +DeinitFS(); #endif diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx index 9e0fa5aeb..4a3ae815f 100644 --- a/src/fs/Path.hxx +++ b/src/fs/Path.hxx @@ -29,6 +29,8 @@ #include <assert.h> #include <string.h> +class AllocatedPath; + /** * A path name in the native file system character set. * @@ -129,6 +131,22 @@ public: std::string ToUTF8() const; /** + * Determine the "base" file name. + * The return value points inside this object. + */ + gcc_pure + Path GetBase() const { + return FromFS(PathTraitsFS::GetBase(value)); + } + + /** + * Gets directory name of this path. + * Returns a "nulled" instance on error. + */ + gcc_pure + AllocatedPath GetDirectoryName() const; + + /** * 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 diff --git a/src/fs/Path2.cxx b/src/fs/Path2.cxx new file mode 100644 index 000000000..966e34dad --- /dev/null +++ b/src/fs/Path2.cxx @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * 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. + */ + +#include "config.h" +#include "Path.hxx" +#include "AllocatedPath.hxx" + +AllocatedPath +Path::GetDirectoryName() const +{ + return AllocatedPath::FromFS(PathTraitsFS::GetParent(c_str())); +} diff --git a/src/fs/io/TextFile.cxx b/src/fs/io/TextFile.cxx index 28d6dabcb..1710e0e89 100644 --- a/src/fs/io/TextFile.cxx +++ b/src/fs/io/TextFile.cxx @@ -28,14 +28,14 @@ TextFile::TextFile(Path path_fs, Error &error) :file_reader(new FileReader(path_fs, error)), -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB gunzip_reader(file_reader->IsDefined() ? new AutoGunzipReader(*file_reader) : nullptr), #endif buffered_reader(file_reader->IsDefined() ? new BufferedReader(* -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB gunzip_reader #else file_reader @@ -48,7 +48,7 @@ TextFile::TextFile(Path path_fs, Error &error) TextFile::~TextFile() { delete buffered_reader; -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB delete gunzip_reader; #endif delete file_reader; diff --git a/src/fs/io/TextFile.hxx b/src/fs/io/TextFile.hxx index 5577363e7..425797ce7 100644 --- a/src/fs/io/TextFile.hxx +++ b/src/fs/io/TextFile.hxx @@ -34,7 +34,7 @@ class BufferedReader; class TextFile { FileReader *const file_reader; -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB AutoGunzipReader *const gunzip_reader; #endif |