From b50173ae8be47849e18fe6e63710acde9465fc5b Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Fri, 20 May 2022 10:59:53 +0200
Subject: [PATCH] util/CircularBuffer: use std::span

---
 src/input/AsyncInputStream.cxx         | 18 ++++----
 src/input/ThreadInputStream.cxx        |  6 +--
 src/input/plugins/AlsaInputPlugin.cxx  |  4 +-
 src/input/plugins/UringInputPlugin.cxx |  6 +--
 src/util/CircularBuffer.hxx            | 12 ++----
 test/util/TestCircularBuffer.cxx       | 60 +++++++++++++-------------
 6 files changed, 51 insertions(+), 55 deletions(-)

diff --git a/src/input/AsyncInputStream.cxx b/src/input/AsyncInputStream.cxx
index 5a6344479..08f04026b 100644
--- a/src/input/AsyncInputStream.cxx
+++ b/src/input/AsyncInputStream.cxx
@@ -117,9 +117,9 @@ AsyncInputStream::Seek(std::unique_lock<Mutex> &lock,
 			break;
 
 		const size_t nbytes =
-			new_offset - offset < (offset_type)r.size
-					       ? new_offset - offset
-					       : r.size;
+			new_offset - offset < (offset_type)r.size()
+			? new_offset - offset
+			: r.size();
 
 		buffer.Consume(nbytes);
 		offset += nbytes;
@@ -193,8 +193,8 @@ AsyncInputStream::Read(std::unique_lock<Mutex> &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(read_size, r.size());
+	memcpy(ptr, r.data(), nbytes);
 	buffer.Consume(nbytes);
 
 	offset += (offset_type)nbytes;
@@ -222,17 +222,17 @@ AsyncInputStream::AppendToBuffer(const void *data, size_t append_size) noexcept
 	auto w = buffer.Write();
 	assert(!w.empty());
 
-	size_t nbytes = std::min(w.size, append_size);
-	memcpy(w.data, data, nbytes);
+	size_t nbytes = std::min(w.size(), append_size);
+	memcpy(w.data(), data, nbytes);
 	buffer.Append(nbytes);
 
 	const size_t remaining = append_size - nbytes;
 	if (remaining > 0) {
 		w = buffer.Write();
 		assert(!w.empty());
-		assert(w.size >= remaining);
+		assert(w.size() >= remaining);
 
-		memcpy(w.data, (const uint8_t *)data + nbytes, remaining);
+		memcpy(w.data(), (const uint8_t *)data + nbytes, remaining);
 		buffer.Append(remaining);
 	}
 
diff --git a/src/input/ThreadInputStream.cxx b/src/input/ThreadInputStream.cxx
index e1ce76052..5def785ca 100644
--- a/src/input/ThreadInputStream.cxx
+++ b/src/input/ThreadInputStream.cxx
@@ -93,7 +93,7 @@ ThreadInputStream::ThreadFunc() noexcept
 
 			try {
 				const ScopeUnlock unlock(mutex);
-				nbytes = ThreadRead(w.data, w.size);
+				nbytes = ThreadRead(w.data(), w.size());
 			} catch (...) {
 				postponed_exception = std::current_exception();
 				InvokeOnAvailable();
@@ -145,8 +145,8 @@ ThreadInputStream::Read(std::unique_lock<Mutex> &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(read_size, r.size());
+			memcpy(ptr, r.data(), nbytes);
 			buffer.Consume(nbytes);
 			wake_cond.notify_all();
 			offset += nbytes;
diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx
index ccf0b10d8..d9563f88c 100644
--- a/src/input/plugins/AlsaInputPlugin.cxx
+++ b/src/input/plugins/AlsaInputPlugin.cxx
@@ -240,7 +240,7 @@ AlsaInputStream::DispatchSockets() noexcept
 	const std::scoped_lock<Mutex> protect(mutex);
 
 	auto w = PrepareWriteBuffer();
-	const snd_pcm_uframes_t w_frames = w.size / frame_size;
+	const snd_pcm_uframes_t w_frames = w.size() / frame_size;
 	if (w_frames == 0) {
 		/* buffer is full */
 		Pause();
@@ -249,7 +249,7 @@ AlsaInputStream::DispatchSockets() noexcept
 
 	snd_pcm_sframes_t n_frames;
 	while ((n_frames = snd_pcm_readi(capture_handle,
-					 w.data, w_frames)) < 0) {
+					 w.data(), w_frames)) < 0) {
 		if (n_frames == -EAGAIN)
 			return;
 
diff --git a/src/input/plugins/UringInputPlugin.cxx b/src/input/plugins/UringInputPlugin.cxx
index 8b8ef06cb..08f545a72 100644
--- a/src/input/plugins/UringInputPlugin.cxx
+++ b/src/input/plugins/UringInputPlugin.cxx
@@ -123,7 +123,7 @@ UringInputStream::SubmitRead() noexcept
 
 	read_operation = std::make_unique<Uring::ReadOperation>();
 	read_operation->Start(uring, fd, next_offset,
-			      std::min(w.size, URING_MAX_READ),
+			      std::min(w.size(), URING_MAX_READ),
 			      *this);
 }
 
@@ -158,8 +158,8 @@ UringInputStream::OnRead(std::unique_ptr<std::byte[]> data,
 	}
 
 	auto w = PrepareWriteBuffer();
-	assert(w.size >= nbytes);
-	memcpy(w.data, data.get(), nbytes);
+	assert(w.size() >= nbytes);
+	memcpy(w.data(), data.get(), nbytes);
 	CommitWriteBuffer(nbytes);
 	next_offset += nbytes;
 	SubmitRead();
diff --git a/src/util/CircularBuffer.hxx b/src/util/CircularBuffer.hxx
index de1c5dfdd..1f42d8197 100644
--- a/src/util/CircularBuffer.hxx
+++ b/src/util/CircularBuffer.hxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright 2014-2022 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,13 +27,11 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef CIRCULAR_BUFFER_HPP
-#define CIRCULAR_BUFFER_HPP
-
-#include "WritableBuffer.hxx"
+#pragma once
 
 #include <cassert>
 #include <cstddef>
+#include <span>
 
 /**
  * A circular buffer.
@@ -50,7 +48,7 @@
 template<typename T>
 class CircularBuffer {
 public:
-	typedef WritableBuffer<T> Range;
+	using Range = std::span<T>;
 	typedef typename Range::pointer pointer;
 	typedef typename Range::size_type size_type;
 
@@ -182,5 +180,3 @@ public:
 			head = 0;
 	}
 };
-
-#endif
diff --git a/test/util/TestCircularBuffer.cxx b/test/util/TestCircularBuffer.cxx
index 210db93d6..2f3a5f830 100644
--- a/test/util/TestCircularBuffer.cxx
+++ b/test/util/TestCircularBuffer.cxx
@@ -24,8 +24,8 @@ TEST(CircularBuffer, Basic)
 	EXPECT_EQ(size_t(7), buffer.GetSpace());
 	EXPECT_TRUE(buffer.Read().empty());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[0], buffer.Write().data);
-	EXPECT_EQ(size_t(7), buffer.Write().size);
+	EXPECT_EQ(&data[0], buffer.Write().data());
+	EXPECT_EQ(size_t(7), buffer.Write().size());
 
 	/* append one element */
 	/* [O......X] */
@@ -35,11 +35,11 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(1), buffer.GetSize());
 	EXPECT_EQ(size_t(6), buffer.GetSpace());
-	EXPECT_EQ(size_t(1), buffer.Read().size);
-	EXPECT_EQ(&data[0], buffer.Read().data);
+	EXPECT_EQ(size_t(1), buffer.Read().size());
+	EXPECT_EQ(&data[0], buffer.Read().data());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[1], buffer.Write().data);
-	EXPECT_EQ(size_t(6), buffer.Write().size);
+	EXPECT_EQ(&data[1], buffer.Write().data());
+	EXPECT_EQ(size_t(6), buffer.Write().size());
 
 	/* append 6 elements, buffer is now full */
 	/* [OOOOOOOX] */
@@ -49,8 +49,8 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(7), buffer.GetSize());
 	EXPECT_EQ(size_t(0), buffer.GetSpace());
