From 258ecb764f926243087ed457aa78c41b84555f2b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Oct 2021 13:35:57 +0200 Subject: [PATCH] PlaylistFile: add class PlaylistFileEditor --- src/PlaylistFile.cxx | 81 ++++++++++++++++++++++++++++++-------------- src/PlaylistFile.hxx | 32 ++++++++++++++--- 2 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index e0b80bd2c..1b72d0ad8 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -34,7 +34,6 @@ #include "config/Defaults.hxx" #include "Idle.hxx" #include "fs/Limits.hxx" -#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "fs/FileInfo.hxx" @@ -173,11 +172,8 @@ ListPlaylistFiles() } static void -SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path) +SavePlaylistFile(Path path_fs, const PlaylistFileContents &contents) { - assert(utf8path != nullptr); - - const auto path_fs = spl_map_to_fs(utf8path); assert(!path_fs.IsNull()); FileOutputStream fos(path_fs); @@ -191,12 +187,11 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path) fos.Commit(); } -PlaylistFileContents -LoadPlaylistFile(const char *utf8path) +static PlaylistFileContents +LoadPlaylistFile(Path path_fs) try { PlaylistFileContents contents; - const auto path_fs = spl_map_to_fs(utf8path); assert(!path_fs.IsNull()); TextFile file(path_fs); @@ -251,16 +246,31 @@ try { throw; } -void -spl_move_index(const char *utf8path, unsigned src, unsigned dest) +static PlaylistFileContents +MaybeLoadPlaylistFile(Path path_fs, PlaylistFileEditor::LoadMode load_mode) +try { + if (load_mode == PlaylistFileEditor::LoadMode::NO) + return {}; + + return LoadPlaylistFile(path_fs); +} catch (const PlaylistError &error) { + if (error.GetCode() == PlaylistResult::NO_SUCH_LIST && + load_mode == PlaylistFileEditor::LoadMode::TRY) + return {}; + + throw; + } + +PlaylistFileEditor::PlaylistFileEditor(const char *name_utf8, + LoadMode load_mode) + :path(spl_map_to_fs(name_utf8)), + contents(MaybeLoadPlaylistFile(path, load_mode)) { - if (src == dest) - /* this doesn't check whether the playlist exists, but - what the hell.. */ - return; - - auto contents = LoadPlaylistFile(utf8path); +} +void +PlaylistFileEditor::MoveIndex(unsigned src, unsigned dest) +{ if (src >= contents.size() || dest >= contents.size()) throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range"); @@ -270,12 +280,37 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest) const auto dest_i = std::next(contents.begin(), dest); contents.insert(dest_i, std::move(value)); +} - SavePlaylistFile(contents, utf8path); +void +PlaylistFileEditor::RemoveIndex(unsigned i) +{ + if (i >= contents.size()) + throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range"); + contents.erase(std::next(contents.begin(), i)); +} + +void +PlaylistFileEditor::Save() +{ + SavePlaylistFile(path, contents); idle_add(IDLE_STORED_PLAYLIST); } +void +spl_move_index(const char *utf8path, unsigned src, unsigned dest) +{ + if (src == dest) + /* this doesn't check whether the playlist exists, but + what the hell.. */ + return; + + PlaylistFileEditor editor(utf8path, PlaylistFileEditor::LoadMode::YES); + editor.MoveIndex(src, dest); + editor.Save(); +} + void spl_clear(const char *utf8path) { @@ -317,15 +352,9 @@ spl_delete(const char *name_utf8) void spl_remove_index(const char *utf8path, unsigned pos) { - auto contents = LoadPlaylistFile(utf8path); - - if (pos >= contents.size()) - throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range"); - - contents.erase(std::next(contents.begin(), pos)); - - SavePlaylistFile(contents, utf8path); - idle_add(IDLE_STORED_PLAYLIST); + PlaylistFileEditor editor(utf8path, PlaylistFileEditor::LoadMode::YES); + editor.RemoveIndex(pos); + editor.Save(); } void diff --git a/src/PlaylistFile.hxx b/src/PlaylistFile.hxx index b156c73e4..2f1c1bc04 100644 --- a/src/PlaylistFile.hxx +++ b/src/PlaylistFile.hxx @@ -20,6 +20,8 @@ #ifndef MPD_PLAYLIST_FILE_HXX #define MPD_PLAYLIST_FILE_HXX +#include "fs/AllocatedPath.hxx" + #include #include @@ -27,12 +29,37 @@ struct ConfigData; class DetachedSong; class SongLoader; class PlaylistVector; -class AllocatedPath; typedef std::vector PlaylistFileContents; extern bool playlist_saveAbsolutePaths; +class PlaylistFileEditor { + const AllocatedPath path; + + PlaylistFileContents contents; + +public: + enum class LoadMode { + NO, + YES, + TRY, + }; + + /** + * Throws on error. + */ + explicit PlaylistFileEditor(const char *name_utf8, LoadMode load_mode); + + void MoveIndex(unsigned src, unsigned dest); + void RemoveIndex(unsigned i); + + void Save(); + +private: + void Load(); +}; + /** * Perform some global initialization, e.g. load configuration values. */ @@ -55,9 +82,6 @@ spl_map_to_fs(const char *name_utf8); PlaylistVector ListPlaylistFiles(); -PlaylistFileContents -LoadPlaylistFile(const char *utf8path); - void spl_move_index(const char *utf8path, unsigned src, unsigned dest);