fs/io/Reader: use C++ exceptions instead of class Error

This commit is contained in:
Max Kellermann 2015-12-16 11:05:33 +01:00
parent fe60c52c70
commit e6e7d6dbd6
33 changed files with 192 additions and 334 deletions

View File

@ -277,13 +277,7 @@ static void help(void)
class ConfigLoader
{
Error &error;
bool result;
public:
ConfigLoader(Error &_error) : error(_error), result(false) { }
bool GetResult() const { return result; }
bool TryFile(const Path path);
bool TryFile(const AllocatedPath &base_path,
PathTraitsFS::const_pointer path);
@ -292,7 +286,7 @@ public:
bool ConfigLoader::TryFile(Path path)
{
if (FileExists(path)) {
result = ReadConfigFile(path, error);
ReadConfigFile(path);
return true;
}
return false;
@ -386,15 +380,16 @@ parse_cmdline(int argc, char **argv, struct options *options,
return false;
}
return ReadConfigFile(Path::FromFS(buffer), error);
ReadConfigFile(Path::FromFS(buffer));
#else
return ReadConfigFile(Path::FromFS(config_file), error);
ReadConfigFile(Path::FromFS(config_file));
#endif
return true;
}
/* use default configuration file path */
ConfigLoader loader(error);
ConfigLoader loader;
bool found =
#ifdef WIN32
@ -413,5 +408,5 @@ parse_cmdline(int argc, char **argv, struct options *options,
return false;
}
return loader.GetResult();
return true;
}

View File

@ -453,11 +453,8 @@ int mpd_main(int argc, char *argv[])
if (!sdcard.IsNull()) {
const auto config_path =
AllocatedPath::Build(sdcard, "mpd.conf");
if (FileExists(config_path) &&
!ReadConfigFile(config_path, error)) {
LogError(error);
return EXIT_FAILURE;
}
if (FileExists(config_path))
ReadConfigFile(config_path);
}
#else
if (!parse_cmdline(argc, argv, &options, error)) {

View File

@ -254,11 +254,7 @@ LoadPlaylistFile(const char *utf8path, Error &error)
if (path_fs.IsNull())
return contents;
TextFile file(path_fs, error);
if (file.HasFailed()) {
TranslatePlaylistError(error);
return contents;
}
TextFile file(path_fs);
char *s;
while ((s = file.ReadLine()) != nullptr) {

View File

@ -102,17 +102,12 @@ StateFile::Write()
void
StateFile::Read()
{
try {
bool success;
FormatDebug(state_file_domain, "Loading state file %s", path_utf8.c_str());
Error error;
TextFile file(path, error);
if (file.HasFailed()) {
LogError(error);
return;
}
TextFile file(path);
#ifdef ENABLE_DATABASE
const SongLoader song_loader(partition.instance.database,
@ -135,6 +130,8 @@ StateFile::Read()
}
RememberVersions();
} catch (const std::exception &e) {
LogError(e);
}
void

View File

@ -25,7 +25,6 @@
#include "ConfigTemplates.hxx"
#include "util/Tokenizer.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/RuntimeError.hxx"
#include "fs/Path.hxx"
@ -65,17 +64,14 @@ config_read_name_value(ConfigBlock &block, char *input, unsigned line)
}
static ConfigBlock *
config_read_block(BufferedReader &reader, Error &error)
config_read_block(BufferedReader &reader)
try {
std::unique_ptr<ConfigBlock> block(new ConfigBlock(reader.GetLineNumber()));
while (true) {
char *line = reader.ReadLine();
if (line == nullptr) {
if (reader.Check(error))
throw std::runtime_error("Expected '}' before end-of-file");
return nullptr;
}
if (line == nullptr)
throw std::runtime_error("Expected '}' before end-of-file");
line = StripLeft(line);
if (*line == 0 || *line == CONF_COMMENT)
@ -114,11 +110,10 @@ Append(ConfigBlock *&head, ConfigBlock *p)
*i = p;
}
static bool
static void
ReadConfigBlock(ConfigData &config_data, BufferedReader &reader,
const char *name, ConfigBlockOption o,
Tokenizer &tokenizer,
Error &error)
Tokenizer &tokenizer)
{
const unsigned i = unsigned(o);
const ConfigTemplate &option = config_block_templates[i];
@ -143,12 +138,9 @@ ReadConfigBlock(ConfigData &config_data, BufferedReader &reader,
throw FormatRuntimeError("line %u: Unknown tokens after '{'",
reader.GetLineNumber());
auto *param = config_read_block(reader, error);
if (param == nullptr)
return false;
auto *param = config_read_block(reader);
assert(param != nullptr);
Append(head, param);
return true;
}
gcc_nonnull_all
@ -196,13 +188,13 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
Append(head, param);
}
static bool
ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error)
static void
ReadConfigFile(ConfigData &config_data, BufferedReader &reader)
{
while (true) {
char *line = reader.ReadLine();
if (line == nullptr)
return true;
return;
line = StripLeft(line);
if (*line == 0 || *line == CONF_COMMENT)
@ -224,9 +216,8 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error)
ReadConfigParam(config_data, reader, name, o,
tokenizer);
} else if ((bo = ParseConfigBlockOptionName(name)) != ConfigBlockOption::MAX) {
if (!ReadConfigBlock(config_data, reader, name, bo,
tokenizer, error))
return false;
ReadConfigBlock(config_data, reader, name, bo,
tokenizer);
} else {
throw FormatRuntimeError("unrecognized parameter in config file at "
"line %u: %s\n",
@ -235,19 +226,16 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error)
}
}
bool
ReadConfigFile(ConfigData &config_data, Path path, Error &error)
void
ReadConfigFile(ConfigData &config_data, Path path)
{
assert(!path.IsNull());
const std::string path_utf8 = path.ToUTF8();
FormatDebug(config_file_domain, "loading file %s", path_utf8.c_str());
FileReader file(path, error);
if (!file.IsDefined())
return false;
FileReader file(path);
BufferedReader reader(file);
return ReadConfigFile(config_data, reader, error) &&
reader.Check(error);
ReadConfigFile(config_data, reader);
}

