string_span_tests.cpp revision f6cc5798a17daccf806bbc402a67c92d1a205091
1/////////////////////////////////////////////////////////////////////////////// 2// 3// Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4// 5// This code is licensed under the MIT License (MIT). 6// 7// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13// THE SOFTWARE. 14// 15/////////////////////////////////////////////////////////////////////////////// 16 17#include <UnitTest++/UnitTest++.h> 18#include <cstdlib> 19#include <gsl/string_span.h> 20#include <vector> 21 22using namespace std; 23using namespace gsl; 24 25 26SUITE(string_span_tests) 27{ 28 29 TEST(TestLiteralConstruction) 30 { 31 cwstring_span<> v = ensure_z(L"Hello"); 32 CHECK(5 == v.length()); 33 34#ifdef CONFIRM_COMPILATION_ERRORS 35 wstring_span<> v2 = ensure0(L"Hello"); 36#endif 37 } 38 39 TEST(TestConstructFromStdString) 40 { 41 std::string s = "Hello there world"; 42 cstring_span<> v = s; 43 CHECK(v.length() == static_cast<cstring_span<>::index_type>(s.length())); 44 } 45 46 TEST(TestConstructFromStdVector) 47 { 48 std::vector<char> vec(5, 'h'); 49 string_span<> v {vec}; 50 CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size())); 51 } 52 53 TEST(TestStackArrayConstruction) 54 { 55 wchar_t stack_string[] = L"Hello"; 56 57 { 58 cwstring_span<> v = ensure_z(stack_string); 59 CHECK(v.length() == 5); 60 } 61 62 { 63 cwstring_span<> v = stack_string; 64 CHECK(v.length() == 5); 65 } 66 67 { 68 wstring_span<> v = ensure_z(stack_string); 69 CHECK(v.length() == 5); 70 } 71 72 { 73 wstring_span<> v = stack_string; 74 CHECK(v.length() == 5); 75 } 76 } 77 78 TEST(TestConstructFromConstCharPointer) 79 { 80 const char* s = "Hello"; 81 cstring_span<> v = ensure_z(s); 82 CHECK(v.length() == 5); 83 } 84 85 TEST(TestConversionToConst) 86 { 87 char stack_string[] = "Hello"; 88 string_span<> v = ensure_z(stack_string); 89 cstring_span<> v2 = v; 90 CHECK(v.length() == v2.length()); 91 } 92 93 TEST(TestConversionFromConst) 94 { 95 char stack_string[] = "Hello"; 96 cstring_span<> v = ensure_z(stack_string); 97 (void)v; 98#ifdef CONFIRM_COMPILATION_ERRORS 99 string_span<> v2 = v; 100 string_span<> v3 = "Hello"; 101#endif 102 } 103 104 TEST(TestToString) 105 { 106 auto s = gsl::to_string(cstring_span<>{}); 107 CHECK(s.length() == 0); 108 109 char stack_string[] = "Hello"; 110 cstring_span<> v = ensure_z(stack_string); 111 auto s2 = gsl::to_string(v); 112 CHECK(static_cast<cstring_span<>::index_type>(s2.length()) == v.length()); 113 CHECK(s2.length() == 5); 114 } 115 116 TEST(EqualityAndImplicitConstructors) 117 { 118 { 119 cstring_span<> span = "Hello"; 120 cstring_span<> span1; 121 122 // comparison to empty span 123 CHECK(span1 != span); 124 CHECK(span != span1); 125 } 126 127 { 128 cstring_span<> span = "Hello"; 129 cstring_span<> span1 = "Hello1"; 130 131 // comparison to different span 132 CHECK(span1 != span); 133 CHECK(span != span1); 134 } 135 136 { 137 cstring_span<> span = "Hello"; 138 139 const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 140 const char ar1[] = "Hello"; 141 const char ar2[10] = "Hello"; 142 const char* ptr = "Hello"; 143 const std::string str = "Hello"; 144 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 145 gsl::span<const char> sp = ensure_z("Hello"); 146 147 // comparison to literal 148 CHECK(span == cstring_span<>("Hello")); 149 150 // comparison to static array with no null termination 151 CHECK(span == cstring_span<>(ar)); 152 153 // comparison to static array with null at the end 154 CHECK(span == cstring_span<>(ar1)); 155 156 // comparison to static array with null in the middle 157 CHECK(span == cstring_span<>(ar2)); 158 159 // comparison to null-terminated c string 160 CHECK(span == cstring_span<>(ptr, 5)); 161 162 // comparison to string 163 CHECK(span == cstring_span<>(str)); 164 165 // comparison to vector of charaters with no null termination 166 CHECK(span == cstring_span<>(vec)); 167 168 // comparison to span 169 CHECK(span == cstring_span<>(sp)); 170 171 // comparison to string_span 172 CHECK(span == span); 173 } 174 175 { 176 char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 177 178 string_span<> span = ar; 179 180 char ar1[] = "Hello"; 181 char ar2[10] = "Hello"; 182 char* ptr = ar; 183 std::string str = "Hello"; 184 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 185 gsl::span<char> sp = ensure_z(ar1); 186 187 // comparison to static array with no null termination 188 CHECK(span == string_span<>(ar)); 189 190 // comparison to static array with null at the end 191 CHECK(span == string_span<>(ar1)); 192 193 // comparison to static array with null in the middle 194 CHECK(span == string_span<>(ar2)); 195 196 // comparison to null-terminated c string 197 CHECK(span == string_span<>(ptr, 5)); 198 199 // comparison to string 200 CHECK(span == string_span<>(str)); 201 202 // comparison to vector of charaters with no null termination 203 CHECK(span == string_span<>(vec)); 204 205 // comparison to span 206 CHECK(span == string_span<>(sp)); 207 208 // comparison to string_span 209 CHECK(span == span); 210 } 211 212 213 { 214 const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 215 const char ar1[] = "Hello"; 216 const char ar2[10] = "Hello"; 217 const std::string str = "Hello"; 218 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 219 gsl::span<const char> sp = ensure_z("Hello"); 220 221 cstring_span<> span = "Hello"; 222 223 // const span, const other type 224 225 CHECK(span == "Hello"); 226 CHECK(span == ar); 227 CHECK(span == ar1); 228 CHECK(span == ar2); 229#ifdef CONFIRM_COMPILATION_ERRORS 230 const char* ptr = "Hello"; 231 CHECK(span == ptr); 232#endif 233 CHECK(span == str); 234 CHECK(span == vec); 235 CHECK(span == sp); 236 237 CHECK("Hello" == span); 238 CHECK(ar == span); 239 CHECK(ar1 == span); 240 CHECK(ar2 == span); 241#ifdef CONFIRM_COMPILATION_ERRORS 242 CHECK(ptr == span); 243#endif 244 CHECK(str == span); 245 CHECK(vec == span); 246 CHECK(sp == span); 247 248 // const span, non-const other type 249 250 char _ar[] = { 'H', 'e', 'l', 'l', 'o' }; 251 char _ar1[] = "Hello"; 252 char _ar2[10] = "Hello"; 253 char* _ptr = _ar; 254 std::string _str = "Hello"; 255 std::vector<char> _vec = { 'H', 'e', 'l', 'l', 'o' }; 256 gsl::span<char> _sp{ _ar, 5 }; 257 258 CHECK(span == _ar); 259 CHECK(span == _ar1); 260 CHECK(span == _ar2); 261#ifdef CONFIRM_COMPILATION_ERRORS 262 CHECK(span == _ptr); 263#endif 264 CHECK(span == _str); 265 CHECK(span == _vec); 266 CHECK(span == _sp); 267 268 CHECK(_ar == span); 269 CHECK(_ar1 == span); 270 CHECK(_ar2 == span); 271#ifdef CONFIRM_COMPILATION_ERRORS 272 CHECK(_ptr == span); 273#endif 274 CHECK(_str == span); 275 CHECK(_vec == span); 276 CHECK(_sp == span); 277 278 string_span<> _span{ _ptr, 5 }; 279 280 // non-const span, non-const other type 281 282 CHECK(_span == _ar); 283 CHECK(_span == _ar1); 284 CHECK(_span == _ar2); 285#ifdef CONFIRM_COMPILATION_ERRORS 286 CHECK(_span == _ptr); 287#endif 288 CHECK(_span == _str); 289 CHECK(_span == _vec); 290 CHECK(_span == _sp); 291 292 CHECK(_ar == _span); 293 CHECK(_ar1 == _span); 294 CHECK(_ar2 == _span); 295#ifdef CONFIRM_COMPILATION_ERRORS 296 CHECK(_ptr == _span); 297#endif 298 CHECK(_str == _span); 299 CHECK(_vec == _span); 300 CHECK(_sp == _span); 301 302 // non-const span, const other type 303 304 CHECK(_span == "Hello"); 305 CHECK(_span == ar); 306 CHECK(_span == ar1); 307 CHECK(_span == ar2); 308#ifdef CONFIRM_COMPILATION_ERRORS 309 CHECK(_span == ptr); 310#endif 311 CHECK(_span == str); 312 CHECK(_span == vec); 313 CHECK(_span == sp); 314 315 CHECK("Hello" == _span); 316 CHECK(ar == _span); 317 CHECK(ar1 == _span); 318 CHECK(ar2 == _span); 319#ifdef CONFIRM_COMPILATION_ERRORS 320 CHECK(ptr == _span); 321#endif 322 CHECK(str == _span); 323 CHECK(vec == _span); 324 CHECK(sp == _span); 325 326 // two spans 327 328 CHECK(_span == span); 329 CHECK(span == _span); 330 } 331 332 { 333 std::vector<char> str1 = { 'H', 'e', 'l', 'l', 'o' }; 334 cstring_span<> span1 = str1; 335 std::vector<char> str2 = std::move(str1); 336 cstring_span<> span2 = str2; 337 338 // comparison of spans from the same vector before and after move (ok) 339 CHECK(span1 == span2); 340 } 341 } 342 343 TEST(ComparisonAndImplicitConstructors) 344 { 345 { 346 cstring_span<> span = "Hello"; 347 348 const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 349 const char ar1[] = "Hello"; 350 const char ar2[10] = "Hello"; 351 const char* ptr = "Hello"; 352 const std::string str = "Hello"; 353 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 354 355 // comparison to literal 356 CHECK(span < cstring_span<>("Helloo")); 357 CHECK(span > cstring_span<>("Hell")); 358 359 // comparison to static array with no null termination 360 CHECK(span >= cstring_span<>(ar)); 361 362 // comparison to static array with null at the end 363 CHECK(span <= cstring_span<>(ar1)); 364 365 // comparison to static array with null in the middle 366 CHECK(span >= cstring_span<>(ar2)); 367 368 // comparison to null-terminated c string 369 CHECK(span <= cstring_span<>(ptr, 5)); 370 371 // comparison to string 372 CHECK(span >= cstring_span<>(str)); 373 374 // comparison to vector of charaters with no null termination 375 CHECK(span <= cstring_span<>(vec)); 376 } 377 378 { 379 char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 380 381 string_span<> span = ar; 382 383 char larr[] = "Hell"; 384 char rarr[] = "Helloo"; 385 386 char ar1[] = "Hello"; 387 char ar2[10] = "Hello"; 388 char* ptr = ar; 389 std::string str = "Hello"; 390 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 391 392 393 // comparison to static array with no null termination 394 CHECK(span <= string_span<>(ar)); 395 CHECK(span < string_span<>(rarr)); 396 CHECK(span > string_span<>(larr)); 397 398 // comparison to static array with null at the end 399 CHECK(span >= string_span<>(ar1)); 400 401 // comparison to static array with null in the middle 402 CHECK(span <= string_span<>(ar2)); 403 404 // comparison to null-terminated c string 405 CHECK(span >= string_span<>(ptr, 5)); 406 407 // comparison to string 408 CHECK(span <= string_span<>(str)); 409 410 // comparison to vector of charaters with no null termination 411 CHECK(span >= string_span<>(vec)); 412 } 413 } 414 TEST(ConstrutorsEnsureZ) 415 { 416 // remove z from literals 417 { 418 cstring_span<> sp = "hello"; 419 CHECK((sp.length() == 5)); 420 } 421 422 // take the string as is 423 { 424 auto str = std::string("hello"); 425 cstring_span<> sp = str; 426 CHECK((sp.length() == 5)); 427 } 428 429 // ensure z on c strings 430 { 431 char* ptr = new char[3]; 432 433 ptr[0] = 'a'; 434 ptr[1] = 'b'; 435 ptr[2] = '\0'; 436 437 string_span<> span = ensure_z(ptr); 438 CHECK(span.length() == 2); 439 440 delete[] ptr; 441 } 442 } 443 444 TEST(Constructors) 445 { 446 // creating cstring_span 447 448 // from span of a final extent 449 { 450 span<const char, 6> sp = "Hello"; 451 cstring_span<> span = sp; 452 CHECK(span.length() == 6); 453 } 454 455 // from const span of a final extent to non-const string_span 456#ifdef CONFIRM_COMPILATION_ERRORS 457 { 458 span<const char, 6> sp = "Hello"; 459 string_span<> span = sp; 460 CHECK(span.length() == 6); 461 } 462#endif 463 464 // from string temporary 465#ifdef CONFIRM_COMPILATION_ERRORS 466 { 467 cstring_span<> span = std::string("Hello"); 468 } 469#endif 470 471 // default 472 { 473 cstring_span<> span; 474 CHECK(span.length() == 0); 475 } 476 477 // from nullptr 478 { 479 cstring_span<> span(nullptr); 480 CHECK(span.length() == 0); 481 } 482 483 // from string literal 484 { 485 cstring_span<> span = "Hello"; 486 CHECK(span.length() == 5); 487 } 488 489 // from const static array 490 { 491 const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 492 cstring_span<> span = ar; 493 CHECK(span.length() == 5); 494 } 495 496 // from non-const static array 497 { 498 char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 499 cstring_span<> span = ar; 500 CHECK(span.length() == 5); 501 } 502 503 // from const ptr and length 504 { 505 const char* ptr = "Hello"; 506 cstring_span<> span{ ptr, 5 }; 507 CHECK(span.length() == 5); 508 } 509 510 // from const ptr and length, include 0 511 { 512 const char* ptr = "Hello"; 513 cstring_span<> span{ ptr, 6 }; 514 CHECK(span.length() == 6); 515 } 516 517 // from const ptr and length, 0 inside 518 { 519 const char* ptr = "He\0lo"; 520 cstring_span<> span{ ptr, 5 }; 521 CHECK(span.length() == 5); 522 } 523 524 // from non-const ptr and length 525 { 526 char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 527 char* ptr = ar; 528 cstring_span<> span{ ptr, 5 }; 529 CHECK(span.length() == 5); 530 } 531 532 // from non-const ptr and length, 0 inside 533 { 534 char ar[] = { 'H', 'e', '\0', 'l', 'o' }; 535 char* ptr = ar; 536 cstring_span<> span{ ptr, 5 }; 537 CHECK(span.length() == 5); 538 } 539 540 // from const string 541 { 542 const std::string str = "Hello"; 543 cstring_span<> span = str; 544 CHECK(span.length() == 5); 545 } 546 547 // from non-const string 548 { 549 std::string str = "Hello"; 550 cstring_span<> span = str; 551 CHECK(span.length() == 5); 552 } 553 554 // from const vector 555 { 556 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 557 cstring_span<> span = vec; 558 CHECK(span.length() == 5); 559 } 560 561 // from non-const vector 562 { 563 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 564 cstring_span<> span = vec; 565 CHECK(span.length() == 5); 566 } 567 568 // from const span 569 { 570 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 571 const span<const char> inner = vec; 572 cstring_span<> span = inner; 573 CHECK(span.length() == 5); 574 } 575 576 // from non-const span 577 { 578 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 579 span<char> inner = vec; 580 cstring_span<> span = inner; 581 CHECK(span.length() == 5); 582 } 583 584 // from const string_span 585 { 586 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 587 cstring_span<> tmp = vec; 588 cstring_span<> span = tmp; 589 CHECK(span.length() == 5); 590 } 591 592 // from non-const string_span 593 { 594 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 595 string_span<> tmp = vec; 596 cstring_span<> span = tmp; 597 CHECK(span.length() == 5); 598 } 599 600 // creating string_span 601 602 // from string literal 603 { 604#ifdef CONFIRM_COMPILATION_ERRORS 605 string_span<> span = "Hello"; 606#endif 607 } 608 609 // from const static array 610 { 611#ifdef CONFIRM_COMPILATION_ERRORS 612 const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 613 string_span<> span = ar; 614 CHECK(span.length() == 5); 615#endif 616 } 617 618 // from non-const static array 619 { 620 char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 621 string_span<> span = ar; 622 CHECK(span.length() == 5); 623 } 624 625 // from const ptr and length 626 { 627#ifdef CONFIRM_COMPILATION_ERRORS 628 const char* ptr = "Hello"; 629 string_span<> span{ ptr, 5 }; 630 CHECK(span.length() == 5); 631#endif 632 } 633 634 // from non-const ptr and length 635 { 636 char ar[] = { 'H', 'e', 'l', 'l', 'o' }; 637 char* ptr = ar; 638 string_span<> span{ ptr, 5 }; 639 CHECK(span.length() == 5); 640 } 641 642 // from const string 643 { 644#ifdef CONFIRM_COMPILATION_ERRORS 645 const std::string str = "Hello"; 646 string_span<> span = str; 647 CHECK(span.length() == 5); 648#endif 649 } 650 651 // from non-const string 652 { 653 std::string str = "Hello"; 654 string_span<> span = str; 655 CHECK(span.length() == 5); 656 } 657 658 // from const vector 659 { 660#ifdef CONFIRM_COMPILATION_ERRORS 661 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 662 string_span<> span = vec; 663 CHECK(span.length() == 5); 664#endif 665 } 666 667 // from non-const vector 668 { 669 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 670 string_span<> span = vec; 671 CHECK(span.length() == 5); 672 } 673 674 // from const span 675 { 676#ifdef CONFIRM_COMPILATION_ERRORS 677 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 678 const span<const char> inner = vec; 679 string_span<> span = inner; 680 CHECK(span.length() == 5); 681#endif 682 } 683 684 // from non-const span 685 { 686 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 687 span<char> inner = vec; 688 string_span<> span = inner; 689 CHECK(span.length() == 5); 690 } 691 692 // from non-const span of non-const data from const vector 693 { 694#ifdef CONFIRM_COMPILATION_ERRORS 695 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 696 const span<char> inner = vec; 697 string_span<> span = inner; 698 CHECK(span.length() == 5); 699#endif 700 } 701 702 // from const string_span 703 { 704#ifdef CONFIRM_COMPILATION_ERRORS 705 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 706 cstring_span<> tmp = vec; 707 string_span<> span = tmp; 708 CHECK(span.length() == 5); 709#endif 710 } 711 712 // from non-const string_span 713 { 714 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 715 string_span<> tmp = vec; 716 string_span<> span = tmp; 717 CHECK(span.length() == 5); 718 } 719 720 // from non-const string_span from const vector 721 { 722#ifdef CONFIRM_COMPILATION_ERRORS 723 const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 724 string_span<> tmp = vec; 725 string_span<> span = tmp; 726 CHECK(span.length() == 5); 727#endif 728 } 729 730 // from const string_span of non-const data 731 { 732 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 733 const string_span<> tmp = vec; 734 string_span<> span = tmp; 735 CHECK(span.length() == 5); 736 } 737 } 738 739 template<typename T> 740 T move_wrapper(T&& t) 741 { 742 return std::move(t); 743 } 744 745 template <class T> 746 T create() { return T{}; } 747 748 template <class T> 749 void use(basic_string_span<T, gsl::dynamic_extent> s) {} 750 751 TEST(MoveConstructors) 752 { 753 // move string_span 754 { 755 cstring_span<> span = "Hello"; 756 auto span1 = std::move(span); 757 CHECK(span1.length() == 5); 758 } 759 { 760 cstring_span<> span = "Hello"; 761 auto span1 = move_wrapper(std::move(span)); 762 CHECK(span1.length() == 5); 763 } 764 { 765 cstring_span<> span = "Hello"; 766 auto span1 = move_wrapper(std::move(span)); 767 CHECK(span1.length() == 5); 768 } 769 770 // move span 771 { 772 span<const char> span = ensure_z("Hello"); 773 cstring_span<> span1 = std::move(span); 774 CHECK(span1.length() == 5); 775 } 776 { 777 span<const char> span = ensure_z("Hello"); 778 cstring_span<> span2 = move_wrapper(std::move(span)); 779 CHECK(span2.length() == 5); 780 } 781 782 // move string 783 { 784#ifdef CONFIRM_COMPILATION_ERRORS 785 std::string str = "Hello"; 786 string_span<> span = std::move(str); 787 CHECK(span.length() == 5); 788#endif 789 } 790 { 791#ifdef CONFIRM_COMPILATION_ERRORS 792 std::string str = "Hello"; 793 string_span<> span = move_wrapper<std::string>(std::move(str)); 794 CHECK(span.length() == 5); 795#endif 796 } 797 { 798#ifdef CONFIRM_COMPILATION_ERRORS 799 use<char>(create<string>()); 800#endif 801 } 802 803 // move container 804 { 805#ifdef CONFIRM_COMPILATION_ERRORS 806 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 807 string_span<> span = std::move(vec); 808 CHECK(span.length() == 5); 809#endif 810 } 811 { 812#ifdef CONFIRM_COMPILATION_ERRORS 813 std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; 814 string_span<> span = move_wrapper<std::vector<char>>(std::move(vec)); 815 CHECK(span.length() == 5); 816#endif 817 } 818 { 819#ifdef CONFIRM_COMPILATION_ERRORS 820 use<char>(create<std::vector<char>>()); 821#endif 822 } 823 } 824 825 TEST(Conversion) 826 { 827#ifdef CONFIRM_COMPILATION_ERRORS 828 cstring_span<> span = "Hello"; 829 cwstring_span<> wspan{ span }; 830 CHECK(wspan.length() == 5); 831#endif 832 } 833 834 czstring_span<> CreateTempName(string_span<> span) 835 { 836 Expects(span.size() > 1); 837 838 int last = 0; 839 if (span.size() > 4) 840 { 841 span[0] = 't'; 842 span[1] = 'm'; 843 span[2] = 'p'; 844 last = 3; 845 } 846 span[last] = '\0'; 847 848 auto ret = span.subspan(0, 4); 849 return{ ret }; 850 } 851 852 TEST(zstring) 853 { 854 855 // create zspan from zero terminated string 856 { 857 char buf[1]; 858 buf[0] = '\0'; 859 860 zstring_span<> zspan({ buf, 1 }); 861 862 CHECK(strlen(zspan.assume_z()) == 0); 863 CHECK(zspan.as_string_span().size() == 0); 864 CHECK(zspan.ensure_z().size() == 0); 865 } 866 867 // create zspan from non-zero terminated string 868 { 869 char buf[1]; 870 buf[0] = 'a'; 871 872 auto workaround_macro = [&]() { zstring_span<> zspan({ buf, 1 }); }; 873 CHECK_THROW(workaround_macro(), fail_fast); 874 } 875 876 // usage scenario: create zero-terminated temp file name and pass to a legacy API 877 { 878 char buf[10]; 879 880 auto name = CreateTempName({ buf, 10 }); 881 if (!name.empty()) 882 { 883 czstring<> str = name.assume_z(); 884 CHECK(strlen(str) == 3); 885 CHECK(*(str+3) == '\0'); 886 } 887 } 888 889 } 890 891 cwzstring_span<> CreateTempNameW(wstring_span<> span) 892 { 893 Expects(span.size() > 1); 894 895 int last = 0; 896 if (span.size() > 4) 897 { 898 span[0] = L't'; 899 span[1] = L'm'; 900 span[2] = L'p'; 901 last = 3; 902 } 903 span[last] = L'\0'; 904 905 auto ret = span.subspan(0, 4); 906 return{ ret }; 907 } 908 909 TEST(wzstring) 910 { 911 912 // create zspan from zero terminated string 913 { 914 wchar_t buf[1]; 915 buf[0] = L'\0'; 916 917 wzstring_span<> zspan({ buf, 1 }); 918 919 CHECK(wcsnlen(zspan.assume_z(), 1) == 0); 920 CHECK(zspan.as_string_span().size() == 0); 921 CHECK(zspan.ensure_z().size() == 0); 922 } 923 924 // create zspan from non-zero terminated string 925 { 926 wchar_t buf[1]; 927 buf[0] = L'a'; 928 929 auto workaround_macro = [&]() { wzstring_span<> zspan({ buf, 1 }); }; 930 CHECK_THROW(workaround_macro(), fail_fast); 931 } 932 933 // usage scenario: create zero-terminated temp file name and pass to a legacy API 934 { 935 wchar_t buf[10]; 936 937 auto name = CreateTempNameW({ buf, 10 }); 938 if (!name.empty()) 939 { 940 cwzstring<> str = name.assume_z(); 941 CHECK(wcsnlen(str, 10) == 3); 942 CHECK(*(str + 3) == L'\0'); 943 } 944 } 945 946 } 947} 948 949int main(int, const char *[]) 950{ 951 return UnitTest::RunAllTests(); 952} 953