aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/PlaylistDatabase.cxx4
-rw-r--r--src/PlaylistFile.cxx29
-rw-r--r--src/SongSave.cxx4
-rw-r--r--src/StateFile.cxx12
-rw-r--r--src/TagSave.cxx2
-rw-r--r--src/db/plugins/simple/DatabaseSave.cxx4
-rw-r--r--src/db/plugins/simple/DirectorySave.cxx4
-rw-r--r--src/db/plugins/simple/SimpleDatabasePlugin.cxx13
-rw-r--r--src/fs/StandardDirectory.cxx5
-rw-r--r--src/fs/TextFile.cxx81
-rw-r--r--src/fs/io/BufferedOutputStream.cxx (renamed from src/fs/output/BufferedOutputStream.cxx)0
-rw-r--r--src/fs/io/BufferedOutputStream.hxx (renamed from src/fs/output/BufferedOutputStream.hxx)0
-rw-r--r--src/fs/io/BufferedReader.cxx82
-rw-r--r--src/fs/io/BufferedReader.hxx75
-rw-r--r--src/fs/io/FileOutputStream.cxx (renamed from src/fs/output/FileOutputStream.cxx)0
-rw-r--r--src/fs/io/FileOutputStream.hxx (renamed from src/fs/output/FileOutputStream.hxx)0
-rw-r--r--src/fs/io/FileReader.cxx98
-rw-r--r--src/fs/io/FileReader.hxx67
-rw-r--r--src/fs/io/GzipOutputStream.cxx (renamed from src/fs/output/GzipOutputStream.cxx)0
-rw-r--r--src/fs/io/GzipOutputStream.hxx (renamed from src/fs/output/GzipOutputStream.hxx)0
-rw-r--r--src/fs/io/OutputStream.hxx (renamed from src/fs/output/OutputStream.hxx)0
-rw-r--r--src/fs/io/Reader.hxx51
-rw-r--r--src/fs/io/StdioOutputStream.hxx (renamed from src/fs/output/StdioOutputStream.hxx)0
-rw-r--r--src/fs/io/TextFile.cxx48
-rw-r--r--src/fs/io/TextFile.hxx (renamed from src/fs/TextFile.hxx)18
-rw-r--r--src/input/TextInputStream.cxx22
-rw-r--r--src/input/TextInputStream.hxx3
-rw-r--r--src/mixer/Volume.cxx2
-rw-r--r--src/output/OutputState.cxx2
-rw-r--r--src/queue/PlaylistState.cxx4
-rw-r--r--src/queue/QueueSave.cxx4
-rw-r--r--src/util/DynamicFifoBuffer.hxx3
-rw-r--r--src/util/TextFile.hxx52
33 files changed, 540 insertions, 149 deletions
diff --git a/src/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx
index e4fd3ff28..3421ecb02 100644
--- a/src/PlaylistDatabase.cxx
+++ b/src/PlaylistDatabase.cxx
@@ -20,8 +20,8 @@
#include "config.h"
#include "PlaylistDatabase.hxx"
#include "db/PlaylistVector.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx
index f5ac2735f..f0aa2d2d7 100644
--- a/src/PlaylistFile.cxx
+++ b/src/PlaylistFile.cxx
@@ -25,7 +25,7 @@
#include "DetachedSong.hxx"
#include "SongLoader.hxx"
#include "Mapper.hxx"
-#include "fs/TextFile.hxx"
+#include "fs/io/TextFile.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "config/ConfigDefaults.hxx"
@@ -116,6 +116,29 @@ spl_map_to_fs(const char *name_utf8, Error &error)
return path_fs;
}
+gcc_pure
+static bool
+IsNotFoundError(const Error &error)
+{
+#ifdef WIN32
+ return error.IsDomain(win32_domain) &&
+ error.GetCode() == ERROR_FILE_NOT_FOUND;
+#else
+ return error.IsDomain(errno_domain) &&
+ error.GetCode() == ENOENT;
+#endif
+}
+
+static void
+TranslatePlaylistError(Error &error)
+{
+ if (IsNotFoundError(error)) {
+ error.Clear();
+ error.Set(playlist_domain, int(PlaylistResult::NO_SUCH_LIST),
+ "No such playlist");
+ }
+}
+
/**
* Create an #Error for the current errno.
*/
@@ -228,9 +251,9 @@ LoadPlaylistFile(const char *utf8path, Error &error)
if (path_fs.IsNull())
return contents;
- TextFile file(path_fs);
+ TextFile file(path_fs, error);
if (file.HasFailed()) {
- playlist_errno(error);
+ TranslatePlaylistError(error);
return contents;
}
diff --git a/src/SongSave.cxx b/src/SongSave.cxx
index bf6194a4f..93613e938 100644
--- a/src/SongSave.cxx
+++ b/src/SongSave.cxx
@@ -22,8 +22,8 @@
#include "db/plugins/simple/Song.hxx"
#include "DetachedSong.hxx"
#include "TagSave.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "tag/Tag.hxx"
#include "tag/TagBuilder.hxx"
#include "util/StringUtil.hxx"
diff --git a/src/StateFile.cxx b/src/StateFile.cxx
index e8df1ec0a..e0f0cedb1 100644
--- a/src/StateFile.cxx
+++ b/src/StateFile.cxx
@@ -21,9 +21,9 @@
#include "StateFile.hxx"
#include "output/OutputState.hxx"
#include "queue/PlaylistState.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/FileOutputStream.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/FileOutputStream.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "mixer/Volume.hxx"
@@ -103,10 +103,10 @@ StateFile::Read()
FormatDebug(state_file_domain, "Loading state file %s", path_utf8.c_str());
- TextFile file(path);
+ Error error;
+ TextFile file(path, error);
if (file.HasFailed()) {
- FormatErrno(state_file_domain, "failed to open %s",
- path_utf8.c_str());
+ LogError(error);
return;
}
diff --git a/src/TagSave.cxx b/src/TagSave.cxx
index 6ec562ec5..c47d778d3 100644
--- a/src/TagSave.cxx
+++ b/src/TagSave.cxx
@@ -20,7 +20,7 @@
#include "config.h"
#include "TagSave.hxx"
#include "tag/Tag.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#define SONG_TIME "Time: "
diff --git a/src/db/plugins/simple/DatabaseSave.cxx b/src/db/plugins/simple/DatabaseSave.cxx
index e10d79d60..c766843b6 100644
--- a/src/db/plugins/simple/DatabaseSave.cxx
+++ b/src/db/plugins/simple/DatabaseSave.cxx
@@ -23,8 +23,8 @@
#include "db/DatabaseError.hxx"
#include "Directory.hxx"
#include "DirectorySave.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
-#include "fs/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
#include "tag/Tag.hxx"
#include "tag/TagSettings.h"
#include "fs/Charset.hxx"
diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx
index 7e7cbc3ba..e1650cbe8 100644
--- a/src/db/plugins/simple/DirectorySave.cxx
+++ b/src/db/plugins/simple/DirectorySave.cxx
@@ -24,8 +24,8 @@
#include "SongSave.hxx"
#include "DetachedSong.hxx"
#include "PlaylistDatabase.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "util/StringUtil.hxx"
#include "util/NumberParser.hxx"
#include "util/Error.hxx"
diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx
index fe712b90b..9e750996c 100644
--- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx
+++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx
@@ -31,9 +31,9 @@
#include "DatabaseSave.hxx"
#include "db/DatabaseLock.hxx"
#include "db/DatabaseError.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
-#include "fs/output/FileOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
+#include "fs/io/FileOutputStream.hxx"
#include "config/ConfigData.hxx"
#include "fs/FileSystem.hxx"
#include "util/CharUtil.hxx"
@@ -168,12 +168,9 @@ SimpleDatabase::Load(Error &error)
assert(!path.IsNull());
assert(root != nullptr);
- TextFile file(path);
- if (file.HasFailed()) {
- error.FormatErrno("Failed to open database file \"%s\"",
- path_utf8.c_str());
+ TextFile file(path, error);
+ if (file.HasFailed())
return false;
- }
if (!db_load_internal(file, *root, error))
return false;
diff --git a/src/fs/StandardDirectory.cxx b/src/fs/StandardDirectory.cxx
index ea91399d1..7a836f906 100644
--- a/src/fs/StandardDirectory.cxx
+++ b/src/fs/StandardDirectory.cxx
@@ -40,8 +40,9 @@
#endif
#ifdef USE_XDG
+#include "util/Error.hxx"
#include "util/StringUtil.hxx"
-#include "TextFile.hxx"
+#include "io/TextFile.hxx"
#include <string.h>
#include <utility>
#endif
@@ -204,7 +205,7 @@ static AllocatedPath GetUserDir(const char *name)
if (config_dir.IsNull())
return result;
auto dirs_file = AllocatedPath::Build(config_dir, "user-dirs.dirs");
- TextFile input(dirs_file);
+ TextFile input(dirs_file, IgnoreError());
if (input.HasFailed())
return result;
char *line;
diff --git a/src/fs/TextFile.cxx b/src/fs/TextFile.cxx
deleted file mode 100644
index b1a92b9cc..000000000
--- a/src/fs/TextFile.cxx
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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 "TextFile.hxx"
-#include "util/Alloc.hxx"
-#include "fs/Path.hxx"
-#include "fs/FileSystem.hxx"
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-TextFile::TextFile(Path path_fs)
- :file(FOpen(path_fs, FOpenMode::ReadText)),
- buffer((char *)xalloc(step)), capacity(step), length(0) {}
-
-TextFile::~TextFile()
-{
- free(buffer);
-
- if (file != nullptr)
- fclose(file);
-}
-
-char *
-TextFile::ReadLine()
-{
- assert(file != nullptr);
-
- while (true) {
- if (length >= capacity) {
- if (capacity >= max_length)
- /* too large already - bail out */
- return nullptr;
-
- capacity <<= 1;
- char *new_buffer = (char *)realloc(buffer, capacity);
- if (new_buffer == nullptr)
- /* out of memory - bail out */
- return nullptr;
- }
-
- char *p = fgets(buffer + length, capacity - length, file);
- if (p == nullptr) {
- if (length == 0 || ferror(file))
- return nullptr;
- break;
- }
-
- length += strlen(buffer + length);
- if (buffer[length - 1] == '\n')
- break;
- }
-
- /* remove the newline characters */
- if (buffer[length - 1] == '\n')
- --length;
- if (buffer[length - 1] == '\r')
- --length;
-
- buffer[length] = 0;
- length = 0;
- return buffer;
-}
diff --git a/src/fs/output/BufferedOutputStream.cxx b/src/fs/io/BufferedOutputStream.cxx
index 088a3e279..088a3e279 100644
--- a/src/fs/output/BufferedOutputStream.cxx
+++ b/src/fs/io/BufferedOutputStream.cxx
diff --git a/src/fs/output/BufferedOutputStream.hxx b/src/fs/io/BufferedOutputStream.hxx
index f2de758a2..f2de758a2 100644
--- a/src/fs/output/BufferedOutputStream.hxx
+++ b/src/fs/io/BufferedOutputStream.hxx
diff --git a/src/fs/io/BufferedReader.cxx b/src/fs/io/BufferedReader.cxx
new file mode 100644
index 000000000..ba2f17dcf
--- /dev/null
+++ b/src/fs/io/BufferedReader.cxx
@@ -0,0 +1,82 @@
+/*
+ * 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 "BufferedReader.hxx"
+#include "Reader.hxx"
+#include "util/TextFile.hxx"
+
+bool
+BufferedReader::Fill(bool need_more)
+{
+ if (gcc_unlikely(last_error.IsDefined()))
+ return false;
+
+ if (eof)
+ return !need_more;
+
+ auto w = buffer.Write();
+ if (w.IsEmpty()) {
+ if (buffer.GetCapacity() >= MAX_SIZE)
+ return !need_more;
+
+ buffer.Grow(buffer.GetCapacity() * 2);
+ w = buffer.Write();
+ assert(!w.IsEmpty());
+ }
+
+ size_t nbytes = reader.Read(w.data, w.size, last_error);
+ if (nbytes == 0) {
+ if (gcc_unlikely(last_error.IsDefined()))
+ return false;
+
+ eof = true;
+ return !need_more;
+ }
+
+ buffer.Append(nbytes);
+ return true;
+}
+
+char *
+BufferedReader::ReadLine()
+{
+ do {
+ char *line = ReadBufferedLine(buffer);
+ if (line != nullptr)
+ return line;
+ } while (Fill(true));
+
+ if (last_error.IsDefined() || !eof || buffer.IsEmpty())
+ return nullptr;
+
+ auto w = buffer.Write();
+ if (w.IsEmpty()) {
+ buffer.Grow(buffer.GetCapacity() + 1);
+ w = buffer.Write();
+ assert(!w.IsEmpty());
+ }
+
+ /* terminate the last line */
+ w[0] = 0;
+
+ char *line = buffer.Read().data;
+ buffer.Clear();
+ return line;
+}
diff --git a/src/fs/io/BufferedReader.hxx b/src/fs/io/BufferedReader.hxx
new file mode 100644
index 000000000..61cc8df83
--- /dev/null
+++ b/src/fs/io/BufferedReader.hxx
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef MPD_BUFFERED_READER_HXX
+#define MPD_BUFFERED_READER_HXX
+
+#include "check.h"
+#include "Compiler.h"
+#include "util/DynamicFifoBuffer.hxx"
+#include "util/Error.hxx"
+
+#include <stddef.h>
+
+class Reader;
+class Error;
+
+class BufferedReader {
+ static constexpr size_t MAX_SIZE = 512 * 1024;
+
+ Reader &reader;
+
+ DynamicFifoBuffer<char> buffer;
+
+ Error last_error;
+
+ bool eof;
+
+public:
+ BufferedReader(Reader &_reader)
+ :reader(_reader), buffer(4096), eof(false) {}
+
+ gcc_pure
+ bool Check() const {
+ return !last_error.IsDefined();
+ }
+
+ bool Check(Error &error) const {
+ if (last_error.IsDefined()) {
+ error.Set(last_error);
+ return false;
+ } else
+ return true;
+ }
+
+ bool Fill(bool need_more);
+
+ gcc_pure
+ WritableBuffer<void> Read() const {
+ return buffer.Read().ToVoid();
+ }
+
+ void Consume(size_t n) {
+ buffer.Consume(n);
+ }
+
+ char *ReadLine();
+};
+
+#endif
diff --git a/src/fs/output/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index dc4456d1f..dc4456d1f 100644
--- a/src/fs/output/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
diff --git a/src/fs/output/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx
index 68174ec83..68174ec83 100644
--- a/src/fs/output/FileOutputStream.hxx
+++ b/src/fs/io/FileOutputStream.hxx
diff --git a/src/fs/io/FileReader.cxx b/src/fs/io/FileReader.cxx
new file mode 100644
index 000000000..d63cd8ab0
--- /dev/null
+++ b/src/fs/io/FileReader.cxx
@@ -0,0 +1,98 @@
+/*
+ * 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 "FileReader.hxx"
+#include "system/fd_util.h"
+#include "util/Error.hxx"
+
+#ifdef WIN32
+
+FileReader::FileReader(Path _path, Error &error)
+ :path(_path),
+ handle(CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ nullptr))
+{
+ if (handle == INVALID_HANDLE_VALUE)
+ error.FormatLastError("Failed to open %s", path.c_str());
+}
+
+size_t
+FileReader::Read(void *data, size_t size, Error &error)
+{
+ assert(IsDefined());
+
+ DWORD nbytes;
+ if (!ReadFile(handle, data, size, &nbytes, nullptr)) {
+ error.FormatLastError("Failed to read from %s", path.c_str());
+ nbytes = 0;
+ }
+
+ return nbytes;
+}
+
+void
+FileReader::Close()
+{
+ assert(IsDefined());
+
+ CloseHandle(handle);
+}
+
+#else
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+FileReader::FileReader(Path _path, Error &error)
+ :path(_path),
+ fd(open_cloexec(path.c_str(),
+ O_RDONLY,
+ 0))
+{
+ if (fd < 0)
+ error.FormatErrno("Failed to open %s", path.c_str());
+}
+
+size_t
+FileReader::Read(void *data, size_t size, Error &error)
+{
+ assert(IsDefined());
+
+ ssize_t nbytes = read(fd, data, size);
+ if (nbytes < 0) {
+ error.FormatErrno("Failed to read from %s", path.c_str());
+ nbytes = 0;
+ }
+
+ return nbytes;
+}
+
+void
+FileReader::Close()
+{
+ assert(IsDefined());
+
+ close(fd);
+ fd = -1;
+}
+
+#endif
diff --git a/src/fs/io/FileReader.hxx b/src/fs/io/FileReader.hxx
new file mode 100644
index 000000000..34b43943c
--- /dev/null
+++ b/src/fs/io/FileReader.hxx
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef MPD_FILE_READER_HXX
+#define MPD_FILE_READER_HXX
+
+#include "check.h"
+#include "Reader.hxx"
+#include "fs/AllocatedPath.hxx"
+
+#include <assert.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+class Path;
+
+class FileReader final : public Reader {
+ AllocatedPath path;
+
+#ifdef WIN32
+ HANDLE handle;
+#else
+ int fd;
+#endif
+
+public:
+ FileReader(Path _path, Error &error);
+
+ ~FileReader() {
+ if (IsDefined())
+ Close();
+ }
+
+
+ bool IsDefined() const {
+#ifdef WIN32
+ return handle != INVALID_HANDLE_VALUE;
+#else
+ return fd >= 0;
+#endif
+ }
+
+ void Close();
+
+ /* virtual methods from class Reader */
+ size_t Read(void *data, size_t size, Error &error) override;
+};
+
+#endif
diff --git a/src/fs/output/GzipOutputStream.cxx b/src/fs/io/GzipOutputStream.cxx
index d05645d9e..d05645d9e 100644
--- a/src/fs/output/GzipOutputStream.cxx
+++ b/src/fs/io/GzipOutputStream.cxx
diff --git a/src/fs/output/GzipOutputStream.hxx b/src/fs/io/GzipOutputStream.hxx
index 4f6d8b357..4f6d8b357 100644
--- a/src/fs/output/GzipOutputStream.hxx
+++ b/src/fs/io/GzipOutputStream.hxx
diff --git a/src/fs/output/OutputStream.hxx b/src/fs/io/OutputStream.hxx
index 71311c71f..71311c71f 100644
--- a/src/fs/output/OutputStream.hxx
+++ b/src/fs/io/OutputStream.hxx
diff --git a/src/fs/io/Reader.hxx b/src/fs/io/Reader.hxx
new file mode 100644
index 000000000..adf7a0667
--- /dev/null
+++ b/src/fs/io/Reader.hxx
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#ifndef MPD_READER_HXX
+#define MPD_READER_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#include <stddef.h>
+
+class Error;
+
+/**
+ * An interface that can read bytes from a stream until the stream
+ * ends.
+ *
+ * This interface is simpler and less cumbersome to use than
+ * #InputStream.
+ */
+class Reader {
+public:
+ Reader() = default;
+ Reader(const Reader &) = delete;
+
+ /**
+ * Read data from the stream.
+ *
+ * @return the number of bytes read into the given buffer or 0
+ * on error/end-of-stream
+ */
+ virtual size_t Read(void *data, size_t size, Error &error) = 0;
+};
+
+#endif
diff --git a/src/fs/output/StdioOutputStream.hxx b/src/fs/io/StdioOutputStream.hxx
index e00db922f..e00db922f 100644
--- a/src/fs/output/StdioOutputStream.hxx
+++ b/src/fs/io/StdioOutputStream.hxx
diff --git a/src/fs/io/TextFile.cxx b/src/fs/io/TextFile.cxx
new file mode 100644
index 000000000..396d0f9cd
--- /dev/null
+++ b/src/fs/io/TextFile.cxx
@@ -0,0 +1,48 @@
+/*
+ * 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 "TextFile.hxx"
+#include "FileReader.hxx"
+#include "BufferedReader.hxx"
+#include "fs/Path.hxx"
+
+#include <assert.h>
+
+TextFile::TextFile(Path path_fs, Error &error)
+ :file_reader(new FileReader(path_fs, error)),
+ buffered_reader(file_reader->IsDefined()
+ ? new BufferedReader(*file_reader)
+ : nullptr)
+{
+}
+
+TextFile::~TextFile()
+{
+ delete buffered_reader;
+ delete file_reader;
+}
+
+char *
+TextFile::ReadLine()
+{
+ assert(buffered_reader != nullptr);
+
+ return buffered_reader->ReadLine();
+}
diff --git a/src/fs/TextFile.hxx b/src/fs/io/TextFile.hxx
index e3a712a88..33a1b8060 100644
--- a/src/fs/TextFile.hxx
+++ b/src/fs/io/TextFile.hxx
@@ -22,29 +22,26 @@
#include "Compiler.h"
-#include <stdio.h>
#include <stddef.h>
class Path;
+class Error;
+class FileReader;
+class BufferedReader;
class TextFile {
- static constexpr size_t max_length = 512 * 1024;
- static constexpr size_t step = 1024;
-
- FILE *const file;
-
- char *buffer;
- size_t capacity, length;
+ FileReader *const file_reader;
+ BufferedReader *const buffered_reader;
public:
- TextFile(Path path_fs);
+ TextFile(Path path_fs, Error &error);
TextFile(const TextFile &other) = delete;
~TextFile();
bool HasFailed() const {
- return gcc_unlikely(file == nullptr);
+ return gcc_unlikely(buffered_reader == nullptr);
}
/**
@@ -53,7 +50,6 @@ public:
* prevent denial of service.
*
* @param file the source file, opened in text mode
- * @param buffer an allocator for the buffer
* @return a pointer to the line, or nullptr on end-of-file or error
*/
char *ReadLine();
diff --git a/src/input/TextInputStream.cxx b/src/input/TextInputStream.cxx
index 1c46c2f2c..c23616782 100644
--- a/src/input/TextInputStream.cxx
+++ b/src/input/TextInputStream.cxx
@@ -21,31 +21,15 @@
#include "TextInputStream.hxx"
#include "InputStream.hxx"
#include "util/Error.hxx"
+#include "util/TextFile.hxx"
#include "Log.hxx"
#include <assert.h>
-#include <string.h>
-
-char *
-TextInputStream::ReadBufferedLine()
-{
- auto r = buffer.Read();
- char *newline = reinterpret_cast<char*>(memchr(r.data, '\n', r.size));
- if (newline == nullptr)
- return nullptr;
-
- buffer.Consume(newline + 1 - r.data);
-
- if (newline > r.data && newline[-1] == '\r')
- --newline;
- *newline = 0;
- return r.data;
-}
char *
TextInputStream::ReadLine()
{
- char *line = ReadBufferedLine();
+ char *line = ReadBufferedLine(buffer);
if (line != nullptr)
return line;
@@ -76,7 +60,7 @@ TextInputStream::ReadLine()
return nullptr;
}
- line = ReadBufferedLine();
+ line = ReadBufferedLine(buffer);
if (line != nullptr)
return line;
diff --git a/src/input/TextInputStream.hxx b/src/input/TextInputStream.hxx
index ce1eaddff..6f39d22cf 100644
--- a/src/input/TextInputStream.hxx
+++ b/src/input/TextInputStream.hxx
@@ -47,9 +47,6 @@ public:
* @return a pointer to the line, or nullptr on end-of-file or error
*/
char *ReadLine();
-
-private:
- char *ReadBufferedLine();
};
#endif
diff --git a/src/mixer/Volume.cxx b/src/mixer/Volume.cxx
index 86ebbf422..abb01fb40 100644
--- a/src/mixer/Volume.cxx
+++ b/src/mixer/Volume.cxx
@@ -24,7 +24,7 @@
#include "util/StringUtil.hxx"
#include "util/Domain.hxx"
#include "system/PeriodClock.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "Log.hxx"
#include <assert.h>
diff --git a/src/output/OutputState.cxx b/src/output/OutputState.cxx
index 0c1424404..fb01b1c65 100644
--- a/src/output/OutputState.cxx
+++ b/src/output/OutputState.cxx
@@ -28,7 +28,7 @@
#include "Internal.hxx"
#include "Domain.hxx"
#include "Log.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "util/StringUtil.hxx"
#include <assert.h>
diff --git a/src/queue/PlaylistState.cxx b/src/queue/PlaylistState.cxx
index 56adb2a9b..18d8c9dc5 100644
--- a/src/queue/PlaylistState.cxx
+++ b/src/queue/PlaylistState.cxx
@@ -27,8 +27,8 @@
#include "PlaylistError.hxx"
#include "Playlist.hxx"
#include "queue/QueueSave.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "PlayerControl.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
diff --git a/src/queue/QueueSave.cxx b/src/queue/QueueSave.cxx
index eca906421..6d871ac19 100644
--- a/src/queue/QueueSave.cxx
+++ b/src/queue/QueueSave.cxx
@@ -25,8 +25,8 @@
#include "SongSave.hxx"
#include "SongLoader.hxx"
#include "playlist/PlaylistSong.hxx"
-#include "fs/TextFile.hxx"
-#include "fs/output/BufferedOutputStream.hxx"
+#include "fs/io/TextFile.hxx"
+#include "fs/io/BufferedOutputStream.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "fs/Traits.hxx"
diff --git a/src/util/DynamicFifoBuffer.hxx b/src/util/DynamicFifoBuffer.hxx
index 91cbbc4c7..36384bda6 100644
--- a/src/util/DynamicFifoBuffer.hxx
+++ b/src/util/DynamicFifoBuffer.hxx
@@ -52,6 +52,8 @@ public:
DynamicFifoBuffer(const DynamicFifoBuffer &) = delete;
+ using ForeignFifoBuffer<T>::GetCapacity;
+ using ForeignFifoBuffer<T>::Clear;
using ForeignFifoBuffer<T>::IsEmpty;
using ForeignFifoBuffer<T>::IsFull;
using ForeignFifoBuffer<T>::GetAvailable;
@@ -103,7 +105,6 @@ public:
protected:
using ForeignFifoBuffer<T>::GetBuffer;
- using ForeignFifoBuffer<T>::GetCapacity;
};
#endif
diff --git a/src/util/TextFile.hxx b/src/util/TextFile.hxx
new file mode 100644
index 000000000..3d7d2d0df
--- /dev/null
+++ b/src/util/TextFile.hxx
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008-2014 Max Kellermann <max@duempel.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TEXT_FILE_HXX
+#define TEXT_FILE_HXX
+
+#include <string.h>
+
+template<typename B>
+char *
+ReadBufferedLine(B &buffer)
+{
+ auto r = buffer.Read();
+ char *newline = reinterpret_cast<char*>(memchr(r.data, '\n', r.size));
+ if (newline == nullptr)
+ return nullptr;
+
+ buffer.Consume(newline + 1 - r.data);
+
+ if (newline > r.data && newline[-1] == '\r')
+ --newline;
+ *newline = 0;
+ return r.data;
+}
+
+#endif