-	EXPECT_EQ(size_t(7), buffer.Read().size);
-	EXPECT_EQ(&data[0], buffer.Read().data);
+	EXPECT_EQ(size_t(7), buffer.Read().size());
+	EXPECT_EQ(&data[0], buffer.Read().data());
 	EXPECT_TRUE(buffer.Write().empty());
 
 	/* consume [0]; can append one at [7] */
@@ -61,11 +61,11 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(6), buffer.GetSize());
 	EXPECT_EQ(size_t(1), buffer.GetSpace());
-	EXPECT_EQ(size_t(6), buffer.Read().size);
-	EXPECT_EQ(&data[1], buffer.Read().data);
+	EXPECT_EQ(size_t(6), buffer.Read().size());
+	EXPECT_EQ(&data[1], buffer.Read().data());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[7], buffer.Write().data);
-	EXPECT_EQ(size_t(1), buffer.Write().size);
+	EXPECT_EQ(&data[7], buffer.Write().data());
+	EXPECT_EQ(size_t(1), buffer.Write().size());
 
 	/* append one element; [0] is still empty but cannot
 	   be written to because head==1 */
@@ -76,8 +76,8 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(7), buffer.GetSize());
 	EXPECT_EQ(size_t(0), buffer.GetSpace());
-	EXPECT_EQ(size_t(7), buffer.Read().size);
-	EXPECT_EQ(&data[1], buffer.Read().data);
+	EXPECT_EQ(size_t(7), buffer.Read().size());
+	EXPECT_EQ(&data[1], buffer.Read().data());
 	EXPECT_TRUE(buffer.Write().empty());
 
 	/* consume [1..3]; can append [0..2] */
