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