diff options
Diffstat (limited to '')
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 |