OXYGENHUB
◆ main openmsx / src / utils / static_string_view.hh
2.4 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#ifndef STATIC_STRING_VIEW_HH
2
#define STATIC_STRING_VIEW_HH
3
4
#include "StringStorage.hh"
5
6
#include <algorithm>
7
#include <cassert>
8
#include <string_view>
9
#include <utility>
10
11
/** static_string_view
12
13
 * This is like std::string_view, but points to a string with static lifetime
14
 * (e.g. a string literal). In other words, the pointed-to-string is guaranteed
15
 * to remain valid. This allows to store just a reference to the string instead
16
 * of having to copy it into e.g. a std::string object.
17
 *
18
 * The intention is that objects of this class can only be constructed from
19
 * string-literals. For example constructing from std::string, std::string_view
20
 * or 'const char*' will result in compile errors. (See unittest for more
21
 * details).
22
 *
23
 * In some (rare?) cases you may want something like this, but string literals
24
 * are too restrictive. Using the 'make_string_storage()' function below might
25
 * be a solution. But then the programmer takes responsibility of correctly
26
 * managing lifetimes (then the c++ compiler doesn't help anymore).
27
 */
28
class static_string_view
29
{
30
public:
31
	// Disallow construction from non-const char array.
32
	template<size_t N>
33
	constexpr static_string_view(char (&buf)[N]) = delete;
34
35
	// Construct from string-literal (a const char array).
36
	template<size_t N>
37
	constexpr static_string_view(const char (&buf)[N])
38
		: s(buf, N-1)
39
	{
40
		assert(buf[N - 1] == '\0');
41
	}
42
43
	// Used by make_string_storage().
44
	struct lifetime_ok_tag {};
45
	constexpr static_string_view(lifetime_ok_tag, std::string_view v)
46
		: s(v) {}
47
48
	// Allow (implicit) conversion to std::string_view.
49
	explicit(false) constexpr operator std::string_view() const { return s; }
50
51
private:
52
	std::string_view s;
53
};
54
55
/** Take a string_view, make a copy of it, and return a pair of
56
  *  - Storage for the copy.
57
  *  - A static_string_view object pointing to that storage.
58
  * The view only remains valid for as long as the storage is kept alive.
59
  *
60
  * Note: using a std::string for the string-storage is not correct when that
61
  * std::string object can be moved. This implementation is correct even when
62
  * the storage-handler object gets moved.
63
  */
64
inline auto make_string_storage(std::string_view sv)
65
{
66
	auto storage = allocate_string_storage(sv.size());
67
	char* p = storage.get();
68
	std::ranges::copy(sv, p);
69
	return std::pair{std::move(storage),
70
	                 static_string_view(static_string_view::lifetime_ok_tag{},
71
			                    std::string_view(p, sv.size()))};
72
}
73
74
#endif