Skip to content

Commit

Permalink
tag/IcyMetadataParser: use std::span
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKellermann committed Dec 21, 2023
1 parent b09654b commit 3c5b864
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/input/IcyInputStream.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ IcyInputStream::Read(std::unique_lock<Mutex> &lock,
return 0;
}

size_t result = parser->ParseInPlace(ptr, nbytes);
size_t result = parser->ParseInPlace({static_cast<std::byte *>(ptr), nbytes});
if (result > 0) {
override_offset += result;
offset = override_offset;
Expand Down
65 changes: 29 additions & 36 deletions src/tag/IcyMetaDataParser.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -156,28 +156,29 @@ icy_parse_tag(
return tag.CommitNew();
}

size_t
IcyMetaDataParser::Meta(const void *data, size_t length) noexcept
std::size_t
IcyMetaDataParser::Meta(std::span<const std::byte> src) noexcept
{
const auto *p = (const unsigned char *)data;

assert(IsDefined());
assert(data_rest == 0);
assert(length > 0);
assert(!src.empty());

std::size_t consumed = 0;

if (meta_size == 0) {
/* read meta_size from the first byte of a meta
block */
meta_size = *p++ * 16;
meta_size = static_cast<std::size_t>(src.front()) * 16;
if (meta_size == 0) {
/* special case: no metadata */
data_rest = data_size;
return 1;
}

/* 1 byte was consumed (must be re-added later for the
return value */
--length;
src = src.subspan(1);

/* 1 byte was consumed */
++consumed;

/* initialize metadata reader, allocate enough
memory (+1 for the null terminator) */
Expand All @@ -187,15 +188,12 @@ IcyMetaDataParser::Meta(const void *data, size_t length) noexcept

assert(meta_position < meta_size);

if (length > meta_size - meta_position)
length = meta_size - meta_position;

memcpy(meta_data + meta_position, p, length);
meta_position += length;
if (src.size() > meta_size - meta_position)
src = src.first(meta_size - meta_position);

if (p != data)
/* re-add the first byte (which contained meta_size) */
++length;
memcpy(meta_data + meta_position, src.data(), src.size());
meta_position += src.size();
consumed += src.size();

if (meta_position == meta_size) {
/* parse */
Expand All @@ -213,34 +211,29 @@ IcyMetaDataParser::Meta(const void *data, size_t length) noexcept
data_rest = data_size;
}

return length;
return consumed;
}

size_t
IcyMetaDataParser::ParseInPlace(void *data, size_t length) noexcept
IcyMetaDataParser::ParseInPlace(std::span<std::byte> buffer) noexcept
{
auto *const dest0 = (std::byte *)data;
std::byte *dest = dest0;
const std::byte *src = dest0;
const auto begin = buffer.begin();
auto dest = begin;
auto src = buffer;

while (length > 0) {
size_t chunk = Data(length);
while (!src.empty()) {
std::size_t chunk = Data(src.size());
if (chunk > 0) {
memmove(dest, src, chunk);
dest += chunk;
src += chunk;
length -= chunk;

if (length == 0)
dest = std::copy_n(src.begin(), chunk, dest);
src = src.subspan(chunk);
if (src.empty())
break;
}

chunk = Meta(src, length);
if (chunk > 0) {
src += chunk;
length -= chunk;
}
chunk = Meta(src);
if (chunk > 0)
src = src.subspan(chunk);
}

return dest - dest0;
return std::distance(begin, dest);
}
11 changes: 6 additions & 5 deletions src/tag/IcyMetaDataParser.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <cstddef>
#include <memory>
#include <span>

class IcyMetaDataParser {
size_t data_size = 0, data_rest;
Expand Down Expand Up @@ -66,18 +67,18 @@ public:
size_t Data(size_t length) noexcept;

/**
* Reads metadata from the stream. Returns the number of bytes
* consumed. If the return value is smaller than "length", the caller
* should invoke icy_data().
* Reads metadata from the stream. Returns the number of
* bytes consumed. If the return value is smaller than
* "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.
*
* @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 {
return std::exchange(tag, nullptr);
Expand Down

0 comments on commit 3c5b864

Please sign in to comment.