tag/IcyMetadataParser: use std::span

This commit is contained in:
Max Kellermann 2023-12-20 19:32:21 +01:00
parent b09654b53a
commit 3c5b864396
3 changed files with 36 additions and 42 deletions

View File

@ -81,7 +81,7 @@ IcyInputStream::Read(std::unique_lock<Mutex> &lock,
return 0; return 0;
} }
size_t result = parser->ParseInPlace(ptr, nbytes); size_t result = parser->ParseInPlace({static_cast<std::byte *>(ptr), nbytes});
if (result > 0) { if (result > 0) {
override_offset += result; override_offset += result;
offset = override_offset; offset = override_offset;

View File

@ -156,28 +156,29 @@ icy_parse_tag(
return tag.CommitNew(); return tag.CommitNew();
} }
size_t std::size_t
IcyMetaDataParser::Meta(const void *data, size_t length) noexcept IcyMetaDataParser::Meta(std::span<const std::byte> src) noexcept
{ {
const auto *p = (const unsigned char *)data;
assert(IsDefined()); assert(IsDefined());
assert(data_rest == 0); assert(data_rest == 0);
assert(length > 0); assert(!src.empty());
std::size_t consumed = 0;
if (meta_size == 0) { if (meta_size == 0) {
/* read meta_size from the first byte of a meta /* read meta_size from the first byte of a meta
block */ block */
meta_size = *p++ * 16; meta_size = static_cast<std::size_t>(src.front()) * 16;
if (meta_size == 0) { if (meta_size == 0) {
/* special case: no metadata */ /* special case: no metadata */
data_rest = data_size; data_rest = data_size;
return 1; return 1;
} }
/* 1 byte was consumed (must be re-added later for the src = src.subspan(1);
return value */
--length; /* 1 byte was consumed */
++consumed;
/* initialize metadata reader, allocate enough /* initialize metadata reader, allocate enough
memory (+1 for the null terminator) */ memory (+1 for the null terminator) */
@ -187,15 +188,12 @@ IcyMetaDataParser::Meta(const void *data, size_t length) noexcept
assert(meta_position < meta_size); assert(meta_position < meta_size);
if (length > meta_size - meta_position) if (src.size() > meta_size - meta_position)
length = meta_size - meta_position; src = src.first(meta_size - meta_position);
memcpy(meta_data + meta_position, p, length); memcpy(meta_data + meta_position, src.data(), src.size());
meta_position += length; meta_position += src.size();
consumed += src.size();
if (p != data)
/* re-add the first byte (which contained meta_size) */
++length;
if (meta_position == meta_size) { if (meta_position == meta_size) {
/* parse */ /* parse */
@ -213,34 +211,29 @@ IcyMetaDataParser::Meta(const void *data, size_t length) noexcept
data_rest = data_size; data_rest = data_size;
} }
return length; return consumed;
} }
size_t size_t
IcyMetaDataParser::ParseInPlace(void *data, size_t length) noexcept IcyMetaDataParser::ParseInPlace(std::span<std::byte> buffer) noexcept
{ {
auto *const dest0 = (std::byte *)data; const auto begin = buffer.begin();
std::byte *dest = dest0; auto dest = begin;
const std::byte *src = dest0; auto src = buffer;
while (length > 0) { while (!src.empty()) {
size_t chunk = Data(length); std::size_t chunk = Data(src.size());
if (chunk > 0) { if (chunk > 0) {
memmove(dest, src, chunk); dest = std::copy_n(src.begin(), chunk, dest);
dest += chunk; src = src.subspan(chunk);
src += chunk; if (src.empty())
length -= chunk;
if (length == 0)
break; break;
} }
chunk = Meta(src, length); chunk = Meta(src);
if (chunk > 0) { if (chunk > 0)
src += chunk; src = src.subspan(chunk);
length -= chunk;
}
} }
return dest - dest0; return std::distance(begin, dest);
} }

View File

@ -10,6 +10,7 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <span>
class IcyMetaDataParser { class IcyMetaDataParser {
size_t data_size = 0, data_rest; size_t data_size = 0, data_rest;
@ -66,18 +67,18 @@ public:
size_t Data(size_t length) noexcept; size_t Data(size_t length) noexcept;
/** /**
* Reads metadata from the stream. Returns the number of bytes * Reads metadata from the stream. Returns the number of
* consumed. If the return value is smaller than "length", the caller * bytes consumed. If the return value is smaller than
* should invoke icy_data(). * "src.size()", the caller should invoke Data().
*/ */
size_t Meta(const void *data, size_t length) noexcept; std::size_t Meta(std::span<const std::byte> src) noexcept;
/** /**
* Parse data and eliminate metadata. * Parse data and eliminate metadata.
* *
* @return the number of data bytes remaining in the buffer * @return the number of data bytes remaining in the buffer
*/ */
size_t ParseInPlace(void *data, size_t length) noexcept; size_t ParseInPlace(std::span<std::byte> buffer) noexcept;
std::unique_ptr<Tag> ReadTag() noexcept { std::unique_ptr<Tag> ReadTag() noexcept {
return std::exchange(tag, nullptr); return std::exchange(tag, nullptr);