diff --git a/src/archive/plugins/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx index 3f18f6067..d1173eb18 100644 --- a/src/archive/plugins/Bzip2ArchivePlugin.cxx +++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx @@ -48,7 +48,7 @@ class Bzip2InputStream final : public InputStream { bool eof = false; - char buffer[5000]; + std::byte buffer[5000]; public: Bzip2InputStream(std::shared_ptr _input, @@ -62,7 +62,7 @@ public: /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; private: void Open(); @@ -114,25 +114,25 @@ Bzip2InputStream::FillBuffer() if (bzstream.avail_in > 0) return true; - size_t count = input->LockRead(buffer, sizeof(buffer)); + size_t count = input->LockRead(buffer); if (count == 0) return false; - bzstream.next_in = buffer; + bzstream.next_in = reinterpret_cast(buffer); bzstream.avail_in = count; return true; } size_t -Bzip2InputStream::Read(std::unique_lock &, void *ptr, size_t length) +Bzip2InputStream::Read(std::unique_lock &, std::span dest) { if (eof) return 0; const ScopeUnlock unlock(mutex); - bzstream.next_out = (char *)ptr; - bzstream.avail_out = length; + bzstream.next_out = reinterpret_cast(dest.data()); + bzstream.avail_out = dest.size(); do { const bool had_input = FillBuffer(); @@ -147,11 +147,11 @@ Bzip2InputStream::Read(std::unique_lock &, void *ptr, size_t length) if (bz_result != BZ_OK) throw std::runtime_error("BZ2_bzDecompress() has failed"); - if (!had_input && bzstream.avail_out == length) + if (!had_input && bzstream.avail_out == dest.size()) throw std::runtime_error("Unexpected end of bzip2 file"); - } while (bzstream.avail_out == length); + } while (bzstream.avail_out == dest.size()); - const size_t nbytes = length - bzstream.avail_out; + const size_t nbytes = dest.size() - bzstream.avail_out; offset += nbytes; return nbytes; diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index 1ef877732..e8c1d9c9d 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -205,7 +205,7 @@ public: /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &, offset_type new_offset) override { if (new_offset > size) @@ -236,14 +236,14 @@ Iso9660ArchiveFile::OpenStream(const char *pathname, size_t Iso9660InputStream::Read(std::unique_lock &, - void *ptr, size_t read_size) + std::span dest) { const offset_type remaining = size - offset; if (remaining == 0) return 0; - if (std::cmp_greater(read_size, remaining)) - read_size = remaining; + if (std::cmp_greater(dest.size(), remaining)) + dest = dest.first(remaining); auto r = buffer.Read(); @@ -256,11 +256,11 @@ Iso9660InputStream::Read(std::unique_lock &, const lsn_t read_lsn = lsn + offset / ISO_BLOCKSIZE; - if (read_size >= ISO_BLOCKSIZE && skip == 0) { + if (dest.size() >= ISO_BLOCKSIZE && skip == 0) { /* big read - read right into the caller's buffer */ - auto nbytes = iso->SeekRead(ptr, read_lsn, - read_size / ISO_BLOCKSIZE); + auto nbytes = iso->SeekRead(dest.data(), read_lsn, + dest.size() / ISO_BLOCKSIZE); if (nbytes <= 0) throw std::runtime_error("Failed to read ISO9660 file"); @@ -294,8 +294,8 @@ Iso9660InputStream::Read(std::unique_lock &, assert(!r.empty()); assert(skip == 0); - size_t nbytes = std::min(read_size, r.size()); - memcpy(ptr, r.data(), nbytes); + size_t nbytes = std::min(dest.size(), r.size()); + memcpy(dest.data(), r.data(), nbytes); buffer.Consume(nbytes); offset += nbytes; return nbytes; diff --git a/src/archive/plugins/ZzipArchivePlugin.cxx b/src/archive/plugins/ZzipArchivePlugin.cxx index bbbb68c91..cc5107a21 100644 --- a/src/archive/plugins/ZzipArchivePlugin.cxx +++ b/src/archive/plugins/ZzipArchivePlugin.cxx @@ -107,7 +107,7 @@ public: /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &lock, offset_type offset) override; }; @@ -136,11 +136,11 @@ ZzipArchiveFile::OpenStream(const char *pathname, } size_t -ZzipInputStream::Read(std::unique_lock &, void *ptr, size_t read_size) +ZzipInputStream::Read(std::unique_lock &, std::span dest) { const ScopeUnlock unlock(mutex); - zzip_ssize_t nbytes = zzip_file_read(file, ptr, read_size); + zzip_ssize_t nbytes = zzip_file_read(file, dest.data(), dest.size()); if (nbytes < 0) throw std::runtime_error("zzip_file_read() has failed"); diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index c29028e9b..1e03a1348 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -197,7 +197,7 @@ read_stream_art(Response &r, const std::string_view art_directory, if (buffer_size > 0) { std::unique_lock lock(is->mutex); is->Seek(lock, offset); - read_size = is->Read(lock, buffer.get(), buffer_size); + read_size = is->Read(lock, {buffer.get(), buffer_size}); } r.Fmt(FMT_STRING("size: {}\n"), art_file_size); diff --git a/src/command/FingerprintCommands.cxx b/src/command/FingerprintCommands.cxx index 294b619c4..0893c3351 100644 --- a/src/command/FingerprintCommands.cxx +++ b/src/command/FingerprintCommands.cxx @@ -70,7 +70,7 @@ private: /* virtual methods from class DecoderClient */ InputStreamPtr OpenUri(const char *uri) override; size_t Read(InputStream &is, - void *buffer, size_t length) noexcept override; + std::span dest) noexcept override; /* virtual methods from class InputStreamHandler */ void OnInputStreamReady() noexcept override { @@ -274,12 +274,12 @@ GetChromaprintCommand::OpenUri(const char *uri2) size_t GetChromaprintCommand::Read(InputStream &is, - void *buffer, size_t length) noexcept + std::span dest) noexcept { /* overriding ChromaprintDecoderClient's implementation to make it cancellable */ - if (length == 0) + if (dest.empty()) return 0; std::unique_lock lock(mutex); @@ -295,7 +295,7 @@ GetChromaprintCommand::Read(InputStream &is, } try { - return is.Read(lock, buffer, length); + return is.Read(lock, dest); } catch (...) { ChromaprintDecoderClient::error = std::current_exception(); return 0; diff --git a/src/decoder/Bridge.cxx b/src/decoder/Bridge.cxx index 3c40bde83..efa598565 100644 --- a/src/decoder/Bridge.cxx +++ b/src/decoder/Bridge.cxx @@ -395,13 +395,12 @@ DecoderBridge::OpenUri(const char *uri) } size_t -DecoderBridge::Read(InputStream &is, void *buffer, size_t length) noexcept +DecoderBridge::Read(InputStream &is, std::span dest) noexcept try { - assert(buffer != nullptr); assert(dc.state == DecoderState::START || dc.state == DecoderState::DECODE); - if (length == 0) + if (dest.empty()) return 0; std::unique_lock lock(is.mutex); @@ -416,7 +415,7 @@ try { dc.cond.wait(lock); } - size_t nbytes = is.Read(lock, buffer, length); + size_t nbytes = is.Read(lock, dest); assert(nbytes > 0 || is.IsEOF()); return nbytes; diff --git a/src/decoder/Bridge.hxx b/src/decoder/Bridge.hxx index 73d58888f..663fd1a1a 100644 --- a/src/decoder/Bridge.hxx +++ b/src/decoder/Bridge.hxx @@ -1,15 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_DECODER_BRIDGE_HXX -#define MPD_DECODER_BRIDGE_HXX +#pragma once #include "Client.hxx" #include "tag/ReplayGainInfo.hxx" #include "MusicChunkPtr.hxx" +#include #include #include +#include class PcmConvert; struct MusicChunk; @@ -159,7 +160,7 @@ public: void SeekError() noexcept override; InputStreamPtr OpenUri(const char *uri) override; size_t Read(InputStream &is, - void *buffer, size_t length) noexcept override; + std::span dest) noexcept override; void SubmitTimestamp(FloatDuration t) noexcept override; DecoderCommand SubmitAudio(InputStream *is, std::span audio, @@ -191,5 +192,3 @@ private: bool UpdateStreamTag(InputStream *is) noexcept; }; - -#endif diff --git a/src/decoder/Client.hxx b/src/decoder/Client.hxx index ebdd5d32f..775b3d227 100644 --- a/src/decoder/Client.hxx +++ b/src/decoder/Client.hxx @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_DECODER_CLIENT_HXX -#define MPD_DECODER_CLIENT_HXX +#pragma once #include "Command.hxx" #include "Chrono.hxx" @@ -93,7 +92,7 @@ public: * occurs: end of file; error; command (like SEEK or STOP). */ virtual size_t Read(InputStream &is, - void *buffer, size_t length) noexcept = 0; + std::span dest) noexcept = 0; /** * Sets the time stamp for the next data chunk [seconds]. The MPD @@ -171,5 +170,3 @@ public: */ virtual void SubmitMixRamp(MixRampInfo &&mix_ramp) noexcept = 0; }; - -#endif diff --git a/src/decoder/DecoderAPI.cxx b/src/decoder/DecoderAPI.cxx index 052031392..4de99cd59 100644 --- a/src/decoder/DecoderAPI.cxx +++ b/src/decoder/DecoderAPI.cxx @@ -10,16 +10,14 @@ size_t decoder_read(DecoderClient *client, InputStream &is, - void *buffer, size_t length) noexcept + std::span dest) noexcept { - assert(buffer != nullptr); - /* XXX don't allow client==nullptr */ if (client != nullptr) - return client->Read(is, buffer, length); + return client->Read(is, dest); try { - return is.LockRead(buffer, length); + return is.LockRead(dest); } catch (...) { LogError(std::current_exception()); return 0; @@ -28,20 +26,17 @@ decoder_read(DecoderClient *client, size_t decoder_read_much(DecoderClient *client, InputStream &is, - void *_buffer, size_t size) noexcept + std::span dest) noexcept { - auto buffer = (uint8_t *)_buffer; - size_t total = 0; - while (size > 0 && !is.LockIsEOF()) { - size_t nbytes = decoder_read(client, is, buffer, size); + while (!dest.empty() && !is.LockIsEOF()) { + size_t nbytes = decoder_read(client, is, dest); if (nbytes == 0) return false; + dest = dest.subspan(nbytes); total += nbytes; - buffer += nbytes; - size -= nbytes; } return total; @@ -49,17 +44,14 @@ decoder_read_much(DecoderClient *client, InputStream &is, bool decoder_read_full(DecoderClient *client, InputStream &is, - void *_buffer, size_t size) noexcept + std::span dest) noexcept { - auto buffer = (uint8_t *)_buffer; - - while (size > 0) { - size_t nbytes = decoder_read(client, is, buffer, size); + while (!dest.empty()) { + size_t nbytes = decoder_read(client, is, dest); if (nbytes == 0) return false; - buffer += nbytes; - size -= nbytes; + dest = dest.subspan(nbytes); } return true; @@ -69,9 +61,10 @@ bool decoder_skip(DecoderClient *client, InputStream &is, size_t size) noexcept { while (size > 0) { - char buffer[1024]; - size_t nbytes = decoder_read(client, is, buffer, - std::min(sizeof(buffer), size)); + std::byte buffer[1024]; + + size_t nbytes = decoder_read(client, is, + std::span{buffer, std::min(sizeof(buffer), size)}); if (nbytes == 0) return false; diff --git a/src/decoder/DecoderAPI.hxx b/src/decoder/DecoderAPI.hxx index dafb98d73..9a3c9a5a1 100644 --- a/src/decoder/DecoderAPI.hxx +++ b/src/decoder/DecoderAPI.hxx @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project +#pragma once + /*! \file * \brief The MPD Decoder API * @@ -8,9 +10,6 @@ * communicate with the mpd core. */ -#ifndef MPD_DECODER_API_HXX -#define MPD_DECODER_API_HXX - // IWYU pragma: begin_exports #include "Client.hxx" @@ -26,7 +25,9 @@ // IWYU pragma: end_exports +#include #include +#include /** * Throw an instance of this class to stop decoding the current song @@ -47,13 +48,13 @@ class StopDecoder {}; */ size_t decoder_read(DecoderClient *decoder, InputStream &is, - void *buffer, size_t length) noexcept; + std::span dest) noexcept; static inline size_t decoder_read(DecoderClient &decoder, InputStream &is, - void *buffer, size_t length) noexcept + std::span dest) noexcept { - return decoder_read(&decoder, is, buffer, length); + return decoder_read(&decoder, is, dest); } /** @@ -66,7 +67,7 @@ decoder_read(DecoderClient &decoder, InputStream &is, */ size_t decoder_read_much(DecoderClient *decoder, InputStream &is, - void *buffer, size_t size) noexcept; + std::span dest) noexcept; /** * Blocking read from the input stream. Attempts to fill the buffer @@ -77,7 +78,7 @@ decoder_read_much(DecoderClient *decoder, InputStream &is, */ bool decoder_read_full(DecoderClient *decoder, InputStream &is, - void *buffer, size_t size) noexcept; + std::span dest) noexcept; /** * Skip data on the #InputStream. @@ -86,5 +87,3 @@ decoder_read_full(DecoderClient *decoder, InputStream &is, */ bool decoder_skip(DecoderClient *decoder, InputStream &is, size_t size) noexcept; - -#endif diff --git a/src/decoder/DecoderBuffer.cxx b/src/decoder/DecoderBuffer.cxx index a65688bca..e506baa21 100644 --- a/src/decoder/DecoderBuffer.cxx +++ b/src/decoder/DecoderBuffer.cxx @@ -12,8 +12,7 @@ DecoderBuffer::Fill() /* buffer is full */ return false; - size_t nbytes = decoder_read(client, is, - w.data(), w.size()); + size_t nbytes = decoder_read(client, is, w); if (nbytes == 0) /* end of file, I/O error or decoder command received */ diff --git a/src/decoder/Reader.cxx b/src/decoder/Reader.cxx index 4e2b50604..15424b63d 100644 --- a/src/decoder/Reader.cxx +++ b/src/decoder/Reader.cxx @@ -7,5 +7,5 @@ std::size_t DecoderReader::Read(std::span dest) { - return decoder_read(client, is, dest.data(), dest.size()); + return decoder_read(client, is, dest); } diff --git a/src/decoder/plugins/AudiofileDecoderPlugin.cxx b/src/decoder/plugins/AudiofileDecoderPlugin.cxx index 8b6f253f2..14e492c37 100644 --- a/src/decoder/plugins/AudiofileDecoderPlugin.cxx +++ b/src/decoder/plugins/AudiofileDecoderPlugin.cxx @@ -42,7 +42,7 @@ struct AudioFileInputStream { /* libaudiofile does not like partial reads at all, and will abort playback; therefore always force full reads */ - return decoder_read_full(client, is, buffer, size) + return decoder_read_full(client, is, {reinterpret_cast(buffer), size}) ? size : 0; } diff --git a/src/decoder/plugins/DsdLib.cxx b/src/decoder/plugins/DsdLib.cxx index 66c16756b..7381340d1 100644 --- a/src/decoder/plugins/DsdLib.cxx +++ b/src/decoder/plugins/DsdLib.cxx @@ -121,7 +121,8 @@ dsdlib_tag_id3(InputStream &is, TagHandler &handler, if (id3_buf == nullptr) return; - if (!decoder_read_full(nullptr, is, id3_buf, count)) { + if (!decoder_read_full(nullptr, is, + {reinterpret_cast(id3_buf), count})) { delete[] id3_buf; return; } diff --git a/src/decoder/plugins/DsdiffDecoderPlugin.cxx b/src/decoder/plugins/DsdiffDecoderPlugin.cxx index 3ee6b69f1..20381ffed 100644 --- a/src/decoder/plugins/DsdiffDecoderPlugin.cxx +++ b/src/decoder/plugins/DsdiffDecoderPlugin.cxx @@ -17,6 +17,7 @@ #include "pcm/CheckAudioFormat.hxx" #include "util/BitReverse.hxx" #include "util/PackedBigEndian.hxx" +#include "util/SpanCast.hxx" #include "tag/Handler.hxx" #include "DsdLib.hxx" @@ -75,26 +76,26 @@ static bool dsdiff_read_id(DecoderClient *client, InputStream &is, DsdId &id) { - return decoder_read_full(client, is, &id, sizeof(id)); + return decoder_read_full(client, is, ReferenceAsWritableBytes(id)); } static bool dsdiff_read_chunk_header(DecoderClient *client, InputStream &is, DsdiffChunkHeader &header) { - return decoder_read_full(client, is, &header, sizeof(header)); + return decoder_read_full(client, is, ReferenceAsWritableBytes(header)); } static bool dsdiff_read_payload(DecoderClient *client, InputStream &is, const DsdiffChunkHeader &header, - void *data, size_t length) + std::span dest) { uint64_t size = header.GetSize(); - if (size != (uint64_t)length) + if (size != (uint64_t)dest.size()) return false; - return decoder_read_full(client, is, data, length); + return decoder_read_full(client, is, dest); } /** @@ -118,8 +119,7 @@ dsdiff_read_prop_snd(DecoderClient *client, InputStream &is, if (header.id.Equals("FS ")) { uint32_t sample_rate; if (!dsdiff_read_payload(client, is, header, - &sample_rate, - sizeof(sample_rate))) + ReferenceAsWritableBytes(sample_rate))) return false; metadata.sample_rate = FromBE32(sample_rate); @@ -127,7 +127,7 @@ dsdiff_read_prop_snd(DecoderClient *client, InputStream &is, uint16_t channels; if (header.GetSize() < sizeof(channels) || !decoder_read_full(client, is, - &channels, sizeof(channels)) || + ReferenceAsWritableBytes(channels)) || !dsdlib_skip_to(client, is, chunk_end_offset)) return false; @@ -136,7 +136,7 @@ dsdiff_read_prop_snd(DecoderClient *client, InputStream &is, DsdId type; if (header.GetSize() < sizeof(type) || !decoder_read_full(client, is, - &type, sizeof(type)) || + ReferenceAsWritableBytes(type)) || !dsdlib_skip_to(client, is, chunk_end_offset)) return false; @@ -189,7 +189,7 @@ dsdiff_handle_native_tag(DecoderClient *client, InputStream &is, struct dsdiff_native_tag metatag; - if (!decoder_read_full(client, is, &metatag, sizeof(metatag))) + if (!decoder_read_full(client, is, ReferenceAsWritableBytes(metatag))) return; uint32_t length = FromBE32(metatag.size); @@ -203,7 +203,8 @@ dsdiff_handle_native_tag(DecoderClient *client, InputStream &is, char *label; label = string; - if (!decoder_read_full(client, is, label, (size_t)length)) + if (!decoder_read_full(client, is, + {reinterpret_cast(label), (size_t)length})) return; handler.OnTag(type, {label, length}); @@ -304,7 +305,7 @@ dsdiff_read_metadata(DecoderClient *client, InputStream &is, DsdiffChunkHeader &chunk_header) { DsdiffHeader header; - if (!decoder_read_full(client, is, &header, sizeof(header)) || + if (!decoder_read_full(client, is, ReferenceAsWritableBytes(header)) || !header.id.Equals("FRM8") || !header.format.Equals("DSD ")) return false; @@ -392,7 +393,8 @@ dsdiff_decode_chunk(DecoderClient &client, InputStream &is, now_size = now_frames * frame_size; } - if (!decoder_read_full(&client, is, buffer, now_size)) + if (!decoder_read_full(&client, is, + std::span{buffer}.first(now_size))) return false; const size_t nbytes = now_size; diff --git a/src/decoder/plugins/DsfDecoderPlugin.cxx b/src/decoder/plugins/DsfDecoderPlugin.cxx index d99af62df..02cc783d0 100644 --- a/src/decoder/plugins/DsfDecoderPlugin.cxx +++ b/src/decoder/plugins/DsfDecoderPlugin.cxx @@ -18,6 +18,7 @@ #include "pcm/CheckAudioFormat.hxx" #include "util/BitReverse.hxx" #include "util/PackedLittleEndian.hxx" +#include "util/SpanCast.hxx" #include "DsdLib.hxx" #include "tag/Handler.hxx" @@ -85,7 +86,7 @@ dsf_read_metadata(DecoderClient *client, InputStream &is, DsfMetaData *metadata) { DsfHeader dsf_header; - if (!decoder_read_full(client, is, &dsf_header, sizeof(dsf_header)) || + if (!decoder_read_full(client, is, ReferenceAsWritableBytes(dsf_header)) || !dsf_header.id.Equals("DSD ")) return false; @@ -100,7 +101,7 @@ dsf_read_metadata(DecoderClient *client, InputStream &is, /* read the 'fmt ' chunk of the DSF file */ DsfFmtChunk dsf_fmt_chunk; if (!decoder_read_full(client, is, - &dsf_fmt_chunk, sizeof(dsf_fmt_chunk)) || + ReferenceAsWritableBytes(dsf_fmt_chunk)) || !dsf_fmt_chunk.id.Equals("fmt ")) return false; @@ -127,7 +128,7 @@ dsf_read_metadata(DecoderClient *client, InputStream &is, /* read the 'data' chunk of the DSF file */ DsfDataChunk data_chunk; - if (!decoder_read_full(client, is, &data_chunk, sizeof(data_chunk)) || + if (!decoder_read_full(client, is, ReferenceAsWritableBytes(data_chunk)) || !data_chunk.id.Equals("data")) return false; @@ -264,7 +265,8 @@ dsf_decode_chunk(DecoderClient &client, InputStream &is, /* worst-case buffer size */ std::byte buffer[MAX_CHANNELS * DSF_BLOCK_SIZE]; - if (!decoder_read_full(&client, is, buffer, block_size)) + if (!decoder_read_full(&client, is, + std::span{buffer}.first(block_size))) return false; if (bitreverse) diff --git a/src/decoder/plugins/FfmpegIo.cxx b/src/decoder/plugins/FfmpegIo.cxx index 285fddcd4..999a59758 100644 --- a/src/decoder/plugins/FfmpegIo.cxx +++ b/src/decoder/plugins/FfmpegIo.cxx @@ -24,9 +24,9 @@ AvioStream::~AvioStream() } inline int -AvioStream::Read(void *dest, int size) +AvioStream::Read(std::span dest) { - const auto nbytes = decoder_read(client, input, dest, size); + const auto nbytes = decoder_read(client, input, dest); if (nbytes == 0) return AVERROR_EOF; @@ -74,7 +74,7 @@ AvioStream::_Read(void *opaque, uint8_t *buf, int size) { AvioStream &stream = *(AvioStream *)opaque; - return stream.Read(buf, size); + return stream.Read({reinterpret_cast(buf), static_cast(size)}); } int64_t diff --git a/src/decoder/plugins/FfmpegIo.hxx b/src/decoder/plugins/FfmpegIo.hxx index 0454903be..e4ce38711 100644 --- a/src/decoder/plugins/FfmpegIo.hxx +++ b/src/decoder/plugins/FfmpegIo.hxx @@ -1,14 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_FFMPEG_IO_HXX -#define MPD_FFMPEG_IO_HXX +#pragma once extern "C" { #include "libavformat/avio.h" } +#include #include +#include class DecoderClient; class InputStream; @@ -27,11 +28,9 @@ struct AvioStream { bool Open(); private: - int Read(void *buffer, int size); + int Read(std::span dest); int64_t Seek(int64_t pos, int whence); static int _Read(void *opaque, uint8_t *buf, int size); static int64_t _Seek(void *opaque, int64_t pos, int whence); }; - -#endif diff --git a/src/decoder/plugins/FlacInput.cxx b/src/decoder/plugins/FlacInput.cxx index 864623664..258e977c3 100644 --- a/src/decoder/plugins/FlacInput.cxx +++ b/src/decoder/plugins/FlacInput.cxx @@ -12,7 +12,8 @@ inline FLAC__StreamDecoderReadStatus FlacInput::Read(FLAC__byte buffer[], size_t *bytes) noexcept { - size_t r = decoder_read(client, input_stream, (void *)buffer, *bytes); + size_t r = decoder_read(client, input_stream, + {reinterpret_cast(buffer), *bytes}); *bytes = r; if (r == 0) { diff --git a/src/decoder/plugins/MadDecoderPlugin.cxx b/src/decoder/plugins/MadDecoderPlugin.cxx index e4523fd4d..9da1eaff5 100644 --- a/src/decoder/plugins/MadDecoderPlugin.cxx +++ b/src/decoder/plugins/MadDecoderPlugin.cxx @@ -237,7 +237,7 @@ MadDecoder::FillBuffer() noexcept return false; size_t nbytes = decoder_read(client, input_stream, - dest, max_read_size); + {reinterpret_cast(dest), max_read_size}); if (nbytes == 0) { if (was_eof || max_read_size < MAD_BUFFER_GUARD) return false; @@ -271,7 +271,7 @@ MadDecoder::ParseId3(size_t tagsize, Tag *mpd_tag) noexcept mad_stream_skip(&(stream), count); if (!decoder_read_full(client, input_stream, - allocated.get() + count, tagsize - count)) { + {reinterpret_cast(allocated.get() + count), tagsize - count})) { LogDebug(mad_domain, "error parsing ID3 tag"); return; } diff --git a/src/decoder/plugins/ModCommon.cxx b/src/decoder/plugins/ModCommon.cxx index f7cebacc3..94501896f 100644 --- a/src/decoder/plugins/ModCommon.cxx +++ b/src/decoder/plugins/ModCommon.cxx @@ -39,7 +39,7 @@ mod_loadfile(const Domain *domain, DecoderClient *client, InputStream &is) std::byte *const end = p + buffer.size(); while (true) { - size_t ret = decoder_read(client, is, p, end - p); + size_t ret = decoder_read(client, is, {p, end}); if (ret == 0) { if (is.LockIsEOF()) /* end of file */ diff --git a/src/decoder/plugins/MpcdecDecoderPlugin.cxx b/src/decoder/plugins/MpcdecDecoderPlugin.cxx index eea1ffb14..bd55fefdb 100644 --- a/src/decoder/plugins/MpcdecDecoderPlugin.cxx +++ b/src/decoder/plugins/MpcdecDecoderPlugin.cxx @@ -36,7 +36,8 @@ mpc_read_cb(mpc_reader *reader, void *ptr, mpc_int32_t size) auto *data = (struct mpc_decoder_data *)reader->data; - return decoder_read(data->client, data->is, ptr, size); + return decoder_read(data->client, data->is, + {reinterpret_cast(ptr), static_cast(size)}); } static mpc_bool_t diff --git a/src/decoder/plugins/Mpg123DecoderPlugin.cxx b/src/decoder/plugins/Mpg123DecoderPlugin.cxx index 9adaef3c3..1675bac07 100644 --- a/src/decoder/plugins/Mpg123DecoderPlugin.cxx +++ b/src/decoder/plugins/Mpg123DecoderPlugin.cxx @@ -77,7 +77,8 @@ mpd_mpg123_read(void *_iohandle, void *data, size_t size) noexcept auto &iohandle = *reinterpret_cast(_iohandle); try { - return decoder_read_much(iohandle.client, iohandle.is, data, size); + return decoder_read_much(iohandle.client, iohandle.is, + {reinterpret_cast(data), size}); } catch (...) { LogError(std::current_exception(), "Read failed"); return -1; diff --git a/src/decoder/plugins/OggCodec.cxx b/src/decoder/plugins/OggCodec.cxx index 7a4eba90d..3b7ee64b9 100644 --- a/src/decoder/plugins/OggCodec.cxx +++ b/src/decoder/plugins/OggCodec.cxx @@ -16,8 +16,8 @@ ogg_codec_detect(DecoderClient *client, InputStream &is) /* oggflac detection based on code in ogg123 and this post * http://lists.xiph.org/pipermail/flac/2004-December/000393.html * ogg123 trunk still doesn't have this patch as of June 2005 */ - unsigned char buf[41]; - size_t r = decoder_read(client, is, buf, sizeof(buf)); + std::byte buf[41]; + size_t r = decoder_read(client, is, buf); if (r < sizeof(buf) || memcmp(buf, "OggS", 4) != 0) return OGG_CODEC_UNKNOWN; diff --git a/src/decoder/plugins/PcmDecoderPlugin.cxx b/src/decoder/plugins/PcmDecoderPlugin.cxx index 88fa28951..78e094330 100644 --- a/src/decoder/plugins/PcmDecoderPlugin.cxx +++ b/src/decoder/plugins/PcmDecoderPlugin.cxx @@ -35,7 +35,7 @@ FillBuffer(DecoderClient &client, InputStream &is, B &buffer) if (w.empty()) return true; - size_t nbytes = decoder_read(client, is, w.data(), w.size()); + size_t nbytes = decoder_read(client, is, w); if (nbytes == 0 && is.LockIsEOF()) return false; @@ -157,7 +157,7 @@ pcm_stream_decode(DecoderClient &client, InputStream &is) client.Ready(audio_format, is.IsSeekable(), total_time); - StaticFifoBuffer buffer; + StaticFifoBuffer buffer; /* a buffer for pcm_unpack_24be() large enough to hold the results for a full source buffer */ @@ -185,9 +185,10 @@ pcm_stream_decode(DecoderClient &client, InputStream &is) (audio/L24) to native-endian 24 bit (in 32 bit integers) */ pcm_unpack_24be(unpack_buffer, - r.data(), r.data() + r.size()); + reinterpret_cast(r.data()), + reinterpret_cast(r.data() + r.size())); r = { - (uint8_t *)&unpack_buffer[0], + (std::byte *)&unpack_buffer[0], (r.size() / 3) * 4, }; } diff --git a/src/decoder/plugins/SndfileDecoderPlugin.cxx b/src/decoder/plugins/SndfileDecoderPlugin.cxx index 953c15c62..7f27fde54 100644 --- a/src/decoder/plugins/SndfileDecoderPlugin.cxx +++ b/src/decoder/plugins/SndfileDecoderPlugin.cxx @@ -30,7 +30,8 @@ struct SndfileInputStream { size_t Read(void *buffer, size_t size) { /* libsndfile chokes on partial reads; therefore always force full reads */ - return decoder_read_much(client, is, buffer, size); + return decoder_read_much(client, is, + {reinterpret_cast(buffer), size}); } }; diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx index 1ce2b1a64..a7cbb4085 100644 --- a/src/decoder/plugins/WavpackDecoderPlugin.cxx +++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx @@ -245,7 +245,7 @@ struct WavpackInput { InputStream &_is) noexcept :client(_client), is(_is), last_byte(EOF) {} - int32_t ReadBytes(void *data, size_t bcount) noexcept; + int32_t ReadBytes(std::span dest) noexcept; [[nodiscard]] InputStream::offset_type GetPos() const noexcept { return is.GetOffset(); @@ -318,34 +318,32 @@ wpin(void *id) noexcept static int32_t wavpack_input_read_bytes(void *id, void *data, int32_t bcount) noexcept { - return wpin(id)->ReadBytes(data, bcount); + return wpin(id)->ReadBytes({reinterpret_cast(data), static_cast(bcount)}); } int32_t -WavpackInput::ReadBytes(void *data, size_t bcount) noexcept +WavpackInput::ReadBytes(std::span dest) noexcept { - auto *buf = (uint8_t *)data; int32_t i = 0; if (last_byte != EOF) { - *buf++ = last_byte; + dest.front() = static_cast(last_byte); + dest = dest.subspan(1); last_byte = EOF; - --bcount; ++i; } /* wavpack fails if we return a partial read, so we just wait until the buffer is full */ - while (bcount > 0) { - size_t nbytes = decoder_read(client, is, buf, bcount); + while (!dest.empty()) { + size_t nbytes = decoder_read(client, is, dest); if (nbytes == 0) { /* EOF, error or a decoder command */ break; } i += nbytes; - bcount -= nbytes; - buf += nbytes; + dest = dest.subspan(nbytes); } return i; diff --git a/src/input/AsyncInputStream.cxx b/src/input/AsyncInputStream.cxx index f871be26f..acdc9c956 100644 --- a/src/input/AsyncInputStream.cxx +++ b/src/input/AsyncInputStream.cxx @@ -166,7 +166,7 @@ AsyncInputStream::IsAvailable() const noexcept size_t AsyncInputStream::Read(std::unique_lock &lock, - void *ptr, size_t read_size) + std::span dest) { assert(!GetEventLoop().IsInside()); @@ -185,8 +185,8 @@ AsyncInputStream::Read(std::unique_lock &lock, cond_handler.cond.wait(lock); } - const size_t nbytes = std::min(read_size, r.size()); - memcpy(ptr, r.data(), nbytes); + const size_t nbytes = std::min(dest.size(), r.size()); + memcpy(dest.data(), r.data(), nbytes); buffer.Consume(nbytes); offset += (offset_type)nbytes; diff --git a/src/input/AsyncInputStream.hxx b/src/input/AsyncInputStream.hxx index aba4936fc..29668a125 100644 --- a/src/input/AsyncInputStream.hxx +++ b/src/input/AsyncInputStream.hxx @@ -72,7 +72,7 @@ public: std::unique_ptr ReadTag() noexcept final; bool IsAvailable() const noexcept final; size_t Read(std::unique_lock &lock, - void *ptr, size_t read_size) final; + std::span dest) final; protected: /** diff --git a/src/input/BufferedInputStream.cxx b/src/input/BufferedInputStream.cxx index b47687b48..25143e654 100644 --- a/src/input/BufferedInputStream.cxx +++ b/src/input/BufferedInputStream.cxx @@ -48,9 +48,9 @@ BufferedInputStream::IsAvailable() const noexcept size_t BufferedInputStream::Read(std::unique_lock &lock, - void *ptr, size_t s) + std::span dest) { - size_t nbytes = BufferingInputStream::Read(lock, offset, ptr, s); + size_t nbytes = BufferingInputStream::Read(lock, offset, dest); InputStream::offset += nbytes; return nbytes; } diff --git a/src/input/BufferedInputStream.hxx b/src/input/BufferedInputStream.hxx index a84199a97..5b8d55569 100644 --- a/src/input/BufferedInputStream.hxx +++ b/src/input/BufferedInputStream.hxx @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_BUFFERED_INPUT_STREAM_BUFFER_HXX -#define MPD_BUFFERED_INPUT_STREAM_BUFFER_HXX +#pragma once #include "InputStream.hxx" #include "BufferingInputStream.hxx" @@ -44,7 +43,7 @@ public: // std::unique_ptr ReadTag() override; bool IsAvailable() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; private: /* virtual methods from class BufferingInputStream */ @@ -52,5 +51,3 @@ private: InvokeOnAvailable(); } }; - -#endif diff --git a/src/input/BufferingInputStream.cxx b/src/input/BufferingInputStream.cxx index 8753ddb53..5e901176b 100644 --- a/src/input/BufferingInputStream.cxx +++ b/src/input/BufferingInputStream.cxx @@ -59,7 +59,7 @@ BufferingInputStream::IsAvailable(size_t offset) const noexcept size_t BufferingInputStream::Read(std::unique_lock &lock, size_t offset, - void *ptr, size_t s) + std::span dest) { if (offset >= size()) return 0; @@ -68,8 +68,8 @@ BufferingInputStream::Read(std::unique_lock &lock, size_t offset, auto r = buffer.Read(offset); if (r.HasData()) { /* yay, we have some data */ - size_t nbytes = std::min(s, r.defined_buffer.size()); - memcpy(ptr, r.defined_buffer.data(), nbytes); + size_t nbytes = std::min(dest.size(), r.defined_buffer.size()); + memcpy(dest.data(), r.defined_buffer.data(), nbytes); return nbytes; } @@ -148,9 +148,10 @@ BufferingInputStream::RunThreadLocked(std::unique_lock &lock) data has been read */ constexpr size_t MAX_READ = 64 * 1024; - size_t nbytes = input->Read(lock, w.data(), - std::min(w.size(), - MAX_READ)); + if (w.size() > MAX_READ) + w = w.first(MAX_READ); + + size_t nbytes = input->Read(lock, w); buffer.Commit(read_offset, read_offset + nbytes); client_cond.notify_all(); diff --git a/src/input/BufferingInputStream.hxx b/src/input/BufferingInputStream.hxx index 625ad63bf..a281f55cd 100644 --- a/src/input/BufferingInputStream.hxx +++ b/src/input/BufferingInputStream.hxx @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_BUFFERING_INPUT_STREAM_BUFFER_HXX -#define MPD_BUFFERING_INPUT_STREAM_BUFFER_HXX +#pragma once #include "Ptr.hxx" #include "Handler.hxx" @@ -11,6 +10,7 @@ #include "thread/Cond.hxx" #include "util/SparseBuffer.hxx" +#include #include /** @@ -39,7 +39,7 @@ private: */ Cond client_cond; - SparseBuffer buffer; + SparseBuffer buffer; bool stop = false; @@ -96,7 +96,7 @@ public: * @return the number of bytes copied into the given pointer. */ size_t Read(std::unique_lock &lock, size_t offset, - void *ptr, size_t size); + std::span dest); protected: /** @@ -122,5 +122,3 @@ private: wake_cond.notify_one(); } }; - -#endif diff --git a/src/input/FailingInputStream.hxx b/src/input/FailingInputStream.hxx index 4bf5e76c9..c7bb48535 100644 --- a/src/input/FailingInputStream.hxx +++ b/src/input/FailingInputStream.hxx @@ -38,7 +38,7 @@ public: return false; } - size_t Read(std::unique_lock &, void *, size_t) override { + size_t Read(std::unique_lock &, std::span) override { std::rethrow_exception(error); } }; diff --git a/src/input/IcyInputStream.cxx b/src/input/IcyInputStream.cxx index d8051d6fa..a0fd787db 100644 --- a/src/input/IcyInputStream.cxx +++ b/src/input/IcyInputStream.cxx @@ -68,20 +68,20 @@ IcyInputStream::ReadTag() noexcept size_t IcyInputStream::Read(std::unique_lock &lock, - void *ptr, size_t read_size) + std::span dest) { if (!IsEnabled()) - return ProxyInputStream::Read(lock, ptr, read_size); + return ProxyInputStream::Read(lock, dest); while (true) { - size_t nbytes = ProxyInputStream::Read(lock, ptr, read_size); + size_t nbytes = ProxyInputStream::Read(lock, dest); if (nbytes == 0) { assert(IsEOF()); offset = override_offset; return 0; } - size_t result = parser->ParseInPlace({static_cast(ptr), nbytes}); + size_t result = parser->ParseInPlace(dest.first(nbytes)); if (result > 0) { override_offset += result; offset = override_offset; diff --git a/src/input/IcyInputStream.hxx b/src/input/IcyInputStream.hxx index cd163a801..9e8befa53 100644 --- a/src/input/IcyInputStream.hxx +++ b/src/input/IcyInputStream.hxx @@ -53,7 +53,7 @@ public: void Update() noexcept override; std::unique_ptr ReadTag() noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; }; #endif diff --git a/src/input/InputStream.cxx b/src/input/InputStream.cxx index ded17ce27..f3b8b7d06 100644 --- a/src/input/InputStream.cxx +++ b/src/input/InputStream.cxx @@ -92,45 +92,35 @@ InputStream::IsAvailable() const noexcept } size_t -InputStream::LockRead(void *ptr, size_t _size) +InputStream::LockRead(std::span dest) { -#if !CLANG_CHECK_VERSION(3,6) - /* disabled on clang due to -Wtautological-pointer-compare */ - assert(ptr != nullptr); -#endif - assert(_size > 0); + assert(!dest.empty()); std::unique_lock lock(mutex); - return Read(lock, ptr, _size); + return Read(lock, dest); } void -InputStream::ReadFull(std::unique_lock &lock, void *_ptr, size_t _size) +InputStream::ReadFull(std::unique_lock &lock, std::span dest) { - auto *ptr = (uint8_t *)_ptr; + assert(!dest.empty()); - size_t nbytes_total = 0; - while (_size > 0) { - size_t nbytes = Read(lock, ptr + nbytes_total, _size); + do { + std::size_t nbytes = Read(lock, dest); if (nbytes == 0) throw std::runtime_error("Unexpected end of file"); - nbytes_total += nbytes; - _size -= nbytes; - } + dest = dest.subspan(nbytes); + } while (!dest.empty()); } void -InputStream::LockReadFull(void *ptr, size_t _size) +InputStream::LockReadFull(std::span dest) { -#if !CLANG_CHECK_VERSION(3,6) - /* disabled on clang due to -Wtautological-pointer-compare */ - assert(ptr != nullptr); -#endif - assert(_size > 0); + assert(!dest.empty()); std::unique_lock lock(mutex); - ReadFull(lock, ptr, _size); + ReadFull(lock, dest); } bool diff --git a/src/input/InputStream.hxx b/src/input/InputStream.hxx index f5ff1b7c7..26dae48ed 100644 --- a/src/input/InputStream.hxx +++ b/src/input/InputStream.hxx @@ -1,15 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_INPUT_STREAM_HXX -#define MPD_INPUT_STREAM_HXX +#pragma once #include "Offset.hxx" #include "Ptr.hxx" #include "thread/Mutex.hxx" #include +#include #include +#include #include #include @@ -350,9 +351,8 @@ public: * @param size the maximum number of bytes to read * @return the number of bytes read */ - [[gnu::nonnull]] - virtual size_t Read(std::unique_lock &lock, - void *ptr, size_t size) = 0; + virtual std::size_t Read(std::unique_lock &lock, + std::span dest) = 0; /** * Wrapper for Read() which locks and unlocks the mutex; @@ -360,8 +360,7 @@ public: * * Throws std::runtime_error on error. */ - [[gnu::nonnull]] - size_t LockRead(void *ptr, size_t size); + std::size_t LockRead(std::span dest); /** * Reads the whole data from the stream into the caller-supplied buffer. @@ -374,8 +373,7 @@ public: * @param size the number of bytes to read * @return true if the whole data was read, false otherwise. */ - [[gnu::nonnull]] - void ReadFull(std::unique_lock &lock, void *ptr, size_t size); + void ReadFull(std::unique_lock &lock, std::span dest); /** * Wrapper for ReadFull() which locks and unlocks the mutex; @@ -383,8 +381,7 @@ public: * * Throws std::runtime_error on error. */ - [[gnu::nonnull]] - void LockReadFull(void *ptr, size_t size); + void LockReadFull(std::span dest); protected: void InvokeOnReady() noexcept; @@ -410,5 +407,3 @@ public: is.SetHandler(old_handler); } }; - -#endif diff --git a/src/input/ProxyInputStream.cxx b/src/input/ProxyInputStream.cxx index 295e0f949..d2013f09f 100644 --- a/src/input/ProxyInputStream.cxx +++ b/src/input/ProxyInputStream.cxx @@ -105,11 +105,11 @@ ProxyInputStream::IsAvailable() const noexcept size_t ProxyInputStream::Read(std::unique_lock &lock, - void *ptr, size_t read_size) + std::span dest) { set_input_cond.wait(lock, [this]{ return !!input; }); - size_t nbytes = input->Read(lock, ptr, read_size); + size_t nbytes = input->Read(lock, dest); CopyAttributes(); return nbytes; } diff --git a/src/input/ProxyInputStream.hxx b/src/input/ProxyInputStream.hxx index efebe5636..93c7959bd 100644 --- a/src/input/ProxyInputStream.hxx +++ b/src/input/ProxyInputStream.hxx @@ -50,7 +50,7 @@ public: std::unique_ptr ReadTag() noexcept override; bool IsAvailable() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t read_size) override; + std::span dest) override; protected: /** diff --git a/src/input/Reader.cxx b/src/input/Reader.cxx index be2b2b5a1..eba00d1cc 100644 --- a/src/input/Reader.cxx +++ b/src/input/Reader.cxx @@ -7,7 +7,7 @@ std::size_t InputStreamReader::Read(std::span dest) { - size_t nbytes = is.LockRead(dest.data(), dest.size()); + size_t nbytes = is.LockRead(dest); assert(nbytes > 0 || is.IsEOF()); return nbytes; diff --git a/src/input/RewindInputStream.cxx b/src/input/RewindInputStream.cxx index 600d06a69..e76915aab 100644 --- a/src/input/RewindInputStream.cxx +++ b/src/input/RewindInputStream.cxx @@ -28,7 +28,7 @@ class RewindInputStream final : public ProxyInputStream { * The origin of this buffer is always the beginning of the * stream (offset 0). */ - char buffer[64 * 1024]; + std::byte buffer[64 * 1024]; public: explicit RewindInputStream(InputStreamPtr _input) @@ -46,7 +46,7 @@ public: } size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &lock, offset_type offset) override; private: @@ -61,7 +61,7 @@ private: size_t RewindInputStream::Read(std::unique_lock &lock, - void *ptr, size_t read_size) + std::span dest) { if (ReadingFromBuffer()) { /* buffered read */ @@ -69,18 +69,18 @@ RewindInputStream::Read(std::unique_lock &lock, assert(head == (size_t)offset); assert(tail == (size_t)input->GetOffset()); - if (read_size > tail - head) - read_size = tail - head; + if (dest.size() > tail - head) + dest = dest.first(tail - head); - memcpy(ptr, buffer + head, read_size); - head += read_size; - offset += read_size; + memcpy(dest.data(), buffer + head, dest.size()); + head += dest.size(); + offset += dest.size(); - return read_size; + return dest.size(); } else { /* pass method call to underlying stream */ - size_t nbytes = input->Read(lock, ptr, read_size); + size_t nbytes = input->Read(lock, dest); if (std::cmp_greater(input->GetOffset(), sizeof(buffer))) /* disable buffering */ @@ -88,7 +88,7 @@ RewindInputStream::Read(std::unique_lock &lock, else if (tail == (size_t)offset) { /* append to buffer */ - memcpy(buffer + tail, ptr, nbytes); + memcpy(buffer + tail, dest.data(), nbytes); tail += nbytes; assert(tail == (size_t)input->GetOffset()); diff --git a/src/input/TextInputStream.cxx b/src/input/TextInputStream.cxx index 0740e643d..201eaa890 100644 --- a/src/input/TextInputStream.cxx +++ b/src/input/TextInputStream.cxx @@ -39,7 +39,7 @@ TextInputStream::ReadLine() character */ dest = dest.first(dest.size() - 1); - size_t nbytes = is->LockRead(dest.data(), dest.size()); + size_t nbytes = is->LockRead(std::as_writable_bytes(dest)); buffer.Append(nbytes); diff --git a/src/input/ThreadInputStream.cxx b/src/input/ThreadInputStream.cxx index a9517a42d..802849a8c 100644 --- a/src/input/ThreadInputStream.cxx +++ b/src/input/ThreadInputStream.cxx @@ -117,7 +117,7 @@ ThreadInputStream::IsAvailable() const noexcept inline size_t ThreadInputStream::Read(std::unique_lock &lock, - void *ptr, size_t read_size) + std::span dest) { assert(!thread.IsInside()); @@ -129,8 +129,8 @@ ThreadInputStream::Read(std::unique_lock &lock, auto r = buffer.Read(); if (!r.empty()) { - size_t nbytes = std::min(read_size, r.size()); - memcpy(ptr, r.data(), nbytes); + size_t nbytes = std::min(dest.size(), r.size()); + memcpy(dest.data(), r.data(), nbytes); buffer.Consume(nbytes); wake_cond.notify_all(); offset += nbytes; diff --git a/src/input/ThreadInputStream.hxx b/src/input/ThreadInputStream.hxx index 2ffd2ce4e..0accabb67 100644 --- a/src/input/ThreadInputStream.hxx +++ b/src/input/ThreadInputStream.hxx @@ -78,7 +78,7 @@ public: bool IsEOF() const noexcept final; bool IsAvailable() const noexcept final; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override final; + std::span dest) override final; protected: /** diff --git a/src/input/cache/Stream.cxx b/src/input/cache/Stream.cxx index 6c3aa78e8..968b148fd 100644 --- a/src/input/cache/Stream.cxx +++ b/src/input/cache/Stream.cxx @@ -51,7 +51,7 @@ CacheInputStream::IsAvailable() const noexcept size_t CacheInputStream::Read(std::unique_lock &lock, - void *ptr, size_t read_size) + std::span dest) { const auto _offset = offset; auto &i = GetCacheItem(); @@ -62,7 +62,7 @@ CacheInputStream::Read(std::unique_lock &lock, const ScopeUnlock unlock(mutex); const std::scoped_lock protect(i.mutex); - nbytes = i.Read(lock, _offset, ptr, read_size); + nbytes = i.Read(lock, _offset, dest); } offset += nbytes; diff --git a/src/input/cache/Stream.hxx b/src/input/cache/Stream.hxx index a317bf22c..459fc2c68 100644 --- a/src/input/cache/Stream.hxx +++ b/src/input/cache/Stream.hxx @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_CACHE_INPUT_STREAM_HXX -#define MPD_CACHE_INPUT_STREAM_HXX +#pragma once #include "Lease.hxx" #include "input/InputStream.hxx" @@ -26,11 +25,9 @@ public: // std::unique_ptr ReadTag() override; bool IsAvailable() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; private: /* virtual methods from class InputCacheLease */ void OnInputCacheAvailable() noexcept override; }; - -#endif diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index b28505502..d20cf0573 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -84,7 +84,7 @@ class CdioParanoiaInputStream final : public InputStream { /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &lock, offset_type offset) override; }; @@ -305,7 +305,7 @@ CdioParanoiaInputStream::Seek(std::unique_lock &, size_t CdioParanoiaInputStream::Read(std::unique_lock &, - void *ptr, size_t length) + std::span dest) { /* end of track ? */ if (IsEOF()) @@ -342,10 +342,10 @@ CdioParanoiaInputStream::Read(std::unique_lock &, } const size_t maxwrite = CDIO_CD_FRAMESIZE_RAW - diff; //# of bytes pending in current buffer - const std::size_t nbytes = std::min(length, maxwrite); + const std::size_t nbytes = std::min(dest.size(), maxwrite); //skip diff bytes from this lsn - memcpy(ptr, ((const char *)rbuf) + diff, nbytes); + memcpy(dest.data(), ((const char *)rbuf) + diff, nbytes); //update offset offset += nbytes; diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index 90c0135eb..dff5fbb7f 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -34,7 +34,7 @@ public: /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &lock, offset_type offset) override; }; @@ -91,13 +91,13 @@ input_ffmpeg_open(const char *uri, size_t FfmpegInputStream::Read(std::unique_lock &, - void *ptr, size_t read_size) + std::span dest) { size_t result; { const ScopeUnlock unlock(mutex); - result = io.Read(ptr, read_size); + result = io.Read(dest); } offset += result; diff --git a/src/input/plugins/FileInputPlugin.cxx b/src/input/plugins/FileInputPlugin.cxx index 0954956c8..d42b89a7e 100644 --- a/src/input/plugins/FileInputPlugin.cxx +++ b/src/input/plugins/FileInputPlugin.cxx @@ -33,7 +33,7 @@ public: } size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &lock, offset_type offset) override; }; @@ -71,14 +71,13 @@ FileInputStream::Seek(std::unique_lock &, } size_t -FileInputStream::Read(std::unique_lock &, - void *ptr, size_t read_size) +FileInputStream::Read(std::unique_lock &, std::span dest) { size_t nbytes; { const ScopeUnlock unlock(mutex); - nbytes = reader.Read({static_cast(ptr), read_size}); + nbytes = reader.Read(dest); } if (nbytes == 0 && !IsEOF()) diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx index eda9dc644..70333df17 100644 --- a/src/input/plugins/SmbclientInputPlugin.cxx +++ b/src/input/plugins/SmbclientInputPlugin.cxx @@ -40,7 +40,7 @@ public: } size_t Read(std::unique_lock &lock, - void *ptr, size_t size) override; + std::span dest) override; void Seek(std::unique_lock &lock, offset_type offset) override; }; @@ -88,13 +88,13 @@ input_smbclient_open(const char *uri, size_t SmbclientInputStream::Read(std::unique_lock &, - void *ptr, size_t read_size) + std::span dest) { ssize_t nbytes; { const ScopeUnlock unlock(mutex); - nbytes = ctx.Read(handle, ptr, read_size); + nbytes = ctx.Read(handle, dest.data(), dest.size()); } if (nbytes < 0) diff --git a/src/lib/chromaprint/DecoderClient.cxx b/src/lib/chromaprint/DecoderClient.cxx index d0a13dea3..8e39e2daa 100644 --- a/src/lib/chromaprint/DecoderClient.cxx +++ b/src/lib/chromaprint/DecoderClient.cxx @@ -68,10 +68,10 @@ ChromaprintDecoderClient::SubmitAudio(InputStream *, size_t ChromaprintDecoderClient::Read(InputStream &is, - void *buffer, size_t length) noexcept + std::span dest) noexcept { try { - return is.LockRead(buffer, length); + return is.LockRead(dest); } catch (...) { error = std::current_exception(); return 0; diff --git a/src/lib/chromaprint/DecoderClient.hxx b/src/lib/chromaprint/DecoderClient.hxx index d359395a7..f5385ca5c 100644 --- a/src/lib/chromaprint/DecoderClient.hxx +++ b/src/lib/chromaprint/DecoderClient.hxx @@ -74,7 +74,7 @@ public: //InputStreamPtr OpenUri(const char *) override; size_t Read(InputStream &is, - void *buffer, size_t length) noexcept override; + std::span dest) noexcept override; void SubmitTimestamp(FloatDuration) noexcept override {} DecoderCommand SubmitAudio(InputStream *is, diff --git a/src/lib/expat/StreamExpatParser.cxx b/src/lib/expat/StreamExpatParser.cxx index f058cf9a7..4d9e26eab 100644 --- a/src/lib/expat/StreamExpatParser.cxx +++ b/src/lib/expat/StreamExpatParser.cxx @@ -3,6 +3,7 @@ #include "ExpatParser.hxx" #include "input/InputStream.hxx" +#include "util/SpanCast.hxx" void ExpatParser::Parse(InputStream &is) @@ -10,12 +11,12 @@ ExpatParser::Parse(InputStream &is) assert(is.IsReady()); while (true) { - char buffer[4096]; - size_t nbytes = is.LockRead(buffer, sizeof(buffer)); + std::byte buffer[4096]; + size_t nbytes = is.LockRead(buffer); if (nbytes == 0) break; - Parse(buffer, nbytes); + Parse(ToStringView(std::span{buffer}.first(nbytes))); } CompleteParse(); diff --git a/src/lib/ffmpeg/IOContext.hxx b/src/lib/ffmpeg/IOContext.hxx index c5fbe5856..074e838e3 100644 --- a/src/lib/ffmpeg/IOContext.hxx +++ b/src/lib/ffmpeg/IOContext.hxx @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_FFMPEG_IO_CONTEXT_HXX -#define MPD_FFMPEG_IO_CONTEXT_HXX +#pragma once #include "Error.hxx" @@ -10,7 +9,9 @@ extern "C" { #include } +#include #include +#include namespace Ffmpeg { @@ -58,9 +59,10 @@ public: return avio_feof(io_context) != 0; } - size_t Read(void *buffer, size_t size) { + size_t Read(std::span dest) { int result = avio_read_partial(io_context, - (unsigned char *)buffer, size); + reinterpret_cast(dest.data()), + dest.size()); if (result < 0) throw MakeFfmpegError(result, "avio_read() failed"); @@ -77,5 +79,3 @@ public: }; } // namespace Ffmpeg - -#endif diff --git a/src/lib/xiph/FlacIOHandle.cxx b/src/lib/xiph/FlacIOHandle.cxx index 2bac4f730..b91de2115 100644 --- a/src/lib/xiph/FlacIOHandle.cxx +++ b/src/lib/xiph/FlacIOHandle.cxx @@ -14,7 +14,7 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle) { auto *is = (InputStream *)handle; - uint8_t *const p0 = (uint8_t *)ptr, *p = p0, + std::byte *const p0 = (std::byte *)ptr, *p = p0, *const end = p0 + size * nmemb; /* libFLAC is very picky about short reads, and expects the IO @@ -22,7 +22,7 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle) while (p < end) { try { - size_t nbytes = is->LockRead(p, end - p); + size_t nbytes = is->LockRead({p, end}); if (nbytes == 0) /* end of file */ break; diff --git a/src/lib/yajl/ParseInputStream.cxx b/src/lib/yajl/ParseInputStream.cxx index 69a212819..130e2b3be 100644 --- a/src/lib/yajl/ParseInputStream.cxx +++ b/src/lib/yajl/ParseInputStream.cxx @@ -10,7 +10,7 @@ Yajl::ParseInputStream(Handle &handle, InputStream &is) { while (true) { unsigned char buffer[4096]; - const size_t nbytes = is.LockRead(buffer, sizeof(buffer)); + const size_t nbytes = is.LockRead(std::as_writable_bytes(std::span{buffer})); if (nbytes == 0) break; diff --git a/src/tag/Aiff.cxx b/src/tag/Aiff.cxx index 40fb47f6d..632a14c7e 100644 --- a/src/tag/Aiff.cxx +++ b/src/tag/Aiff.cxx @@ -4,6 +4,7 @@ #include "Aiff.hxx" #include "input/InputStream.hxx" #include "util/ByteOrder.hxx" +#include "util/SpanCast.hxx" #include #include @@ -30,7 +31,7 @@ aiff_seek_id3(InputStream &is, std::unique_lock &lock) is.Rewind(lock); aiff_header header; - is.ReadFull(lock, &header, sizeof(header)); + is.ReadFull(lock, ReferenceAsWritableBytes(header)); if (memcmp(header.id, "FORM", 4) != 0 || (is.KnownSize() && FromBE32(header.size) > is.GetSize()) || (memcmp(header.format, "AIFF", 4) != 0 && @@ -41,7 +42,7 @@ aiff_seek_id3(InputStream &is, std::unique_lock &lock) /* read the chunk header */ aiff_chunk_header chunk; - is.ReadFull(lock, &chunk, sizeof(chunk)); + is.ReadFull(lock, ReferenceAsWritableBytes(chunk)); size_t size = FromBE32(chunk.size); if (size > size_t(std::numeric_limits::max())) diff --git a/src/tag/ApeLoader.cxx b/src/tag/ApeLoader.cxx index 71725c07d..167645d43 100644 --- a/src/tag/ApeLoader.cxx +++ b/src/tag/ApeLoader.cxx @@ -4,6 +4,7 @@ #include "ApeLoader.hxx" #include "input/InputStream.hxx" #include "util/PackedLittleEndian.hxx" +#include "util/SpanCast.hxx" #include #include @@ -30,7 +31,7 @@ try { /* determine if file has an apeV2 tag */ ApeFooter footer; is.Seek(lock, is.GetSize() - sizeof(footer)); - is.ReadFull(lock, &footer, sizeof(footer)); + is.ReadFull(lock, ReferenceAsWritableBytes(footer)); if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0 || FromLE32(footer.version) != 2000) @@ -49,12 +50,12 @@ try { remaining -= sizeof(footer); assert(remaining > 10); - auto buffer = std::make_unique(remaining); - is.ReadFull(lock, buffer.get(), remaining); + auto buffer = std::make_unique(remaining); + is.ReadFull(lock, {buffer.get(), remaining}); /* read tags */ unsigned n = FromLE32(footer.count); - const char *p = buffer.get(); + const char *p = (const char *)buffer.get(); while (n-- && remaining > 10) { size_t size = *(const PackedLE32 *)p; p += 4; diff --git a/src/tag/Id3Load.cxx b/src/tag/Id3Load.cxx index 6d95d177a..19d3da565 100644 --- a/src/tag/Id3Load.cxx +++ b/src/tag/Id3Load.cxx @@ -25,7 +25,7 @@ get_id3v2_footer_size(InputStream &is, std::unique_lock &lock, try { id3_byte_t buf[ID3_TAG_QUERYSIZE]; is.Seek(lock, offset); - is.ReadFull(lock, buf, sizeof(buf)); + is.ReadFull(lock, std::as_writable_bytes(std::span{buf})); return id3_tag_query(buf, sizeof(buf)); } catch (...) { @@ -36,7 +36,7 @@ static UniqueId3Tag ReadId3Tag(InputStream &is, std::unique_lock &lock) try { id3_byte_t query_buffer[ID3_TAG_QUERYSIZE]; - is.ReadFull(lock, query_buffer, sizeof(query_buffer)); + is.ReadFull(lock, std::as_writable_bytes(std::span{query_buffer})); /* Look for a tag header */ long tag_size = id3_tag_query(query_buffer, sizeof(query_buffer)); @@ -56,7 +56,7 @@ try { /* now read the remaining bytes */ const size_t remaining = tag_size - sizeof(query_buffer); - is.ReadFull(lock, end, remaining); + is.ReadFull(lock, std::as_writable_bytes(std::span{end, remaining})); return UniqueId3Tag(id3_tag_parse(tag_buffer.get(), tag_size)); } catch (...) { @@ -77,7 +77,7 @@ static UniqueId3Tag ReadId3v1Tag(InputStream &is, std::unique_lock &lock) try { id3_byte_t buffer[ID3V1_SIZE]; - is.ReadFull(lock, buffer, ID3V1_SIZE); + is.ReadFull(lock, std::as_writable_bytes(std::span{buffer})); return UniqueId3Tag(id3_tag_parse(buffer, ID3V1_SIZE)); } catch (...) { @@ -183,7 +183,7 @@ try { return nullptr; auto buffer = std::make_unique(size); - is.ReadFull(lock, buffer.get(), size); + is.ReadFull(lock, std::as_writable_bytes(std::span{buffer.get(), size})); return UniqueId3Tag(id3_tag_parse(buffer.get(), size)); } catch (...) { diff --git a/src/tag/RiffId3.cxx b/src/tag/RiffId3.cxx index 11d6c476a..902027890 100644 --- a/src/tag/RiffId3.cxx +++ b/src/tag/RiffId3.cxx @@ -5,6 +5,7 @@ #include "RiffFormat.hxx" #include "input/InputStream.hxx" #include "util/ByteOrder.hxx" +#include "util/SpanCast.hxx" #include #include @@ -19,7 +20,7 @@ riff_seek_id3(InputStream &is, std::unique_lock &lock) is.Rewind(lock); RiffFileHeader header; - is.ReadFull(lock, &header, sizeof(header)); + is.ReadFull(lock, ReferenceAsWritableBytes(header)); if (memcmp(header.id, "RIFF", 4) != 0 || (is.KnownSize() && FromLE32(header.size) > is.GetSize())) throw std::runtime_error("Not a RIFF file"); @@ -28,7 +29,7 @@ riff_seek_id3(InputStream &is, std::unique_lock &lock) /* read the chunk header */ RiffChunkHeader chunk; - is.ReadFull(lock, &chunk, sizeof(chunk)); + is.ReadFull(lock, ReferenceAsWritableBytes(chunk)); size_t size = FromLE32(chunk.size); if (size > size_t(std::numeric_limits::max())) diff --git a/test/DumpDatabase.cxx b/test/DumpDatabase.cxx index a3e615a48..ec9e57a04 100644 --- a/test/DumpDatabase.cxx +++ b/test/DumpDatabase.cxx @@ -42,7 +42,7 @@ public: #ifdef ENABLE_UPNP #include "input/InputStream.hxx" size_t -InputStream::LockRead(void *, size_t) +InputStream::LockRead(std::span) { return 0; } diff --git a/test/DumpDecoderClient.cxx b/test/DumpDecoderClient.cxx index bc35399b5..3e85b09b8 100644 --- a/test/DumpDecoderClient.cxx +++ b/test/DumpDecoderClient.cxx @@ -60,10 +60,10 @@ DumpDecoderClient::OpenUri(const char *uri) } size_t -DumpDecoderClient::Read(InputStream &is, void *buffer, size_t length) noexcept +DumpDecoderClient::Read(InputStream &is, std::span dest) noexcept { try { - return is.LockRead(buffer, length); + return is.LockRead(dest); } catch (...) { return 0; } diff --git a/test/DumpDecoderClient.hxx b/test/DumpDecoderClient.hxx index 66f4a35ad..828a5b73b 100644 --- a/test/DumpDecoderClient.hxx +++ b/test/DumpDecoderClient.hxx @@ -33,7 +33,7 @@ public: void SeekError() noexcept override; InputStreamPtr OpenUri(const char *uri) override; size_t Read(InputStream &is, - void *buffer, size_t length) noexcept override; + std::span dest) noexcept override; void SubmitTimestamp(FloatDuration t) noexcept override; DecoderCommand SubmitAudio(InputStream *is, std::span audio, diff --git a/test/TestRewindInputStream.cxx b/test/TestRewindInputStream.cxx index 7420bb853..d367316d2 100644 --- a/test/TestRewindInputStream.cxx +++ b/test/TestRewindInputStream.cxx @@ -29,9 +29,9 @@ public: } size_t Read(std::unique_lock &, - void *ptr, size_t read_size) override { - size_t nbytes = std::min(remaining, read_size); - memcpy(ptr, data, nbytes); + std::span dest) override { + size_t nbytes = std::min(remaining, dest.size()); + memcpy(dest.data(), data, nbytes); data += nbytes; remaining -= nbytes; offset += nbytes; @@ -60,14 +60,14 @@ TEST(RewindInputStream, Basic) EXPECT_EQ(offset_type(0), ris->GetOffset()); char buffer[16]; - size_t nbytes = ris->Read(lock, buffer, 2); + size_t nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer}.first(2))); EXPECT_EQ(size_t(2), nbytes); EXPECT_EQ('f', buffer[0]); EXPECT_EQ('o', buffer[1]); EXPECT_EQ(offset_type(2), ris->GetOffset()); EXPECT_FALSE(ris->IsEOF()); - nbytes = ris->Read(lock, buffer, 2); + nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer}.first(2))); EXPECT_EQ(size_t(2), nbytes); EXPECT_EQ('o', buffer[0]); EXPECT_EQ(' ', buffer[1]); @@ -78,7 +78,7 @@ TEST(RewindInputStream, Basic) EXPECT_EQ(offset_type(1), ris->GetOffset()); EXPECT_FALSE(ris->IsEOF()); - nbytes = ris->Read(lock, buffer, 2); + nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer}.first(2))); EXPECT_EQ(size_t(2), nbytes); EXPECT_EQ('o', buffer[0]); EXPECT_EQ('o', buffer[1]); @@ -89,21 +89,21 @@ TEST(RewindInputStream, Basic) EXPECT_EQ(offset_type(0), ris->GetOffset()); EXPECT_FALSE(ris->IsEOF()); - nbytes = ris->Read(lock, buffer, 2); + nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer}.first(2))); EXPECT_EQ(size_t(2), nbytes); EXPECT_EQ('f', buffer[0]); EXPECT_EQ('o', buffer[1]); EXPECT_EQ(offset_type(2), ris->GetOffset()); EXPECT_FALSE(ris->IsEOF()); - nbytes = ris->Read(lock, buffer, sizeof(buffer)); + nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer})); EXPECT_EQ(size_t(2), nbytes); EXPECT_EQ('o', buffer[0]); EXPECT_EQ(' ', buffer[1]); EXPECT_EQ(offset_type(4), ris->GetOffset()); EXPECT_FALSE(ris->IsEOF()); - nbytes = ris->Read(lock, buffer, sizeof(buffer)); + nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer})); EXPECT_EQ(size_t(3), nbytes); EXPECT_EQ('b', buffer[0]); EXPECT_EQ('a', buffer[1]); @@ -115,7 +115,7 @@ TEST(RewindInputStream, Basic) EXPECT_EQ(offset_type(3), ris->GetOffset()); EXPECT_FALSE(ris->IsEOF()); - nbytes = ris->Read(lock, buffer, sizeof(buffer)); + nbytes = ris->Read(lock, std::as_writable_bytes(std::span{buffer})); EXPECT_EQ(size_t(4), nbytes); EXPECT_EQ(' ', buffer[0]); EXPECT_EQ('b', buffer[1]); diff --git a/test/run_input.cxx b/test/run_input.cxx index 4e9729869..4ae8df388 100644 --- a/test/run_input.cxx +++ b/test/run_input.cxx @@ -172,7 +172,7 @@ dump_input_stream(InputStream &is, FileDescriptor out, std::byte buffer[MAX_CHUNK_SIZE]; assert(chunk_size <= sizeof(buffer)); - size_t num_read = is.Read(lock, buffer, chunk_size); + size_t num_read = is.Read(lock, {buffer, chunk_size}); if (num_read == 0) break;