From cfb7f8ab84ca4c2d6d2f2826f893992c27a7f591 Mon Sep 17 00:00:00 2001
From: Max Kellermann <mk@cm4all.com>
Date: Thu, 14 Jan 2021 12:39:45 +0100
Subject: [PATCH] util/AllocatedString: rename to BasicAllocatedString

To make things simpler, AllocatedString is now a non-template class.
---
 src/decoder/plugins/SidplayDecoderPlugin.cxx  | 16 ++++-----
 src/fs/NarrowPath.hxx                         |  2 +-
 src/lib/icu/CaseFold.cxx                      |  8 ++---
 src/lib/icu/CaseFold.hxx                      |  4 +--
 src/lib/icu/Collate.cxx                       |  2 +-
 src/lib/icu/Compare.cxx                       |  2 +-
 src/lib/icu/Compare.hxx                       |  4 +--
 src/lib/icu/Converter.cxx                     | 10 +++---
 src/lib/icu/Converter.hxx                     |  6 ++--
 src/lib/icu/Util.cxx                          |  4 +--
 src/lib/icu/Util.hxx                          |  4 +--
 src/lib/icu/Win32.cxx                         |  8 ++---
 src/lib/icu/Win32.hxx                         |  7 ++--
 src/output/plugins/WasapiOutputPlugin.cxx     |  2 +-
 src/output/plugins/httpd/HttpdClient.cxx      |  2 +-
 .../plugins/httpd/IcyMetaDataServer.cxx       |  4 +--
 .../plugins/httpd/IcyMetaDataServer.hxx       |  4 +--
 src/util/AllocatedString.hxx                  | 36 +++++++++++--------
 src/util/FormatString.cxx                     |  6 ++--
 src/util/FormatString.hxx                     |  6 ++--
 20 files changed, 73 insertions(+), 64 deletions(-)

diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx
index 207f2088c..edc0ab028 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.cxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx
@@ -456,7 +456,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
 	} while (cmd != DecoderCommand::STOP);
 }
 
-static AllocatedString<char>
+static AllocatedString
 Windows1252ToUTF8(const char *s) noexcept
 {
 #ifdef HAVE_ICU_CONVERTER
@@ -469,9 +469,9 @@ Windows1252ToUTF8(const char *s) noexcept
 	 * Fallback to not transcoding windows-1252 to utf-8, that may result
 	 * in invalid utf-8 unless nonprintable characters are replaced.
 	 */
-	auto t = AllocatedString<char>::Duplicate(s);
+	auto t = AllocatedString::Duplicate(s);
 
-	for (size_t i = 0; t[i] != AllocatedString<char>::SENTINEL; i++)
+	for (size_t i = 0; t[i] != AllocatedString::SENTINEL; i++)
 		if (!IsPrintableASCII(t[i]))
 			t[i] = '?';
 
@@ -479,7 +479,7 @@ Windows1252ToUTF8(const char *s) noexcept
 }
 
 gcc_pure
-static AllocatedString<char>
+static AllocatedString
 GetInfoString(const SidTuneInfo &info, unsigned i) noexcept
 {
 #ifdef HAVE_SIDPLAYFP
@@ -496,7 +496,7 @@ GetInfoString(const SidTuneInfo &info, unsigned i) noexcept
 }
 
 gcc_pure
