2022-12-08 21:44:46 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2022, Lucas Chollet <lucas.chollet@free.fr>
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <AK/ByteBuffer.h>
|
|
|
|
#include <AK/Error.h>
|
|
|
|
#include <AK/Noncopyable.h>
|
2023-05-03 09:14:36 +00:00
|
|
|
#include <AK/Vector.h>
|
2022-12-08 21:44:46 +00:00
|
|
|
|
|
|
|
namespace AK {
|
|
|
|
|
|
|
|
class CircularBuffer {
|
|
|
|
AK_MAKE_NONCOPYABLE(CircularBuffer);
|
|
|
|
|
|
|
|
public:
|
|
|
|
static ErrorOr<CircularBuffer> create_empty(size_t size);
|
|
|
|
static ErrorOr<CircularBuffer> create_initialized(ByteBuffer);
|
|
|
|
|
2023-01-07 21:58:11 +00:00
|
|
|
CircularBuffer(CircularBuffer&& other) = default;
|
|
|
|
CircularBuffer& operator=(CircularBuffer&& other) = default;
|
2022-12-08 21:44:46 +00:00
|
|
|
|
|
|
|
~CircularBuffer() = default;
|
|
|
|
|
|
|
|
size_t write(ReadonlyBytes bytes);
|
|
|
|
Bytes read(Bytes bytes);
|
|
|
|
ErrorOr<void> discard(size_t discarded_bytes);
|
2023-03-30 00:25:34 +00:00
|
|
|
ErrorOr<size_t> fill_from_stream(Stream&);
|
2023-05-01 00:56:20 +00:00
|
|
|
ErrorOr<size_t> flush_to_stream(Stream&);
|
2022-12-08 21:44:46 +00:00
|
|
|
|
2022-12-31 22:35:45 +00:00
|
|
|
/// Compared to `read()`, this starts reading from an offset that is `distance` bytes
|
|
|
|
/// before the current write pointer and allows for reading already-read data.
|
|
|
|
ErrorOr<Bytes> read_with_seekback(Bytes bytes, size_t distance);
|
|
|
|
|
2023-04-04 16:29:43 +00:00
|
|
|
ErrorOr<size_t> copy_from_seekback(size_t distance, size_t length);
|
2023-03-30 18:02:22 +00:00
|
|
|
|
2023-05-03 09:14:36 +00:00
|
|
|
struct Match {
|
|
|
|
size_t distance;
|
|
|
|
size_t length;
|
|
|
|
};
|
|
|
|
/// This searches the seekback buffer (between read head and limit) for occurrences where it matches the next `length` bytes from the read buffer.
|
|
|
|
/// Supplying any hints will only consider those distances, in case existing offsets need to be validated.
|
|
|
|
/// Note that, since we only start searching at the read head, the length between read head and write head is excluded from the distance.
|
|
|
|
ErrorOr<Vector<Match>> find_copy_in_seekback(size_t maximum_length, size_t minimum_length = 2, Optional<Vector<size_t> const&> distance_hints = {}) const;
|
|
|
|
|
2022-12-08 21:44:46 +00:00
|
|
|
[[nodiscard]] size_t empty_space() const;
|
|
|
|
[[nodiscard]] size_t used_space() const;
|
|
|
|
[[nodiscard]] size_t capacity() const;
|
2023-03-16 14:15:44 +00:00
|
|
|
[[nodiscard]] size_t seekback_limit() const;
|
2022-12-08 21:44:46 +00:00
|
|
|
|
2023-01-07 18:09:20 +00:00
|
|
|
Optional<size_t> offset_of(StringView needle, Optional<size_t> from = {}, Optional<size_t> until = {}) const;
|
2022-12-08 21:44:46 +00:00
|
|
|
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
private:
|
|
|
|
CircularBuffer(ByteBuffer);
|
|
|
|
|
|
|
|
[[nodiscard]] bool is_wrapping_around() const;
|
|
|
|
|
|
|
|
[[nodiscard]] Bytes next_write_span();
|
|
|
|
[[nodiscard]] ReadonlyBytes next_read_span() const;
|
2022-12-31 22:35:45 +00:00
|
|
|
[[nodiscard]] ReadonlyBytes next_read_span_with_seekback(size_t distance) const;
|
2022-12-08 21:44:46 +00:00
|
|
|
|
|
|
|
ByteBuffer m_buffer {};
|
|
|
|
|
|
|
|
size_t m_reading_head {};
|
|
|
|
size_t m_used_space {};
|
2022-12-31 22:35:45 +00:00
|
|
|
size_t m_seekback_limit {};
|
2022-12-08 21:44:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|