charset: add class Utf8ToLocale
authorMax Kellermann <max@musicpd.org>
Fri, 16 Mar 2018 15:50:55 +0000 (16:50 +0100)
committerMax Kellermann <max@musicpd.org>
Fri, 16 Mar 2018 16:15:41 +0000 (17:15 +0100)
12 files changed:
src/AlbumListPage.cxx
src/ArtistListPage.cxx
src/TextPage.cxx
src/charset.cxx
src/charset.hxx
src/db_completion.cxx
src/screen_artist.cxx
src/screen_browser.cxx
src/screen_chat.cxx
src/screen_client.cxx
src/screen_file.cxx
src/wreadln.cxx

index ea7a49f..ce71de1 100644 (file)
@@ -57,12 +57,9 @@ album_lw_callback(unsigned idx, void *data)
        assert(idx < list.size());
 
        const char *str_utf8 = list[idx].c_str();
-       char *str = utf8_to_locale(str_utf8);
 
        static char buf[BUFSIZE];
-       g_strlcpy(buf, str, sizeof(buf));
-       g_free(str);
-
+       g_strlcpy(buf, Utf8ToLocale(str_utf8).c_str(), sizeof(buf));
        return buf;
 }
 
@@ -163,9 +160,8 @@ AlbumListPage::GetTitle(char *str, size_t size) const
        if (artist.empty())
                return _("Albums");
 
-       char *s1 = utf8_to_locale(artist.c_str());
-       g_snprintf(str, size, _("Albums of artist: %s"), s1);
-       g_free(s1);
+       g_snprintf(str, size, _("Albums of artist: %s"),
+                  Utf8ToLocale(artist.c_str()).c_str());
        return str;
 }
 
@@ -193,9 +189,8 @@ add_query(struct mpdclient *c, enum mpd_tag_type table, const char *_filter,
        if (connection == nullptr)
                return;
 
-       char *str = utf8_to_locale(_filter);
-       screen_status_printf(_("Adding \'%s\' to queue"), str);
-       g_free(str);
+       screen_status_printf(_("Adding \'%s\' to queue"),
+                            Utf8ToLocale(_filter).c_str());
 
        mpd_search_add_db_songs(connection, true);
        mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
index 2369ffa..bac116e 100644 (file)
@@ -56,12 +56,9 @@ screen_artist_lw_callback(unsigned idx, void *data)
        assert(idx < list.size());
 
        const char *str_utf8 = list[idx].c_str();
-       char *str = utf8_to_locale(str_utf8);
 
        static char buf[BUFSIZE];
-       g_strlcpy(buf, str, sizeof(buf));
-       g_free(str);
-
+       g_strlcpy(buf, Utf8ToLocale(str_utf8).c_str(), sizeof(buf));
        return buf;
 }
 
@@ -112,10 +109,8 @@ paint_artist_callback(WINDOW *w, unsigned i,
                      bool selected, const void *data)
 {
        const auto &list = *(const std::vector<std::string> *)data;
-       char *p = utf8_to_locale(list[i].c_str());
-
-       screen_browser_paint_directory(w, width, selected, p);
-       g_free(p);
+       screen_browser_paint_directory(w, width, selected,
+                                      Utf8ToLocale(list[i].c_str()).c_str());
 }
 
 void
@@ -151,9 +146,8 @@ add_query(struct mpdclient *c, enum mpd_tag_type table, const char *_filter)
        if (connection == nullptr)
                return;
 
-       char *str = utf8_to_locale(_filter);
-       screen_status_printf(_("Adding \'%s\' to queue"), str);
-       g_free(str);
+       screen_status_printf(_("Adding \'%s\' to queue"),
+                            Utf8ToLocale(_filter).c_str());
 
        mpd_search_add_db_songs(connection, true);
        mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
index cbd8606..8343d90 100644 (file)
@@ -75,12 +75,9 @@ TextPage::ListCallback(unsigned idx) const
 {
        assert(idx < lines.size());
 
-       char *value = utf8_to_locale(lines[idx].c_str());
-
        static char buffer[256];
-       g_strlcpy(buffer, value, sizeof(buffer));
-       g_free(value);
-
+       g_strlcpy(buffer, Utf8ToLocale(lines[idx].c_str()).c_str(),
+                 sizeof(buffer));
        return buffer;
 }
 
index 875cfa7..1612975 100644 (file)
@@ -232,3 +232,12 @@ replace_locale_to_utf8(char *src)
        return src;
 #endif
 }
+
+#ifdef ENABLE_LOCALE
+
+Utf8ToLocale::~Utf8ToLocale()
+{
+       g_free(value);
+}
+
+#endif
index 1949816..22519af 100644 (file)
@@ -69,4 +69,35 @@ replace_utf8_to_locale(char *src);
 char *
 replace_locale_to_utf8(char *src);
 
