From aee49d1c1c75089891cbbe023c9f1675eeff954e Mon Sep 17 00:00:00 2001
From: Max Kellermann <max.kellermann@gmail.com>
Date: Thu, 30 Jan 2025 13:13:36 +0100
Subject: [PATCH] input/cdio: pass std::string_view to parse_cdio_uri()

---
 src/input/plugins/CdioParanoiaInputPlugin.cxx | 51 ++++++-------------
 1 file changed, 16 insertions(+), 35 deletions(-)

diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx
index d20cf0573..94021befa 100644
--- a/src/input/plugins/CdioParanoiaInputPlugin.cxx
+++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx
@@ -10,11 +10,12 @@
 #include "lib/fmt/RuntimeError.hxx"
 #include "../InputStream.hxx"
 #include "../InputPlugin.hxx"
-#include "util/TruncateString.hxx"
 #include "util/StringCompare.hxx"
 #include "util/Domain.hxx"
 #include "util/ByteOrder.hxx"
+#include "util/NumberParser.hxx"
 #include "util/ScopeExit.hxx"
+#include "util/StringSplit.hxx"
 #include "fs/AllocatedPath.hxx"
 #include "Log.hxx"
 #include "config/Block.hxx"
@@ -23,12 +24,10 @@
 #include <cassert>
 #include <cstdint>
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
 #include <cdio/cd_types.h>
 
+using std::string_view_literals::operator""sv;
+
 static constexpr Domain cdio_domain("cdio");
 
 static bool default_reverse_endian;
@@ -130,40 +129,25 @@ struct CdioUri {
 };
 
 static CdioUri
-parse_cdio_uri(const char *src)
+parse_cdio_uri(std::string_view src)
 {
 	CdioUri dest;
 
-	if (*src == 0) {
-		/* play the whole CD in the default drive */
-		dest.device[0] = 0;
-		dest.track = -1;
-		return dest;
-	}
+	src = StringAfterPrefixIgnoreCase(src, "cdda://"sv);
 
-	const char *slash = std::strrchr(src, '/');
-	if (slash == nullptr) {
-		/* play the whole CD in the specified drive */
-		CopyTruncateString(dest.device, src, sizeof(dest.device));
-		dest.track = -1;
-		return dest;
-	}
+	const auto [device, track] = Split(src, '/');
+	if (device.size() >= sizeof(dest.device))
+		throw std::invalid_argument{"Device name is too long"};
 
-	size_t device_length = slash - src;
-	if (device_length >= sizeof(dest.device))
-		device_length = sizeof(dest.device) - 1;
+	*std::copy(device.begin(), device.end(), dest.device) = '\0';
 
-	memcpy(dest.device, src, device_length);
-	dest.device[device_length] = 0;
+	if (!track.empty()) {
+		auto value = ParseInteger<uint_least16_t>(track);
+		if (!value)
+			throw std::invalid_argument{"Bad track number"};
 
-	const char *track = slash + 1;
-
-	char *endptr;
-	dest.track = strtoul(track, &endptr, 10);
-	if (*endptr != 0)
-		throw std::runtime_error("Malformed track number");
-
-	if (endptr == track)
+		dest.track = *value;
+	} else
 		/* play the whole CD */
 		dest.track = -1;
 
@@ -190,9 +174,6 @@ static InputStreamPtr
 input_cdio_open(const char *uri,
 		Mutex &mutex)
 {
-	uri = StringAfterPrefixIgnoreCase(uri, "cdda://");
-	assert(uri != nullptr);
-
 	const auto parsed_uri = parse_cdio_uri(uri);
 
 	/* get list of CD's supporting CD-DA */