xtd 0.2.0
Loading...
Searching...
No Matches
basic_string_.hpp
Go to the documentation of this file.
1
4#pragma once
6#if !defined(__XTD_BASIC_STRING_INTERNAL__)
7#error "Do not include this file: Internal use only. Include <xtd/basic_string> or <xtd/basic_string.hpp> instead."
8#endif
9
10#include "array.hpp"
11//#include "formatter.hpp"
12
14template<class char_t, class traits_t, class allocator_t>
15inline xtd::basic_string<char_t, traits_t, allocator_t>::basic_string(const allocator_type& allocator) noexcept : chars_(allocator) {}
16
17template<class char_t, class traits_t, class allocator_t>
19 return index_of_any(values, 0, length());
20}
21
22template<class char_t, class traits_t, class allocator_t>
24 return index_of_any(values, start_index, length() - start_index);
25}
26
27template<class char_t, class traits_t, class allocator_t>
30 auto index = xtd::size {0};
31 for (const auto& item : self_) {
32 if (index++ < start_index) continue;
33 if (index - 1 > start_index + count) break;
34 if (std::find(values.begin(), values.end(), item) != values.end()) return index - 1;
35 }
36 return npos;
37}
38
39template<class char_t, class traits_t, class allocator_t>
40inline xtd::size xtd::basic_string<char_t, traits_t, allocator_t>::index_of_any(const std::initializer_list<value_type>& values) const noexcept {
41 return index_of_any(xtd::array<value_type>(values));
42}
43
44template<class char_t, class traits_t, class allocator_t>
45inline xtd::size xtd::basic_string<char_t, traits_t, allocator_t>::index_of_any(const std::initializer_list<value_type>& values, xtd::size start_index) const {
46 return index_of_any(xtd::array<value_type>(values), start_index);
47}
48
49template<class char_t, class traits_t, class allocator_t>
50inline xtd::size xtd::basic_string<char_t, traits_t, allocator_t>::index_of_any(const std::initializer_list<value_type>& values, xtd::size start_index, xtd::size count) const {
51 return index_of_any(xtd::array<value_type>(values), start_index, count);
52}
53
54template<class char_t, class traits_t, class allocator_t>
56 return last_index_of_any(values, 0, length());
57}
58
59template<class char_t, class traits_t, class allocator_t>
61 return last_index_of_any(values, start_index, length() - start_index);
62}
63
64template<class char_t, class traits_t, class allocator_t>
67 auto index = length() - 1;
68 for (auto iterator = chars().crbegin(); iterator != chars().crend(); ++iterator) {
69 if (index-- > start_index + count) continue;
70 if (index + 1 < start_index) break;
71 if (std::find(values.begin(), values.end(), *iterator) != values.end()) return index + 1;
72 }
73 return npos;
74}
75
76template<class char_t, class traits_t, class allocator_t>
77inline xtd::size xtd::basic_string<char_t, traits_t, allocator_t>::last_index_of_any(const std::initializer_list<value_type>& values) const noexcept {
78 return last_index_of_any(xtd::array<value_type>(values));
79}
80
81template<class char_t, class traits_t, class allocator_t>
82inline xtd::size xtd::basic_string<char_t, traits_t, allocator_t>::last_index_of_any(const std::initializer_list<value_type>& values, xtd::size start_index) const {
83 return last_index_of_any(xtd::array<value_type>(values), start_index);
84}
85
86template<class char_t, class traits_t, class allocator_t>
87inline xtd::size xtd::basic_string<char_t, traits_t, allocator_t>::last_index_of_any(const std::initializer_list<value_type>& values, xtd::size start_index, xtd::size count) const {
88 return last_index_of_any(xtd::array<value_type>(values), start_index, count);
89}
90
91template<class char_t, class traits_t, class allocator_t>
93 return split(default_split_separators, std::numeric_limits<xtd::size>::max(), xtd::string_split_options::none);
94}
95
96template<class char_t, class traits_t, class allocator_t>
98 return split(xtd::array<value_type> {separator}, std::numeric_limits<xtd::size>::max(), xtd::string_split_options::none);
99}
100
101template<class char_t, class traits_t, class allocator_t>
103 return split(xtd::array<value_type> {separator}, std::numeric_limits<xtd::size>::max(), options);
104}
105
106template<class char_t, class traits_t, class allocator_t>
109}
110
111template<class char_t, class traits_t, class allocator_t>
113 return split(xtd::array<value_type> {separator}, count, options);
114}
115
116template<class char_t, class traits_t, class allocator_t>
118 return split(separators, std::numeric_limits<xtd::size>::max(), xtd::string_split_options::none);
119}
120
121template<class char_t, class traits_t, class allocator_t>
123 return split(separators, std::numeric_limits<xtd::size>::max(), options);
124}
125
126template<class char_t, class traits_t, class allocator_t>
128 return split(separators, count, xtd::string_split_options::none);
129}
130
131template<class char_t, class traits_t, class allocator_t>
133 if (count == 0) return {};
134 if (count == 1) return {self_};
135
136 auto result = std::vector<basic_string> {};
137 auto sub_string = basic_string {};
138 auto split_char_separators = separators.length() == 0 ? default_split_separators : separators;
139 for (auto it = chars().begin(); it != chars().end(); ++it) {
140 auto is_separator = std::find(split_char_separators.begin(), split_char_separators.end(), *it) != split_char_separators.end();
141 if (!is_separator) sub_string.chars_.append(basic_string(1, *it));
142 auto is_last = (it + 1 == chars().end());
143 auto should_add = is_last || is_separator;
144 auto keep_empty = sub_string.length() > 0 || (options != xtd::string_split_options::remove_empty_entries);
145
146 if (should_add && keep_empty) {
147 if (result.size() == count - 1) {
148 result.push_back(sub_string + basic_string(chars().c_str(), it - chars().begin() + (is_separator ? 0 : 1), length() - (it - chars().begin()) + (is_separator ? 0 : 1)));
149 return result;
150 }
151 result.push_back(sub_string);
152 sub_string.chars_.clear();
153 }
154 }
155
156 if (length() > 0 && std::find(split_char_separators.begin(), split_char_separators.end(), self_[length() - 1]) != split_char_separators.end() && options != xtd::string_split_options::remove_empty_entries) result.push_back(basic_string {});
157
158 return result;
159}
160
161template<class char_t, class traits_t, class allocator_t>
163 return to_array(0, length());
164}
165
166template<class char_t, class traits_t, class allocator_t>
168 return to_array(start_index, length() - start_index);
169}
170
171template<class char_t, class traits_t, class allocator_t>
173 if (start_index >= self_.length()) return {};
174 if (start_index + length >= self_.length()) return {chars().begin() + start_index, chars().end()};
175 return {chars().begin() + start_index, chars().begin() + start_index + length};
176}
177
178template<class char_t, class traits_t, class allocator_t>
180 return to_array(0, length());
181}
182
183template<class char_t, class traits_t, class allocator_t>
185 return to_array(start_index, length);
186}
187
188template<class char_t, class traits_t, class allocator_t>
190 auto words = split({' '});
191 for (auto& word : words)
192 if (word.length() && word != word.to_upper()) word = static_cast<value_type>(toupper(word[0])) + word.substring(1).to_lower();
193 return basic_string::join(" ", words);
194}
195
196template<class char_t, class traits_t, class allocator_t>
198 return trim(xtd::array<value_type> {trim_char});
199}
200
201template<class char_t, class traits_t, class allocator_t>
203 return trim_start(trim_chars).trim_end(trim_chars);
204}
205
206template<class char_t, class traits_t, class allocator_t>
208 return trim_end(xtd::array<value_type> {trim_char});
209}
210
211template<class char_t, class traits_t, class allocator_t>
213 if (!length()) return self_;
214 auto result = chars_;
215 while (std::find(trim_chars.begin(), trim_chars.end(), result[result.size() - 1]) != trim_chars.end())
216 result.erase(result.size() - 1, 1);
217 return result;
218}
219
220template<class char_t, class traits_t, class allocator_t>
222
223template<class char_t, class traits_t, class allocator_t>
225 if (!length()) return self_;
226 auto result = chars_;
227 while (std::find(trim_chars.begin(), trim_chars.end(), result[0]) != trim_chars.end())
228 result.erase(0, 1);
229 return result;
230}
231
232template<class char_t, class traits_t, class allocator_t>
234 auto result = basic_string::empty_string;
235 std::for_each(values.begin(), values.end(), [&](const auto & item) {result += item;});
236 return result;
237}
238
239template<class char_t, class traits_t, class allocator_t>
241 auto result = basic_string::empty_string;
242 std::for_each(values.begin(), values.end(), [&](const auto & item) {result += item;});
243 return result;
244}
245
246template<class char_t, class traits_t, class allocator_t>
247template<class other_char_t>
249 auto result = basic_string::empty_string;
250 std::for_each(values.begin(), values.end(), [&](const auto & item) {result += item;});
251 return result;
252}
253
254
255template<class char_t, class traits_t, class allocator_t>
256template<class object_t>
258 basic_string result;
259 for (const auto& arg : args)
260 result += format("{}", arg);
261 return result;
262}
263
264template<class char_t, class traits_t, class allocator_t>
265template<class ...args_t>
267 auto result = basic_string<char> {};
268 auto index = xtd::size {0};
269 auto formats = std::vector<__format_information<char>> {};
270 auto begin_format_iterator = fmt.end();
271 auto end_format_iterator = fmt.end();
272 for (auto iterator = fmt.begin(); iterator != fmt.end(); ++iterator) {
273 if (*iterator == '{') {
274 if (++iterator == fmt.end())
276 if (*iterator == '{')
277 result += *iterator;
278 else {
279 begin_format_iterator = iterator;
280 while (iterator != fmt.end() && *iterator != '}') ++iterator;
281 if (iterator == fmt.end())
283 end_format_iterator = iterator;
284 __format_information<char> fi;
285 fi.location = result.length();
286 auto format_str = std::basic_string<char> {begin_format_iterator, end_format_iterator};
287 if (format_str.length() == 0)
288 fi.index = index++;
289 else {
290 xtd::size index_alignment_separator = basic_string(format_str).index_of(',');
291 xtd::size index_format_separator = basic_string(format_str).index_of(u':');
292
293 if (index_alignment_separator != std::basic_string<char>::npos && index_format_separator != std::basic_string<char>::npos && index_alignment_separator > index_format_separator)
294 index_alignment_separator = std::basic_string<char>::npos;
295
296 if (index_alignment_separator != basic_string<char_t>::npos)
297 fi.alignment = format_str.substr(index_alignment_separator + 1, index_format_separator != std::basic_string<char>::npos ? index_format_separator - index_alignment_separator - 1 : std::basic_string<char>::npos);
298
299 if (index_format_separator != basic_string<char>::npos)
300 fi.format = format_str.substr(index_format_separator + 1);
301
302 if (index_alignment_separator == 0 || index_format_separator == 0)
303 fi.index = index++;
304 else {
305 auto index_str = std::basic_string<char> {};
306 if (index_alignment_separator != basic_string<char>::npos)
307 index_str = format_str.substr(0, index_alignment_separator);
308 else if (index_format_separator != basic_string<char>::npos)
309 index_str = format_str.substr(0, index_format_separator);
310 else
311 index_str = std::move(format_str);
312 try {
313 for (auto c : index_str)
315 fi.index = std::stoi(index_str);
316 } catch (...) {
318 }
319 }
320 }
321 formats.push_back(fi);
322 }
323 } else if (*iterator == '}') {
324 if (++iterator == fmt.end())
326 if (*iterator != '}')
328 result += *iterator;
329 } else
330 result += *iterator;
331 }
332
333 __basic_string_extract_format_arg(result, formats, std::forward<args_t>(args)...);
334 return result.chars().c_str();
335}
336
337template<class char_t, class traits_t, class allocator_t>
338template<class value_t>
339inline xtd::basic_string<char_t, traits_t, allocator_t> xtd::basic_string<char_t, traits_t, allocator_t>::join(const basic_string& separator, const std::initializer_list<value_t>& values) noexcept {
340 return join(separator, xtd::array<value_t>(values));
341}
342
343template<class char_t, class traits_t, class allocator_t>
344template<class value_t>
345inline xtd::basic_string<char_t, traits_t, allocator_t> xtd::basic_string<char_t, traits_t, allocator_t>::join(const basic_string& separator, const std::initializer_list<value_t>& values, xtd::size index) {
346 return join(separator, xtd::array<value_t>(values), index);
347}
348
349template<class char_t, class traits_t, class allocator_t>
350template<class value_t>
351inline xtd::basic_string<char_t, traits_t, allocator_t> xtd::basic_string<char_t, traits_t, allocator_t>::join(const basic_string& separator, const std::initializer_list<value_t>& values, xtd::size index, xtd::size count) {
352 return join(separator, xtd::array<value_t>(values), index, count);
353}
354
355template<class char_t, class traits_t, class allocator_t>
357
358template<class char_t, class traits_t, class allocator_t>
359inline const xtd::array<typename xtd::basic_string<char_t, traits_t, allocator_t>::value_type> xtd::basic_string<char_t, traits_t, allocator_t>::default_split_separators = {9, 10, 11, 12, 13, 32};
360
361template<class char_t, class traits_t, class allocator_t>
362inline const xtd::array<typename xtd::basic_string<char_t, traits_t, allocator_t>::value_type> xtd::basic_string<char_t, traits_t, allocator_t>::default_trim_chars = {9, 10, 11, 12, 13, 32};
363
364template<class arg_t>
365void __basic_string_extract_format_arg(std::basic_string<char>& fmt, xtd::size& index, std::vector<__format_information<char >> & formats, arg_t&& arg) {
366 //void __basic_string_extract_format_arg(xtd::basic_string<char>& fmt, xtd::size& index, std::vector<__format_information<char>>& formats, arg_t&& arg) {
367 auto offset = xtd::size {0};
368 for (auto& format : formats) {
369 format.location += offset;
370 if (format.index == index) {
371 //xtd::basic_string<char> arg_str = xtd::formatter<arg_t> {}(arg, format.format, std::locale());
372 xtd::basic_string<char> arg_str = xtd::to_string(arg, format.format);
373
374 if (!format.alignment.empty()) {
375 xtd::int32 alignment = 0;
376 try {
377 alignment = std::stoi(format.alignment);
378 } catch (...) {
380 }
381 if (alignment > 0) arg_str = arg_str.pad_left(alignment);
382 else if (alignment < 0) arg_str = arg_str.pad_right(-alignment);
383 }
384 fmt.insert(format.location, arg_str);
385 offset += arg_str.length();
386 }
387 }
388 ++index;
389}
390
391template<class ...args_t>
392void __basic_string_extract_format_arg(xtd::basic_string<char>& fmt, std::vector<__format_information<char >> & formats, args_t&&... args) {
393 auto index = xtd::size {0};
394 (__basic_string_extract_format_arg(const_cast<std::basic_string<char>& > (fmt.chars()), index, formats, args), ...);
395 //(__basic_string_extract_format_arg(fmt, index, formats, args), ...);
396 unused_(index); // workaround to mute gcc warning: unused-but-set-variable
397}
398
399template<class target_t, class source_t>
400inline std::basic_string<target_t> __xtd_convert_to_string(std::basic_string<source_t>&& str) noexcept {
401 auto out = std::basic_string<target_t> {};
402 auto codepoint = 0u;
403 for (const auto& character : str) {
404 if (character >= 0xd800 && character <= 0xdbff)
405 codepoint = ((character - 0xd800) << 10) + 0x10000;
406 else {
407 if (character >= 0xdc00 && character <= 0xdfff) codepoint |= character - 0xdc00;
408 else codepoint = character;
409
410 if (codepoint <= 0x7f)
411 out.append(1, static_cast<target_t>(codepoint));
412 else if (codepoint <= 0x7ff) {
413 out.append(1, static_cast<target_t>(0xc0 | ((codepoint >> 6) & 0x1f)));
414 out.append(1, static_cast<target_t>(0x80 | (codepoint & 0x3f)));
415 } else if (codepoint <= 0xffff) {
416 out.append(1, static_cast<target_t>(0xe0 | ((codepoint >> 12) & 0x0f)));
417 out.append(1, static_cast<target_t>(0x80 | ((codepoint >> 6) & 0x3f)));
418 out.append(1, static_cast<target_t>(0x80 | (codepoint & 0x3f)));
419 } else {
420 out.append(1, static_cast<target_t>(0xf0 | ((codepoint >> 18) & 0x07)));
421 out.append(1, static_cast<target_t>(0x80 | ((codepoint >> 12) & 0x3f)));
422 out.append(1, static_cast<target_t>(0x80 | ((codepoint >> 6) & 0x3f)));
423 out.append(1, static_cast<target_t>(0x80 | (codepoint & 0x3f)));
424 }
425 codepoint = 0;
426 }
427 }
428 return out;
429}
430
434template<>
435inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, char>(std::basic_string<char>&& str) noexcept {
436 auto out = std::basic_string<xtd::char16> {}; // Output UTF-16 string
437 auto codepoint = 0u; // Current Unicode code point
438 auto expected_bytes = 0; // Number of continuation bytes expected
439 auto str_ptr = str.data(); // Pointer to traverse input string
440
441 while (*str_ptr != 0) {
442 auto ch = static_cast<unsigned char>(*str_ptr++);
443
444 if (expected_bytes == 0) {
445 // Determine the sequence length based on the first byte
446 if (ch <= 0x7f) {
447 codepoint = ch;
448 expected_bytes = 0;
449 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
450 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
451 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
452 else {
453 // Invalid first byte → replacement character
454 out.push_back(0xfffd);
455 continue;
456 }
457 } else {
458 // Continuation byte
459 if ((ch & 0xc0) != 0x80) {
460 // Unexpected byte → invalid sequence
461 out.push_back(0xfffd);
462 expected_bytes = 0;
463 --str_ptr; // Re-evaluate this byte as first byte
464 continue;
465 }
466 codepoint = (codepoint << 6) | (ch & 0x3f);
467 --expected_bytes;
468 }
469
470 // Sequence complete
471 if (expected_bytes == 0) {
472 if (codepoint > 0x10ffff) codepoint = 0xfffd; // Unicode limit
473
474 if (codepoint > 0xffff) {
475 // Code point requires surrogate pair
476 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
477 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
478 out.push_back(static_cast<xtd::char16>(high));
479 out.push_back(static_cast<xtd::char16>(low));
480 } else if (codepoint < 0xd800 || codepoint >= 0xe000) out.push_back(static_cast<xtd::char16>(codepoint)); // Normal BMP character, not a surrogate
481 else out.push_back(0xfffd); // Surrogate range in input → replace
482 }
483 }
484
485 // If string ends prematurely, insert replacement character
486 if (expected_bytes != 0) out.push_back(0xfffd);
487 return out;
488}
489
493template<>
494inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::char8>(std::basic_string<xtd::char8>&& str) noexcept {
495 auto out = std::basic_string<xtd::char16> {}; // Output UTF-16 string
496 auto codepoint = 0u; // Current Unicode code point
497 auto expected_bytes = 0; // Number of continuation bytes expected
498 auto str_ptr = str.data(); // Pointer to traverse input string
499
500 while (*str_ptr != 0) {
501 auto ch = static_cast<unsigned char>(*str_ptr++);
502
503 if (expected_bytes == 0) {
504 // Determine the sequence length based on the first byte
505 if (ch <= 0x7f) {
506 codepoint = ch;
507 expected_bytes = 0;
508 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
509 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
510 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
511 else {
512 // Invalid first byte → replacement character
513 out.push_back(0xfffd);
514 continue;
515 }
516 } else {
517 // Continuation byte
518 if ((ch & 0xc0) != 0x80) {
519 // Unexpected byte → invalid sequence
520 out.push_back(0xfffd);
521 expected_bytes = 0;
522 --str_ptr; // Re-evaluate this byte as first byte
523 continue;
524 }
525 codepoint = (codepoint << 6) | (ch & 0x3f);
526 --expected_bytes;
527 }
528
529 // Sequence complete
530 if (expected_bytes == 0) {
531 if (codepoint > 0x10ffff) codepoint = 0xfffd; // Unicode limit
532
533 if (codepoint > 0xffff) {
534 // Code point requires surrogate pair
535 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
536 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
537 out.push_back(static_cast<xtd::char16>(high));
538 out.push_back(static_cast<xtd::char16>(low));
539 } else if (codepoint < 0xd800 || codepoint >= 0xe000) out.push_back(static_cast<xtd::char16>(codepoint)); // Normal BMP character, not a surrogate
540 else out.push_back(0xfffd); // Surrogate range in input → replace
541 }
542 }
543
544 // If string ends prematurely, insert replacement character
545 if (expected_bytes != 0) out.push_back(0xfffd);
546 return out;
547}
548
552template<>
553inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, char>(std::basic_string<char>&& str) noexcept {
554 auto out = std::basic_string<xtd::wchar> {}; // Output UTF string
555 auto codepoint = 0u; // Current Unicode code point
556 auto expected_bytes = 0; // Continuation bytes expected
557 auto str_ptr = str.data(); // Pointer to traverse input
558
559 while (*str_ptr != 0) {
560 auto ch = static_cast<unsigned char>(*str_ptr++);
561
562 if (expected_bytes == 0) {
563 // Determine sequence length based on first byte
564 if (ch <= 0x7f) {
565 codepoint = ch;
566 expected_bytes = 0;
567 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
568 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
569 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
570 else {
571 out.push_back(0xfffd); // Invalid first byte → replace
572 continue;
573 }
574 } else {
575 // Continuation byte
576 if ((ch & 0xc0) != 0x80) {
577 // Unexpected byte → invalid sequence
578 out.push_back(0xfffd);
579 expected_bytes = 0;
580 --str_ptr; // Re-evaluate this byte as first byte
581 continue;
582 }
583 codepoint = (codepoint << 6) | (ch & 0x3f);
584 --expected_bytes;
585 }
586
587 // Sequence complete
588 if (expected_bytes == 0) {
589 if (codepoint > 0x10ffff) codepoint = 0xfffd;
590
591 if (sizeof(xtd::wchar) > 2) {
592 // UTF-32 capable
593 out.push_back(static_cast<xtd::wchar>(codepoint));
594 } else {
595 // UTF-16, may need surrogate pairs
596 if (codepoint > 0xffff) {
597 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
598 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
599 out.push_back(static_cast<xtd::wchar>(high));
600 out.push_back(static_cast<xtd::wchar>(low));
601 } else if (codepoint < 0xd800 || codepoint >= 0xe000)
602 out.push_back(static_cast<xtd::wchar>(codepoint));
603 else {
604 // Surrogate range in input → replace
605 out.push_back(0xfffd);
606 }
607 }
608 }
609 }
610
611 // If string ends prematurely, insert replacement character
612 if (expected_bytes != 0) out.push_back(0xfffd);
613 return out;
614}
615
619template<>
620inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::char8>(std::basic_string<xtd::char8>&& str) noexcept {
621 auto out = std::basic_string<xtd::wchar> {}; // Output UTF string
622 auto codepoint = 0u; // Current Unicode code point
623 auto expected_bytes = 0; // Continuation bytes expected
624 auto str_ptr = str.data(); // Pointer to traverse input
625
626 while (*str_ptr != 0) {
627 auto ch = static_cast<unsigned char>(*str_ptr++);
628
629 if (expected_bytes == 0) {
630 // Determine sequence length based on first byte
631 if (ch <= 0x7f) {
632 codepoint = ch;
633 expected_bytes = 0;
634 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
635 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
636 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
637 else {
638 out.push_back(0xfffd); // Invalid first byte → replace
639 continue;
640 }
641 } else {
642 // Continuation byte
643 if ((ch & 0xc0) != 0x80) {
644 // Unexpected byte → invalid sequence
645 out.push_back(0xfffd);
646 expected_bytes = 0;
647 --str_ptr; // Re-evaluate this byte as first byte
648 continue;
649 }
650 codepoint = (codepoint << 6) | (ch & 0x3f);
651 --expected_bytes;
652 }
653
654 // Sequence complete
655 if (expected_bytes == 0) {
656 if (codepoint > 0x10ffff) codepoint = 0xfffd;
657
658 if (sizeof(xtd::wchar) > 2) {
659 // UTF-32 capable
660 out.push_back(static_cast<xtd::wchar>(codepoint));
661 } else {
662 // UTF-16, may need surrogate pairs
663 if (codepoint > 0xffff) {
664 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
665 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
666 out.push_back(static_cast<xtd::wchar>(high));
667 out.push_back(static_cast<xtd::wchar>(low));
668 } else if (codepoint < 0xd800 || codepoint >= 0xe000)
669 out.push_back(static_cast<xtd::wchar>(codepoint));
670 else {
671 // Surrogate range in input → replace
672 out.push_back(0xfffd);
673 }
674 }
675 }
676 }
677
678 // If string ends prematurely, insert replacement character
679 if (expected_bytes != 0) out.push_back(0xfffd);
680 return out;
681}
682
686template<>
687inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, char>(std::basic_string<char>&& str) noexcept {
688 auto out = std::basic_string<xtd::char32> {}; // Output UTF-32 string
689 auto codepoint = 0u; // Current Unicode code point
690 auto expected_bytes = 0; // Number of continuation bytes expected
691 auto str_ptr = str.data(); // Pointer to traverse input string
692
693 while (*str_ptr != 0) {
694 auto ch = static_cast<unsigned char>(*str_ptr++);
695
696 if (expected_bytes == 0) {
697 // Determine sequence length based on first byte
698 if (ch <= 0x7f) {
699 codepoint = ch;
700 out.push_back(static_cast<xtd::char32>(codepoint));
701 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
702 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
703 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
704 else out.push_back(0xfffd); // Invalid first byte → replace
705 } else {
706 // Continuation byte
707 if ((ch & 0xc0) != 0x80) {
708 // Unexpected byte → invalid sequence
709 out.push_back(0xfffd);
710 expected_bytes = 0;
711 --str_ptr; // Re-evaluate this byte as first byte
712 continue;
713 }
714 codepoint = (codepoint << 6) | (ch & 0x3f);
715 --expected_bytes;
716
717 if (expected_bytes == 0) {
718 // Sequence complete, check valid Unicode range
719 if (codepoint > 0x10ffff) codepoint = 0xfffd;
720 out.push_back(static_cast<xtd::char32>(codepoint));
721 }
722 }
723 }
724
725 // If string ends prematurely, insert replacement character
726 if (expected_bytes != 0) out.push_back(0xfffd);
727 return out;
728}
729
733template<>
734inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::char8>(std::basic_string<xtd::char8>&& str) noexcept {
735 auto out = std::basic_string<xtd::char32> {}; // Output UTF-32 string
736 auto codepoint = 0u; // Current Unicode code point
737 auto expected_bytes = 0; // Number of continuation bytes expected
738 auto str_ptr = str.data(); // Pointer to traverse input string
739
740 while (*str_ptr != 0) {
741 auto ch = static_cast<unsigned char>(*str_ptr++);
742
743 if (expected_bytes == 0) {
744 // Determine sequence length based on first byte
745 if (ch <= 0x7f) {
746 codepoint = ch;
747 out.push_back(static_cast<xtd::char32>(codepoint));
748 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
749 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
750 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
751 else out.push_back(0xfffd); // Invalid first byte → replace
752 } else {
753 // Continuation byte
754 if ((ch & 0xc0) != 0x80) {
755 // Unexpected byte → invalid sequence
756 out.push_back(0xfffd);
757 expected_bytes = 0;
758 --str_ptr; // Re-evaluate this byte as first byte
759 continue;
760 }
761 codepoint = (codepoint << 6) | (ch & 0x3f);
762 --expected_bytes;
763
764 if (expected_bytes == 0) {
765 // Sequence complete, check valid Unicode range
766 if (codepoint > 0x10ffff) codepoint = 0xfffd;
767 out.push_back(static_cast<xtd::char32>(codepoint));
768 }
769 }
770 }
771
772 // If string ends prematurely, insert replacement character
773 if (expected_bytes != 0) out.push_back(0xfffd);
774 return out;
775}
776
777template<>
778inline std::basic_string<char> __xtd_convert_to_string<char, char>(std::basic_string<char>&& str) noexcept {
779 return std::move(str);
780}
781
782template<>
783inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::char16>(std::basic_string<xtd::char16>&& str) noexcept {
784 return std::move(str);
785}
786
787template<>
788inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::char32>(std::basic_string<xtd::char32>&& str) noexcept {
789 return std::move(str);
790}
791
792template<>
793inline std::basic_string<xtd::char8> __xtd_convert_to_string<xtd::char8, xtd::char8>(std::basic_string<xtd::char8>&& str) noexcept {
794 return std::move(str);
795}
796
797template<>
798inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::wchar>(std::basic_string<xtd::wchar>&& str) noexcept {
799 return std::move(str);
800}
801
802template<>
803inline std::basic_string<xtd::char8> __xtd_convert_to_string<xtd::char8, char>(std::basic_string<char>&& str) noexcept {
804 return std::basic_string<xtd::char8> {reinterpret_cast<const xtd::char8*>(str.c_str())};
805}
806
807template<>
808inline std::basic_string<char> __xtd_convert_to_string<char, xtd::char8>(std::basic_string<xtd::char8>&& str) noexcept {
809 return std::basic_string<char> {reinterpret_cast<const char*>(str.c_str())};
810}
811
812template<>
813inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::char32>(std::basic_string<xtd::char32>&& str) noexcept {
814 return __xtd_convert_to_string<xtd::char16>(__xtd_convert_to_string<char>(std::move(str)));
815}
816
817template<>
818inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::wchar>(std::basic_string<xtd::wchar>&& str) noexcept {
819 return __xtd_convert_to_string<xtd::char16>(__xtd_convert_to_string<char>(std::move(str)));
820}
821
822template<>
823inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::char16>(std::basic_string<xtd::char16>&& str) noexcept {
824 return __xtd_convert_to_string<xtd::char32>(__xtd_convert_to_string<char>(std::move(str)));
825}
826
827template<>
828inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::wchar>(std::basic_string<xtd::wchar>&& str) noexcept {
829 return __xtd_convert_to_string<xtd::char32>(__xtd_convert_to_string<char>(std::move(str)));
830}
831
832template<>
833inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::char16>(std::basic_string<xtd::char16>&& str) noexcept {
834 return __xtd_convert_to_string<xtd::wchar>(__xtd_convert_to_string<char>(std::move(str)));
835}
836
837template<>
838inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::char32>(std::basic_string<xtd::char32>&& str) noexcept {
839 return __xtd_convert_to_string<xtd::wchar>(__xtd_convert_to_string<char>(std::move(str)));
840}
841
842template<class target_t, class source_t>
843inline std::basic_string<target_t> __xtd_convert_to_string(const std::basic_string<source_t>& str) noexcept {
844 auto out = std::basic_string<target_t> {};
845 auto codepoint = 0u;
846 for (const auto& character : str) {
847 if (character >= 0xd800 && character <= 0xdbff)
848 codepoint = ((character - 0xd800) << 10) + 0x10000;
849 else {
850 if (character >= 0xdc00 && character <= 0xdfff) codepoint |= character - 0xdc00;
851 else codepoint = character;
852
853 if (codepoint <= 0x7f)
854 out.append(1, static_cast<target_t>(codepoint));
855 else if (codepoint <= 0x7ff) {
856 out.append(1, static_cast<target_t>(0xc0 | ((codepoint >> 6) & 0x1f)));
857 out.append(1, static_cast<target_t>(0x80 | (codepoint & 0x3f)));
858 } else if (codepoint <= 0xffff) {
859 out.append(1, static_cast<target_t>(0xe0 | ((codepoint >> 12) & 0x0f)));
860 out.append(1, static_cast<target_t>(0x80 | ((codepoint >> 6) & 0x3f)));
861 out.append(1, static_cast<target_t>(0x80 | (codepoint & 0x3f)));
862 } else {
863 out.append(1, static_cast<target_t>(0xf0 | ((codepoint >> 18) & 0x07)));
864 out.append(1, static_cast<target_t>(0x80 | ((codepoint >> 12) & 0x3f)));
865 out.append(1, static_cast<target_t>(0x80 | ((codepoint >> 6) & 0x3f)));
866 out.append(1, static_cast<target_t>(0x80 | (codepoint & 0x3f)));
867 }
868 codepoint = 0;
869 }
870 }
871 return out;
872}
873
877template<>
878inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, char>(const std::basic_string<char>& str) noexcept {
879 auto out = std::basic_string<xtd::char16> {}; // Output UTF-16 string
880 auto codepoint = 0u; // Current Unicode code point
881 auto expected_bytes = 0; // Number of continuation bytes expected
882 auto str_ptr = str.data(); // Pointer to traverse input string
883
884 while (*str_ptr != 0) {
885 auto ch = static_cast<unsigned char>(*str_ptr++);
886
887 if (expected_bytes == 0) {
888 // Determine the sequence length based on the first byte
889 if (ch <= 0x7f) {
890 codepoint = ch;
891 expected_bytes = 0;
892 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
893 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
894 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
895 else {
896 // Invalid first byte → replacement character
897 out.push_back(0xfffd);
898 continue;
899 }
900 } else {
901 // Continuation byte
902 if ((ch & 0xc0) != 0x80) {
903 // Unexpected byte → invalid sequence
904 out.push_back(0xfffd);
905 expected_bytes = 0;
906 --str_ptr; // Re-evaluate this byte as first byte
907 continue;
908 }
909 codepoint = (codepoint << 6) | (ch & 0x3f);
910 --expected_bytes;
911 }
912
913 // Sequence complete
914 if (expected_bytes == 0) {
915 if (codepoint > 0x10ffff) codepoint = 0xfffd; // Unicode limit
916
917 if (codepoint > 0xffff) {
918 // Code point requires surrogate pair
919 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
920 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
921 out.push_back(static_cast<xtd::char16>(high));
922 out.push_back(static_cast<xtd::char16>(low));
923 } else if (codepoint < 0xd800 || codepoint >= 0xe000) out.push_back(static_cast<xtd::char16>(codepoint)); // Normal BMP character, not a surrogate
924 else out.push_back(0xfffd); // Surrogate range in input → replace
925 }
926 }
927
928 // If string ends prematurely, insert replacement character
929 if (expected_bytes != 0) out.push_back(0xfffd);
930 return out;
931}
932
936template<>
937inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::char8>(const std::basic_string<xtd::char8>& str) noexcept {
938 auto out = std::basic_string<xtd::char16> {}; // Output UTF-16 string
939 auto codepoint = 0u; // Current Unicode code point
940 auto expected_bytes = 0; // Number of continuation bytes expected
941 auto str_ptr = str.data(); // Pointer to traverse input string
942
943 while (*str_ptr != 0) {
944 auto ch = static_cast<unsigned char>(*str_ptr++);
945
946 if (expected_bytes == 0) {
947 // Determine the sequence length based on the first byte
948 if (ch <= 0x7f) {
949 codepoint = ch;
950 expected_bytes = 0;
951 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
952 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
953 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
954 else {
955 // Invalid first byte → replacement character
956 out.push_back(0xfffd);
957 continue;
958 }
959 } else {
960 // Continuation byte
961 if ((ch & 0xc0) != 0x80) {
962 // Unexpected byte → invalid sequence
963 out.push_back(0xfffd);
964 expected_bytes = 0;
965 --str_ptr; // Re-evaluate this byte as first byte
966 continue;
967 }
968 codepoint = (codepoint << 6) | (ch & 0x3f);
969 --expected_bytes;
970 }
971
972 // Sequence complete
973 if (expected_bytes == 0) {
974 if (codepoint > 0x10ffff) codepoint = 0xfffd; // Unicode limit
975
976 if (codepoint > 0xffff) {
977 // Code point requires surrogate pair
978 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
979 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
980 out.push_back(static_cast<xtd::char16>(high));
981 out.push_back(static_cast<xtd::char16>(low));
982 } else if (codepoint < 0xd800 || codepoint >= 0xe000) out.push_back(static_cast<xtd::char16>(codepoint)); // Normal BMP character, not a surrogate
983 else out.push_back(0xfffd); // Surrogate range in input → replace
984 }
985 }
986
987 // If string ends prematurely, insert replacement character
988 if (expected_bytes != 0) out.push_back(0xfffd);
989 return out;
990}
991
995template<>
996inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, char>(const std::basic_string<char>& str) noexcept {
997 auto out = std::basic_string<xtd::wchar> {}; // Output UTF string
998 auto codepoint = 0u; // Current Unicode code point
999 auto expected_bytes = 0; // Continuation bytes expected
1000 auto str_ptr = str.data(); // Pointer to traverse input
1001
1002 while (*str_ptr != 0) {
1003 auto ch = static_cast<unsigned char>(*str_ptr++);
1004
1005 if (expected_bytes == 0) {
1006 // Determine sequence length based on first byte
1007 if (ch <= 0x7f) {
1008 codepoint = ch;
1009 expected_bytes = 0;
1010 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
1011 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
1012 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
1013 else {
1014 out.push_back(0xfffd); // Invalid first byte → replace
1015 continue;
1016 }
1017 } else {
1018 // Continuation byte
1019 if ((ch & 0xc0) != 0x80) {
1020 // Unexpected byte → invalid sequence
1021 out.push_back(0xfffd);
1022 expected_bytes = 0;
1023 --str_ptr; // Re-evaluate this byte as first byte
1024 continue;
1025 }
1026 codepoint = (codepoint << 6) | (ch & 0x3f);
1027 --expected_bytes;
1028 }
1029
1030 // Sequence complete
1031 if (expected_bytes == 0) {
1032 if (codepoint > 0x10ffff) codepoint = 0xfffd;
1033
1034 if (sizeof(xtd::wchar) > 2) {
1035 // UTF-32 capable
1036 out.push_back(static_cast<xtd::wchar>(codepoint));
1037 } else {
1038 // UTF-16, may need surrogate pairs
1039 if (codepoint > 0xffff) {
1040 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
1041 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
1042 out.push_back(static_cast<xtd::wchar>(high));
1043 out.push_back(static_cast<xtd::wchar>(low));
1044 } else if (codepoint < 0xd800 || codepoint >= 0xe000)
1045 out.push_back(static_cast<xtd::wchar>(codepoint));
1046 else {
1047 // Surrogate range in input → replace
1048 out.push_back(0xfffd);
1049 }
1050 }
1051 }
1052 }
1053
1054 // If string ends prematurely, insert replacement character
1055 if (expected_bytes != 0) out.push_back(0xfffd);
1056 return out;
1057}
1058
1062template<>
1063inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::char8>(const std::basic_string<xtd::char8>& str) noexcept {
1064 auto out = std::basic_string<xtd::wchar> {}; // Output UTF string
1065 auto codepoint = 0u; // Current Unicode code point
1066 auto expected_bytes = 0; // Continuation bytes expected
1067 auto str_ptr = str.data(); // Pointer to traverse input
1068
1069 while (*str_ptr != 0) {
1070 auto ch = static_cast<unsigned char>(*str_ptr++);
1071
1072 if (expected_bytes == 0) {
1073 // Determine sequence length based on first byte
1074 if (ch <= 0x7f) {
1075 codepoint = ch;
1076 expected_bytes = 0;
1077 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
1078 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
1079 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
1080 else {
1081 out.push_back(0xfffd); // Invalid first byte → replace
1082 continue;
1083 }
1084 } else {
1085 // Continuation byte
1086 if ((ch & 0xc0) != 0x80) {
1087 // Unexpected byte → invalid sequence
1088 out.push_back(0xfffd);
1089 expected_bytes = 0;
1090 --str_ptr; // Re-evaluate this byte as first byte
1091 continue;
1092 }
1093 codepoint = (codepoint << 6) | (ch & 0x3f);
1094 --expected_bytes;
1095 }
1096
1097 // Sequence complete
1098 if (expected_bytes == 0) {
1099 if (codepoint > 0x10ffff) codepoint = 0xfffd;
1100
1101 if (sizeof(xtd::wchar) > 2) {
1102 // UTF-32 capable
1103 out.push_back(static_cast<xtd::wchar>(codepoint));
1104 } else {
1105 // UTF-16, may need surrogate pairs
1106 if (codepoint > 0xffff) {
1107 unsigned int high = 0xd800 + ((codepoint - 0x10000) >> 10);
1108 unsigned int low = 0xdc00 + ((codepoint - 0x10000) & 0x3ff);
1109 out.push_back(static_cast<xtd::wchar>(high));
1110 out.push_back(static_cast<xtd::wchar>(low));
1111 } else if (codepoint < 0xd800 || codepoint >= 0xe000)
1112 out.push_back(static_cast<xtd::wchar>(codepoint));
1113 else {
1114 // Surrogate range in input → replace
1115 out.push_back(0xfffd);
1116 }
1117 }
1118 }
1119 }
1120
1121 // If string ends prematurely, insert replacement character
1122 if (expected_bytes != 0) out.push_back(0xfffd);
1123 return out;
1124}
1125
1129template<>
1130inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, char>(const std::basic_string<char>& str) noexcept {
1131 auto out = std::basic_string<xtd::char32> {}; // Output UTF-32 string
1132 auto codepoint = 0u; // Current Unicode code point
1133 auto expected_bytes = 0; // Number of continuation bytes expected
1134 auto str_ptr = str.data(); // Pointer to traverse input string
1135
1136 while (*str_ptr != 0) {
1137 auto ch = static_cast<unsigned char>(*str_ptr++);
1138
1139 if (expected_bytes == 0) {
1140 // Determine sequence length based on first byte
1141 if (ch <= 0x7f) {
1142 codepoint = ch;
1143 out.push_back(static_cast<xtd::char32>(codepoint));
1144 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
1145 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
1146 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
1147 else out.push_back(0xfffd); // Invalid first byte → replace
1148 } else {
1149 // Continuation byte
1150 if ((ch & 0xc0) != 0x80) {
1151 // Unexpected byte → invalid sequence
1152 out.push_back(0xfffd);
1153 expected_bytes = 0;
1154 --str_ptr; // Re-evaluate this byte as first byte
1155 continue;
1156 }
1157 codepoint = (codepoint << 6) | (ch & 0x3f);
1158 --expected_bytes;
1159
1160 if (expected_bytes == 0) {
1161 // Sequence complete, check valid Unicode range
1162 if (codepoint > 0x10ffff) codepoint = 0xfffd;
1163 out.push_back(static_cast<xtd::char32>(codepoint));
1164 }
1165 }
1166 }
1167
1168 // If string ends prematurely, insert replacement character
1169 if (expected_bytes != 0) out.push_back(0xfffd);
1170 return out;
1171}
1172
1176template<>
1177inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::char8>(const std::basic_string<xtd::char8>& str) noexcept {
1178 auto out = std::basic_string<xtd::char32> {}; // Output UTF-32 string
1179 auto codepoint = 0u; // Current Unicode code point
1180 auto expected_bytes = 0; // Number of continuation bytes expected
1181 auto str_ptr = str.data(); // Pointer to traverse input string
1182
1183 while (*str_ptr != 0) {
1184 auto ch = static_cast<unsigned char>(*str_ptr++);
1185
1186 if (expected_bytes == 0) {
1187 // Determine sequence length based on first byte
1188 if (ch <= 0x7f) {
1189 codepoint = ch;
1190 out.push_back(static_cast<xtd::char32>(codepoint));
1191 } else if (ch <= 0xdf) { codepoint = ch & 0x1f; expected_bytes = 1; }
1192 else if (ch <= 0xef) { codepoint = ch & 0x0f; expected_bytes = 2; }
1193 else if (ch <= 0xf7) { codepoint = ch & 0x07; expected_bytes = 3; }
1194 else out.push_back(0xfffd); // Invalid first byte → replace
1195 } else {
1196 // Continuation byte
1197 if ((ch & 0xc0) != 0x80) {
1198 // Unexpected byte → invalid sequence
1199 out.push_back(0xfffd);
1200 expected_bytes = 0;
1201 --str_ptr; // Re-evaluate this byte as first byte
1202 continue;
1203 }
1204 codepoint = (codepoint << 6) | (ch & 0x3f);
1205 --expected_bytes;
1206
1207 if (expected_bytes == 0) {
1208 // Sequence complete, check valid Unicode range
1209 if (codepoint > 0x10ffff) codepoint = 0xfffd;
1210 out.push_back(static_cast<xtd::char32>(codepoint));
1211 }
1212 }
1213 }
1214
1215 // If string ends prematurely, insert replacement character
1216 if (expected_bytes != 0) out.push_back(0xfffd);
1217 return out;
1218}
1219
1220template<>
1221inline std::basic_string<char> __xtd_convert_to_string<char, char>(const std::basic_string<char>& str) noexcept {
1222 return str;
1223}
1224
1225template<>
1226inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::char16>(const std::basic_string<xtd::char16>& str) noexcept {
1227 return str;
1228}
1229
1230template<>
1231inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::char32>(const std::basic_string<xtd::char32>& str) noexcept {
1232 return str;
1233}
1234
1235template<>
1236inline std::basic_string<xtd::char8> __xtd_convert_to_string<xtd::char8, xtd::char8>(const std::basic_string<xtd::char8>& str) noexcept {
1237 return str;
1238}
1239
1240template<>
1241inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::wchar>(const std::basic_string<xtd::wchar>& str) noexcept {
1242 return str;
1243}
1244
1245template<>
1246inline std::basic_string<xtd::char8> __xtd_convert_to_string<xtd::char8, char>(const std::basic_string<char>& str) noexcept {
1247 return reinterpret_cast<const xtd::char8*>(str.c_str());
1248}
1249
1250template<>
1251inline std::basic_string<char> __xtd_convert_to_string<char, xtd::char8>(const std::basic_string<xtd::char8>& str) noexcept {
1252 return reinterpret_cast<const char*>(str.c_str());
1253}
1254
1255template<>
1256inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::char32>(const std::basic_string<xtd::char32>& str) noexcept {
1257 return __xtd_convert_to_string<xtd::char16>(__xtd_convert_to_string<char>(str));
1258}
1259
1260template<>
1261inline std::basic_string<xtd::char16> __xtd_convert_to_string<xtd::char16, xtd::wchar>(const std::basic_string<xtd::wchar>& str) noexcept {
1262 return __xtd_convert_to_string<xtd::char16>(__xtd_convert_to_string<char>(str));
1263}
1264
1265template<>
1266inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::char16>(const std::basic_string<xtd::char16>& str) noexcept {
1267 return __xtd_convert_to_string<xtd::char32>(__xtd_convert_to_string<char>(str));
1268}
1269
1270template<>
1271inline std::basic_string<xtd::char32> __xtd_convert_to_string<xtd::char32, xtd::wchar>(const std::basic_string<xtd::wchar>& str) noexcept {
1272 return __xtd_convert_to_string<xtd::char32>(__xtd_convert_to_string<char>(str));
1273}
1274
1275template<>
1276inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::char16>(const std::basic_string<xtd::char16>& str) noexcept {
1277 return __xtd_convert_to_string<xtd::wchar>(__xtd_convert_to_string<char>(str));
1278}
1279
1280template<>
1281inline std::basic_string<xtd::wchar> __xtd_convert_to_string<xtd::wchar, xtd::char32>(const std::basic_string<xtd::char32>& str) noexcept {
1282 return __xtd_convert_to_string<xtd::wchar>(__xtd_convert_to_string<char>(str));
1283}
Contains xtd::array class.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition array.hpp:63
const_iterator end() const noexcept override
Returns an iterator to the element following the last element of the enumerable.
Definition basic_array.hpp:152
const_iterator begin() const noexcept override
Returns an iterator to the first element of the enumerable.
Definition basic_array.hpp:112
Represents text as a sequence of character units.
Definition basic_string.hpp:71
basic_string pad_left(xtd::size total_width) const noexcept
Right-aligns the characters in this basic_string, padding with spaces on the left for a specified tot...
Definition basic_string.hpp:1527
xtd::size index_of_any(const xtd::array< value_type > &values) const noexcept
Reports the index of the first occurrence in this instance of any character in a specified array of c...
xtd::size last_index_of_any(const xtd::array< value_type > &values) const noexcept
Reports the index of the last occurrence in this instance of any character in a specified array of ch...
basic_string pad_right(xtd::size total_width) const noexcept
Left-aligns the characters in this basic_string, padding with spaces on the right for a specified tot...
Definition basic_string.hpp:1541
auto concat(const ienumerable< char_t > &second) const noexcept
Definition enumerable.hpp:185
static void throws(xtd::helpers::exception_case exception_case, const source_location &location=source_location::current())
Throws an exption with specified exception case.
xtd::string format(const xtd::string &fmt, args_t &&... args)
Writes the text representation of the specified arguments list, to string using the specified format ...
Definition format.hpp:20
@ format
The format is not valid.
Definition exception_case.hpp:49
@ index_out_of_range
The index is out of range.
Definition exception_case.hpp:59
@ format_opened_bracket_without_end_bracket
The format contains open backet_without_end_bracket.
Definition exception_case.hpp:53
@ format_closing_bracket_without_open_bracket
The format contains close backet_without_open_bracket.
Definition exception_case.hpp:51
#define self_
The self_ expression is a reference value expression whose value is the reference of the implicit obj...
Definition self.hpp:20
#define unused_
It may be used to suppress the "unused variable" or "unused local typedefs" compiler warnings when th...
Definition unused.hpp:30
constexpr xtd::size npos
Represents a value that is not a valid position in a collection.
Definition npos.hpp:26
@ character
Specifies that the text is trimmed to the nearest character.
Definition string_trimming.hpp:21
@ word
Specifies that text is trimmed to the nearest word.
Definition string_trimming.hpp:23
size_t size
Represents a size of any object in bytes.
Definition size.hpp:23
char8_t char8
Represents a 8-bit unicode character.
Definition char8.hpp:26
wchar_t wchar
Represents a wide character.
Definition wchar.hpp:24
char16_t char16
Represents a 16-bit unicode character.
Definition char16.hpp:26
std::int32_t int32
Represents a 32-bit signed integer.
Definition int32.hpp:23
char32_t char32
Represents a 32-bit unicode character.
Definition char32.hpp:23
string_split_options
Specifies whether applicable xtd::string::split method overloads include or omit empty substrings fro...
Definition string_split_options.hpp:14
@ none
The return value includes array elements that contain an empty string.
Definition string_split_options.hpp:16
@ remove_empty_entries
The return value does not include array elements that contain an empty string.
Definition string_split_options.hpp:18
@ high
Specifies that the process performs time-critical tasks that must be executed immediately,...
Definition process_priority_class.hpp:32
@ u
The U key.
Definition console_key.hpp:128
@ separator
The Separator key.
Definition console_key.hpp:172
@ low
Specifies low quality interpolation.
Definition interpolation_mode.hpp:26
const_iterator begin() const
Returns an iterator to the beginning.
Definition read_only_span.hpp:183
string to_string() const noexcept override
Returns the string representation of this xtd::read_only_span <type_t> object.
Definition read_only_span.hpp:375
const_reverse_iterator crbegin() const
Returns a reverse iterator to the beginning.
Definition read_only_span.hpp:194
constexpr size_type length() const noexcept
Returns the length of the current read_only_span.
Definition read_only_span.hpp:229
xtd::array< std::remove_cv_t< type_t > > to_array() const noexcept
Copies the contents of this read_only_span into a new array.
Definition read_only_span.hpp:368