-static AllocatedString<char>
+static AllocatedString
 GetDateString(const SidTuneInfo &info) noexcept
 {
 	/*
@@ -507,12 +507,12 @@ GetDateString(const SidTuneInfo &info) noexcept
 	 * author or group> may be for example Rob Hubbard. A full field
 	 * may be for example "1987 Rob Hubbard".
 	 */
-	AllocatedString<char> release = GetInfoString(info, 2);
+	AllocatedString release = GetInfoString(info, 2);
 
 	/* Keep the <year> part only for the date. */
-	for (size_t i = 0; release[i] != AllocatedString<char>::SENTINEL; i++)
+	for (size_t i = 0; release[i] != AllocatedString::SENTINEL; i++)
 		if (std::isspace(release[i])) {
-			release[i] = AllocatedString<char>::SENTINEL;
+			release[i] = AllocatedString::SENTINEL;
 			break;
 		}
 
diff --git a/src/fs/NarrowPath.hxx b/src/fs/NarrowPath.hxx
index c74999f44..740342d7d 100644
--- a/src/fs/NarrowPath.hxx
+++ b/src/fs/NarrowPath.hxx
@@ -36,7 +36,7 @@
  */
 class NarrowPath {
 #ifdef _UNICODE
-	using Value = AllocatedString<>;
+	using Value = AllocatedString;
 #else
 	using Value = StringPointer<>;
 #endif
diff --git a/src/lib/icu/CaseFold.cxx b/src/lib/icu/CaseFold.cxx
index edc466a48..ebb75f324 100644
--- a/src/lib/icu/CaseFold.cxx
+++ b/src/lib/icu/CaseFold.cxx
@@ -38,13 +38,13 @@
 
 #include <string.h>
 
-AllocatedString<>
+AllocatedString
 IcuCaseFold(std::string_view src) noexcept
 try {
 #ifdef HAVE_ICU
 	const auto u = UCharFromUTF8(src);
 	if (u.IsNull())
-		return AllocatedString<>::Duplicate(src);
+		return AllocatedString::Duplicate(src);
 
 	AllocatedArray<UChar> folded(u.size() * 2U);
 
@@ -54,7 +54,7 @@ try {
 					     U_FOLD_CASE_DEFAULT,
 					     &error_code);
 	if (folded_length == 0 || error_code != U_ZERO_ERROR)
-		return AllocatedString<>::Duplicate(src);
+		return AllocatedString::Duplicate(src);
 
 	folded.SetSize(folded_length);
 	return UCharToUTF8({folded.begin(), folded.size()});
@@ -63,7 +63,7 @@ try {
 #error not implemented
 #endif
 } catch (...) {
-	return AllocatedString<>::Duplicate(src);
+	return AllocatedString::Duplicate(src);
 }
 
 #endif /* HAVE_ICU_CASE_FOLD */
diff --git a/src/lib/icu/CaseFold.hxx b/src/lib/icu/CaseFold.hxx
index 73d4e2289..3aed54af0 100644
--- a/src/lib/icu/CaseFold.hxx
+++ b/src/lib/icu/CaseFold.hxx
@@ -27,9 +27,9 @@
 
 #include <string_view>
 
-template<typename T> class AllocatedString;
+class AllocatedString;
 
-AllocatedString<char>
+AllocatedString
 IcuCaseFold(std::string_view src) noexcept;
 
 #endif
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx
index 859e60978..c31f46883 100644
--- a/src/lib/icu/Collate.cxx
+++ b/src/lib/icu/Collate.cxx
@@ -88,7 +88,7 @@ IcuCollate(std::string_view a, std::string_view b) noexcept
 				     b.data(), b.size(), &code);
 
 #elif defined(_WIN32)
-	AllocatedString<wchar_t> wa = nullptr, wb = nullptr;
+	BasicAllocatedString<wchar_t> wa = nullptr, wb = nullptr;
 
 	try {
 		wa = MultiByteToWideChar(CP_UTF8, a);
diff --git a/src/lib/icu/Compare.cxx b/src/lib/icu/Compare.cxx
index 14184752d..6bc82bdd5 100644
--- a/src/lib/icu/Compare.cxx
+++ b/src/lib/icu/Compare.cxx
@@ -46,7 +46,7 @@ IcuCompare::IcuCompare(std::string_view _needle) noexcept
 #else
 
 IcuCompare::IcuCompare(std::string_view _needle) noexcept
-	:needle(AllocatedString<>::Duplicate(_needle)) {}
+	:needle(AllocatedString::Duplicate(_needle)) {}
 
 #endif
 
diff --git a/src/lib/icu/Compare.hxx b/src/lib/icu/Compare.hxx
index 2751f1b4b..6f4841739 100644
--- a/src/lib/icu/Compare.hxx
+++ b/src/lib/icu/Compare.hxx
@@ -38,9 +38,9 @@ class IcuCompare {
 #ifdef _WIN32
 	/* Windows API functions work with wchar_t strings, so let's
 	   cache the MultiByteToWideChar() result for performance */
-	AllocatedString<wchar_t> needle;
+	BasicAllocatedString<wchar_t> needle;
 #else
-	AllocatedString<> needle;
+	AllocatedString needle;
 #endif
 
 public:
diff --git a/src/lib/icu/Converter.cxx b/src/lib/icu/Converter.cxx
index 228010c80..a231668a8 100644
--- a/src/lib/icu/Converter.cxx
+++ b/src/lib/icu/Converter.cxx
@@ -77,7 +77,7 @@ IcuConverter::Create(const char *charset)
 #ifdef HAVE_ICU
 #elif defined(HAVE_ICONV)
 
-static AllocatedString<char>
+static AllocatedString
 DoConvert(iconv_t conv, std::string_view src)
 {
 	// TODO: dynamic buffer?
@@ -95,12 +95,12 @@ DoConvert(iconv_t conv, std::string_view src)
 	if (in_left > 0)
 		throw std::runtime_error("Charset conversion failed");
 
-	return AllocatedString<>::Duplicate({buffer, sizeof(buffer) - out_left});
+	return AllocatedString::Duplicate({buffer, sizeof(buffer) - out_left});
 }
 
 #endif
 
-AllocatedString<char>
+AllocatedString
 IcuConverter::ToUTF8(std::string_view s) const
 {
 #ifdef HAVE_ICU
@@ -128,7 +128,7 @@ IcuConverter::ToUTF8(std::string_view s) const
 #endif
 }
 
-AllocatedString<char>
+AllocatedString
 IcuConverter::FromUTF8(std::string_view s) const
 {
 #ifdef HAVE_ICU
@@ -151,7 +151,7 @@ IcuConverter::FromUTF8(std::string_view s) const
 		throw std::runtime_error(FormatString("Failed to convert from Unicode: %s",
 						      u_errorName(code)).c_str());
 
-	return AllocatedString<>::Duplicate({buffer, size_t(target - buffer)});
+	return AllocatedString::Duplicate({buffer, size_t(target - buffer)});
 
 #elif defined(HAVE_ICONV)
 	return DoConvert(from_utf8, s);
diff --git a/src/lib/icu/Converter.hxx b/src/lib/icu/Converter.hxx
index 8368cc166..fc7d6ae40 100644
--- a/src/lib/icu/Converter.hxx
+++ b/src/lib/icu/Converter.hxx
@@ -40,7 +40,7 @@
 struct UConverter;
 #endif
 
-template<typename T> class AllocatedString;
+class AllocatedString;
 
 /**
  * This class can convert strings with a certain character set to and
@@ -85,7 +85,7 @@ public:
 	 * Throws std::runtime_error on error.
 	 */
 	gcc_nonnull_all
-	AllocatedString<char> ToUTF8(std::string_view s) const;
+	AllocatedString ToUTF8(std::string_view s) const;
 
 	/**
 	 * Convert the string from UTF-8.
@@ -93,7 +93,7 @@ public:
 	 * Throws std::runtime_error on error.
 	 */
 	gcc_nonnull_all
-	AllocatedString<char> FromUTF8(std::string_view s) const;
+	AllocatedString FromUTF8(std::string_view s) const;
 };
 
 #endif
diff --git a/src/lib/icu/Util.cxx b/src/lib/icu/Util.cxx
index 3087bed73..a473f987b 100644
--- a/src/lib/icu/Util.cxx
+++ b/src/lib/icu/Util.cxx
@@ -48,7 +48,7 @@ UCharFromUTF8(std::string_view src)
 	return dest;
 }
 
-AllocatedString<>
+AllocatedString
 UCharToUTF8(std::basic_string_view<UChar> src)
 {
 	/* worst-case estimate */
@@ -65,5 +65,5 @@ UCharToUTF8(std::basic_string_view<UChar> src)
 		throw std::runtime_error(u_errorName(error_code));
 
 	dest[dest_length] = 0;
-	return AllocatedString<>::Donate(dest.release());
+	return AllocatedString::Donate(dest.release());
 }
diff --git a/src/lib/icu/Util.hxx b/src/lib/icu/Util.hxx
index 7b2958e22..835acb4f6 100644
--- a/src/lib/icu/Util.hxx
+++ b/src/lib/icu/Util.hxx
@@ -25,7 +25,7 @@
 #include <string_view>
 
 template<typename T> class AllocatedArray;
-template<typename T> class AllocatedString;
+class AllocatedString;
 
 /**
  * Wrapper for u_strFromUTF8().
@@ -40,7 +40,7 @@ UCharFromUTF8(std::string_view src);
  *
  * Throws std::runtime_error on error.
  */
-AllocatedString<char>
+AllocatedString
 UCharToUTF8(std::basic_string_view<UChar> src);
 
 #endif
diff --git a/src/lib/icu/Win32.cxx b/src/lib/icu/Win32.cxx
index e556a3b2b..05da2ef49 100644
--- a/src/lib/icu/Win32.cxx
+++ b/src/lib/icu/Win32.cxx
@@ -25,7 +25,7 @@
 
 #include <windows.h>
 
-AllocatedString<char>
+AllocatedString
 WideCharToMultiByte(unsigned code_page, std::wstring_view src)
 {
 	int length = WideCharToMultiByte(code_page, 0, src.data(), src.size(),
@@ -42,10 +42,10 @@ WideCharToMultiByte(unsigned code_page, std::wstring_view src)
 		throw MakeLastError("Failed to convert from Unicode");
 
 	buffer[length] = '\0';
-	return AllocatedString<char>::Donate(buffer.release());
+	return AllocatedString::Donate(buffer.release());
 }
 
-AllocatedString<wchar_t>
+BasicAllocatedString<wchar_t>
 MultiByteToWideChar(unsigned code_page, std::string_view src)
 {
 	int length = MultiByteToWideChar(code_page, 0, src.data(), src.size(),
@@ -60,5 +60,5 @@ MultiByteToWideChar(unsigned code_page, std::string_view src)
 		throw MakeLastError("Failed to convert to Unicode");
 
 	buffer[length] = L'\0';
-	return AllocatedString<wchar_t>::Donate(buffer.release());
+	return BasicAllocatedString<wchar_t>::Donate(buffer.release());
 }
diff --git a/src/lib/icu/Win32.hxx b/src/lib/icu/Win32.hxx
index ab804d82c..287495010 100644
--- a/src/lib/icu/Win32.hxx
+++ b/src/lib/icu/Win32.hxx
@@ -24,20 +24,21 @@
 
 #include <string_view>
 
-template<typename T> class AllocatedString;
+class AllocatedString;
+template<typename T> class BasicAllocatedString;
 
 /**
  * Throws std::system_error on error.
  */
 gcc_pure gcc_nonnull_all
-AllocatedString<char>
+AllocatedString
 WideCharToMultiByte(unsigned code_page, std::wstring_view src);
 
 /**
  * Throws std::system_error on error.
  */
 gcc_pure gcc_nonnull_all
-AllocatedString<wchar_t>
+BasicAllocatedString<wchar_t>
 MultiByteToWideChar(unsigned code_page, std::string_view src);
 
 #endif
diff --git a/src/output/plugins/WasapiOutputPlugin.cxx b/src/output/plugins/WasapiOutputPlugin.cxx
index ce91f4e5b..a6c1d483b 100644
--- a/src/output/plugins/WasapiOutputPlugin.cxx
+++ b/src/output/plugins/WasapiOutputPlugin.cxx
@@ -194,7 +194,7 @@ private:
 	bool is_exclusive;
 	bool enumerate_devices;
 	std::string device_config;
-	std::vector<std::pair<unsigned int, AllocatedString<char>>> device_desc;
+	std::vector<std::pair<unsigned int, AllocatedString>> device_desc;
 	std::shared_ptr<WinEvent> event;
 	std::optional<COM> com;
 	ComPtr<IMMDeviceEnumerator> enumerator;
diff --git a/src/output/plugins/httpd/HttpdClient.cxx b/src/output/plugins/httpd/HttpdClient.cxx
index c5e2d819e..36e9b3abc 100644
--- a/src/output/plugins/httpd/HttpdClient.cxx
+++ b/src/output/plugins/httpd/HttpdClient.cxx
@@ -136,7 +136,7 @@ bool
 HttpdClient::SendResponse() noexcept
 {
 	char buffer[1024];
-	AllocatedString<> allocated = nullptr;
+	AllocatedString allocated = nullptr;
 	const char *response;
 
 	assert(state == State::RESPONSE);
diff --git a/src/output/plugins/httpd/IcyMetaDataServer.cxx b/src/output/plugins/httpd/IcyMetaDataServer.cxx
index d923835f3..6e4a0d24d 100644
--- a/src/output/plugins/httpd/IcyMetaDataServer.cxx
+++ b/src/output/plugins/httpd/IcyMetaDataServer.cxx
@@ -27,7 +27,7 @@
 
 #include <string.h>
 
-AllocatedString<>
+AllocatedString
 icy_server_metadata_header(const char *name,
 			   const char *genre, const char *url,
 			   const char *content_type, int metaint) noexcept
@@ -54,7 +54,7 @@ icy_server_metadata_header(const char *name,
 			    content_type);
 }
 
-static AllocatedString<>
+static AllocatedString
 icy_server_metadata_string(const char *stream_title,
 			   const char* stream_url) noexcept
 {
diff --git a/src/output/plugins/httpd/IcyMetaDataServer.hxx b/src/output/plugins/httpd/IcyMetaDataServer.hxx
index ef7b32646..f3762dd59 100644
--- a/src/output/plugins/httpd/IcyMetaDataServer.hxx
+++ b/src/output/plugins/httpd/IcyMetaDataServer.hxx
@@ -24,9 +24,9 @@
 #include "tag/Type.h"
 
 struct Tag;
-template<typename T> class AllocatedString;
+class AllocatedString;
 
-AllocatedString<char>
+AllocatedString
 icy_server_metadata_header(const char *name,
 			   const char *genre, const char *url,
 			   const char *content_type, int metaint) noexcept;
diff --git a/src/util/AllocatedString.hxx b/src/util/AllocatedString.hxx
index 162654e68..3c9a7b9b9 100644
--- a/src/util/AllocatedString.hxx
+++ b/src/util/AllocatedString.hxx
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2020 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright 2015-2021 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
@@ -41,8 +41,8 @@
  *
  * Unlike std::string, this object can hold a "nullptr" special value.
  */
-template<typename T=char>
-class AllocatedString {
+template<typename T>
+class BasicAllocatedString {
 public:
 	using value_type = typename StringPointer<T>::value_type;
 	using reference = typename StringPointer<T>::reference;
@@ -57,41 +57,41 @@ public:
 private:
 	pointer value;
 
-	explicit AllocatedString(pointer _value) noexcept
+	explicit BasicAllocatedString(pointer _value) noexcept
 		:value(_value) {}
 
 public:
-	AllocatedString(std::nullptr_t n) noexcept
+	BasicAllocatedString(std::nullptr_t n) noexcept
 		:value(n) {}
 
-	AllocatedString(AllocatedString &&src) noexcept
+	BasicAllocatedString(BasicAllocatedString &&src) noexcept
 		:value(src.Steal()) {}
 
-	~AllocatedString() noexcept {
+	~BasicAllocatedString() noexcept {
 		delete[] value;
 	}
 
-	static AllocatedString Donate(pointer value) noexcept {
-		return AllocatedString(value);
+	static BasicAllocatedString Donate(pointer value) noexcept {
+		return BasicAllocatedString(value);
 	}
 
-	static AllocatedString Null() noexcept {
+	static BasicAllocatedString Null() noexcept {
 		return nullptr;
 	}
 
-	static AllocatedString Empty() {
+	static BasicAllocatedString Empty() {
 		auto p = new value_type[1];
 		p[0] = SENTINEL;
 		return Donate(p);
 	}
 
-	static AllocatedString Duplicate(string_view src) {
+	static BasicAllocatedString Duplicate(string_view src) {
 		auto p = new value_type[src.size() + 1];
 		*std::copy_n(src.data(), src.size(), p) = SENTINEL;
 		return Donate(p);
 	}
 
-	AllocatedString &operator=(AllocatedString &&src) noexcept {
+	BasicAllocatedString &operator=(BasicAllocatedString &&src) noexcept {
 		std::swap(value, src.value);
 		return *this;
 	}
@@ -136,9 +136,17 @@ public:
 		return std::exchange(value, nullptr);
 	}
 
-	AllocatedString Clone() const {
+	BasicAllocatedString Clone() const {
 		return Duplicate(*this);
 	}
 };
 
+class AllocatedString : public BasicAllocatedString<char> {
+public:
+	using BasicAllocatedString::BasicAllocatedString;
+
+	AllocatedString(BasicAllocatedString<value_type> &&src) noexcept
+		:BasicAllocatedString(std::move(src)) {}
+};
+
 #endif
diff --git a/src/util/FormatString.cxx b/src/util/FormatString.cxx
index 7f6592e4f..7cf43192d 100644
--- a/src/util/FormatString.cxx
+++ b/src/util/FormatString.cxx
@@ -23,7 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-AllocatedString<>
+AllocatedString
 FormatStringV(const char *fmt, std::va_list args) noexcept
 {
 	std::va_list tmp;
@@ -37,10 +37,10 @@ FormatStringV(const char *fmt, std::va_list args) noexcept
 
 	char *buffer = new char[length + 1];
 	vsnprintf(buffer, length + 1, fmt, args);
-	return AllocatedString<>::Donate(buffer);
+	return AllocatedString::Donate(buffer);
 }
 
-AllocatedString<>
+AllocatedString
 FormatString(const char *fmt, ...) noexcept
 {
 	std::va_list args;
diff --git a/src/util/FormatString.hxx b/src/util/FormatString.hxx
index 54069abd5..83f112a91 100644
--- a/src/util/FormatString.hxx
+++ b/src/util/FormatString.hxx
@@ -24,20 +24,20 @@
 
 #include <cstdarg>
 
-template<typename T> class AllocatedString;
+class AllocatedString;
 
 /**
  * Format into an #AllocatedString.
  */
 gcc_nonnull_all
-AllocatedString<char>
+AllocatedString
 FormatStringV(const char *fmt, std::va_list args) noexcept;
 
 /**
  * Format into an #AllocatedString.
  */
 gcc_nonnull(1) gcc_printf(1,2)
-AllocatedString<char>
+AllocatedString
 FormatString(const char *fmt, ...) noexcept;
 
 #endif