input/InputStream: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann
2016-09-09 18:47:42 +02:00
parent 597e59f10d
commit 8c744efd56
64 changed files with 440 additions and 473 deletions

View File

@@ -21,10 +21,9 @@
#include "Aiff.hxx"
#include "input/InputStream.hxx"
#include "system/ByteOrder.hxx"
#include "Log.hxx"
#include "util/Error.hxx"
#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <string.h>
@@ -45,33 +44,27 @@ aiff_seek_id3(InputStream &is)
{
/* seek to the beginning and read the AIFF header */
Error error;
if (!is.Rewind(error)) {
LogError(error, "Failed to seek");
return 0;
}
is.Rewind();
aiff_header header;
if (!is.ReadFull(&header, sizeof(header), IgnoreError()) ||
memcmp(header.id, "FORM", 4) != 0 ||
is.ReadFull(&header, sizeof(header));
if (memcmp(header.id, "FORM", 4) != 0 ||
(is.KnownSize() && FromLE32(header.size) > is.GetSize()) ||
(memcmp(header.format, "AIFF", 4) != 0 &&
memcmp(header.format, "AIFC", 4) != 0))
/* not a AIFF file */
return 0;
throw std::runtime_error("Not an AIFF file");
while (true) {
/* read the chunk header */
aiff_chunk_header chunk;
if (!is.ReadFull(&chunk, sizeof(chunk), IgnoreError()))
return 0;
is.ReadFull(&chunk, sizeof(chunk));
size_t size = FromBE32(chunk.size);
if (size > size_t(std::numeric_limits<int>::max()))
/* too dangerous, bail out: possible integer
underflow when casting to off_t */
return 0;
throw std::runtime_error("AIFF chunk is too large");
if (memcmp(chunk.id, "ID3 ", 4) == 0)
/* found it! */
@@ -81,7 +74,6 @@ aiff_seek_id3(InputStream &is)
/* pad byte */
++size;
if (!is.Skip(size, IgnoreError()))
return 0;
is.Skip(size);
}
}

View File

@@ -32,9 +32,10 @@ class InputStream;
/**
* Seeks the AIFF file to the ID3 chunk.
*
* Throws std::runtime_error on error.
*
* @param is a locked #InputStream
* @return the size of the ID3 chunk on success, or 0 if this is not a
* AIFF file or no ID3 chunk was found
* @return the size of the ID3 chunk
*/
size_t
aiff_seek_id3(InputStream &is);

View File

@@ -50,9 +50,10 @@ try {
/* determine if file has an apeV2 tag */
ApeFooter footer;
if (!is.Seek(is.GetSize() - sizeof(footer), IgnoreError()) ||
!is.ReadFull(&footer, sizeof(footer), IgnoreError()) ||
memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0 ||
is.Seek(is.GetSize() - sizeof(footer));
is.ReadFull(&footer, sizeof(footer));
if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0 ||
FromLE32(footer.version) != 2000)
return false;
@@ -60,17 +61,17 @@ try {
size_t remaining = FromLE32(footer.length);
if (remaining <= sizeof(footer) + 10 ||
/* refuse to load more than one megabyte of tag data */
remaining > 1024 * 1024 ||
!is.Seek(is.GetSize() - remaining, IgnoreError()))
remaining > 1024 * 1024)
return false;
is.Seek(is.GetSize() - remaining);
/* read tag into buffer */
remaining -= sizeof(footer);
assert(remaining > 10);
std::unique_ptr<char[]> buffer(new char[remaining]);
if (!is.ReadFull(buffer.get(), remaining, IgnoreError()))
return false;
is.ReadFull(buffer.get(), remaining);
/* read tags */
unsigned n = FromLE32(footer.count);

View File

@@ -38,8 +38,11 @@ ScanGenericTags(InputStream &is, const TagHandler &handler, void *ctx)
return true;
#ifdef ENABLE_ID3TAG
if (!is.LockRewind(IgnoreError()))
try {
is.LockRewind();
} catch (const std::runtime_error &) {
return false;
}
return tag_id3_scan(is, handler, ctx);
#else

View File

@@ -19,8 +19,6 @@
#include "config.h"
#include "Id3Load.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
#include "Riff.hxx"
#include "Aiff.hxx"
@@ -31,8 +29,6 @@
#include <algorithm>
#include <stdexcept>
static constexpr Domain id3_domain("id3");
static constexpr size_t ID3V1_SIZE = 128;
gcc_pure
@@ -46,11 +42,8 @@ static long
get_id3v2_footer_size(InputStream &is, offset_type offset)
try {
id3_byte_t buf[ID3_TAG_QUERYSIZE];
if (!is.Seek(offset, IgnoreError()))
return 0;
if (!is.ReadFull(buf, sizeof(buf), IgnoreError()))
return 0;
is.Seek(offset);
is.ReadFull(buf, sizeof(buf));
return id3_tag_query(buf, sizeof(buf));
} catch (const std::runtime_error &) {
@@ -61,8 +54,7 @@ static UniqueId3Tag
ReadId3Tag(InputStream &is)
try {
id3_byte_t query_buffer[ID3_TAG_QUERYSIZE];
if (!is.ReadFull(query_buffer, sizeof(query_buffer), IgnoreError()))
return nullptr;
is.ReadFull(query_buffer, sizeof(query_buffer));
/* Look for a tag header */
long tag_size = id3_tag_query(query_buffer, sizeof(query_buffer));
@@ -82,9 +74,7 @@ try {
/* now read the remaining bytes */
const size_t remaining = tag_size - sizeof(query_buffer);
const size_t nbytes = is.Read(end, remaining, IgnoreError());
if (nbytes != remaining)
return nullptr;
is.ReadFull(end, remaining);
return UniqueId3Tag(id3_tag_parse(tag_buffer.get(), tag_size));
} catch (const std::runtime_error &) {
@@ -94,8 +84,7 @@ try {
static UniqueId3Tag
ReadId3Tag(InputStream &is, offset_type offset)
try {
if (!is.Seek(offset, IgnoreError()))
return nullptr;
is.Seek(offset);
return ReadId3Tag(is);
} catch (const std::runtime_error &) {
@@ -106,9 +95,7 @@ static UniqueId3Tag
ReadId3v1Tag(InputStream &is)
try {
id3_byte_t buffer[ID3V1_SIZE];
if (is.Read(buffer, ID3V1_SIZE, IgnoreError()) != ID3V1_SIZE)
return nullptr;
is.ReadFull(buffer, ID3V1_SIZE);
return UniqueId3Tag(id3_tag_parse(buffer, ID3V1_SIZE));
} catch (const std::runtime_error &) {
@@ -118,9 +105,7 @@ try {
static UniqueId3Tag
ReadId3v1Tag(InputStream &is, offset_type offset)
try {
if (!is.Seek(offset, IgnoreError()))
return nullptr;
is.Seek(offset);
return ReadId3v1Tag(is);
} catch (const std::runtime_error &) {
return nullptr;
@@ -203,21 +188,19 @@ try {
static UniqueId3Tag
tag_id3_riff_aiff_load(InputStream &is)
try {
size_t size = riff_seek_id3(is);
if (size == 0)
size_t size;
try {
size = riff_seek_id3(is);
} catch (const std::runtime_error &) {
size = aiff_seek_id3(is);
if (size == 0)
return nullptr;
}
if (size > 4 * 1024 * 1024)
/* too large, don't allocate so much memory */
return nullptr;
std::unique_ptr<id3_byte_t[]> buffer(new id3_byte_t[size]);
if (!is.ReadFull(buffer.get(), size, IgnoreError())) {
LogWarning(id3_domain, "Failed to read RIFF chunk");
return nullptr;
}
is.ReadFull(buffer.get(), size);
return UniqueId3Tag(id3_tag_parse(buffer.get(), size));
} catch (const std::runtime_error &) {

View File

@@ -21,10 +21,9 @@
#include "Riff.hxx"
#include "input/InputStream.hxx"
#include "system/ByteOrder.hxx"
#include "Log.hxx"
#include "util/Error.hxx"
#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <string.h>
@@ -45,31 +44,25 @@ riff_seek_id3(InputStream &is)
{
/* seek to the beginning and read the RIFF header */
Error error;
if (!is.Rewind(error)) {
LogError(error, "Failed to seek");
return 0;
}
is.Rewind();
riff_header header;
if (!is.ReadFull(&header, sizeof(header), IgnoreError()) ||
memcmp(header.id, "RIFF", 4) != 0 ||
is.ReadFull(&header, sizeof(header));
if (memcmp(header.id, "RIFF", 4) != 0 ||
(is.KnownSize() && FromLE32(header.size) > is.GetSize()))
/* not a RIFF file */
return 0;
throw std::runtime_error("Not a RIFF file");
while (true) {
/* read the chunk header */
riff_chunk_header chunk;
if (!is.ReadFull(&chunk, sizeof(chunk), IgnoreError()))
return 0;
is.ReadFull(&chunk, sizeof(chunk));
size_t size = FromLE32(chunk.size);
if (size > size_t(std::numeric_limits<int>::max()))
/* too dangerous, bail out: possible integer
underflow when casting to off_t */
return 0;
throw std::runtime_error("RIFF chunk is too large");
if (memcmp(chunk.id, "id3 ", 4) == 0 ||
memcmp(chunk.id, "ID3 ", 4) == 0)
@@ -80,7 +73,6 @@ riff_seek_id3(InputStream &is)
/* pad byte */
++size;
if (!is.Skip(size, IgnoreError()))
return 0;
is.Skip(size);
}
}

View File

@@ -32,9 +32,10 @@ class InputStream;
/**
* Seeks the RIFF file to the ID3 chunk.
*
* Throws std::runtime_error on error.
*
* @param is a locked #InputStream
* @return the size of the ID3 chunk on success, or 0 if this is not a
* RIFF file or no ID3 chunk was found
* @return the size of the ID3 chunk
*/
size_t
riff_seek_id3(InputStream &is);