@@ -28,70 +28,114 @@ concept StringLikeTy =
28
28
! std::is_same_v<StringTy, String> &&
29
29
std::convertible_to<StringTy, std::string_view>;
30
30
31
- /* * An immutable string with shared ownership.
32
- */
33
31
class MRDOX_DECL
34
32
String final
35
33
{
36
- struct Impl ;
34
+ const char * ptr_ = nullptr ;
37
35
38
- union
39
- {
40
- Impl* impl_;
41
- // len is stored with the low bit moved to
42
- // the hi bit, and the low bit always set.
43
- std::size_t len_;
44
- };
45
- char const * psz_;
46
-
47
- static void allocate (std::string_view s,Impl*&, char const *&);
48
- static void deallocate (Impl*) noexcept ;
49
- static consteval std::size_t len (std::size_t n)
36
+ bool
37
+ is_literal () const noexcept
50
38
{
51
- return (n << (sizeof (std::size_t )*8 - 1 )) | n | 1UL ;
39
+ MRDOX_ASSERT (! empty ());
40
+ // for string literals, data_ stores a pointer
41
+ // to the first character of the string.
42
+ // for ref-counted strings, data_ stores a pointer
43
+ // to the null-terminator of the string.
44
+ return *ptr_;
52
45
}
53
46
54
- constexpr bool is_literal () const noexcept
55
- {
56
- return (len_ & 1 ) != 0 ;
57
- }
47
+ class impl_view ;
58
48
59
- public:
60
- /* * Destructor.
49
+ impl_view impl () const noexcept ;
50
+
51
+ /* * Construct a ref-counted string.
61
52
*/
62
- ~String ();
53
+ void
54
+ construct (
55
+ const char * s,
56
+ std::size_t n);
63
57
58
+ public:
64
59
/* * Constructor.
65
60
66
61
Default constructed strings have a zero size,
67
62
and include a null terminator.
68
63
*/
69
- String () noexcept ;
64
+ constexpr String () noexcept = default ;
70
65
71
66
/* * Constructor.
72
67
73
68
Ownership of the string is transferred to
74
69
the newly constructed string. The moved-from
75
70
string behaves as if default constructed.
76
71
*/
77
- String (String&& other) noexcept ;
72
+ constexpr String (String&& other) noexcept
73
+ {
74
+ swap (other);
75
+ }
78
76
79
77
/* * Constructor.
80
78
81
79
The newly constructed string acquries shared
82
80
ownership of the string referenced by other.
83
81
*/
84
- String (String const & other) noexcept ;
82
+ String (const String& other) noexcept ;
83
+
84
+ /* * Destructor.
85
+ */
86
+ ~String () noexcept ;
87
+
88
+ /* * Constructor.
89
+
90
+ This function constructs a string literal
91
+ which references the buffer pointed to by
92
+ `str`. Ownership is not transferred; the lifetime
93
+ of the buffer must extend until the string is
94
+ destroyed, otherwise the behavior is undefined.
95
+
96
+ @param str A null-terminated string. If the
97
+ string is not null-terminated, the result is
98
+ undefined.
99
+ */
100
+ template <std::size_t N>
101
+ constexpr
102
+ String (const char (&str)[N])
103
+ {
104
+ // empty strings are stored as nullptr
105
+ if constexpr (N > 1 )
106
+ ptr_ = str;
107
+ }
85
108
86
109
/* * Constructor.
87
110
88
111
This function constructs a new string from
89
- the buffer pointed to by `s `.
112
+ the string pointed to by `str` of length `len `.
90
113
91
- @param s The string to construct with.
114
+ @param `str` The string to construct with.
115
+ A copy of this string is made.
116
+ @param `len` The length of the string.
117
+ */
118
+ String (
119
+ const char * str,
120
+ std::size_t len)
121
+ {
122
+ // empty strings are stored as nullptr
123
+ if (len)
124
+ construct (str, len);
125
+ }
126
+
127
+ /* * Constructor.
128
+
129
+ This function constructs a new string from
130
+ the buffer pointed to by `sv`.
131
+
132
+ @param sv The string to construct with.
92
133
A copy of this string is made.
93
134
*/
94
- String (std::string_view s);
135
+ String (std::string_view sv)
136
+ : String(sv.data(), sv.size())
137
+ {
138
+ }
95
139
96
140
/* * Constructor.
97
141
@@ -107,25 +151,19 @@ class MRDOX_DECL
107
151
{
108
152
}
109
153
110
- /* * Constructor.
111
-
112
- This function constructs a string literal
113
- which references the buffer pointed to by
114
- sz. Ownership is not transferred; the lifetime
115
- of the buffer must extend until the string is
116
- destroyed, otherwise the behavior is undefined.
154
+ /* * Assignment.
117
155
118
- @param psz A null-terminated string. If the
119
- string is not null-terminated, the result is
120
- undefined .
156
+ This acquires shared ownership of the
157
+ string referenced by other. Ownership of
158
+ the previously referenced string is released .
121
159
*/
122
- template <std::size_t N>
123
- constexpr String (char const (&psz)[N]) noexcept
124
- : len_(len(N-1 ))
125
- , psz_(psz)
160
+ String&
161
+ operator =(
162
+ const String& other) noexcept
126
163
{
127
- static_assert (N > 0 );
128
- static_assert (N <= std::size_t (-1 )>>1 );
164
+ String temp (other);
165
+ swap (temp);
166
+ return *this ;
129
167
}
130
168
131
169
/* * Assignment.
@@ -136,33 +174,29 @@ class MRDOX_DECL
136
174
After the assignment, the moved-from string
137
175
behaves as if default constructed.
138
176
*/
139
- String& operator =(String&& other) noexcept ;
140
-
141
- /* * Assignment.
142
-
143
- This acquires shared ownership of the
144
- string referenced by other. Ownership of
145
- the previously referenced string is released.
146
- */
147
- String& operator =(String const & other) noexcept ;
148
-
149
- /* * Return true if the string is empty.
150
- */
151
- constexpr bool empty () const noexcept
177
+ String&
178
+ operator =(
179
+ String&& other) noexcept
152
180
{
153
- return psz_[0 ] == ' \0 ' ;
181
+ String temp (std::move (other));
182
+ swap (temp);
183
+ return *this ;
154
184
}
155
185
156
186
/* * Return the string.
157
187
*/
158
- std::string_view
159
- get () const noexcept ;
188
+ operator std::string_view () const noexcept
189
+ {
190
+ return get ();
191
+ }
160
192
161
193
/* * Return the string.
162
194
*/
163
- operator std::string_view () const noexcept
195
+ std::string_view
196
+ get () const noexcept
164
197
{
165
- return get ();
198
+ return std::string_view (
199
+ data (), size ());
166
200
}
167
201
168
202
/* * Return the string.
@@ -172,19 +206,24 @@ class MRDOX_DECL
172
206
return std::string (get ());
173
207
}
174
208
175
- /* * Return the size .
209
+ /* * Return true if the string is empty .
176
210
*/
177
- std::size_t size () const noexcept
211
+ bool
212
+ empty () const noexcept
178
213
{
179
- return get (). size () ;
214
+ return ! ptr_ ;
180
215
}
181
216
182
217
/* * Return the size.
183
218
*/
184
- char const * data () const noexcept
185
- {
186
- return get ().data ();
187
- }
219
+ std::size_t size () const noexcept ;
220
+
221
+ /* * Return the string.
222
+
223
+ The pointed-to character buffer returned
224
+ by this function is always null-terminated.
225
+ */
226
+ const char * data () const noexcept ;
188
227
189
228
/* * Return the string.
190
229
@@ -193,20 +232,26 @@ class MRDOX_DECL
193
232
*/
194
233
char const * c_str () const noexcept
195
234
{
196
- return psz_ ;
235
+ return data () ;
197
236
}
198
237
199
238
/* * Swap two strings.
200
239
*/
201
- void swap (String& other) noexcept
240
+ constexpr
241
+ void
242
+ swap (String& other) noexcept
202
243
{
203
- std::swap (impl_, other.impl_ );
204
- std::swap (psz_, other.psz_ );
244
+ std::swap (ptr_, other.ptr_ );
205
245
}
206
246
207
247
/* * Swap two strings.
208
248
*/
209
- friend void swap (String& lhs, String& rhs) noexcept
249
+ friend
250
+ constexpr
251
+ void
252
+ swap (
253
+ String& lhs,
254
+ String& rhs) noexcept
210
255
{
211
256
lhs.swap (rhs);
212
257
}
0 commit comments