View File

@ -24,7 +24,7 @@ class Error;
class Path;
struct ConfigData;
bool
ReadConfigFile(ConfigData &data, Path path, Error &error);
void
ReadConfigFile(ConfigData &data, Path path);
#endif

View File

@ -45,10 +45,10 @@ void config_global_init(void)
{
}
bool
ReadConfigFile(Path path, Error &error)
void
ReadConfigFile(Path path)
{
return ReadConfigFile(config_data, path, error);
return ReadConfigFile(config_data, path);
}
static void

View File

@ -42,8 +42,8 @@ config_global_finish();
void
config_global_check();
bool
ReadConfigFile(Path path, Error &error);
void
ReadConfigFile(Path path);
gcc_pure
const config_param *

View File

@ -184,11 +184,9 @@ SimpleDatabase::Load(Error &error)
assert(!path.IsNull());
assert(root != nullptr);
TextFile file(path, error);
if (file.HasFailed())
return false;
TextFile file(path);
if (!db_load_internal(file, *root, error) || !file.Check(error))
if (!db_load_internal(file, *root, error))
return false;
FileInfo fi;
@ -200,7 +198,7 @@ SimpleDatabase::Load(Error &error)
bool
SimpleDatabase::Open(Error &error)
{
try {
assert(prefixed_light_song == nullptr);
root = Directory::NewRoot();
@ -223,6 +221,9 @@ SimpleDatabase::Open(Error &error)
}
return true;
} catch (const std::exception &e) {
error.Set(e);
return false;
}
void

View File

