Embedded Template Library 1.0
Loading...
Searching...
No Matches
u32string.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2016 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_U32STRING_INCLUDED
32#define ETL_U32STRING_INCLUDED
33
34#include "platform.h"
35#include "basic_string.h"
36#include "hash.h"
37#include "initializer_list.h"
38#include "string_view.h"
39
40#include "private/minmax_push.h"
41
42namespace etl
43{
44#if ETL_USING_CPP11
45 inline namespace literals
46 {
47 inline namespace string_literals
48 {
49 inline constexpr etl::u32string_view operator""_sv(const char32_t* str, size_t length) ETL_NOEXCEPT
50 {
51 return etl::u32string_view{str, length};
52 }
53 } // namespace string_literals
54 } // namespace literals
55#endif
56
57 typedef ibasic_string<char32_t> iu32string;
58
59 //***************************************************************************
63 //***************************************************************************
64 template <size_t MAX_SIZE_>
65 class u32string : public iu32string
66 {
67 public:
68
69 typedef iu32string base_type;
70 typedef iu32string interface_type;
71
72 typedef iu32string::value_type value_type;
73
74 static const size_t MAX_SIZE = MAX_SIZE_;
75
76 //*************************************************************************
78 //*************************************************************************
80 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
81 {
82 this->initialise();
83 }
84
85 //*************************************************************************
88 //*************************************************************************
90 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
91 {
92 this->assign(other);
93 }
94
95 //*************************************************************************
98 //*************************************************************************
99 u32string(const etl::iu32string& other)
100 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
101 {
102 this->assign(other);
103 }
104
105 //*************************************************************************
110 //*************************************************************************
111 u32string(const etl::iu32string& other, size_type position, size_type length = npos)
112 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
113 {
114 ETL_ASSERT(position < other.size(), ETL_ERROR(string_out_of_bounds));
115
116 this->assign(other, position, length);
117 }
118
119 //*************************************************************************
122 //*************************************************************************
123 ETL_EXPLICIT_STRING_FROM_CHAR u32string(const value_type* text)
124 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
125 {
126 this->assign(text);
127 }
128
129 //*************************************************************************
133 //*************************************************************************
134 u32string(const value_type* text, size_type count)
135 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
136 {
137 this->assign(text, text + count);
138 }
139
140 //*************************************************************************
144 //*************************************************************************
145 u32string(size_type count, value_type c)
146 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
147 {
148 this->initialise();
149 this->resize(count, c);
150 }
151
152 //*************************************************************************
157 //*************************************************************************
158 template <typename TIterator>
159 u32string(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
160 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
161 {
162 this->assign(first, last);
163 }
164
165#if ETL_HAS_INITIALIZER_LIST
166 //*************************************************************************
168 //*************************************************************************
169 u32string(std::initializer_list<value_type> init)
170 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
171 {
172 this->assign(init.begin(), init.end());
173 }
174#endif
175
176 //*************************************************************************
179 //*************************************************************************
180 explicit u32string(const etl::u32string_view& view)
181 : iu32string(reinterpret_cast<value_type*>(&buffer), MAX_SIZE)
182 {
183 this->assign(view.begin(), view.end());
184 }
185
186 //*************************************************************************
190 //*************************************************************************
191 etl::u32string<MAX_SIZE_> substr(size_type position = 0, size_type length_ = npos) const
192 {
193 etl::u32string<MAX_SIZE_> new_string;
194
195 if (position != size())
196 {
197 ETL_ASSERT(position < size(), ETL_ERROR(string_out_of_bounds));
198
199 length_ = etl::min(length_, size() - position);
200
201 new_string.assign(buffer + position, buffer + position + length_);
202 }
203
204 return new_string;
205 }
206
207 //*************************************************************************
209 //*************************************************************************
211 {
212 if (&rhs != this)
213 {
214 this->assign(rhs);
215 }
216
217 return *this;
218 }
219
220 //*************************************************************************
222 //*************************************************************************
223 u32string& operator=(const value_type* text)
224 {
225 this->assign(text);
226
227 return *this;
228 }
229
230 //*************************************************************************
232 //*************************************************************************
233 u32string& operator=(const etl::u32string_view& view)
234 {
235 this->assign(view);
236
237 return *this;
238 }
239
240 //*************************************************************************
242 //*************************************************************************
243#if ETL_HAS_ISTRING_REPAIR
244 virtual void repair() ETL_OVERRIDE
245#else
246 void repair()
247#endif
248 {
250 }
251
252 private:
253
254 value_type buffer[MAX_SIZE + 1];
255 };
256
257 //***************************************************************************
260 //***************************************************************************
261 class u32string_ext : public iu32string
262 {
263 public:
264
265 typedef iu32string base_type;
266 typedef iu32string interface_type;
267
268 typedef iu32string::value_type value_type;
269 typedef iu32string::size_type size_type;
270
271 //*************************************************************************
273 //*************************************************************************
274 u32string_ext(value_type* buffer, size_type buffer_size)
275 : iu32string(buffer, buffer_size - 1U)
276 {
277 this->initialise();
278 }
279
280 //*************************************************************************
283 //*************************************************************************
284 template <size_t Size>
285 u32string_ext(value_type (&buffer)[Size])
286 : iu32string(buffer, Size - 1U)
287 {
288 this->initialise();
289 }
290
291 //*************************************************************************
294 //*************************************************************************
295 u32string_ext(const etl::u32string_ext& other, value_type* buffer, size_type buffer_size)
296 : iu32string(buffer, buffer_size - 1U)
297 {
298 if (this->is_within_buffer(other.data()))
299 {
300 this->current_size = other.size();
301 }
302 else
303 {
304 this->assign(other);
305 }
306 }
307
308 //*************************************************************************
311 //*************************************************************************
312 u32string_ext(const etl::iu32string& other, value_type* buffer, size_type buffer_size)
313 : iu32string(buffer, buffer_size - 1U)
314 {
315 if (this->is_within_buffer(other.data()))
316 {
317 this->current_size = other.size();
318 }
319 else
320 {
321 this->assign(other);
322 }
323 }
324
325 //*************************************************************************
329 //*************************************************************************
330 template <size_t BufferSize>
331 u32string_ext(const etl::iu32string& other, value_type (&buffer)[BufferSize])
332 : iu32string(buffer, BufferSize - 1U)
333 {
334 if (this->is_within_buffer(other.data()))
335 {
336 this->current_size = other.size();
337 }
338 else
339 {
340 this->assign(other);
341 }
342 }
343
344 //*************************************************************************
349 //*************************************************************************
350 u32string_ext(const etl::iu32string& other, value_type* buffer, size_type buffer_size, size_type position, size_type length = npos)
351 : iu32string(buffer, buffer_size - 1U)
352 {
353 ETL_ASSERT(position < other.size(), ETL_ERROR(string_out_of_bounds));
354
355 if (this->is_within_buffer(other.data()))
356 {
357 this->current_size = other.size();
358 }
359 else
360 {
361 this->assign(other, position, length);
362 }
363 }
364
365 //*************************************************************************
371 //*************************************************************************
372 template <size_t BufferSize>
373 u32string_ext(const etl::iu32string& other, value_type (&buffer)[BufferSize], size_type position, size_type length = npos)
374 : iu32string(buffer, BufferSize - 1U)
375 {
376 ETL_ASSERT(position < other.size(), ETL_ERROR(string_out_of_bounds));
377
378 if (this->is_within_buffer(other.data()))
379 {
380 this->current_size = other.size();
381 }
382 else
383 {
384 this->assign(other, position, length);
385 }
386 }
387
388 //*************************************************************************
391 //*************************************************************************
392 template <typename TPointer>
393 u32string_ext(TPointer text, value_type* buffer, size_type buffer_size,
394 typename etl::enable_if<etl::is_same<const value_type*, TPointer>::value, int>::type* = ETL_NULLPTR)
395 : iu32string(buffer, buffer_size - 1U)
396 {
397 if (this->is_within_buffer(text))
398 {
399 this->current_size = etl::strlen(buffer);
400 }
401 else
402 {
403 this->assign(text);
404 }
405 }
406
407 //*************************************************************************
411 //*************************************************************************
412 template <typename TPointer, size_t BufferSize>
413 u32string_ext(TPointer text, value_type (&buffer)[BufferSize],
414 typename etl::enable_if<etl::is_same<const value_type*, TPointer>::value, int>::type* = ETL_NULLPTR)
415 : iu32string(buffer, BufferSize - 1U)
416 {
417 if (this->is_within_buffer(text))
418 {
419 this->current_size = etl::strlen(buffer);
420 }
421 else
422 {
423 this->assign(text);
424 }
425 }
426
427 //*************************************************************************
430 //*************************************************************************
431 template <size_t Size>
432 u32string_ext(const value_type (&literal)[Size], value_type* buffer, size_type buffer_size)
433 : iu32string(buffer, buffer_size - 1U)
434 {
435 if (this->is_within_buffer(literal))
436 {
437 this->current_size = etl::strlen(literal);
438 }
439 else
440 {
441 this->assign(literal);
442 }
443 }
444
445 //*************************************************************************
449 //*************************************************************************
450 template <size_t LiteralSize, size_t BufferSize>
451 u32string_ext(const value_type (&literal)[LiteralSize], value_type (&buffer)[BufferSize])
452 : iu32string(buffer, BufferSize - 1U)
453 {
454 if (this->is_within_buffer(literal))
455 {
456 this->current_size = etl::strlen(literal);
457 }
458 else
459 {
460 this->assign(literal);
461 }
462 }
463
464 //*************************************************************************
468 //*************************************************************************
469 u32string_ext(const value_type* text, size_type count, value_type* buffer, size_type buffer_size)
470 : iu32string(buffer, buffer_size - 1U)
471 {
472 if (this->is_within_buffer(text))
473 {
474 this->current_size = count;
475 }
476 else
477 {
478 this->assign(text, text + count);
479 }
480 }
481
482 //*************************************************************************
487 //*************************************************************************
488 template <size_t BufferSize>
489 u32string_ext(const value_type* text, size_type count, value_type (&buffer)[BufferSize])
490 : iu32string(buffer, BufferSize - 1U)
491 {
492 if (this->is_within_buffer(text))
493 {
494 this->current_size = count;
495 }
496 else
497 {
498 this->assign(text, text + count);
499 }
500 }
501
502 //*************************************************************************
506 //*************************************************************************
507 u32string_ext(size_type count, value_type c, value_type* buffer, size_type buffer_size)
508 : iu32string(buffer, buffer_size - 1U)
509 {
510 this->initialise();
511 this->resize(count, c);
512 }
513
514 //*************************************************************************
519 //*************************************************************************
520 template <size_t BufferSize>
521 u32string_ext(size_type count, value_type c, value_type (&buffer)[BufferSize])
522 : iu32string(buffer, BufferSize - 1U)
523 {
524 this->initialise();
525 this->resize(count, c);
526 }
527
528 //*************************************************************************
531 //*************************************************************************
532 explicit u32string_ext(const etl::u32string_view& view, value_type* buffer, size_type buffer_size)
533 : iu32string(buffer, buffer_size - 1U)
534 {
535 if (this->is_within_buffer(view.data()))
536 {
537 this->current_size = view.size();
538 }
539 else
540 {
541 this->assign(view.begin(), view.end());
542 }
543 }
544
545 //*************************************************************************
549 //*************************************************************************
550 template <size_t BufferSize>
551 explicit u32string_ext(const etl::u32string_view& view, value_type (&buffer)[BufferSize])
552 : iu32string(buffer, BufferSize - 1U)
553 {
554 if (this->is_within_buffer(view.data()))
555 {
556 this->current_size = view.size();
557 }
558 else
559 {
560 this->assign(view.begin(), view.end());
561 }
562 }
563
564 //*************************************************************************
569 //*************************************************************************
570 template <typename TIterator>
571 u32string_ext(TIterator first, TIterator last, value_type* buffer, size_type buffer_size,
572 typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
573 : iu32string(buffer, buffer_size - 1U)
574 {
575 if (this->is_within_buffer(reinterpret_cast<const_iterator>(etl::addressof(*first))))
576 {
577 this->current_size = static_cast<size_type>(etl::distance(first, last));
578 }
579 else
580 {
581 this->assign(first, last);
582 }
583 }
584
585 //*************************************************************************
591 //*************************************************************************
592 template <typename TIterator, size_t BufferSize>
593 u32string_ext(TIterator first, TIterator last, value_type (&buffer)[BufferSize],
594 typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
595 : iu32string(buffer, BufferSize - 1U)
596 {
597 if (this->is_within_buffer(reinterpret_cast<const_iterator>(etl::addressof(*first))))
598 {
599 this->current_size = static_cast<size_type>(etl::distance(first, last));
600 }
601 else
602 {
603 this->assign(first, last);
604 }
605 }
606
607#if ETL_HAS_INITIALIZER_LIST
608 //*************************************************************************
610 //*************************************************************************
611 u32string_ext(std::initializer_list<value_type> init, value_type* buffer, size_type buffer_size)
612 : iu32string(buffer, buffer_size - 1U)
613 {
614 this->assign(init.begin(), init.end());
615 }
616
617 //*************************************************************************
621 //*************************************************************************
622 template <size_t BufferSize>
623 u32string_ext(std::initializer_list<value_type> init, value_type (&buffer)[BufferSize])
624 : iu32string(buffer, BufferSize - 1U)
625 {
626 this->assign(init.begin(), init.end());
627 }
628#endif
629
630 //*************************************************************************
632 //*************************************************************************
634 {
635 if (&rhs != this)
636 {
637 this->assign(rhs);
638 }
639
640 return *this;
641 }
642
643 //*************************************************************************
645 //*************************************************************************
646 u32string_ext& operator=(const iu32string& rhs)
647 {
648 if (&rhs != this)
649 {
650 this->assign(rhs);
651 }
652
653 return *this;
654 }
655
656 //*************************************************************************
658 //*************************************************************************
659 u32string_ext& operator=(const value_type* text)
660 {
661 this->assign(text);
662
663 return *this;
664 }
665
666 //*************************************************************************
668 //*************************************************************************
669 u32string_ext& operator=(const etl::u32string_view& view)
670 {
671 this->assign(view);
672
673 return *this;
674 }
675
676 //*************************************************************************
678 //*************************************************************************
679#if ETL_HAS_ISTRING_REPAIR
680 virtual void repair() ETL_OVERRIDE
681#else
682 void repair()
683#endif
684 {
685 }
686
687 private:
688
689 //*************************************************************************
691 //*************************************************************************
692 u32string_ext(const u32string_ext& other) ETL_DELETE;
693 };
694
695 //*************************************************************************
697 //*************************************************************************
698#if ETL_USING_8BIT_TYPES
699 template <>
700 struct hash<etl::iu32string>
701 {
702 size_t operator()(const etl::iu32string& text) const
703 {
704 return etl::private_hash::generic_hash<size_t>(reinterpret_cast<const uint8_t*>(text.data()),
705 reinterpret_cast<const uint8_t*>(text.data() + text.size()));
706 }
707 };
708
709 template <size_t SIZE>
710 struct hash<etl::u32string<SIZE> >
711 {
712 size_t operator()(const etl::u32string<SIZE>& text) const
713 {
714 return etl::private_hash::generic_hash<size_t>(reinterpret_cast<const uint8_t*>(text.data()),
715 reinterpret_cast<const uint8_t*>(text.data() + text.size()));
716 }
717 };
718
719 template <>
720 struct hash<etl::u32string_ext >
721 {
722 size_t operator()(const etl::u32string_ext& text) const
723 {
724 return etl::private_hash::generic_hash<size_t>(reinterpret_cast<const uint8_t*>(text.data()),
725 reinterpret_cast<const uint8_t*>(text.data() + text.size()));
726 }
727 };
728#endif
729
730 //***************************************************************************
732 //***************************************************************************
733 template <size_t Array_Size>
734 etl::u32string<Array_Size - 1U> make_string(const char32_t (&text)[Array_Size])
735 {
736 return etl::u32string<Array_Size - 1U>(text, etl::strlen(text, Array_Size - 1U));
737 }
738
739 //***************************************************************************
741 //***************************************************************************
742 template <size_t MAX_SIZE, size_t SIZE>
744 {
745 return etl::u32string<MAX_SIZE>(text, etl::strlen(text, SIZE));
746 }
747} // namespace etl
748
749#include "private/minmax_pop.h"
750
751#endif
ETL_CONSTEXPR const_pointer data() const ETL_NOEXCEPT
Returns a const pointer to the first element of the internal storage.
Definition string_view.h:223
ETL_CONSTEXPR const_iterator end() const ETL_NOEXCEPT
Returns a const iterator to the end of the array.
Definition string_view.h:247
ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT
Returns a const iterator to the beginning of the array.
Definition string_view.h:231
Definition basic_string.h:350
bool is_within_buffer(const_pointer ptr) const
Definition basic_string.h:2711
void resize(size_type new_size)
Definition basic_string.h:480
void assign(const etl::ibasic_string< char32_t > &other)
Definition basic_string.h:685
pointer data()
Definition basic_string.h:648
void initialise()
Definition basic_string.h:2482
void repair_buffer(char32_t *p_buffer_)
Definition basic_string.h:2494
size_type length() const
Definition basic_string.h:202
size_type current_size
The current number of elements in the string.
Definition basic_string.h:334
size_type size() const
Definition basic_string.h:193
Definition basic_string.h:115
Definition u32string.h:262
u32string_ext(const value_type(&literal)[LiteralSize], value_type(&buffer)[BufferSize])
Definition u32string.h:451
u32string_ext(TPointer text, value_type *buffer, size_type buffer_size, typename etl::enable_if< etl::is_same< const value_type *, TPointer >::value, int >::type *=ETL_NULLPTR)
Definition u32string.h:393
u32string_ext(TPointer text, value_type(&buffer)[BufferSize], typename etl::enable_if< etl::is_same< const value_type *, TPointer >::value, int >::type *=ETL_NULLPTR)
Definition u32string.h:413
u32string_ext(const etl::iu32string &other, value_type(&buffer)[BufferSize], size_type position, size_type length=npos)
Definition u32string.h:373
u32string_ext(const value_type *text, size_type count, value_type *buffer, size_type buffer_size)
Definition u32string.h:469
u32string_ext & operator=(const value_type *text)
Assignment operator.
Definition u32string.h:659
u32string_ext & operator=(const u32string_ext &rhs)
Assignment operator.
Definition u32string.h:633
u32string_ext(const value_type *text, size_type count, value_type(&buffer)[BufferSize])
Definition u32string.h:489
u32string_ext(const etl::u32string_ext &other, value_type *buffer, size_type buffer_size)
Definition u32string.h:295
u32string_ext(size_type count, value_type c, value_type *buffer, size_type buffer_size)
Definition u32string.h:507
u32string_ext & operator=(const etl::u32string_view &view)
Assignment operator.
Definition u32string.h:669
void repair()
Fix the internal pointers after a low level memory copy.
Definition u32string.h:682
u32string_ext(TIterator first, TIterator last, value_type *buffer, size_type buffer_size, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition u32string.h:571
u32string_ext(const etl::u32string_view &view, value_type *buffer, size_type buffer_size)
Definition u32string.h:532
u32string_ext(TIterator first, TIterator last, value_type(&buffer)[BufferSize], typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition u32string.h:593
u32string_ext(const value_type(&literal)[Size], value_type *buffer, size_type buffer_size)
Definition u32string.h:432
u32string_ext(const etl::u32string_view &view, value_type(&buffer)[BufferSize])
Definition u32string.h:551
u32string_ext(size_type count, value_type c, value_type(&buffer)[BufferSize])
Definition u32string.h:521
u32string_ext & operator=(const iu32string &rhs)
Assignment operator.
Definition u32string.h:646
u32string_ext(const etl::iu32string &other, value_type *buffer, size_type buffer_size, size_type position, size_type length=npos)
Definition u32string.h:350
u32string_ext(const etl::iu32string &other, value_type *buffer, size_type buffer_size)
Definition u32string.h:312
u32string_ext(value_type *buffer, size_type buffer_size)
Constructor.
Definition u32string.h:274
u32string_ext(const etl::iu32string &other, value_type(&buffer)[BufferSize])
Definition u32string.h:331
u32string_ext(value_type(&buffer)[Size])
Definition u32string.h:285
Definition u32string.h:66
u32string(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition u32string.h:159
ETL_EXPLICIT_STRING_FROM_CHAR u32string(const value_type *text)
Definition u32string.h:123
u32string()
Constructor.
Definition u32string.h:79
u32string(const etl::u32string_view &view)
Definition u32string.h:180
u32string(const etl::iu32string &other, size_type position, size_type length=npos)
Definition u32string.h:111
u32string(const etl::u32string< MAX_SIZE_ > &other)
Definition u32string.h:89
u32string & operator=(const etl::u32string_view &view)
Assignment operator.
Definition u32string.h:233
u32string & operator=(const value_type *text)
Assignment operator.
Definition u32string.h:223
etl::u32string< MAX_SIZE_ > substr(size_type position=0, size_type length_=npos) const
Definition u32string.h:191
void repair()
Fix the internal pointers after a low level memory copy.
Definition u32string.h:246
u32string(const etl::iu32string &other)
Definition u32string.h:99
u32string(size_type count, value_type c)
Definition u32string.h:145
u32string & operator=(const u32string &rhs)
Assignment operator.
Definition u32string.h:210
u32string(const value_type *text, size_type count)
Definition u32string.h:134
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
bitset_ext
Definition absolute.h:40
etl::string< Array_Size - 1U > make_string(const char(&text)[Array_Size])
Hash function.
Definition string.h:753
etl::string< MAX_SIZE > make_string_with_capacity(const char(&text)[SIZE])
Make string with max capacity from string literal or array.
Definition string.h:762
ETL_CONSTEXPR14 size_t strlen(const T *t) ETL_NOEXCEPT
Alternative strlen for all character types.
Definition char_traits.h:293