+/**
+ * Convert an UTF-8 string to the locale charset.  The source string
+ * must remain valid while this object is used.  If no conversion is
+ * necessary, then this class is a no-op.
+ */
+class Utf8ToLocale {
+#ifdef ENABLE_LOCALE
+       char *const value;
+#else
+       const char *const value;
+#endif
+
+public:
+#ifdef ENABLE_LOCALE
+       explicit Utf8ToLocale(const char *src)
+               :value(utf8_to_locale(src)) {}
+
+       ~Utf8ToLocale();
+
+       Utf8ToLocale(const Utf8ToLocale &) = delete;
+       Utf8ToLocale &operator=(const Utf8ToLocale &) = delete;
+#else
+       explicit Utf8ToLocale(const char *src)
+               :value(src) {}
+#endif
+
+       const char *c_str() const {
+               return value;
+       }
+};
+
 #endif
index 79b6ff5..5ad08e6 100644 (file)
@@ -39,9 +39,8 @@ gcmp_list_from_path(struct mpdclient *c, const gchar *path,
                    types & GCMP_TYPE_DIR) {
                        const struct mpd_directory *dir =
                                mpd_entity_get_directory(entity);
-                       gchar *tmp = utf8_to_locale(mpd_directory_get_path(dir));
-                       name = g_strconcat(tmp, "/", nullptr);
-                       g_free(tmp);
+                       name = g_strconcat(Utf8ToLocale(mpd_directory_get_path(dir)).c_str(),
+                                          "/", nullptr);
                } else if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG &&
                           types & GCMP_TYPE_FILE) {
                        const struct mpd_song *song =
index e8a70b1..cdf6822 100644 (file)
@@ -178,19 +178,20 @@ screen_artist_init(ScreenManager &_screen, WINDOW *w, Size size)
 const char *
 SongListPage::GetTitle(char *str, size_t size) const
 {
-       char *s1 = utf8_to_locale(artist.c_str());
+       const Utf8ToLocale artist_locale(artist.c_str());
 
        if (IsNulled(album))
                g_snprintf(str, size,
-                          _("All tracks of artist: %s"), s1);
+                          _("All tracks of artist: %s"),
+                          artist_locale.c_str());
        else if (!album.empty()) {
-               char *s2 = utf8_to_locale(album.c_str());
-               g_snprintf(str, size, _("Album: %s - %s"), s1, s2);
-               g_free(s2);
+               const Utf8ToLocale album_locale(album.c_str());
+               g_snprintf(str, size, _("Album: %s - %s"),
+                          artist_locale.c_str(), album_locale.c_str());
        } else
                g_snprintf(str, size,
-                          _("Tracks of no album of artist: %s"), s1);
-       g_free(s1);
+                          _("Tracks of no album of artist: %s"),
+                          artist_locale.c_str());
 
        return str;
 }
index f0a898d..3f1667c 100644 (file)
@@ -91,9 +91,8 @@ browser_lw_callback(unsigned idx, void *data)
 
        if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_DIRECTORY) {
                const auto *dir = mpd_entity_get_directory(entity);
-               char *directory = utf8_to_locale(g_basename(mpd_directory_get_path(dir)));
-               g_strlcpy(buf, directory, sizeof(buf));
-               g_free(directory);
+               const char *name = g_basename(mpd_directory_get_path(dir));
+               g_strlcpy(buf, Utf8ToLocale(name).c_str(), sizeof(buf));
                return buf;
        } else if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
                const auto *song = mpd_entity_get_song(entity);
@@ -102,10 +101,8 @@ browser_lw_callback(unsigned idx, void *data)
                return buf;
        } else if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_PLAYLIST) {
                const auto *playlist = mpd_entity_get_playlist(entity);
-               char *filename = utf8_to_locale(g_basename(mpd_playlist_get_path(playlist)));
-
-               g_strlcpy(buf, filename, sizeof(buf));
-               g_free(filename);
+               const char *name = g_basename(mpd_playlist_get_path(playlist));
+               g_strlcpy(buf, Utf8ToLocale(name).c_str(), sizeof(buf));
                return buf;
        }
 
@@ -121,10 +118,9 @@ load_playlist(struct mpdclient *c, const struct mpd_playlist *playlist)
                return false;
 
        if (mpd_run_load(connection, mpd_playlist_get_path(playlist))) {
-               char *filename = utf8_to_locale(mpd_playlist_get_path(playlist));
+               const char *name = g_basename(mpd_playlist_get_path(playlist));
                screen_status_printf(_("Loading playlist %s..."),
-                                    g_basename(filename));
-               g_free(filename);
+                                    Utf8ToLocale(name).c_str());
 
                c->events |= MPD_IDLE_QUEUE;
        } else
