@@ -48,12 +48,60 @@ class string
48
48
using const_iterator = const char *;
49
49
static constexpr size_t npos = -1 ;
50
50
51
- ~string () /* noexcept */ ;
52
- string (string_view) noexcept ;
53
- string (const char *) noexcept ;
54
- string (const string&) noexcept ;
55
- string (const char *, size_t ) noexcept ;
56
- explicit string (size_t , char = 0 ) noexcept ;
51
+ string () noexcept
52
+ {
53
+ __builtin_memset (blob, 0 , sizeof (size_t ) * 2 );
54
+ // equivalent to set_small_size(0) but also zeroes memory
55
+ *(((size_t *)blob) + 2 ) = __::sso_max << (sizeof (size_t ) - 1 ) * 8 ;
56
+ }
57
+
58
+ string (const string_view s) noexcept
59
+ {
60
+ if (s.n <= __::sso_max) {
61
+ __builtin_memcpy (blob, s.p , s.n );
62
+ __builtin_memset (blob + s.n , 0 , __::sso_max - s.n );
63
+ set_small_size (s.n );
64
+ } else {
65
+ init_big (s);
66
+ }
67
+ }
68
+
69
+ explicit string (const size_t n, const char ch = 0 ) noexcept
70
+ {
71
+ if (n <= __::sso_max) {
72
+ __builtin_memset (blob, ch, n);
73
+ __builtin_memset (blob + n, 0 , __::sso_max - n);
74
+ set_small_size (n);
75
+ } else {
76
+ init_big (n, ch);
77
+ }
78
+ }
79
+
80
+ string (const char * const p) noexcept
81
+ : string(string_view(p, __builtin_strlen(p)))
82
+ {
83
+ }
84
+
85
+ string (const string& r) noexcept
86
+ {
87
+ if (r.size () <= __::sso_max) {
88
+ __builtin_memcpy (blob, r.data (), __::string_size);
89
+ set_small_size (r.size ());
90
+ } else {
91
+ init_big (r);
92
+ }
93
+ }
94
+
95
+ string (const char * const p, const size_t n) noexcept
96
+ : string(string_view(p, n))
97
+ {
98
+ }
99
+
100
+ ~string () /* noexcept */
101
+ {
102
+ if (isbig ())
103
+ destroy_big ();
104
+ }
57
105
58
106
string& operator =(string) noexcept ;
59
107
const char * c_str () const noexcept ;
@@ -78,13 +126,6 @@ class string
78
126
size_t find (char , size_t = 0 ) const noexcept ;
79
127
size_t find (string_view, size_t = 0 ) const noexcept ;
80
128
81
- string () noexcept
82
- {
83
- __builtin_memset (blob, 0 , sizeof (size_t ) * 2 );
84
- // equivalent to set_small_size(0) but also zeroes memory
85
- *(((size_t *)blob) + 2 ) = __::sso_max << (sizeof (size_t ) - 1 ) * 8 ;
86
- }
87
-
88
129
void swap (string& s) noexcept
89
130
{
90
131
ctl::swap (blob, s.blob );
@@ -110,17 +151,17 @@ class string
110
151
return isbig () ? !big ()->n : small ()->rem >= __::sso_max;
111
152
}
112
153
113
- inline char * data () noexcept
154
+ char * data () noexcept
114
155
{
115
156
return isbig () ? big ()->p : small ()->buf ;
116
157
}
117
158
118
- inline const char * data () const noexcept
159
+ const char * data () const noexcept
119
160
{
120
161
return isbig () ? big ()->p : small ()->buf ;
121
162
}
122
163
123
- inline size_t size () const noexcept
164
+ size_t size () const noexcept
124
165
{
125
166
#if 0
126
167
if (!isbig() && small()->rem > __::sso_max)
@@ -215,7 +256,7 @@ class string
215
256
append (s.p , s.n );
216
257
}
217
258
218
- inline operator string_view () const noexcept
259
+ operator string_view () const noexcept
219
260
{
220
261
return string_view (data (), size ());
221
262
}
@@ -277,63 +318,68 @@ class string
277
318
}
278
319
279
320
private:
280
- inline bool isbig () const noexcept
321
+ void destroy_big () noexcept ;
322
+ void init_big (const string&) noexcept ;
323
+ void init_big (string_view) noexcept ;
324
+ void init_big (size_t , char ) noexcept ;
325
+
326
+ bool isbig () const noexcept
281
327
{
282
328
return *(blob + __::sso_max) & 0x80 ;
283
329
}
284
330
285
- inline void set_small_size (const size_t size) noexcept
331
+ void set_small_size (const size_t size) noexcept
286
332
{
287
333
if (size > __::sso_max)
288
334
__builtin_trap ();
289
- *(blob + __::sso_max) = ( __::sso_max - size) ;
335
+ __s. rem = __::sso_max - size;
290
336
}
291
337
292
- inline void set_big_string (char * const p,
293
- const size_t n,
294
- const size_t c2) noexcept
338
+ void set_big_string (char * const p, const size_t n, const size_t c2) noexcept
295
339
{
296
340
if (c2 > __::big_mask)
297
341
__builtin_trap ();
298
- *( char **)blob = p;
299
- *((( size_t *)blob) + 1 ) = n;
300
- *((( size_t *)blob) + 2 ) = c2 | ~__::big_mask;
342
+ __b. p = p;
343
+ __b. n = n;
344
+ __b. c = c2 | ~__::big_mask;
301
345
}
302
346
303
- inline __::small_string* small () noexcept
347
+ __::small_string* small () noexcept
304
348
{
305
349
if (isbig ())
306
350
__builtin_trap ();
307
- return reinterpret_cast <__::small_string*>(blob) ;
351
+ return &__s ;
308
352
}
309
353
310
- inline const __::small_string* small () const noexcept
354
+ const __::small_string* small () const noexcept
311
355
{
312
356
if (isbig ())
313
357
__builtin_trap ();
314
- return reinterpret_cast < const __::small_string*>(blob) ;
358
+ return &__s ;
315
359
}
316
360
317
- inline __::big_string* big () noexcept
361
+ __::big_string* big () noexcept
318
362
{
319
363
if (!isbig ())
320
364
__builtin_trap ();
321
- return reinterpret_cast <__::big_string*>(blob) ;
365
+ return &__b ;
322
366
}
323
367
324
- inline const __::big_string* big () const noexcept
368
+ const __::big_string* big () const noexcept
325
369
{
326
370
if (!isbig ())
327
371
__builtin_trap ();
328
- return reinterpret_cast < const __::big_string*>(blob) ;
372
+ return &__b ;
329
373
}
330
374
331
- friend string strcat (string_view, string_view);
375
+ friend string strcat (string_view, string_view) noexcept ;
332
376
333
- alignas (union {
334
- __::big_string a;
335
- __::small_string b;
336
- }) char blob[__::string_size];
377
+ union
378
+ {
379
+ __::big_string __b;
380
+ __::small_string __s;
381
+ char blob[__::string_size];
382
+ };
337
383
};
338
384
339
385
static_assert (sizeof (string) == __::string_size);
0 commit comments