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
23 using namespace std;
24 using namespace gsl;
25
26
SUITE(string_span_tests)27 SUITE(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
main(int,const char * [])968 int main(int, const char *[])
969 {
970 return UnitTest::RunAllTests();
971 }
972