tag/IcyMetadataParser: use std::span
This commit is contained in:
parent
b09654b53a
commit
3c5b864396
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue