mirror of
https://github.com/SerenityOS/serenity
synced 2024-07-21 10:05:32 +00:00
Streams: Distinguish recoverable and fatal errors.
This commit is contained in:
parent
daeb2bdc60
commit
9ce4475907
|
@ -57,7 +57,7 @@ public:
|
|||
bool read_or_error(Bytes bytes) override
|
||||
{
|
||||
if (read(bytes) != bytes.size()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ public:
|
|||
if (m_bit_offset++ == 7)
|
||||
m_next_byte.clear();
|
||||
} else if (m_stream.eof()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
} else {
|
||||
m_stream >> m_next_byte;
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
bool write_or_error(ReadonlyBytes bytes) override
|
||||
{
|
||||
if (Capacity - m_queue.size() < bytes.size()) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -70,10 +70,8 @@ public:
|
|||
|
||||
size_t read(Bytes bytes, size_t seekback)
|
||||
{
|
||||
ASSERT(seekback <= Capacity);
|
||||
|
||||
if (seekback > m_total_written) {
|
||||
m_error = true;
|
||||
if (seekback > Capacity || seekback > m_total_written) {
|
||||
set_recoverable_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -90,7 +88,7 @@ public:
|
|||
bool read_or_error(Bytes bytes) override
|
||||
{
|
||||
if (m_queue.size() < bytes.size()) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -101,7 +99,7 @@ public:
|
|||
bool discard_or_error(size_t count) override
|
||||
{
|
||||
if (m_queue.size() < count) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
47
AK/Stream.h
47
AK/Stream.h
|
@ -40,17 +40,36 @@ namespace AK::Detail {
|
|||
|
||||
class Stream {
|
||||
public:
|
||||
virtual ~Stream()
|
||||
virtual ~Stream() { ASSERT(!has_any_error()); }
|
||||
|
||||
bool has_recoverable_error() const { return m_recoverable_error; }
|
||||
bool has_fatal_error() const { return m_fatal_error; }
|
||||
bool has_any_error() const { return has_recoverable_error() || has_fatal_error(); }
|
||||
|
||||
bool handle_recoverable_error()
|
||||
{
|
||||
ASSERT(!has_error());
|
||||
ASSERT(!has_fatal_error());
|
||||
return exchange(m_recoverable_error, false);
|
||||
}
|
||||
bool handle_fatal_error() { return exchange(m_fatal_error, false); }
|
||||
bool handle_any_error()
|
||||
{
|
||||
if (has_any_error()) {
|
||||
m_recoverable_error = false;
|
||||
m_fatal_error = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_error() const { return m_error; }
|
||||
void set_recoverable_error() const { m_recoverable_error = true; }
|
||||
void set_fatal_error() const { m_fatal_error = true; }
|
||||
|
||||
bool handle_error() { return exchange(m_error, false); }
|
||||
|
||||
protected:
|
||||
mutable bool m_error { false };
|
||||
private:
|
||||
mutable bool m_recoverable_error { false };
|
||||
mutable bool m_fatal_error { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -200,7 +219,7 @@ public:
|
|||
bool read_or_error(Bytes bytes) override
|
||||
{
|
||||
if (remaining() < bytes.size()) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -212,7 +231,7 @@ public:
|
|||
bool discard_or_error(size_t count) override
|
||||
{
|
||||
if (remaining() < count) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -229,7 +248,7 @@ public:
|
|||
u8 peek_or_error() const
|
||||
{
|
||||
if (remaining() == 0) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -248,7 +267,7 @@ public:
|
|||
// past the end, this is fixed here.
|
||||
if (eof()) {
|
||||
m_offset = backup;
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -277,7 +296,7 @@ public:
|
|||
// past the end, this is fixed here.
|
||||
if (eof()) {
|
||||
m_offset = backup;
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -320,7 +339,7 @@ public:
|
|||
bool discard_or_error(size_t count) override
|
||||
{
|
||||
if (m_write_offset - m_read_offset < count) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -411,7 +430,7 @@ public:
|
|||
bool read_or_error(Bytes bytes) override
|
||||
{
|
||||
if (m_write_offset - m_read_offset < bytes.size()) {
|
||||
m_error = true;
|
||||
set_recoverable_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -288,8 +288,7 @@ inline InputStream& operator>>(InputStream& stream, String& string)
|
|||
if (stream.eof()) {
|
||||
string = nullptr;
|
||||
|
||||
// FIXME: We need an InputStream::set_error_flag method.
|
||||
stream.discard_or_error(1);
|
||||
stream.set_fatal_error();
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ TEST_CASE(read_an_integer)
|
|||
InputMemoryStream stream { { &expected, sizeof(expected) } };
|
||||
stream >> actual;
|
||||
|
||||
EXPECT(!stream.has_error() && stream.eof());
|
||||
EXPECT(!stream.has_any_error() && stream.eof());
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
|
@ -60,15 +60,15 @@ TEST_CASE(recoverable_error)
|
|||
|
||||
InputMemoryStream stream { { &expected, sizeof(expected) } };
|
||||
|
||||
EXPECT(!stream.has_error() && !stream.eof());
|
||||
EXPECT(!stream.has_any_error() && !stream.eof());
|
||||
stream >> to_large_value;
|
||||
EXPECT(stream.has_error() && !stream.eof());
|
||||
EXPECT(stream.has_recoverable_error() && !stream.eof());
|
||||
|
||||
EXPECT(stream.handle_error());
|
||||
EXPECT(!stream.has_error() && !stream.eof());
|
||||
EXPECT(stream.handle_recoverable_error());
|
||||
EXPECT(!stream.has_any_error() && !stream.eof());
|
||||
|
||||
stream >> actual;
|
||||
EXPECT(!stream.has_error() && stream.eof());
|
||||
EXPECT(!stream.has_any_error() && stream.eof());
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ TEST_CASE(chain_stream_operator)
|
|||
InputMemoryStream stream { { expected, sizeof(expected) } };
|
||||
|
||||
stream >> actual[0] >> actual[1] >> actual[2] >> actual[3];
|
||||
EXPECT(!stream.has_error() && stream.eof());
|
||||
EXPECT(!stream.has_any_error() && stream.eof());
|
||||
|
||||
EXPECT(compare({ expected, sizeof(expected) }, { actual, sizeof(actual) }));
|
||||
}
|
||||
|
@ -95,17 +95,17 @@ TEST_CASE(seeking_slicing_offset)
|
|||
InputMemoryStream stream { { input, sizeof(input) } };
|
||||
|
||||
stream >> Bytes { actual0, sizeof(actual0) };
|
||||
EXPECT(!stream.has_error() && !stream.eof());
|
||||
EXPECT(!stream.has_any_error() && !stream.eof());
|
||||
EXPECT(compare({ expected0, sizeof(expected0) }, { actual0, sizeof(actual0) }));
|
||||
|
||||
stream.seek(4);
|
||||
stream >> Bytes { actual1, sizeof(actual1) };
|
||||
EXPECT(!stream.has_error() && stream.eof());
|
||||
EXPECT(!stream.has_any_error() && stream.eof());
|
||||
EXPECT(compare({ expected1, sizeof(expected1) }, { actual1, sizeof(actual1) }));
|
||||
|
||||
stream.seek(1);
|
||||
stream >> Bytes { actual2, sizeof(actual2) };
|
||||
EXPECT(!stream.has_error() && !stream.eof());
|
||||
EXPECT(!stream.has_any_error() && !stream.eof());
|
||||
EXPECT(compare({ expected2, sizeof(expected2) }, { actual2, sizeof(actual2) }));
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ size_t DeflateDecompressor::read(Bytes bytes)
|
|||
m_input_stream >> length >> negated_length;
|
||||
|
||||
if ((length ^ 0xffff) != negated_length) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ size_t DeflateDecompressor::read(Bytes bytes)
|
|||
bool DeflateDecompressor::read_or_error(Bytes bytes)
|
||||
{
|
||||
if (read(bytes) < bytes.size()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ bool DeflateDecompressor::discard_or_error(size_t count)
|
|||
size_t ndiscarded = 0;
|
||||
while (ndiscarded < count) {
|
||||
if (eof()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -371,7 +371,7 @@ void DeflateDecompressor::decode_codes(CanonicalCode& literal_code, Optional<Can
|
|||
|
||||
auto code_length_code_result = CanonicalCode::from_bytes({ code_lengths_code_lengths, sizeof(code_lengths_code_lengths) });
|
||||
if (!code_length_code_result.has_value()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return;
|
||||
}
|
||||
const auto code_length_code = code_length_code_result.value();
|
||||
|
@ -399,7 +399,7 @@ void DeflateDecompressor::decode_codes(CanonicalCode& literal_code, Optional<Can
|
|||
ASSERT(symbol == 16);
|
||||
|
||||
if (code_lengths.is_empty()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -410,7 +410,7 @@ void DeflateDecompressor::decode_codes(CanonicalCode& literal_code, Optional<Can
|
|||
}
|
||||
|
||||
if (code_lengths.size() != literal_code_count + distance_code_count) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -418,7 +418,7 @@ void DeflateDecompressor::decode_codes(CanonicalCode& literal_code, Optional<Can
|
|||
|
||||
auto literal_code_result = CanonicalCode::from_bytes(code_lengths.span().trim(literal_code_count));
|
||||
if (!literal_code_result.has_value()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return;
|
||||
}
|
||||
literal_code = literal_code_result.value();
|
||||
|
@ -431,14 +431,14 @@ void DeflateDecompressor::decode_codes(CanonicalCode& literal_code, Optional<Can
|
|||
if (length == 0) {
|
||||
return;
|
||||
} else if (length != 1) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto distance_code_result = CanonicalCode::from_bytes(code_lengths.span().slice(literal_code_count));
|
||||
if (!distance_code_result.has_value()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return;
|
||||
}
|
||||
distance_code = distance_code_result.value();
|
||||
|
|
|
@ -77,12 +77,12 @@ size_t GzipDecompressor::read(Bytes bytes)
|
|||
m_input_stream >> crc32 >> input_size;
|
||||
|
||||
if (crc32 != current_member().m_checksum.digest()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (input_size != current_member().m_nread) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ size_t GzipDecompressor::read(Bytes bytes)
|
|||
m_input_stream >> Bytes { &header, sizeof(header) };
|
||||
|
||||
if (!header.valid_magic_number() || !header.supported_by_implementation()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ size_t GzipDecompressor::read(Bytes bytes)
|
|||
bool GzipDecompressor::read_or_error(Bytes bytes)
|
||||
{
|
||||
if (read(bytes) < bytes.size()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ bool GzipDecompressor::discard_or_error(size_t count)
|
|||
size_t ndiscarded = 0;
|
||||
while (ndiscarded < count) {
|
||||
if (eof()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
while (nread < bytes.size() && !eof()) {
|
||||
if (m_file->has_error()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ public:
|
|||
bool read_or_error(Bytes bytes) override
|
||||
{
|
||||
if (read(bytes) < bytes.size()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
ndiscarded += read({ buffer, min<size_t>(count - ndiscarded, sizeof(buffer)) });
|
||||
|
||||
if (eof()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ public:
|
|||
void close()
|
||||
{
|
||||
if (!m_file->close())
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -153,7 +153,7 @@ public:
|
|||
size_t write(ReadonlyBytes bytes) override
|
||||
{
|
||||
if (!m_file->write(bytes.data(), bytes.size())) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ public:
|
|||
bool write_or_error(ReadonlyBytes bytes) override
|
||||
{
|
||||
if (write(bytes) < bytes.size()) {
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ public:
|
|||
void close()
|
||||
{
|
||||
if (!m_file->close())
|
||||
m_error = true;
|
||||
set_fatal_error();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -66,9 +66,9 @@ void LineProgram::parse_source_directories()
|
|||
#endif
|
||||
m_source_directories.append(move(directory));
|
||||
}
|
||||
m_stream.handle_error();
|
||||
m_stream.handle_recoverable_error();
|
||||
m_stream.discard_or_error(1);
|
||||
ASSERT(!m_stream.handle_error());
|
||||
ASSERT(!m_stream.has_any_error());
|
||||
}
|
||||
|
||||
void LineProgram::parse_source_files()
|
||||
|
@ -88,7 +88,7 @@ void LineProgram::parse_source_files()
|
|||
m_source_files.append({ file_name, directory_index });
|
||||
}
|
||||
m_stream.discard_or_error(1);
|
||||
ASSERT(!m_stream.handle_error());
|
||||
ASSERT(!m_stream.has_any_error());
|
||||
}
|
||||
|
||||
void LineProgram::append_to_line_info()
|
||||
|
|
Loading…
Reference in a new issue