@ -27,41 +27,18 @@
#include "fs/Path.hxx"
#include "fs/NarrowPath.hxx"
#include "fs/io/TextFile.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "system/Error.hxx"
#include "Log.hxx"
#include <assert.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_CLASS_GLOB
gcc_pure
static bool
IsFileNotFound(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
}
#endif
bool
ExcludeList::LoadFile(Path path_fs)
{
try {
#ifdef HAVE_CLASS_GLOB
Error error;
TextFile file(path_fs, error);
if (file.HasFailed()) {
if (!IsFileNotFound(error))
LogError(error);
return false;
}
TextFile file(path_fs);
char *line;
while ((line = file.ReadLine()) != nullptr) {
@ -79,6 +56,13 @@ ExcludeList::LoadFile(Path path_fs)
#endif
return true;
} catch (const std::system_error &e) {
if (!IsFileNotFound(e))
LogError(e);
return false;
} catch (const std::exception &e) {
LogError(e);
return false;
}
bool

View File

@ -23,6 +23,7 @@
#include "check.h"
#include "Path.hxx"
#include "util/Error.hxx"
#include "system/Error.hxx"
#include <stdint.h>
@ -63,6 +64,20 @@ class FileInfo {
#endif
public:
FileInfo() = default;
FileInfo(Path path, bool follow_symlinks=true) {
if (!GetFileInfo(path, *this, follow_symlinks)) {
#ifdef WIN32
throw FormatLastError("Failed to access %s",
path.ToUTF8().c_str());
#else
throw FormatErrno("Failed to access %s",
path.ToUTF8().c_str());
#endif
}
}
bool IsRegular() const {
#ifdef WIN32
return (data.dwFileAttributes &

View File

@ -200,20 +200,21 @@ ParseConfigLine(char *line, const char *dir_name, AllocatedPath &result_dir)
}
static AllocatedPath GetUserDir(const char *name)
{
try {
auto result = AllocatedPath::Null();
auto config_dir = GetUserConfigDir();
if (config_dir.IsNull())
return result;
auto dirs_file = AllocatedPath::Build(config_dir, "user-dirs.dirs");
TextFile input(dirs_file, IgnoreError());
if (input.HasFailed())
return result;
TextFile input(dirs_file);
char *line;
while ((line = input.ReadLine()) != nullptr)
if (ParseConfigLine(line, name, result))
return result;
return result;
} catch (const std::exception &e) {
return AllocatedPath::Null();
}
#endif

View File

@ -20,7 +20,6 @@
#include "config.h"
#include "AutoGunzipReader.hxx"
#include "GunzipReader.hxx"
#include "util/Error.hxx"
AutoGunzipReader::~AutoGunzipReader()
{
@ -35,36 +34,27 @@ IsGzip(const uint8_t data[4])
(data[3] & 0xe0) == 0;
}
inline bool
AutoGunzipReader::Detect(Error &error)
inline void
AutoGunzipReader::Detect()
{
const uint8_t *data = (const uint8_t *)peek.Peek(4, error);
const uint8_t *data = (const uint8_t *)peek.Peek(4);
if (data == nullptr) {
if (error.IsDefined())
return false;
next = &peek;
return true;
return;
}
if (IsGzip(data)) {
gunzip = new GunzipReader(peek, error);
if (!gunzip->IsDefined())
return false;
next = gunzip;
} else
if (IsGzip(data))
next = gunzip = new GunzipReader(peek);
else
next = &peek;
return true;
}
size_t
AutoGunzipReader::Read(void *data, size_t size, Error &error)
AutoGunzipReader::Read(void *data, size_t size)
{
if (next == nullptr && !Detect(error))
return false;
if (next == nullptr)
Detect();
return next->Read(data, size, error);
assert(next != nullptr);
return next->Read(data, size);
}

View File

@ -43,10 +43,10 @@ public:
~AutoGunzipReader();
/* virtual methods from class Reader */
virtual size_t Read(void *data, size_t size, Error &error) override;
virtual size_t Read(void *data, size_t size) override;
private:
bool Detect(Error &error);
void Detect();
};
#endif

View File

@ -25,9 +25,6 @@
bool
BufferedReader::Fill(bool need_more)
{
if (gcc_unlikely(last_error.IsDefined()))
return false;
if (eof)
return !need_more;
@ -41,11 +38,8 @@ BufferedReader::Fill(bool need_more)
assert(!w.IsEmpty());
}
size_t nbytes = reader.Read(w.data, w.size, last_error);
size_t nbytes = reader.Read(w.data, w.size);
if (nbytes == 0) {
if (gcc_unlikely(last_error.IsDefined()))
return false;
eof = true;
return !need_more;
}
@ -65,7 +59,7 @@ BufferedReader::ReadLine()
}
} while (Fill(true));
if (last_error.IsDefined() || !eof || buffer.IsEmpty())
if (!eof || buffer.IsEmpty())
return nullptr;
auto w = buffer.Write();

View File

@ -23,12 +23,10 @@
#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;
@ -37,8 +35,6 @@ class BufferedReader {
DynamicFifoBuffer<char> buffer;
Error last_error;
bool eof;
unsigned line_number;
@ -48,19 +44,6 @@ public:
:reader(_reader), buffer(4096), eof(false),
line_number(0) {}
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

View File

@ -20,57 +20,49 @@
#include "config.h"
#include "FileReader.hxx"
#include "fs/FileInfo.hxx"
#include "util/Error.hxx"
#include "system/Error.hxx"
#ifdef WIN32
FileReader::FileReader(Path _path, Error &error)
FileReader::FileReader(Path _path)
:path(_path),
handle(CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr))
{
if (handle == INVALID_HANDLE_VALUE) {
const auto path_utf8 = path.ToUTF8();
error.FormatLastError("Failed to open %s", path_utf8.c_str());
}
if (handle == INVALID_HANDLE_VALUE)
throw FormatLastError("Failed to open %s", path.ToUTF8().c_str());
}
bool
FileReader::GetFileInfo(FileInfo &info, Error &error) const
FileInfo
FileReader::GetFileInfo() const
{
assert(IsDefined());
return ::GetFileInfo(path, info, error);
return FileInfo(path);
}
size_t
FileReader::Read(void *data, size_t size, Error &error)
FileReader::Read(void *data, size_t size)
{
assert(IsDefined());
DWORD nbytes;
if (!ReadFile(handle, data, size, &nbytes, nullptr)) {
const auto path_utf8 = path.ToUTF8();
error.FormatLastError("Failed to read from %s",
path_utf8.c_str());
nbytes = 0;
}
if (!ReadFile(handle, data, size, &nbytes, nullptr))
throw FormatLastError("Failed to read from %s",
path.ToUTF8().c_str());
return nbytes;
}
bool
FileReader::Seek(off_t offset, Error &error)
void
FileReader::Seek(off_t offset)
{
assert(IsDefined());
auto result = SetFilePointer(handle, offset, nullptr, FILE_BEGIN);
const bool success = result != INVALID_SET_FILE_POINTER;
if (!success)
error.SetLastError("Failed to seek");
return success;
if (result == INVALID_SET_FILE_POINTER)
throw MakeLastError("Failed to seek");
}
void
@ -83,52 +75,49 @@ FileReader::Close()
#else
FileReader::FileReader(Path _path, Error &error)
FileReader::FileReader(Path _path)
:path(_path)
{
fd.OpenReadOnly(path.c_str());
if (!fd.IsDefined())
error.FormatErrno("Failed to open %s", path.c_str());
throw FormatErrno("Failed to open %s", path.ToUTF8().c_str());
}
bool
FileReader::GetFileInfo(FileInfo &info, Error &error) const
FileInfo
FileReader::GetFileInfo() const
{
assert(IsDefined());
FileInfo info;
const bool success = fstat(fd.Get(), &info.st) == 0;
if (!success)
error.FormatErrno("Failed to access %s",
throw FormatErrno("Failed to access %s",
path.ToUTF8().c_str());
return success;
return info;
}
size_t
FileReader::Read(void *data, size_t size, Error &error)
FileReader::Read(void *data, size_t size)
{
assert(IsDefined());
ssize_t nbytes = fd.Read(data, size);
if (nbytes < 0) {
error.FormatErrno("Failed to read from %s", path.c_str());
nbytes = 0;
}
if (nbytes < 0)
throw FormatErrno("Failed to read from %s", path.ToUTF8().c_str());
return nbytes;
}
bool
FileReader::Seek(off_t offset, Error &error)
void
FileReader::Seek(off_t offset)
{
assert(IsDefined());
auto result = fd.Seek(offset);
const bool success = result >= 0;
if (!success)
error.SetErrno("Failed to seek");
return success;
throw MakeErrno("Failed to seek");
}
void

View File

@ -48,7 +48,7 @@ class FileReader final : public Reader {
#endif
public:
FileReader(Path _path, Error &error);
FileReader(Path _path);
#ifdef WIN32
FileReader(FileReader &&other)
@ -70,6 +70,7 @@ public:
}
protected:
bool IsDefined() const {
#ifdef WIN32
return handle != INVALID_HANDLE_VALUE;
@ -78,6 +79,7 @@ public:
#endif
}
public:
#ifndef WIN32
FileDescriptor GetFD() const {
return fd;
@ -86,12 +88,13 @@ public:
void Close();
bool GetFileInfo(FileInfo &info, Error &error) const;
gcc_pure
FileInfo GetFileInfo() const;
bool Seek(off_t offset, Error &error);
void Seek(off_t offset);
/* virtual methods from class Reader */
size_t Read(void *data, size_t size, Error &error) override;
size_t Read(void *data, size_t size) override;
};
#endif

View File

@ -20,10 +20,8 @@
#include "config.h"
#include "GunzipReader.hxx"
#include "lib/zlib/Domain.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
GunzipReader::GunzipReader(Reader &_next, Error &error)
GunzipReader::GunzipReader(Reader &_next) throw(ZlibError)
:next(_next), eof(false)
{
z.next_in = nullptr;
@ -33,25 +31,17 @@ GunzipReader::GunzipReader(Reader &_next, Error &error)
z.opaque = Z_NULL;
int result = inflateInit2(&z, 16 + MAX_WBITS);
if (result != Z_OK) {
z.opaque = this;
error.Set(zlib_domain, result, zError(result));
}
}
GunzipReader::~GunzipReader()
{
if (IsDefined())
inflateEnd(&z);
if (result != Z_OK)
throw ZlibError(result);
}
inline bool
GunzipReader::FillBuffer(Error &error)
GunzipReader::FillBuffer()
{
auto w = buffer.Write();
assert(!w.IsEmpty());
size_t nbytes = next.Read(w.data, w.size, error);
size_t nbytes = next.Read(w.data, w.size);
if (nbytes == 0)
return false;
@ -60,7 +50,7 @@ GunzipReader::FillBuffer(Error &error)
}
size_t
GunzipReader::Read(void *data, size_t size, Error &error)
GunzipReader::Read(void *data, size_t size)
{
if (eof)
return 0;
@ -73,10 +63,8 @@ GunzipReader::Read(void *data, size_t size, Error &error)
auto r = buffer.Read();
if (r.IsEmpty()) {
if (FillBuffer(error))
if (FillBuffer())
r = buffer.Read();
else if (error.IsDefined())
return 0;
else
flush = Z_FINISH;
}
@ -88,10 +76,8 @@ GunzipReader::Read(void *data, size_t size, Error &error)
if (result == Z_STREAM_END) {
eof = true;
return size - z.avail_out;
} else if (result != Z_OK) {
error.Set(zlib_domain, result, zError(result));
return 0;
}
} else if (result != Z_OK)
throw ZlibError(result);
buffer.Consume(r.size - z.avail_in);

View File

@ -23,13 +23,11 @@
#include "check.h"
#include "Reader.hxx"
#include "util/StaticFifoBuffer.hxx"
#include "lib/zlib/Error.hxx"
#include "Compiler.h"
#include <zlib.h>
class Error;
class Domain;
/**
* A filter that decompresses data using zlib.
*/
@ -44,25 +42,19 @@ class GunzipReader final : public Reader {
public:
/**
* Construct the filter. Call IsDefined() to check whether
* the constructor has succeeded. If not, #error will hold
* information about the failure.
* Construct the filter.
*/
GunzipReader(Reader &_next, Error &error);
~GunzipReader();
GunzipReader(Reader &_next) throw(ZlibError);
/**
* Check whether the constructor has succeeded.
*/
bool IsDefined() const {
return z.opaque == nullptr;
~GunzipReader() {
inflateEnd(&z);
}
/* virtual methods from class Reader */
virtual size_t Read(void *data, size_t size, Error &error) override;
size_t Read(void *data, size_t size) override;
private:
bool FillBuffer(Error &error);
bool FillBuffer();
};
#endif

View File

@ -26,7 +26,7 @@
#include <string.h>
const void *
PeekReader::Peek(size_t size, Error &error)
PeekReader::Peek(size_t size)
{
assert(size > 0);
assert(size < sizeof(buffer));
@ -35,7 +35,7 @@ PeekReader::Peek(size_t size, Error &error)
do {
size_t nbytes = next.Read(buffer + buffer_size,
size - buffer_size, error);
size - buffer_size);
if (nbytes == 0)
return nullptr;
@ -46,7 +46,7 @@ PeekReader::Peek(size_t size, Error &error)
}
size_t
PeekReader::Read(void *data, size_t size, Error &error)
PeekReader::Read(void *data, size_t size)
{
size_t buffer_remaining = buffer_size - buffer_position;
if (buffer_remaining > 0) {
@ -56,5 +56,5 @@ PeekReader::Read(void *data, size_t size, Error &error)
return nbytes;
}
return next.Read(data, size, error);
return next.Read(data, size);
}

View File

@ -44,10 +44,10 @@ public:
PeekReader(Reader &_next)
:next(_next), buffer_size(0), buffer_position(0) {}
const void *Peek(size_t size, Error &error);
const void *Peek(size_t size);
/* virtual methods from class Reader */
virtual size_t Read(void *data, size_t size, Error &error) override;
virtual size_t Read(void *data, size_t size) override;
};
#endif

View File

@ -25,8 +25,6 @@
#include <stddef.h>
class Error;
/**
* An interface that can read bytes from a stream until the stream
* ends.
@ -43,10 +41,10 @@ public:
* Read data from the stream.
*
* @return the number of bytes read into the given buffer or 0
* on error/end-of-stream
* on end-of-stream
*/
gcc_nonnull_all
virtual size_t Read(void *data, size_t size, Error &error) = 0;
virtual size_t Read(void *data, size_t size) = 0;
};
#endif

View File

@ -26,22 +26,18 @@
#include <assert.h>
TextFile::TextFile(Path path_fs, Error &error)
:file_reader(new FileReader(path_fs, error)),
TextFile::TextFile(Path path_fs)
:file_reader(new FileReader(path_fs)),
#ifdef ENABLE_ZLIB
gunzip_reader(file_reader->IsDefined()
? new AutoGunzipReader(*file_reader)
: nullptr),
gunzip_reader(new AutoGunzipReader(*file_reader)),
#endif
buffered_reader(file_reader->IsDefined()
? new BufferedReader(*
buffered_reader(new BufferedReader(*
#ifdef ENABLE_ZLIB
gunzip_reader
gunzip_reader
#else
file_reader
file_reader
#endif
)
: nullptr)
))
{
}
@ -61,11 +57,3 @@ TextFile::ReadLine()
return buffered_reader->ReadLine();
}
bool
TextFile::Check(Error &error) const
{
assert(buffered_reader != nullptr);
return buffered_reader->Check(error);
}

View File

@ -23,10 +23,7 @@
#include "check.h"
#include "Compiler.h"
#include <stddef.h>
class Path;
class Error;
class FileReader;
class AutoGunzipReader;
class BufferedReader;
@ -41,32 +38,20 @@ class TextFile {
BufferedReader *const buffered_reader;
public:
TextFile(Path path_fs, Error &error);
TextFile(Path path_fs);
TextFile(const TextFile &other) = delete;
~TextFile();
bool HasFailed() const {
return gcc_unlikely(buffered_reader == nullptr);
}
/**
* Reads a line from the input file, and strips trailing
* space. There is a reasonable maximum line length, only to
* prevent denial of service.
*
* Use Check() after nullptr has been returned to check
* whether an error occurred or end-of-file has been reached.
*
* @return a pointer to the line, or nullptr on end-of-file or error
* @return a pointer to the line, or nullptr on end-of-file
*/
char *ReadLine();
/**
* Check whether a ReadLine() call has thrown an error.
*/
bool Check(Error &error) const;
};
#endif

View File

@ -61,14 +61,10 @@ InputStream *
OpenFileInputStream(Path path,
Mutex &mutex, Cond &cond,
Error &error)
{
FileReader reader(path, error);
if (!reader.IsDefined())
return nullptr;
try {
FileReader reader(path);
FileInfo info;
if (!reader.GetFileInfo(info, error))
return nullptr;
const FileInfo info = reader.GetFileInfo();
if (!info.IsRegular()) {
error.Format(file_domain, "Not a regular file: %s",
@ -84,6 +80,9 @@ OpenFileInputStream(Path path,
return new FileInputStream(path.ToUTF8().c_str(),
std::move(reader), info.GetSize(),
mutex, cond);
} catch (const std::exception &e) {
error.Set(e);
return nullptr;
}
static InputStream *
@ -98,23 +97,24 @@ input_file_open(gcc_unused const char *filename,
bool
FileInputStream::Seek(offset_type new_offset, Error &error)
{
if (!reader.Seek((off_t)new_offset, error))
return false;
try {
reader.Seek((off_t)new_offset);
offset = new_offset;
return true;
} catch (const std::exception &e) {
error.Set(e);
return false;
}
size_t
FileInputStream::Read(void *ptr, size_t read_size, Error &error)
{
ssize_t nbytes = reader.Read(ptr, read_size, error);
if (nbytes < 0)
return 0;
try {
size_t nbytes = reader.Read(ptr, read_size);
offset += nbytes;
return (size_t)nbytes;
return nbytes;
} catch (const std::exception &e) {
error.Set(e);
return 0;
}
const InputPlugin input_plugin_file = {

View File

@ -110,10 +110,7 @@ try {
config_global_init();
Error error;
if (!ReadConfigFile(config_path, error)) {
cerr << error.GetMessage() << endl;
return EXIT_FAILURE;
}
ReadConfigFile(config_path);
TagLoadConfig();

View File

@ -65,10 +65,7 @@ try {
config_global_init();
Error error;
if (!ReadConfigFile(config_path, error)) {
LogError(error);
return EXIT_FAILURE;
}
ReadConfigFile(config_path);
const ScopeIOThread io_thread;

View File

@ -20,7 +20,6 @@
#include "config.h"
#include "config/ConfigGlobal.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include <assert.h>
@ -39,11 +38,7 @@ try {
config_global_init();
Error error;
if (!ReadConfigFile(config_path, error)) {
LogError(error);
return EXIT_FAILURE;
}
ReadConfigFile(config_path);
ConfigOption option = ParseConfigOptionName(name);
const char *value = option != ConfigOption::MAX

View File

@ -69,7 +69,6 @@ load_filter(const char *name)
int main(int argc, char **argv)
try {
struct audio_format_string af_string;
Error error2;
char buffer[4096];
if (argc < 3 || argc > 4) {
@ -84,8 +83,7 @@ try {
/* read configuration file (mpd.conf) */
config_global_init();
if (!ReadConfigFile(config_path, error2))
FatalError(error2);
ReadConfigFile(config_path);
/* parse the audio format */

View File

@ -28,32 +28,32 @@
#include <stdlib.h>
#include <unistd.h>
static bool
Copy(OutputStream &dest, Reader &src, Error &error)
static void
Copy(OutputStream &dest, Reader &src)
{
while (true) {
char buffer[4096];
size_t nbytes = src.Read(buffer, sizeof(buffer), error);
size_t nbytes = src.Read(buffer, sizeof(buffer));
if (nbytes == 0)
return !error.IsDefined();
break;
dest.Write(buffer, nbytes);
}
}
static bool
CopyGunzip(OutputStream &dest, Reader &_src, Error &error)
static void
CopyGunzip(OutputStream &dest, Reader &_src)
{
GunzipReader src(_src, error);
return src.IsDefined() && Copy(dest, src, error);
GunzipReader src(_src);
Copy(dest, src);
}
static bool
CopyGunzip(FILE *_dest, Path src_path, Error &error)
static void
CopyGunzip(FILE *_dest, Path src_path)
{
StdioOutputStream dest(_dest);
FileReader src(src_path, error);
return src.IsDefined() && CopyGunzip(dest, src, error);
FileReader src(src_path);
CopyGunzip(dest, src);
}
int
@ -67,12 +67,7 @@ main(int argc, gcc_unused char **argv)
Path path = Path::FromFS(argv[1]);
try {
Error error;
if (!CopyGunzip(stdout, path, error)) {
fprintf(stderr, "%s\n", error.GetMessage());
return EXIT_FAILURE;
}
CopyGunzip(stdout, path);
return EXIT_SUCCESS;
} catch (const std::exception &e) {
LogError(e);

View File

@ -59,10 +59,7 @@ try {
Error error;
config_global_init();
if (!ReadConfigFile(config_path, error)) {
LogError(error);
return EXIT_FAILURE;
}
ReadConfigFile(config_path);
/* initialize the core */

View File

@ -161,10 +161,7 @@ try {
/* read configuration file (mpd.conf) */
config_global_init();
if (!ReadConfigFile(config_path, error)) {
LogError(error);
return EXIT_FAILURE;
}
ReadConfigFile(config_path);
EventLoop event_loop;