@@ -88,11 +88,11 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(4), buffer.GetSize());
 	EXPECT_EQ(size_t(3), buffer.GetSpace());
-	EXPECT_EQ(size_t(4), buffer.Read().size);
-	EXPECT_EQ(&data[4], buffer.Read().data);
+	EXPECT_EQ(size_t(4), buffer.Read().size());
+	EXPECT_EQ(&data[4], buffer.Read().data());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[0], buffer.Write().data);
-	EXPECT_EQ(size_t(3), buffer.Write().size);
+	EXPECT_EQ(&data[0], buffer.Write().data());
+	EXPECT_EQ(size_t(3), buffer.Write().size());
 
 	/* append [0..1] */
 	/* [OO.XOOOO] */
@@ -102,11 +102,11 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(6), buffer.GetSize());
 	EXPECT_EQ(size_t(1), buffer.GetSpace());
-	EXPECT_EQ(size_t(4), buffer.Read().size);
-	EXPECT_EQ(&data[4], buffer.Read().data);
+	EXPECT_EQ(size_t(4), buffer.Read().size());
+	EXPECT_EQ(&data[4], buffer.Read().data());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[2], buffer.Write().data);
-	EXPECT_EQ(size_t(1), buffer.Write().size);
+	EXPECT_EQ(&data[2], buffer.Write().data());
+	EXPECT_EQ(size_t(1), buffer.Write().size());
 
 	/* append [2] */
 	/* [OOOXOOOO] */
@@ -116,8 +116,8 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(7), buffer.GetSize());
 	EXPECT_EQ(size_t(0), buffer.GetSpace());
-	EXPECT_EQ(size_t(4), buffer.Read().size);
-	EXPECT_EQ(&data[4], buffer.Read().data);
+	EXPECT_EQ(size_t(4), buffer.Read().size());
+	EXPECT_EQ(&data[4], buffer.Read().data());
 	EXPECT_TRUE(buffer.Write().empty());
 
 	/* consume [4..7] */
@@ -128,11 +128,11 @@ TEST(CircularBuffer, Basic)
 	EXPECT_FALSE(buffer.Read().empty());
 	EXPECT_EQ(size_t(3), buffer.GetSize());
 	EXPECT_EQ(size_t(4), buffer.GetSpace());
-	EXPECT_EQ(size_t(3), buffer.Read().size);
-	EXPECT_EQ(&data[0], buffer.Read().data);
+	EXPECT_EQ(size_t(3), buffer.Read().size());
+	EXPECT_EQ(&data[0], buffer.Read().data());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[3], buffer.Write().data);
-	EXPECT_EQ(size_t(4), buffer.Write().size);
+	EXPECT_EQ(&data[3], buffer.Write().data());
+	EXPECT_EQ(size_t(4), buffer.Write().size());
 
 	/* consume [0..2]; after that, we can only write 5,
 	   because the CircularBuffer class doesn't have
@@ -145,6 +145,6 @@ TEST(CircularBuffer, Basic)
 	EXPECT_EQ(size_t(7), buffer.GetSpace());
 	EXPECT_TRUE(buffer.Read().empty());
 	EXPECT_FALSE(buffer.Write().empty());
-	EXPECT_EQ(&data[3], buffer.Write().data);
-	EXPECT_EQ(size_t(5), buffer.Write().size);
+	EXPECT_EQ(&data[3], buffer.Write().data());
+	EXPECT_EQ(size_t(5), buffer.Write().size());
 }