@@ -250,10 +246,8 @@ browser_select_entry(struct mpdclient *c, FileListEntry *entry,
                const auto *dir = mpd_entity_get_directory(entry->entity);
 
                if (mpdclient_cmd_add_path(c, mpd_directory_get_path(dir))) {
-                       char *tmp = utf8_to_locale(mpd_directory_get_path(dir));
-
-                       screen_status_printf(_("Adding \'%s\' to queue"), tmp);
-                       g_free(tmp);
+                       screen_status_printf(_("Adding \'%s\' to queue"),
+                                            Utf8ToLocale(mpd_directory_get_path(dir)).c_str());
                }
 
                return true;
@@ -512,13 +506,13 @@ FileListPage::PaintRow(WINDOW *w, unsigned i,
        switch (mpd_entity_get_type(entity)) {
                const struct mpd_directory *directory;
                const struct mpd_playlist *playlist;
-               char *p;
+               const char *name;
 
        case MPD_ENTITY_TYPE_DIRECTORY:
                directory = mpd_entity_get_directory(entity);
-               p = utf8_to_locale(g_basename(mpd_directory_get_path(directory)));
-               screen_browser_paint_directory(w, width, selected, p);
-               g_free(p);
+               name = g_basename(mpd_directory_get_path(directory));
+               screen_browser_paint_directory(w, width, selected,
+                                              Utf8ToLocale(name).c_str());
                break;
 
        case MPD_ENTITY_TYPE_SONG:
@@ -529,9 +523,9 @@ FileListPage::PaintRow(WINDOW *w, unsigned i,
 
        case MPD_ENTITY_TYPE_PLAYLIST:
                playlist = mpd_entity_get_playlist(entity);
-               p = utf8_to_locale(g_basename(mpd_playlist_get_path(playlist)));
-               screen_browser_paint_playlist(w, width, selected, p);
-               g_free(p);
+               name = g_basename(mpd_playlist_get_path(playlist));
+               screen_browser_paint_playlist(w, width, selected,
+                                             Utf8ToLocale(name).c_str());
                break;
 
        default:
index d1ad37b..1e7591a 100644 (file)
@@ -104,9 +104,7 @@ ChatPage::ProcessMessage(const struct mpd_message &message)
           client-to-client messages anywhere else */
        assert(g_strcmp0(mpd_message_get_channel(&message), chat_channel) == 0);
 
-       char *message_text = utf8_to_locale(mpd_message_get_text(&message));
-       Append(message_text);
-       g_free(message_text);
+       Append(Utf8ToLocale(mpd_message_get_text(&message)).c_str());
 
        SetDirty();
 }
index 17028c2..8d91d22 100644 (file)
@@ -47,9 +47,8 @@ screen_database_update(struct mpdclient *c, const char *path)
        }
 
        if (path != nullptr && *path != 0) {
-               char *path_locale = utf8_to_locale(path);
-               screen_status_printf(_("Database update of %s started"), path);
-               g_free(path_locale);
+               screen_status_printf(_("Database update of %s started"),
+                                    Utf8ToLocale(path).c_str());
        } else
                screen_status_message(_("Database update started"));
 }
index 404158d..fe6fd4b 100644 (file)
@@ -269,9 +269,8 @@ FileBrowserPage::HandleDelete(struct mpdclient &c)
                }
 
                const auto *playlist = mpd_entity_get_playlist(entity);
-               char *str = utf8_to_locale(g_basename(mpd_playlist_get_path(playlist)));
-               char *buf = g_strdup_printf(_("Delete playlist %s?"), str);
-               g_free(str);
+               char *buf = g_strdup_printf(_("Delete playlist %s?"),
+                                           Utf8ToLocale(g_basename(mpd_playlist_get_path(playlist))).c_str());
                bool confirmed = screen_get_yesno(buf, false);
                g_free(buf);
 
@@ -315,11 +314,9 @@ FileBrowserPage::GetTitle(char *str, size_t size) const
                /* fall back to full path */
                path = current_path;
 
-       char *path_locale = utf8_to_locale(path);
        g_snprintf(str, size, "%s: %s",
                   /* translators: caption of the browser screen */
-                  _("Browse"), path_locale);
-       g_free(path_locale);
+                  _("Browse"), Utf8ToLocale(path).c_str());
        return str;
 }
 
index 3cb5f6f..5416dde 100644 (file)
@@ -158,7 +158,7 @@ right_align_bytes(const gchar *data, size_t right, unsigned width)
        dup[right] = 0;
 
        while (dup[start] != 0) {
-               char *p = locale_to_utf8(dup + start), *q;
+               char *p = locale_to_utf8(dup + start);
                unsigned p_width = utf8_width(p);
 
                if (p_width < width) {
@@ -168,11 +168,9 @@ right_align_bytes(const gchar *data, size_t right, unsigned width)
 
                gunichar c = g_utf8_get_char(p);
                p[g_unichar_to_utf8(c, nullptr)] = 0;
-               q = utf8_to_locale(p);
-               g_free(p);
 
-               start += strlen(q);
-               g_free(q);
+               start += strlen(Utf8ToLocale(p).c_str());
+               g_free(p);
        }
 
        g_free(dup);
@@ -190,16 +188,13 @@ static inline size_t
 next_char_size(const gchar *data)
 {
 #if defined(HAVE_CURSES_ENHANCED) || defined(ENABLE_MULTIBYTE)
-       char *p = locale_to_utf8(data), *q;
+       char *p = locale_to_utf8(data);
 
        gunichar c = g_utf8_get_char(p);
        p[g_unichar_to_utf8(c, nullptr)] = 0;
-       q = utf8_to_locale(p);
+       size_t size = strlen(Utf8ToLocale(p).c_str());
        g_free(p);
 
-       size_t size = strlen(q);
-       g_free(q);
-
        return size;
 #else
        (void)data;