1 /** 2 This module is a submodule of $(MREF std, range). 3 4 It defines the bidirectional and forward range primitives for arrays: 5 $(LREF empty), $(LREF front), $(LREF back), $(LREF popFront), $(LREF popBack) and $(LREF save). 6 7 It provides basic range functionality by defining several templates for testing 8 whether a given object is a range, and what kind of range it is: 9 10 $(SCRIPT inhibitQuickIndex = 1;) 11 $(DIVC quickindex, 12 $(BOOKTABLE , 13 $(TR $(TD $(LREF isInputRange)) 14 $(TD Tests if something is an $(I input range), defined to be 15 something from which one can sequentially read data using the 16 primitives `front`, `popFront`, and `empty`. 17 )) 18 $(TR $(TD $(LREF isOutputRange)) 19 $(TD Tests if something is an $(I output range), defined to be 20 something to which one can sequentially write data using the 21 $(LREF put) primitive. 22 )) 23 $(TR $(TD $(LREF isForwardRange)) 24 $(TD Tests if something is a $(I forward range), defined to be an 25 input range with the additional capability that one can save one's 26 current position with the `save` primitive, thus allowing one to 27 iterate over the same range multiple times. 28 )) 29 $(TR $(TD $(LREF isBidirectionalRange)) 30 $(TD Tests if something is a $(I bidirectional range), that is, a 31 forward range that allows reverse traversal using the primitives $(D 32 back) and `popBack`. 33 )) 34 $(TR $(TD $(LREF isRandomAccessRange)) 35 $(TD Tests if something is a $(I random access range), which is a 36 bidirectional range that also supports the array subscripting 37 operation via the primitive `opIndex`. 38 )) 39 )) 40 41 It also provides number of templates that test for various range capabilities: 42 43 $(BOOKTABLE , 44 $(TR $(TD $(LREF hasMobileElements)) 45 $(TD Tests if a given range's elements can be moved around using the 46 primitives `moveFront`, `moveBack`, or `moveAt`. 47 )) 48 $(TR $(TD $(LREF ElementType)) 49 $(TD Returns the element type of a given range. 50 )) 51 $(TR $(TD $(LREF ElementEncodingType)) 52 $(TD Returns the encoding element type of a given range. 53 )) 54 $(TR $(TD $(LREF hasSwappableElements)) 55 $(TD Tests if a range is a forward range with swappable elements. 56 )) 57 $(TR $(TD $(LREF hasAssignableElements)) 58 $(TD Tests if a range is a forward range with mutable elements. 59 )) 60 $(TR $(TD $(LREF hasLvalueElements)) 61 $(TD Tests if a range is a forward range with elements that can be 62 passed by reference and have their address taken. 63 )) 64 $(TR $(TD $(LREF hasLength)) 65 $(TD Tests if a given range has the `length` attribute. 66 )) 67 $(TR $(TD $(LREF isInfinite)) 68 $(TD Tests if a given range is an $(I infinite range). 69 )) 70 $(TR $(TD $(LREF hasSlicing)) 71 $(TD Tests if a given range supports the array slicing operation $(D 72 R[x .. y]). 73 )) 74 ) 75 76 Finally, it includes some convenience functions for manipulating ranges: 77 78 $(BOOKTABLE , 79 $(TR $(TD $(LREF popFrontN)) 80 $(TD Advances a given range by up to $(I n) elements. 81 )) 82 $(TR $(TD $(LREF popBackN)) 83 $(TD Advances a given bidirectional range from the right by up to 84 $(I n) elements. 85 )) 86 $(TR $(TD $(LREF popFrontExactly)) 87 $(TD Advances a given range by up exactly $(I n) elements. 88 )) 89 $(TR $(TD $(LREF popBackExactly)) 90 $(TD Advances a given bidirectional range from the right by exactly 91 $(I n) elements. 92 )) 93 $(TR $(TD $(LREF moveFront)) 94 $(TD Removes the front element of a range. 95 )) 96 $(TR $(TD $(LREF moveBack)) 97 $(TD Removes the back element of a bidirectional range. 98 )) 99 $(TR $(TD $(LREF moveAt)) 100 $(TD Removes the $(I i)'th element of a random-access range. 101 )) 102 $(TR $(TD $(LREF walkLength)) 103 $(TD Computes the length of any range in O(n) time. 104 )) 105 $(TR $(TD $(LREF put)) 106 $(TD Outputs element `e` to a range. 107 )) 108 ) 109 110 Source: $(PHOBOSSRC std/range/primitives.d) 111 112 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). 113 114 Authors: $(HTTP erdani.com, Andrei Alexandrescu), David Simcha, and 115 $(HTTP jmdavisprog.com, Jonathan M Davis). Credit for some of the ideas 116 in building this module goes to 117 $(HTTP fantascienza.net/leonardo/so/, Leonardo Maffi). 118 */ 119 module std.range.primitives; 120 121 import std.traits; 122 123 /** 124 Returns `true` if `R` is an input range. An input range must 125 define the primitives `empty`, `popFront`, and `front`. The 126 following code should compile for any input range. 127 128 ---- 129 R r; // can define a range object 130 if (r.empty) {} // can test for empty 131 r.popFront(); // can invoke popFront() 132 auto h = r.front; // can get the front of the range of non-void type 133 ---- 134 135 The following are rules of input ranges are assumed to hold true in all 136 Phobos code. These rules are not checkable at compile-time, so not conforming 137 to these rules when writing ranges or range based code will result in 138 undefined behavior. 139 140 $(UL 141 $(LI `r.empty` returns `false` if and only if there is more data 142 available in the range.) 143 $(LI `r.empty` evaluated multiple times, without calling 144 `r.popFront`, or otherwise mutating the range object or the 145 underlying data, yields the same result for every evaluation.) 146 $(LI `r.front` returns the current element in the range. 147 It may return by value or by reference.) 148 $(LI `r.front` can be legally evaluated if and only if evaluating 149 `r.empty` has, or would have, equaled `false`.) 150 $(LI `r.front` evaluated multiple times, without calling 151 `r.popFront`, or otherwise mutating the range object or the 152 underlying data, yields the same result for every evaluation.) 153 $(LI `r.popFront` advances to the next element in the range.) 154 $(LI `r.popFront` can be called if and only if evaluating `r.empty` 155 has, or would have, equaled `false`.) 156 ) 157 158 Also, note that Phobos code assumes that the primitives `r.front` and 159 `r.empty` are $(BIGOH 1) time complexity wise or "cheap" in terms of 160 running time. $(BIGOH) statements in the documentation of range functions 161 are made with this assumption. 162 163 See_Also: 164 The header of $(MREF std,range) for tutorials on ranges. 165 166 Params: 167 R = type to be tested 168 169 Returns: 170 `true` if R is an input range, `false` if not 171 */ 172 enum bool isInputRange(R) = 173 is(typeof(R.init) == R) 174 && is(ReturnType!((R r) => r.empty) == bool) 175 && is(typeof((return ref R r) => r.front)) 176 && !is(ReturnType!((R r) => r.front) == void) 177 && is(typeof((R r) => r.popFront)); 178 179 /// 180 @safe unittest 181 { 182 struct A {} 183 struct B 184 { 185 void popFront(); 186 @property bool empty(); 187 @property int front(); 188 } 189 static assert(!isInputRange!A); 190 static assert( isInputRange!B); 191 static assert( isInputRange!(int[])); 192 static assert( isInputRange!(char[])); 193 static assert(!isInputRange!(char[4])); 194 static assert( isInputRange!(inout(int)[])); 195 196 static struct NotDefaultConstructible 197 { 198 @disable this(); 199 void popFront(); 200 @property bool empty(); 201 @property int front(); 202 } 203 static assert( isInputRange!NotDefaultConstructible); 204 205 static struct NotDefaultConstructibleOrCopyable 206 { 207 @disable this(); 208 @disable this(this); 209 void popFront(); 210 @property bool empty(); 211 @property int front(); 212 } 213 static assert(isInputRange!NotDefaultConstructibleOrCopyable); 214 215 static struct Frontless 216 { 217 void popFront(); 218 @property bool empty(); 219 } 220 static assert(!isInputRange!Frontless); 221 222 static struct VoidFront 223 { 224 void popFront(); 225 @property bool empty(); 226 void front(); 227 } 228 static assert(!isInputRange!VoidFront); 229 } 230 231 @safe unittest 232 { 233 import std.algorithm.comparison : equal; 234 235 static struct R 236 { 237 static struct Front 238 { 239 R* impl; 240 @property int value() { return impl._front; } 241 alias value this; 242 } 243 244 int _front; 245 246 @property bool empty() { return _front >= 3; } 247 @property auto front() { return Front(&this); } 248 void popFront() { _front++; } 249 } 250 R r; 251 252 static assert(isInputRange!R); 253 assert(r.equal([ 0, 1, 2 ])); 254 } 255 256 /+ 257 puts the whole raw element `e` into `r`. doPut will not attempt to 258 iterate, slice or transcode `e` in any way shape or form. It will $(B only) 259 call the correct primitive (`r.put(e)`, $(D r.front = e) or 260 `r(e)` once. 261 262 This can be important when `e` needs to be placed in `r` unchanged. 263 Furthermore, it can be useful when working with `InputRange`s, as doPut 264 guarantees that no more than a single element will be placed. 265 +/ 266 private void doPut(R, E)(ref R r, auto ref E e) 267 { 268 static if (is(PointerTarget!R == struct)) 269 enum usingPut = hasMember!(PointerTarget!R, "put"); 270 else 271 enum usingPut = hasMember!(R, "put"); 272 273 static if (usingPut) 274 { 275 static assert(is(typeof(r.put(e))), 276 "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ "."); 277 r.put(e); 278 } 279 else static if (isNarrowString!R && is(const(E) == const(typeof(r[0])))) 280 { 281 // one character, we can put it 282 r[0] = e; 283 r = r[1 .. $]; 284 } 285 else static if (isNarrowString!R && isNarrowString!E && is(typeof(r[] = e))) 286 { 287 // slice assign. Note that this is a duplicate from put, but because 288 // putChar uses doPut exclusively, we have to copy it here. 289 immutable len = e.length; 290 r[0 .. len] = e; 291 r = r[len .. $]; 292 } 293 else static if (isInputRange!R) 294 { 295 static assert(is(typeof(r.front = e)), 296 "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ "."); 297 r.front = e; 298 r.popFront(); 299 } 300 else static if (is(typeof(r(e)))) 301 { 302 r(e); 303 } 304 else 305 { 306 static assert(false, 307 "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ "."); 308 } 309 } 310 311 @safe unittest 312 { 313 static assert(!isNativeOutputRange!(int, int)); 314 static assert( isNativeOutputRange!(int[], int)); 315 static assert(!isNativeOutputRange!(int[][], int)); 316 317 static assert(!isNativeOutputRange!(int, int[])); 318 static assert(!isNativeOutputRange!(int[], int[])); 319 static assert( isNativeOutputRange!(int[][], int[])); 320 321 static assert(!isNativeOutputRange!(int, int[][])); 322 static assert(!isNativeOutputRange!(int[], int[][])); 323 static assert(!isNativeOutputRange!(int[][], int[][])); 324 325 static assert(!isNativeOutputRange!(int[4], int)); 326 static assert( isNativeOutputRange!(int[4][], int)); //Scary! 327 static assert( isNativeOutputRange!(int[4][], int[4])); 328 329 static assert( isNativeOutputRange!( char[], char)); 330 static assert(!isNativeOutputRange!( char[], dchar)); 331 static assert( isNativeOutputRange!(dchar[], char)); 332 static assert( isNativeOutputRange!(dchar[], dchar)); 333 334 } 335 336 /++ 337 Outputs `e` to `r`. The exact effect is dependent upon the two 338 types. Several cases are accepted, as described below. The code snippets 339 are attempted in order, and the first to compile "wins" and gets 340 evaluated. 341 342 In this table "doPut" is a method that places `e` into `r`, using the 343 correct primitive: `r.put(e)` if `R` defines `put`, $(D r.front = e) 344 if `r` is an input range (followed by `r.popFront()`), or `r(e)` 345 otherwise. 346 347 $(BOOKTABLE , 348 $(TR 349 $(TH Code Snippet) 350 $(TH Scenario) 351 ) 352 $(TR 353 $(TD `r.doPut(e);`) 354 $(TD `R` specifically accepts an `E`.) 355 ) 356 $(TR 357 $(TD $(D r.doPut([ e ]);)) 358 $(TD `R` specifically accepts an `E[]`.) 359 ) 360 $(TR 361 $(TD `r.putChar(e);`) 362 $(TD `R` accepts some form of string or character. put will 363 transcode the character `e` accordingly.) 364 ) 365 $(TR 366 $(TD $(D for (; !e.empty; e.popFront()) put(r, e.front);)) 367 $(TD Copying range `E` into `R`.) 368 ) 369 ) 370 371 Tip: `put` should $(I not) be used "UFCS-style", e.g. `r.put(e)`. 372 Doing this may call `R.put` directly, by-passing any transformation 373 feature provided by `Range.put`. $(D put(r, e)) is prefered. 374 +/ 375 void put(R, E)(ref R r, E e) 376 { 377 //First level: simply straight up put. 378 static if (is(typeof(doPut(r, e)))) 379 { 380 doPut(r, e); 381 } 382 //Optional optimization block for straight up array to array copy. 383 else static if (isDynamicArray!R && 384 !isAutodecodableString!R && 385 isDynamicArray!E && 386 is(typeof(r[] = e[]))) 387 { 388 immutable len = e.length; 389 r[0 .. len] = e[]; 390 r = r[len .. $]; 391 } 392 //Accepts E[] ? 393 else static if (is(typeof(doPut(r, [e]))) && !isDynamicArray!R) 394 { 395 if (__ctfe) 396 { 397 E[1] arr = [e]; 398 doPut(r, arr[]); 399 } 400 else 401 doPut(r, (ref e) @trusted { return (&e)[0 .. 1]; }(e)); 402 } 403 //special case for char to string. 404 else static if (isSomeChar!E && is(typeof(putChar(r, e)))) 405 { 406 putChar(r, e); 407 } 408 //Extract each element from the range 409 //We can use "put" here, so we can recursively test a RoR of E. 410 else static if (isInputRange!E && is(typeof(put(r, e.front)))) 411 { 412 //Special optimization: If E is a narrow string, and r accepts characters no-wider than the string's 413 //Then simply feed the characters 1 by 1. 414 static if (isAutodecodableString!E && !isAggregateType!E && ( 415 (is(E : const char[]) && is(typeof(doPut(r, char.max))) && !is(typeof(doPut(r, dchar.max))) && 416 !is(typeof(doPut(r, wchar.max)))) || 417 (is(E : const wchar[]) && is(typeof(doPut(r, wchar.max))) && !is(typeof(doPut(r, dchar.max)))) ) ) 418 { 419 foreach (c; e) 420 doPut(r, c); 421 } 422 else 423 { 424 for (; !e.empty; e.popFront()) 425 put(r, e.front); 426 } 427 } 428 else 429 { 430 static assert(false, "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ "."); 431 } 432 } 433 434 /** 435 * When an output range's `put` method only accepts elements of type 436 * `T`, use the global `put` to handle outputting a `T[]` to the range 437 * or vice-versa. 438 */ 439 @safe pure unittest 440 { 441 import std.traits : isSomeChar; 442 443 static struct A 444 { 445 string data; 446 447 void put(C)(C c) if (isSomeChar!C) 448 { 449 data ~= c; 450 } 451 } 452 static assert(isOutputRange!(A, char)); 453 454 auto a = A(); 455 put(a, "Hello"); 456 assert(a.data == "Hello"); 457 } 458 459 /** 460 * `put` treats dynamic arrays as array slices, and will call `popFront` 461 * on the slice after an element has been copied. 462 * 463 * Be sure to save the position of the array before calling `put`. 464 */ 465 @safe pure nothrow unittest 466 { 467 int[] a = [1, 2, 3], b = [10, 20]; 468 auto c = a; 469 put(a, b); 470 assert(c == [10, 20, 3]); 471 // at this point, a was advanced twice, so it only contains 472 // its last element while c represents the whole array 473 assert(a == [3]); 474 } 475 476 /** 477 * It's also possible to `put` any width strings or characters into narrow 478 * strings -- put does the conversion for you. 479 * 480 * Note that putting the same width character as the target buffer type is 481 * `nothrow`, but transcoding can throw a $(REF UTFException, std, utf). 482 */ 483 @safe pure unittest 484 { 485 // the elements must be mutable, so using string or const(char)[] 486 // won't compile 487 char[] s1 = new char[13]; 488 auto r1 = s1; 489 put(r1, "Hello, World!"w); 490 assert(s1 == "Hello, World!"); 491 } 492 493 @safe pure nothrow unittest 494 { 495 // same thing, just using same character width. 496 char[] s1 = new char[13]; 497 auto r1 = s1; 498 put(r1, "Hello, World!"); 499 assert(s1 == "Hello, World!"); 500 } 501 502 503 @safe pure nothrow @nogc unittest 504 { 505 static struct R() { void put(scope const(char)[]) {} } 506 R!() r; 507 put(r, 'a'); 508 } 509 510 //Helper function to handle chars as quickly and as elegantly as possible 511 //Assumes r.put(e)/r(e) has already been tested 512 private void putChar(R, E)(ref R r, E e) 513 if (isSomeChar!E) 514 { 515 // https://issues.dlang.org/show_bug.cgi?id=9186: Can't use (E[]).init 516 ref const( char)[] cstringInit(); 517 ref const(wchar)[] wstringInit(); 518 ref const(dchar)[] dstringInit(); 519 520 enum csCond = is(typeof(doPut(r, cstringInit()))); 521 enum wsCond = is(typeof(doPut(r, wstringInit()))); 522 enum dsCond = is(typeof(doPut(r, dstringInit()))); 523 524 //Use "max" to avoid static type demotion 525 enum ccCond = is(typeof(doPut(r, char.max))); 526 enum wcCond = is(typeof(doPut(r, wchar.max))); 527 //enum dcCond = is(typeof(doPut(r, dchar.max))); 528 529 //Fast transform a narrow char into a wider string 530 static if ((wsCond && E.sizeof < wchar.sizeof) || (dsCond && E.sizeof < dchar.sizeof)) 531 { 532 enum w = wsCond && E.sizeof < wchar.sizeof; 533 Select!(w, wchar, dchar) c = e; 534 typeof(c)[1] arr = [c]; 535 doPut(r, arr[]); 536 } 537 //Encode a wide char into a narrower string 538 else static if (wsCond || csCond) 539 { 540 import std.utf : encode; 541 /+static+/ Select!(wsCond, wchar[2], char[4]) buf; //static prevents purity. 542 doPut(r, buf[0 .. encode(buf, e)]); 543 } 544 //Slowly encode a wide char into a series of narrower chars 545 else static if (wcCond || ccCond) 546 { 547 import std.encoding : encode; 548 alias C = Select!(wcCond, wchar, char); 549 encode!(C, R)(e, r); 550 } 551 else 552 { 553 static assert(false, "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ "."); 554 } 555 } 556 557 pure @safe unittest 558 { 559 auto f = delegate (const(char)[]) {}; 560 putChar(f, cast(dchar)'a'); 561 } 562 563 564 @safe pure unittest 565 { 566 static struct R() { void put(scope const(char)[]) {} } 567 R!() r; 568 putChar(r, 'a'); 569 } 570 571 @safe unittest 572 { 573 struct A {} 574 static assert(!isInputRange!(A)); 575 struct B 576 { 577 void put(int) {} 578 } 579 B b; 580 put(b, 5); 581 } 582 583 @safe unittest 584 { 585 int[] a = new int[10]; 586 int b; 587 static assert(isInputRange!(typeof(a))); 588 put(a, b); 589 } 590 591 @safe unittest 592 { 593 void myprint(scope const(char)[] s) { } 594 auto r = &myprint; 595 put(r, 'a'); 596 } 597 598 @safe unittest 599 { 600 int[] a = new int[10]; 601 static assert(!__traits(compiles, put(a, 1.0L))); 602 put(a, 1); 603 assert(a.length == 9); 604 /* 605 * a[0] = 65; // OK 606 * a[0] = 'A'; // OK 607 * a[0] = "ABC"[0]; // OK 608 * put(a, "ABC"); // OK 609 */ 610 put(a, "ABC"); 611 assert(a.length == 6); 612 } 613 614 @safe unittest 615 { 616 char[] a = new char[10]; 617 static assert(!__traits(compiles, put(a, 1.0L))); 618 static assert(!__traits(compiles, put(a, 1))); 619 //char[] is now an output range for char, wchar, dchar, and ranges of such. 620 static assert(__traits(compiles, putChar(a, 'a'))); 621 static assert(__traits(compiles, put(a, wchar('a')))); 622 static assert(__traits(compiles, put(a, dchar('a')))); 623 static assert(__traits(compiles, put(a, "ABC"))); 624 static assert(__traits(compiles, put(a, "ABC"w))); 625 static assert(__traits(compiles, put(a, "ABC"d))); 626 } 627 628 @safe unittest 629 { 630 // attempt putting into narrow strings by transcoding 631 char[] a = new char[10]; 632 auto b = a; 633 put(a, "ABC"w); 634 assert(b[0 .. 3] == "ABC"); 635 assert(a.length == 7); 636 637 a = b; // reset 638 put(a, 'λ'); 639 assert(b[0 .. 2] == "λ"); 640 assert(a.length == 8); 641 642 a = b; // reset 643 put(a, "ABC"d); 644 assert(b[0 .. 3] == "ABC"); 645 assert(a.length == 7); 646 647 a = b; // reset 648 put(a, ''); 649 assert(b[0 .. 4] == ""); 650 assert(a.length == 6); 651 652 wchar[] aw = new wchar[10]; 653 auto bw = aw; 654 put(aw, "ABC"); 655 assert(bw[0 .. 3] == "ABC"w); 656 assert(aw.length == 7); 657 658 aw = bw; // reset 659 put(aw, 'λ'); 660 assert(bw[0 .. 1] == "λ"w); 661 assert(aw.length == 9); 662 663 aw = bw; // reset 664 put(aw, "ABC"d); 665 assert(bw[0 .. 3] == "ABC"w); 666 assert(aw.length == 7); 667 668 aw = bw; // reset 669 put(aw, ''); 670 assert(bw[0 .. 2] == ""w); 671 assert(aw.length == 8); 672 673 aw = bw; // reset 674 put(aw, ""); // try transcoding from char[] 675 assert(bw[0 .. 2] == ""w); 676 assert(aw.length == 8); 677 } 678 679 @safe unittest 680 { 681 int[][] a = new int[][10]; 682 int[] b = new int[10]; 683 int c; 684 put(b, c); 685 assert(b.length == 9); 686 put(a, b); 687 assert(a.length == 9); 688 static assert(!__traits(compiles, put(a, c))); 689 } 690 691 @safe unittest 692 { 693 int[][] a = new int[][](3); 694 int[] b = [1]; 695 auto aa = a; 696 put(aa, b); 697 assert(aa == [[], []]); 698 assert(a == [[1], [], []]); 699 int[][3] c = [2]; 700 aa = a; 701 put(aa, c[]); 702 assert(aa.empty); 703 assert(a == [[2], [2], [2]]); 704 } 705 706 @safe unittest 707 { 708 // Test fix for bug 7476. 709 struct LockingTextWriter 710 { 711 void put(dchar c){} 712 } 713 struct RetroResult 714 { 715 bool end = false; 716 @property bool empty() const { return end; } 717 @property dchar front(){ return 'a'; } 718 void popFront(){ end = true; } 719 } 720 LockingTextWriter w; 721 RetroResult re; 722 put(w, re); 723 } 724 725 @system unittest 726 { 727 import std.conv : to; 728 import std.meta : AliasSeq; 729 import std.typecons : tuple; 730 731 static struct PutC(C) 732 { 733 string result; 734 void put(const(C) c) { result ~= to!string((&c)[0 .. 1]); } 735 } 736 static struct PutS(C) 737 { 738 string result; 739 void put(const(C)[] s) { result ~= to!string(s); } 740 } 741 static struct PutSS(C) 742 { 743 string result; 744 void put(const(C)[][] ss) 745 { 746 foreach (s; ss) 747 result ~= to!string(s); 748 } 749 } 750 751 PutS!char p; 752 putChar(p, cast(dchar)'a'); 753 754 //Source Char 755 static foreach (SC; AliasSeq!(char, wchar, dchar)) 756 {{ 757 SC ch = 'I'; 758 dchar dh = '♥'; 759 immutable(SC)[] s = "日本語!"; 760 immutable(SC)[][] ss = ["日本語", "が", "好き", "ですか", "?"]; 761 762 //Target Char 763 static foreach (TC; AliasSeq!(char, wchar, dchar)) 764 { 765 //Testing PutC and PutS 766 static foreach (Type; AliasSeq!(PutC!TC, PutS!TC)) 767 {{ 768 Type type; 769 auto sink = new Type(); 770 771 //Testing put and sink 772 foreach (value ; tuple(type, sink)) 773 { 774 put(value, ch); 775 assert(value.result == "I"); 776 put(value, dh); 777 assert(value.result == "I♥"); 778 put(value, s); 779 assert(value.result == "I♥日本語!"); 780 put(value, ss); 781 assert(value.result == "I♥日本語!日本語が好きですか?"); 782 } 783 }} 784 } 785 }} 786 } 787 788 @safe unittest 789 { 790 static struct CharRange 791 { 792 char c; 793 enum empty = false; 794 void popFront(){} 795 ref char front() return @property 796 { 797 return c; 798 } 799 } 800 CharRange c; 801 put(c, cast(dchar)'H'); 802 put(c, "hello"d); 803 } 804 805 // https://issues.dlang.org/show_bug.cgi?id=9823 806 @system unittest 807 { 808 const(char)[] r; 809 void delegate(const(char)[]) dg = (s) { r = s; }; 810 put(dg, ["ABC"]); 811 assert(r == "ABC"); 812 } 813 814 // https://issues.dlang.org/show_bug.cgi?id=10571 815 @safe unittest 816 { 817 import std.format.write : formattedWrite; 818 string buf; 819 formattedWrite((scope const(char)[] s) { buf ~= s; }, "%s", "hello"); 820 assert(buf == "hello"); 821 } 822 823 @safe unittest 824 { 825 import std.format.write : formattedWrite; 826 import std.meta : AliasSeq; 827 struct PutC(C) 828 { 829 void put(C){} 830 } 831 struct PutS(C) 832 { 833 void put(const(C)[]){} 834 } 835 struct CallC(C) 836 { 837 void opCall(C){} 838 } 839 struct CallS(C) 840 { 841 void opCall(const(C)[]){} 842 } 843 struct FrontC(C) 844 { 845 enum empty = false; 846 auto front()@property{return C.init;} 847 void front(C)@property{} 848 void popFront(){} 849 } 850 struct FrontS(C) 851 { 852 enum empty = false; 853 auto front()@property{return C[].init;} 854 void front(const(C)[])@property{} 855 void popFront(){} 856 } 857 void foo() 858 { 859 static foreach (C; AliasSeq!(char, wchar, dchar)) 860 {{ 861 formattedWrite((C c){}, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 862 formattedWrite((const(C)[]){}, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 863 formattedWrite(PutC!C(), "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 864 formattedWrite(PutS!C(), "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 865 CallC!C callC; 866 CallS!C callS; 867 formattedWrite(callC, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 868 formattedWrite(callS, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 869 formattedWrite(FrontC!C(), "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 870 formattedWrite(FrontS!C(), "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 871 }} 872 formattedWrite((dchar[]).init, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d); 873 } 874 } 875 876 /+ 877 Returns `true` if `R` is a native output range for elements of type 878 `E`. An output range is defined functionally as a range that 879 supports the operation $(D doPut(r, e)) as defined above. if $(D doPut(r, e)) 880 is valid, then `put(r,e)` will have the same behavior. 881 882 The two guarantees isNativeOutputRange gives over the larger `isOutputRange` 883 are: 884 1: `e` is $(B exactly) what will be placed (not `[e]`, for example). 885 2: if `E` is a non $(empty) `InputRange`, then placing `e` is 886 guaranteed to not overflow the range. 887 +/ 888 package(std) enum bool isNativeOutputRange(R, E) = 889 is(typeof(doPut(lvalueOf!R, lvalueOf!E))); 890 891 @safe unittest 892 { 893 int[] r = new int[](4); 894 static assert(isInputRange!(int[])); 895 static assert( isNativeOutputRange!(int[], int)); 896 static assert(!isNativeOutputRange!(int[], int[])); 897 static assert( isOutputRange!(int[], int[])); 898 899 if (!r.empty) 900 put(r, 1); //guaranteed to succeed 901 if (!r.empty) 902 put(r, [1, 2]); //May actually error out. 903 } 904 905 /++ 906 Returns `true` if `R` is an output range for elements of type 907 `E`. An output range is defined functionally as a range that 908 supports the operation $(D put(r, e)) as defined above. 909 910 See_Also: 911 The header of $(MREF std,range) for tutorials on ranges. 912 +/ 913 enum bool isOutputRange(R, E) = 914 is(typeof(put(lvalueOf!R, lvalueOf!E))); 915 916 /// 917 @safe unittest 918 { 919 void myprint(scope const(char)[] s) { } 920 static assert(isOutputRange!(typeof(&myprint), char)); 921 922 static assert( isOutputRange!(char[], char)); 923 static assert( isOutputRange!(dchar[], wchar)); 924 static assert( isOutputRange!(dchar[], dchar)); 925 } 926 927 @safe unittest 928 { 929 import std.array; 930 import std.stdio : writeln; 931 932 auto app = appender!string(); 933 string s; 934 static assert( isOutputRange!(Appender!string, string)); 935 static assert( isOutputRange!(Appender!string*, string)); 936 static assert(!isOutputRange!(Appender!string, int)); 937 static assert( isOutputRange!(wchar[], wchar)); 938 static assert( isOutputRange!(dchar[], char)); 939 static assert( isOutputRange!(dchar[], string)); 940 static assert( isOutputRange!(dchar[], wstring)); 941 static assert( isOutputRange!(dchar[], dstring)); 942 943 static assert(!isOutputRange!(const(int)[], int)); 944 static assert(!isOutputRange!(inout(int)[], int)); 945 } 946 947 948 /** 949 Returns `true` if `R` is a forward range. A forward range is an 950 input range `r` that can save "checkpoints" by saving `r.save` 951 to another value of type `R`. Notable examples of input ranges that 952 are $(I not) forward ranges are file/socket ranges; copying such a 953 range will not save the position in the stream, and they most likely 954 reuse an internal buffer as the entire stream does not sit in 955 memory. Subsequently, advancing either the original or the copy will 956 advance the stream, so the copies are not independent. 957 958 The following code should compile for any forward range. 959 960 ---- 961 static assert(isInputRange!R); 962 R r1; 963 auto s1 = r1.save; 964 static assert(is(typeof(s1) == R)); 965 ---- 966 967 Saving a range is not duplicating it; in the example above, `r1` 968 and `r2` still refer to the same underlying data. They just 969 navigate that data independently. 970 971 The semantics of a forward range (not checkable during compilation) 972 are the same as for an input range, with the additional requirement 973 that backtracking must be possible by saving a copy of the range 974 object with `save` and using it later. 975 976 `save` behaves in many ways like a copy constructor, and its 977 implementation typically is done using copy construction. 978 979 The existence of a copy constructor, however, does not imply 980 the range is a forward range. For example, a range that reads 981 from a TTY consumes its input and cannot save its place and 982 read it again, and so cannot be a forward range and cannot 983 have a `save` function. 984 985 986 See_Also: 987 The header of $(MREF std,range) for tutorials on ranges. 988 */ 989 enum bool isForwardRange(R) = isInputRange!R 990 && is(ReturnType!((R r) => r.save) == R); 991 992 /// 993 @safe unittest 994 { 995 static assert(!isForwardRange!(int)); 996 static assert( isForwardRange!(int[])); 997 static assert( isForwardRange!(inout(int)[])); 998 } 999 1000 @safe unittest 1001 { 1002 // BUG 14544 1003 struct R14544 1004 { 1005 int front() { return 0;} 1006 void popFront() {} 1007 bool empty() { return false; } 1008 R14544 save() {return this;} 1009 } 1010 1011 static assert( isForwardRange!R14544 ); 1012 } 1013 1014 /** 1015 Returns `true` if `R` is a bidirectional range. A bidirectional 1016 range is a forward range that also offers the primitives `back` and 1017 `popBack`. The following code should compile for any bidirectional 1018 range. 1019 1020 The semantics of a bidirectional range (not checkable during 1021 compilation) are assumed to be the following (`r` is an object of 1022 type `R`): 1023 1024 $(UL $(LI `r.back` returns (possibly a reference to) the last 1025 element in the range. Calling `r.back` is allowed only if calling 1026 `r.empty` has, or would have, returned `false`.)) 1027 1028 See_Also: 1029 The header of $(MREF std,range) for tutorials on ranges. 1030 */ 1031 enum bool isBidirectionalRange(R) = isForwardRange!R 1032 && is(typeof((R r) => r.popBack)) 1033 && is(ReturnType!((R r) => r.back) == ElementType!R); 1034 1035 /// 1036 @safe unittest 1037 { 1038 alias R = int[]; 1039 R r = [0,1]; 1040 static assert(isForwardRange!R); // is forward range 1041 r.popBack(); // can invoke popBack 1042 auto t = r.back; // can get the back of the range 1043 auto w = r.front; 1044 static assert(is(typeof(t) == typeof(w))); // same type for front and back 1045 } 1046 1047 @safe unittest 1048 { 1049 struct A {} 1050 struct B 1051 { 1052 void popFront(); 1053 @property bool empty(); 1054 @property int front(); 1055 } 1056 struct C 1057 { 1058 @property bool empty(); 1059 @property C save(); 1060 void popFront(); 1061 @property int front(); 1062 void popBack(); 1063 @property int back(); 1064 } 1065 static assert(!isBidirectionalRange!(A)); 1066 static assert(!isBidirectionalRange!(B)); 1067 static assert( isBidirectionalRange!(C)); 1068 static assert( isBidirectionalRange!(int[])); 1069 static assert( isBidirectionalRange!(char[])); 1070 static assert( isBidirectionalRange!(inout(int)[])); 1071 } 1072 1073 /** 1074 Returns `true` if `R` is a random-access range. A random-access 1075 range is a bidirectional range that also offers the primitive $(D 1076 opIndex), OR an infinite forward range that offers `opIndex`. In 1077 either case, the range must either offer `length` or be 1078 infinite. The following code should compile for any random-access 1079 range. 1080 1081 The semantics of a random-access range (not checkable during 1082 compilation) are assumed to be the following (`r` is an object of 1083 type `R`): $(UL $(LI `r.opIndex(n)` returns a reference to the 1084 `n`th element in the range.)) 1085 1086 Although `char[]` and `wchar[]` (as well as their qualified 1087 versions including `string` and `wstring`) are arrays, $(D 1088 isRandomAccessRange) yields `false` for them because they use 1089 variable-length encodings (UTF-8 and UTF-16 respectively). These types 1090 are bidirectional ranges only. 1091 1092 See_Also: 1093 The header of $(MREF std,range) for tutorials on ranges. 1094 */ 1095 enum bool isRandomAccessRange(R) = 1096 is(typeof(lvalueOf!R[1]) == ElementType!R) 1097 && !(isAutodecodableString!R && !isAggregateType!R) 1098 && isForwardRange!R 1099 && (isBidirectionalRange!R || isInfinite!R) 1100 && (hasLength!R || isInfinite!R) 1101 && (isInfinite!R || !is(typeof(lvalueOf!R[$ - 1])) 1102 || is(typeof(lvalueOf!R[$ - 1]) == ElementType!R)); 1103 1104 /// 1105 @safe unittest 1106 { 1107 import std.traits : isAggregateType, isAutodecodableString; 1108 1109 alias R = int[]; 1110 1111 // range is finite and bidirectional or infinite and forward. 1112 static assert(isBidirectionalRange!R || 1113 isForwardRange!R && isInfinite!R); 1114 1115 R r = [0,1]; 1116 auto e = r[1]; // can index 1117 auto f = r.front; 1118 static assert(is(typeof(e) == typeof(f))); // same type for indexed and front 1119 static assert(!(isAutodecodableString!R && !isAggregateType!R)); // narrow strings cannot be indexed as ranges 1120 static assert(hasLength!R || isInfinite!R); // must have length or be infinite 1121 1122 // $ must work as it does with arrays if opIndex works with $ 1123 static if (is(typeof(r[$]))) 1124 { 1125 static assert(is(typeof(f) == typeof(r[$]))); 1126 1127 // $ - 1 doesn't make sense with infinite ranges but needs to work 1128 // with finite ones. 1129 static if (!isInfinite!R) 1130 static assert(is(typeof(f) == typeof(r[$ - 1]))); 1131 } 1132 } 1133 1134 @safe unittest 1135 { 1136 struct A {} 1137 struct B 1138 { 1139 void popFront(); 1140 @property bool empty(); 1141 @property int front(); 1142 } 1143 struct C 1144 { 1145 void popFront(); 1146 @property bool empty(); 1147 @property int front(); 1148 void popBack(); 1149 @property int back(); 1150 } 1151 struct D 1152 { 1153 @property bool empty(); 1154 @property D save(); 1155 @property int front(); 1156 void popFront(); 1157 @property int back(); 1158 void popBack(); 1159 ref int opIndex(uint); 1160 @property size_t length(); 1161 alias opDollar = length; 1162 //int opSlice(uint, uint); 1163 } 1164 struct E 1165 { 1166 bool empty(); 1167 E save(); 1168 int front(); 1169 void popFront(); 1170 int back(); 1171 void popBack(); 1172 ref int opIndex(uint); 1173 size_t length(); 1174 alias opDollar = length; 1175 //int opSlice(uint, uint); 1176 } 1177 static assert(!isRandomAccessRange!(A)); 1178 static assert(!isRandomAccessRange!(B)); 1179 static assert(!isRandomAccessRange!(C)); 1180 static assert( isRandomAccessRange!(D)); 1181 static assert( isRandomAccessRange!(E)); 1182 static assert( isRandomAccessRange!(int[])); 1183 static assert( isRandomAccessRange!(inout(int)[])); 1184 } 1185 1186 @safe unittest 1187 { 1188 // Test fix for bug 6935. 1189 struct R 1190 { 1191 @disable this(); 1192 1193 @property bool empty() const { return false; } 1194 @property int front() const { return 0; } 1195 void popFront() {} 1196 1197 @property R save() { return this; } 1198 1199 @property int back() const { return 0; } 1200 void popBack(){} 1201 1202 int opIndex(size_t n) const { return 0; } 1203 @property size_t length() const { return 0; } 1204 alias opDollar = length; 1205 1206 void put(int e){ } 1207 } 1208 static assert(isInputRange!R); 1209 static assert(isForwardRange!R); 1210 static assert(isBidirectionalRange!R); 1211 static assert(isRandomAccessRange!R); 1212 static assert(isOutputRange!(R, int)); 1213 } 1214 1215 /** 1216 Returns `true` iff `R` is an input range that supports the 1217 `moveFront` primitive, as well as `moveBack` and `moveAt` if it's a 1218 bidirectional or random access range. These may be explicitly implemented, or 1219 may work via the default behavior of the module level functions `moveFront` 1220 and friends. The following code should compile for any range 1221 with mobile elements. 1222 1223 ---- 1224 alias E = ElementType!R; 1225 R r; 1226 static assert(isInputRange!R); 1227 static assert(is(typeof(moveFront(r)) == E)); 1228 static if (isBidirectionalRange!R) 1229 static assert(is(typeof(moveBack(r)) == E)); 1230 static if (isRandomAccessRange!R) 1231 static assert(is(typeof(moveAt(r, 0)) == E)); 1232 ---- 1233 */ 1234 enum bool hasMobileElements(R) = 1235 isInputRange!R 1236 && is(typeof(moveFront(lvalueOf!R)) == ElementType!R) 1237 && (!isBidirectionalRange!R 1238 || is(typeof(moveBack(lvalueOf!R)) == ElementType!R)) 1239 && (!isRandomAccessRange!R 1240 || is(typeof(moveAt(lvalueOf!R, 0)) == ElementType!R)); 1241 1242 /// 1243 @safe unittest 1244 { 1245 import std.algorithm.iteration : map; 1246 import std.range : iota, repeat; 1247 1248 static struct HasPostblit 1249 { 1250 this(this) {} 1251 } 1252 1253 auto nonMobile = map!"a"(repeat(HasPostblit.init)); 1254 static assert(!hasMobileElements!(typeof(nonMobile))); 1255 static assert( hasMobileElements!(int[])); 1256 static assert( hasMobileElements!(inout(int)[])); 1257 static assert( hasMobileElements!(typeof(iota(1000)))); 1258 1259 static assert( hasMobileElements!( string)); 1260 static assert( hasMobileElements!(dstring)); 1261 static assert( hasMobileElements!( char[])); 1262 static assert( hasMobileElements!(dchar[])); 1263 } 1264 1265 /** 1266 The element type of `R`. `R` does not have to be a range. The 1267 element type is determined as the type yielded by `r.front` for an 1268 object `r` of type `R`. For example, `ElementType!(T[])` is 1269 `T` if `T[]` isn't a narrow string; if it is, the element type is 1270 `dchar`. If `R` doesn't have `front`, `ElementType!R` is 1271 `void`. 1272 */ 1273 template ElementType(R) 1274 { 1275 static if (is(typeof(R.init.front.init) T)) 1276 alias ElementType = T; 1277 else 1278 alias ElementType = void; 1279 } 1280 1281 /// 1282 @safe unittest 1283 { 1284 import std.range : iota; 1285 1286 // Standard arrays: returns the type of the elements of the array 1287 static assert(is(ElementType!(int[]) == int)); 1288 1289 // Accessing .front retrieves the decoded dchar 1290 static assert(is(ElementType!(char[]) == dchar)); // rvalue 1291 static assert(is(ElementType!(dchar[]) == dchar)); // lvalue 1292 1293 // Ditto 1294 static assert(is(ElementType!(string) == dchar)); 1295 static assert(is(ElementType!(dstring) == immutable(dchar))); 1296 1297 // For ranges it gets the type of .front. 1298 auto range = iota(0, 10); 1299 static assert(is(ElementType!(typeof(range)) == int)); 1300 } 1301 1302 @safe unittest 1303 { 1304 static assert(is(ElementType!(byte[]) == byte)); 1305 static assert(is(ElementType!(wchar[]) == dchar)); // rvalue 1306 static assert(is(ElementType!(wstring) == dchar)); 1307 } 1308 1309 @safe unittest 1310 { 1311 enum XYZ : string { a = "foo" } 1312 auto x = XYZ.a.front; 1313 immutable char[3] a = "abc"; 1314 int[] i; 1315 void[] buf; 1316 static assert(is(ElementType!(XYZ) == dchar)); 1317 static assert(is(ElementType!(typeof(a)) == dchar)); 1318 static assert(is(ElementType!(typeof(i)) == int)); 1319 static assert(is(ElementType!(typeof(buf)) == void)); 1320 static assert(is(ElementType!(inout(int)[]) == inout(int))); 1321 static assert(is(ElementType!(inout(int[])) == inout(int))); 1322 } 1323 1324 @safe unittest 1325 { 1326 static assert(is(ElementType!(int[5]) == int)); 1327 static assert(is(ElementType!(int[0]) == int)); 1328 static assert(is(ElementType!(char[5]) == dchar)); 1329 static assert(is(ElementType!(char[0]) == dchar)); 1330 } 1331 1332 // https://issues.dlang.org/show_bug.cgi?id=11336 1333 @safe unittest 1334 { 1335 static struct S 1336 { 1337 this(this) @disable; 1338 } 1339 static assert(is(ElementType!(S[]) == S)); 1340 } 1341 1342 // https://issues.dlang.org/show_bug.cgi?id=11401 1343 @safe unittest 1344 { 1345 // ElementType should also work for non-@propety 'front' 1346 struct E { ushort id; } 1347 struct R 1348 { 1349 E front() { return E.init; } 1350 } 1351 static assert(is(ElementType!R == E)); 1352 } 1353 1354 /** 1355 The encoding element type of `R`. For narrow strings (`char[]`, 1356 `wchar[]` and their qualified variants including `string` and 1357 `wstring`), `ElementEncodingType` is the character type of the 1358 string. For all other types, `ElementEncodingType` is the same as 1359 `ElementType`. 1360 */ 1361 template ElementEncodingType(R) 1362 { 1363 static if (is(StringTypeOf!R) && is(R : E[], E)) 1364 alias ElementEncodingType = E; 1365 else 1366 alias ElementEncodingType = ElementType!R; 1367 } 1368 1369 /// 1370 @safe unittest 1371 { 1372 import std.range : iota; 1373 // internally the range stores the encoded type 1374 static assert(is(ElementEncodingType!(char[]) == char)); 1375 1376 static assert(is(ElementEncodingType!(wstring) == immutable(wchar))); 1377 1378 static assert(is(ElementEncodingType!(byte[]) == byte)); 1379 1380 auto range = iota(0, 10); 1381 static assert(is(ElementEncodingType!(typeof(range)) == int)); 1382 } 1383 1384 @safe unittest 1385 { 1386 static assert(is(ElementEncodingType!(wchar[]) == wchar)); 1387 static assert(is(ElementEncodingType!(dchar[]) == dchar)); 1388 static assert(is(ElementEncodingType!(string) == immutable(char))); 1389 static assert(is(ElementEncodingType!(dstring) == immutable(dchar))); 1390 static assert(is(ElementEncodingType!(int[]) == int)); 1391 } 1392 1393 @safe unittest 1394 { 1395 enum XYZ : string { a = "foo" } 1396 auto x = XYZ.a.front; 1397 immutable char[3] a = "abc"; 1398 int[] i; 1399 void[] buf; 1400 static assert(is(ElementType!(XYZ) : dchar)); 1401 static assert(is(ElementEncodingType!(char[]) == char)); 1402 static assert(is(ElementEncodingType!(string) == immutable char)); 1403 static assert(is(ElementType!(typeof(a)) : dchar)); 1404 static assert(is(ElementType!(typeof(i)) == int)); 1405 static assert(is(ElementEncodingType!(typeof(i)) == int)); 1406 static assert(is(ElementType!(typeof(buf)) : void)); 1407 1408 static assert(is(ElementEncodingType!(inout char[]) : inout(char))); 1409 } 1410 1411 @safe unittest 1412 { 1413 static assert(is(ElementEncodingType!(int[5]) == int)); 1414 static assert(is(ElementEncodingType!(int[0]) == int)); 1415 static assert(is(ElementEncodingType!(char[5]) == char)); 1416 static assert(is(ElementEncodingType!(char[0]) == char)); 1417 } 1418 1419 /** 1420 Returns `true` if `R` is an input range and has swappable 1421 elements. The following code should compile for any range 1422 with swappable elements. 1423 1424 ---- 1425 R r; 1426 static assert(isInputRange!R); 1427 swap(r.front, r.front); 1428 static if (isBidirectionalRange!R) swap(r.back, r.front); 1429 static if (isRandomAccessRange!R) swap(r[0], r.front); 1430 ---- 1431 */ 1432 template hasSwappableElements(R) 1433 { 1434 import std.algorithm.mutation : swap; 1435 enum bool hasSwappableElements = isInputRange!R 1436 && is(typeof((ref R r) => swap(r.front, r.front))) 1437 && (!isBidirectionalRange!R 1438 || is(typeof((ref R r) => swap(r.back, r.front)))) 1439 && (!isRandomAccessRange!R 1440 || is(typeof((ref R r) => swap(r[0], r.front)))); 1441 } 1442 1443 /// 1444 @safe unittest 1445 { 1446 static assert(!hasSwappableElements!(const int[])); 1447 static assert(!hasSwappableElements!(const(int)[])); 1448 static assert(!hasSwappableElements!(inout(int)[])); 1449 static assert( hasSwappableElements!(int[])); 1450 1451 static assert(!hasSwappableElements!( string)); 1452 static assert(!hasSwappableElements!(dstring)); 1453 static assert(!hasSwappableElements!( char[])); 1454 static assert( hasSwappableElements!(dchar[])); 1455 } 1456 1457 /** 1458 Returns `true` if `R` is an input range and has mutable 1459 elements. The following code should compile for any range 1460 with assignable elements. 1461 1462 ---- 1463 R r; 1464 static assert(isInputRange!R); 1465 r.front = r.front; 1466 static if (isBidirectionalRange!R) r.back = r.front; 1467 static if (isRandomAccessRange!R) r[0] = r.front; 1468 ---- 1469 */ 1470 enum bool hasAssignableElements(R) = isInputRange!R 1471 && is(typeof(lvalueOf!R.front = lvalueOf!R.front)) 1472 && (!isBidirectionalRange!R 1473 || is(typeof(lvalueOf!R.back = lvalueOf!R.back))) 1474 && (!isRandomAccessRange!R 1475 || is(typeof(lvalueOf!R[0] = lvalueOf!R.front))); 1476 1477 /// 1478 @safe unittest 1479 { 1480 static assert(!hasAssignableElements!(const int[])); 1481 static assert(!hasAssignableElements!(const(int)[])); 1482 static assert( hasAssignableElements!(int[])); 1483 static assert(!hasAssignableElements!(inout(int)[])); 1484 1485 static assert(!hasAssignableElements!( string)); 1486 static assert(!hasAssignableElements!(dstring)); 1487 static assert(!hasAssignableElements!( char[])); 1488 static assert( hasAssignableElements!(dchar[])); 1489 } 1490 1491 /** 1492 Tests whether the range `R` has lvalue elements. These are defined as 1493 elements that can be passed by reference and have their address taken. 1494 The following code should compile for any range with lvalue elements. 1495 ---- 1496 void passByRef(ref ElementType!R stuff); 1497 ... 1498 static assert(isInputRange!R); 1499 passByRef(r.front); 1500 static if (isBidirectionalRange!R) passByRef(r.back); 1501 static if (isRandomAccessRange!R) passByRef(r[0]); 1502 ---- 1503 */ 1504 enum bool hasLvalueElements(R) = isInputRange!R 1505 && is(typeof(isLvalue(lvalueOf!R.front))) 1506 && (!isBidirectionalRange!R 1507 || is(typeof(isLvalue(lvalueOf!R.back)))) 1508 && (!isRandomAccessRange!R 1509 || is(typeof(isLvalue(lvalueOf!R[0])))); 1510 1511 /* Compile successfully if argument of type T is an lvalue 1512 */ 1513 private void isLvalue(T)(T) 1514 if (0); 1515 1516 private void isLvalue(T)(ref T) 1517 if (1); 1518 1519 /// 1520 @safe unittest 1521 { 1522 import std.range : iota, chain; 1523 1524 static assert( hasLvalueElements!(int[])); 1525 static assert( hasLvalueElements!(const(int)[])); 1526 static assert( hasLvalueElements!(inout(int)[])); 1527 static assert( hasLvalueElements!(immutable(int)[])); 1528 static assert(!hasLvalueElements!(typeof(iota(3)))); 1529 1530 static assert(!hasLvalueElements!( string)); 1531 static assert( hasLvalueElements!(dstring)); 1532 static assert(!hasLvalueElements!( char[])); 1533 static assert( hasLvalueElements!(dchar[])); 1534 1535 auto c = chain([1, 2, 3], [4, 5, 6]); 1536 static assert( hasLvalueElements!(typeof(c))); 1537 } 1538 1539 @safe unittest 1540 { 1541 // bugfix 6336 1542 struct S { immutable int value; } 1543 static assert( isInputRange!(S[])); 1544 static assert( hasLvalueElements!(S[])); 1545 } 1546 1547 /** 1548 Yields `true` if `R` has a `length` member that returns a value of `size_t` 1549 type. `R` does not have to be a range. If `R` is a range, algorithms in the 1550 standard library are only guaranteed to support `length` with type `size_t`. 1551 1552 Note that `length` is an optional primitive as no range must implement it. Some 1553 ranges do not store their length explicitly, some cannot compute it without 1554 actually exhausting the range (e.g. socket streams), and some other ranges may 1555 be infinite. 1556 1557 Although narrow string types (`char[]`, `wchar[]`, and their qualified 1558 derivatives) do define a `length` property, `hasLength` yields `false` for them. 1559 This is because a narrow string's length does not reflect the number of 1560 characters, but instead the number of encoding units, and as such is not useful 1561 with range-oriented algorithms. To use strings as random-access ranges with 1562 length, use $(REF representation, std, string) or $(REF byCodeUnit, std, utf). 1563 */ 1564 template hasLength(R) 1565 { 1566 static if (is(typeof(((R* r) => r.length)(null)) Length)) 1567 enum bool hasLength = is(Length == size_t) && 1568 !(isAutodecodableString!R && !isAggregateType!R); 1569 else 1570 enum bool hasLength = false; 1571 } 1572 1573 /// 1574 @safe unittest 1575 { 1576 static assert(!hasLength!(char[])); 1577 static assert( hasLength!(int[])); 1578 static assert( hasLength!(inout(int)[])); 1579 1580 struct A { size_t length() { return 0; } } 1581 struct B { @property size_t length() { return 0; } } 1582 static assert( hasLength!(A)); 1583 static assert( hasLength!(B)); 1584 } 1585 1586 // test combinations which are invalid on some platforms 1587 @safe unittest 1588 { 1589 struct A { ulong length; } 1590 struct B { @property uint length() { return 0; } } 1591 1592 static if (is(size_t == uint)) 1593 { 1594 static assert(!hasLength!(A)); 1595 static assert(hasLength!(B)); 1596 } 1597 else static if (is(size_t == ulong)) 1598 { 1599 static assert(hasLength!(A)); 1600 static assert(!hasLength!(B)); 1601 } 1602 } 1603 1604 // test combinations which are invalid on all platforms 1605 @safe unittest 1606 { 1607 struct A { long length; } 1608 struct B { int length; } 1609 struct C { ubyte length; } 1610 struct D { char length; } 1611 static assert(!hasLength!(A)); 1612 static assert(!hasLength!(B)); 1613 static assert(!hasLength!(C)); 1614 static assert(!hasLength!(D)); 1615 } 1616 1617 /** 1618 Returns `true` if `R` is an infinite input range. An 1619 infinite input range is an input range that has a statically-defined 1620 enumerated member called `empty` that is always `false`, 1621 for example: 1622 1623 ---- 1624 struct MyInfiniteRange 1625 { 1626 enum bool empty = false; 1627 ... 1628 } 1629 ---- 1630 */ 1631 1632 template isInfinite(R) 1633 { 1634 static if (isInputRange!R && __traits(compiles, { enum e = R.empty; })) 1635 enum bool isInfinite = !R.empty; 1636 else 1637 enum bool isInfinite = false; 1638 } 1639 1640 /// 1641 @safe unittest 1642 { 1643 import std.range : Repeat; 1644 static assert(!isInfinite!(int[])); 1645 static assert( isInfinite!(Repeat!(int))); 1646 } 1647 1648 /** 1649 Returns `true` if `R` offers a slicing operator with integral boundaries 1650 that returns a forward range type. 1651 1652 For finite ranges, the result of `opSlice` must be of the same type as the 1653 original range type. If the range defines `opDollar`, then it must support 1654 subtraction. 1655 1656 For infinite ranges, when $(I not) using `opDollar`, the result of 1657 `opSlice` must be the result of $(LREF take) or $(LREF takeExactly) on the 1658 original range (they both return the same type for infinite ranges). However, 1659 when using `opDollar`, the result of `opSlice` must be that of the 1660 original range type. 1661 1662 The following expression must be true for `hasSlicing` to be `true`: 1663 1664 ---- 1665 isForwardRange!R 1666 && !isNarrowString!R 1667 && is(ReturnType!((R r) => r[1 .. 1].length) == size_t) 1668 && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R) 1669 && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R)) 1670 && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R 1671 || is(typeof(lvalueOf!R[0 .. $ - 1]) == R)) 1672 && is(typeof((ref R r) 1673 { 1674 static assert(isForwardRange!(typeof(r[1 .. 2]))); 1675 })); 1676 ---- 1677 */ 1678 enum bool hasSlicing(R) = isForwardRange!R 1679 && !(isAutodecodableString!R && !isAggregateType!R) 1680 && is(ReturnType!((R r) => r[1 .. 1].length) == size_t) 1681 && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R) 1682 && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R)) 1683 && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R 1684 || is(typeof(lvalueOf!R[0 .. $ - 1]) == R)) 1685 && is(typeof((ref R r) 1686 { 1687 static assert(isForwardRange!(typeof(r[1 .. 2]))); 1688 })); 1689 1690 /// 1691 @safe unittest 1692 { 1693 import std.range : takeExactly; 1694 static assert( hasSlicing!(int[])); 1695 static assert( hasSlicing!(const(int)[])); 1696 static assert(!hasSlicing!(const int[])); 1697 static assert( hasSlicing!(inout(int)[])); 1698 static assert(!hasSlicing!(inout int [])); 1699 static assert( hasSlicing!(immutable(int)[])); 1700 static assert(!hasSlicing!(immutable int[])); 1701 static assert(!hasSlicing!string); 1702 static assert( hasSlicing!dstring); 1703 1704 enum rangeFuncs = "@property int front();" ~ 1705 "void popFront();" ~ 1706 "@property bool empty();" ~ 1707 "@property auto save() { return this; }" ~ 1708 "@property size_t length();"; 1709 1710 struct A { mixin(rangeFuncs); int opSlice(size_t, size_t); } 1711 struct B { mixin(rangeFuncs); B opSlice(size_t, size_t); } 1712 struct C { mixin(rangeFuncs); @disable this(); C opSlice(size_t, size_t); } 1713 struct D { mixin(rangeFuncs); int[] opSlice(size_t, size_t); } 1714 static assert(!hasSlicing!(A)); 1715 static assert( hasSlicing!(B)); 1716 static assert( hasSlicing!(C)); 1717 static assert(!hasSlicing!(D)); 1718 1719 struct InfOnes 1720 { 1721 enum empty = false; 1722 void popFront() {} 1723 @property int front() { return 1; } 1724 @property InfOnes save() { return this; } 1725 auto opSlice(size_t i, size_t j) { return takeExactly(this, j - i); } 1726 auto opSlice(size_t i, Dollar d) { return this; } 1727 1728 struct Dollar {} 1729 Dollar opDollar() const { return Dollar.init; } 1730 } 1731 1732 static assert(hasSlicing!InfOnes); 1733 } 1734 1735 /** 1736 This is a best-effort implementation of `length` for any kind of 1737 range. 1738 1739 If `hasLength!Range`, simply returns `range.length` without 1740 checking `upTo` (when specified). 1741 1742 Otherwise, walks the range through its length and returns the number 1743 of elements seen. Performes $(BIGOH n) evaluations of `range.empty` 1744 and `range.popFront()`, where `n` is the effective length of $(D 1745 range). 1746 1747 The `upTo` parameter is useful to "cut the losses" in case 1748 the interest is in seeing whether the range has at least some number 1749 of elements. If the parameter `upTo` is specified, stops if $(D 1750 upTo) steps have been taken and returns `upTo`. 1751 1752 Infinite ranges are compatible, provided the parameter `upTo` is 1753 specified, in which case the implementation simply returns upTo. 1754 */ 1755 auto walkLength(Range)(Range range) 1756 if (isInputRange!Range && !isInfinite!Range) 1757 { 1758 static if (hasLength!Range) 1759 return range.length; 1760 else 1761 { 1762 size_t result; 1763 static if (autodecodeStrings && isNarrowString!Range) 1764 { 1765 import std.utf : codeUnitLimit; 1766 result = range.length; 1767 foreach (const i, const c; range) 1768 { 1769 if (c >= codeUnitLimit!Range) 1770 { 1771 result = i; 1772 break; 1773 } 1774 } 1775 range = range[result .. $]; 1776 } 1777 for ( ; !range.empty ; range.popFront() ) 1778 ++result; 1779 return result; 1780 } 1781 } 1782 /// ditto 1783 auto walkLength(Range)(Range range, const size_t upTo) 1784 if (isInputRange!Range) 1785 { 1786 static if (hasLength!Range) 1787 return range.length; 1788 else static if (isInfinite!Range) 1789 return upTo; 1790 else 1791 { 1792 size_t result; 1793 static if (autodecodeStrings && isNarrowString!Range) 1794 { 1795 import std.utf : codeUnitLimit; 1796 result = upTo > range.length ? range.length : upTo; 1797 foreach (const i, const c; range[0 .. result]) 1798 { 1799 if (c >= codeUnitLimit!Range) 1800 { 1801 result = i; 1802 break; 1803 } 1804 } 1805 range = range[result .. $]; 1806 } 1807 for ( ; result < upTo && !range.empty ; range.popFront() ) 1808 ++result; 1809 return result; 1810 } 1811 } 1812 1813 /// 1814 @safe unittest 1815 { 1816 import std.range : iota; 1817 1818 assert(10.iota.walkLength == 10); 1819 // iota has a length function, and therefore the 1820 // doesn't have to be walked, and the upTo 1821 // parameter is ignored 1822 assert(10.iota.walkLength(5) == 10); 1823 } 1824 1825 @safe unittest 1826 { 1827 import std.algorithm.iteration : filter; 1828 import std.range : recurrence, take; 1829 1830 //hasLength Range 1831 int[] a = [ 1, 2, 3 ]; 1832 assert(walkLength(a) == 3); 1833 assert(walkLength(a, 0) == 3); 1834 assert(walkLength(a, 2) == 3); 1835 assert(walkLength(a, 4) == 3); 1836 1837 //Forward Range 1838 auto b = filter!"true"([1, 2, 3, 4]); 1839 assert(b.walkLength() == 4); 1840 assert(b.walkLength(0) == 0); 1841 assert(b.walkLength(2) == 2); 1842 assert(b.walkLength(4) == 4); 1843 assert(b.walkLength(6) == 4); 1844 1845 //Infinite Range 1846 auto fibs = recurrence!"a[n-1] + a[n-2]"(1, 1); 1847 assert(!__traits(compiles, fibs.walkLength())); 1848 assert(fibs.take(10).walkLength() == 10); 1849 assert(fibs.walkLength(55) == 55); 1850 } 1851 1852 /** 1853 `popFrontN` eagerly advances `r` itself (not a copy) up to `n` times 1854 (by calling `r.popFront`). `popFrontN` takes `r` by `ref`, 1855 so it mutates the original range. Completes in $(BIGOH 1) steps for ranges 1856 that support slicing and have length. 1857 Completes in $(BIGOH n) time for all other ranges. 1858 1859 `popBackN` behaves the same as `popFrontN` but instead removes 1860 elements from the back of the (bidirectional) range instead of the front. 1861 1862 Returns: 1863 How much `r` was actually advanced, which may be less than `n` if 1864 `r` did not have at least `n` elements. 1865 1866 See_Also: $(REF drop, std, range), $(REF dropBack, std, range) 1867 */ 1868 size_t popFrontN(Range)(ref Range r, size_t n) 1869 if (isInputRange!Range) 1870 { 1871 static if (hasLength!Range) 1872 { 1873 n = cast(size_t) (n < r.length ? n : r.length); 1874 } 1875 1876 static if (hasSlicing!Range && is(typeof(r = r[n .. $]))) 1877 { 1878 r = r[n .. $]; 1879 } 1880 else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar. 1881 { 1882 r = r[n .. r.length]; 1883 } 1884 else 1885 { 1886 static if (hasLength!Range) 1887 { 1888 foreach (i; 0 .. n) 1889 r.popFront(); 1890 } 1891 else 1892 { 1893 foreach (i; 0 .. n) 1894 { 1895 if (r.empty) return i; 1896 r.popFront(); 1897 } 1898 } 1899 } 1900 return n; 1901 } 1902 1903 /// ditto 1904 size_t popBackN(Range)(ref Range r, size_t n) 1905 if (isBidirectionalRange!Range) 1906 { 1907 static if (hasLength!Range) 1908 { 1909 n = cast(size_t) (n < r.length ? n : r.length); 1910 } 1911 1912 static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n]))) 1913 { 1914 r = r[0 .. $ - n]; 1915 } 1916 else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar. 1917 { 1918 r = r[0 .. r.length - n]; 1919 } 1920 else 1921 { 1922 static if (hasLength!Range) 1923 { 1924 foreach (i; 0 .. n) 1925 r.popBack(); 1926 } 1927 else 1928 { 1929 foreach (i; 0 .. n) 1930 { 1931 if (r.empty) return i; 1932 r.popBack(); 1933 } 1934 } 1935 } 1936 return n; 1937 } 1938 1939 /// 1940 @safe unittest 1941 { 1942 int[] a = [ 1, 2, 3, 4, 5 ]; 1943 a.popFrontN(2); 1944 assert(a == [ 3, 4, 5 ]); 1945 a.popFrontN(7); 1946 assert(a == [ ]); 1947 } 1948 1949 /// 1950 @safe unittest 1951 { 1952 import std.algorithm.comparison : equal; 1953 import std.range : iota; 1954 auto LL = iota(1L, 7L); 1955 auto r = popFrontN(LL, 2); 1956 assert(equal(LL, [3L, 4L, 5L, 6L])); 1957 assert(r == 2); 1958 } 1959 1960 /// 1961 @safe unittest 1962 { 1963 int[] a = [ 1, 2, 3, 4, 5 ]; 1964 a.popBackN(2); 1965 assert(a == [ 1, 2, 3 ]); 1966 a.popBackN(7); 1967 assert(a == [ ]); 1968 } 1969 1970 /// 1971 @safe unittest 1972 { 1973 import std.algorithm.comparison : equal; 1974 import std.range : iota; 1975 auto LL = iota(1L, 7L); 1976 auto r = popBackN(LL, 2); 1977 assert(equal(LL, [1L, 2L, 3L, 4L])); 1978 assert(r == 2); 1979 } 1980 1981 /** 1982 Eagerly advances `r` itself (not a copy) exactly `n` times (by 1983 calling `r.popFront`). `popFrontExactly` takes `r` by `ref`, 1984 so it mutates the original range. Completes in $(BIGOH 1) steps for ranges 1985 that support slicing, and have either length or are infinite. 1986 Completes in $(BIGOH n) time for all other ranges. 1987 1988 Note: Unlike $(LREF popFrontN), `popFrontExactly` will assume that the 1989 range holds at least `n` elements. This makes `popFrontExactly` 1990 faster than `popFrontN`, but it also means that if `range` does 1991 not contain at least `n` elements, it will attempt to call `popFront` 1992 on an empty range, which is undefined behavior. So, only use 1993 `popFrontExactly` when it is guaranteed that `range` holds at least 1994 `n` elements. 1995 1996 `popBackExactly` will behave the same but instead removes elements from 1997 the back of the (bidirectional) range instead of the front. 1998 1999 See_Also: $(REF dropExactly, std, range), $(REF dropBackExactly, std, range) 2000 */ 2001 void popFrontExactly(Range)(ref Range r, size_t n) 2002 if (isInputRange!Range) 2003 { 2004 static if (hasLength!Range) 2005 assert(n <= r.length, "range is smaller than amount of items to pop"); 2006 2007 static if (hasSlicing!Range && is(typeof(r = r[n .. $]))) 2008 r = r[n .. $]; 2009 else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar. 2010 r = r[n .. r.length]; 2011 else 2012 foreach (i; 0 .. n) 2013 r.popFront(); 2014 } 2015 2016 /// ditto 2017 void popBackExactly(Range)(ref Range r, size_t n) 2018 if (isBidirectionalRange!Range) 2019 { 2020 static if (hasLength!Range) 2021 assert(n <= r.length, "range is smaller than amount of items to pop"); 2022 2023 static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n]))) 2024 r = r[0 .. $ - n]; 2025 else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar. 2026 r = r[0 .. r.length - n]; 2027 else 2028 foreach (i; 0 .. n) 2029 r.popBack(); 2030 } 2031 2032 /// 2033 @safe unittest 2034 { 2035 import std.algorithm.comparison : equal; 2036 import std.algorithm.iteration : filterBidirectional; 2037 2038 auto a = [1, 2, 3]; 2039 a.popFrontExactly(1); 2040 assert(a == [2, 3]); 2041 a.popBackExactly(1); 2042 assert(a == [2]); 2043 2044 string s = "日本語"; 2045 s.popFrontExactly(1); 2046 assert(s == "本語"); 2047 s.popBackExactly(1); 2048 assert(s == "本"); 2049 2050 auto bd = filterBidirectional!"true"([1, 2, 3]); 2051 bd.popFrontExactly(1); 2052 assert(bd.equal([2, 3])); 2053 bd.popBackExactly(1); 2054 assert(bd.equal([2])); 2055 } 2056 2057 /** 2058 Moves the front of `r` out and returns it. 2059 2060 If `r.front` is a struct with a destructor or copy constructor defined, it 2061 is reset to its `.init` value after its value is moved. Otherwise, it is 2062 left unchanged. 2063 2064 In either case, `r.front` is left in a destroyable state that does not 2065 allocate any resources. 2066 */ 2067 ElementType!R moveFront(R)(R r) 2068 { 2069 static if (is(typeof(&r.moveFront))) 2070 { 2071 return r.moveFront(); 2072 } 2073 else static if (!hasElaborateCopyConstructor!(ElementType!R)) 2074 { 2075 return r.front; 2076 } 2077 else static if (is(typeof(&(r.front())) == ElementType!R*)) 2078 { 2079 import std.algorithm.mutation : move; 2080 return move(r.front); 2081 } 2082 else 2083 { 2084 static assert(0, 2085 "Cannot move front of a range with a postblit and an rvalue front."); 2086 } 2087 } 2088 2089 /// 2090 @safe unittest 2091 { 2092 auto a = [ 1, 2, 3 ]; 2093 assert(moveFront(a) == 1); 2094 assert(a.length == 3); 2095 2096 // define a perfunctory input range 2097 struct InputRange 2098 { 2099 enum bool empty = false; 2100 enum int front = 7; 2101 void popFront() {} 2102 int moveFront() { return 43; } 2103 } 2104 InputRange r; 2105 // calls r.moveFront 2106 assert(moveFront(r) == 43); 2107 } 2108 2109 @safe unittest 2110 { 2111 struct R 2112 { 2113 @property ref int front() { static int x = 42; return x; } 2114 this(this){} 2115 } 2116 R r; 2117 assert(moveFront(r) == 42); 2118 } 2119 2120 /** 2121 Moves the back of `r` out and returns it. Leaves `r.back` in a 2122 destroyable state that does not allocate any resources (usually equal 2123 to its `.init` value). 2124 */ 2125 ElementType!R moveBack(R)(R r) 2126 { 2127 static if (is(typeof(&r.moveBack))) 2128 { 2129 return r.moveBack(); 2130 } 2131 else static if (!hasElaborateCopyConstructor!(ElementType!R)) 2132 { 2133 return r.back; 2134 } 2135 else static if (is(typeof(&(r.back())) == ElementType!R*)) 2136 { 2137 import std.algorithm.mutation : move; 2138 return move(r.back); 2139 } 2140 else 2141 { 2142 static assert(0, 2143 "Cannot move back of a range with a postblit and an rvalue back."); 2144 } 2145 } 2146 2147 /// 2148 @safe unittest 2149 { 2150 struct TestRange 2151 { 2152 int payload = 5; 2153 @property bool empty() { return false; } 2154 @property TestRange save() { return this; } 2155 @property ref int front() return { return payload; } 2156 @property ref int back() return { return payload; } 2157 void popFront() { } 2158 void popBack() { } 2159 } 2160 static assert(isBidirectionalRange!TestRange); 2161 TestRange r; 2162 auto x = moveBack(r); 2163 assert(x == 5); 2164 } 2165 2166 /** 2167 Moves element at index `i` of `r` out and returns it. Leaves $(D 2168 r[i]) in a destroyable state that does not allocate any resources 2169 (usually equal to its `.init` value). 2170 */ 2171 ElementType!R moveAt(R)(R r, size_t i) 2172 { 2173 static if (is(typeof(&r.moveAt))) 2174 { 2175 return r.moveAt(i); 2176 } 2177 else static if (!hasElaborateCopyConstructor!(ElementType!(R))) 2178 { 2179 return r[i]; 2180 } 2181 else static if (is(typeof(&r[i]) == ElementType!R*)) 2182 { 2183 import std.algorithm.mutation : move; 2184 return move(r[i]); 2185 } 2186 else 2187 { 2188 static assert(0, 2189 "Cannot move element of a range with a postblit and rvalue elements."); 2190 } 2191 } 2192 2193 /// 2194 @safe unittest 2195 { 2196 auto a = [1,2,3,4]; 2197 foreach (idx, it; a) 2198 { 2199 assert(it == moveAt(a, idx)); 2200 } 2201 } 2202 2203 @safe unittest 2204 { 2205 import std.internal.test.dummyrange; 2206 2207 foreach (DummyType; AllDummyRanges) 2208 { 2209 auto d = DummyType.init; 2210 assert(moveFront(d) == 1); 2211 2212 static if (isBidirectionalRange!DummyType) 2213 { 2214 assert(moveBack(d) == 10); 2215 } 2216 2217 static if (isRandomAccessRange!DummyType) 2218 { 2219 assert(moveAt(d, 2) == 3); 2220 } 2221 } 2222 } 2223 2224 /** 2225 Implements the range interface primitive `empty` for types that 2226 obey $(LREF hasLength) property and for narrow strings. Due to the 2227 fact that nonmember functions can be called with the first argument 2228 using the dot notation, `a.empty` is equivalent to `empty(a)`. 2229 */ 2230 @property bool empty(T)(auto ref scope T a) 2231 if (is(typeof(a.length) : size_t)) 2232 { 2233 return !a.length; 2234 } 2235 2236 /// 2237 @safe pure nothrow unittest 2238 { 2239 auto a = [ 1, 2, 3 ]; 2240 assert(!a.empty); 2241 assert(a[3 .. $].empty); 2242 2243 int[string] b; 2244 assert(b.empty); 2245 b["zero"] = 0; 2246 assert(!b.empty); 2247 } 2248 2249 /** 2250 Implements the range interface primitive `save` for built-in 2251 arrays. Due to the fact that nonmember functions can be called with 2252 the first argument using the dot notation, `array.save` is 2253 equivalent to `save(array)`. The function does not duplicate the 2254 content of the array, it simply returns its argument. 2255 */ 2256 @property inout(T)[] save(T)(return scope inout(T)[] a) @safe pure nothrow @nogc 2257 { 2258 return a; 2259 } 2260 2261 /// 2262 @safe pure nothrow unittest 2263 { 2264 auto a = [ 1, 2, 3 ]; 2265 auto b = a.save; 2266 assert(b is a); 2267 } 2268 2269 /** 2270 Implements the range interface primitive `popFront` for built-in 2271 arrays. Due to the fact that nonmember functions can be called with 2272 the first argument using the dot notation, `array.popFront` is 2273 equivalent to `popFront(array)`. For $(GLOSSARY narrow strings), 2274 `popFront` automatically advances to the next $(GLOSSARY code 2275 point). 2276 */ 2277 void popFront(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc 2278 if (!isAutodecodableString!(T[]) && !is(T[] == void[])) 2279 { 2280 assert(a.length, "Attempting to popFront() past the end of an array of " ~ T.stringof); 2281 a = a[1 .. $]; 2282 } 2283 2284 /// 2285 @safe pure nothrow unittest 2286 { 2287 auto a = [ 1, 2, 3 ]; 2288 a.popFront(); 2289 assert(a == [ 2, 3 ]); 2290 } 2291 2292 @safe unittest 2293 { 2294 static assert(!is(typeof({ int[4] a; popFront(a); }))); 2295 static assert(!is(typeof({ immutable int[] a; popFront(a); }))); 2296 static assert(!is(typeof({ void[] a; popFront(a); }))); 2297 } 2298 2299 /// ditto 2300 void popFront(C)(scope ref inout(C)[] str) @trusted pure nothrow 2301 if (isAutodecodableString!(C[])) 2302 { 2303 import std.algorithm.comparison : min; 2304 2305 assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof); 2306 2307 static if (is(immutable C == immutable char)) 2308 { 2309 static immutable ubyte[] charWidthTab = [ 2310 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2311 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2312 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2313 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 2314 ]; 2315 2316 immutable c = str[0]; 2317 immutable charWidth = c < 192 ? 1 : charWidthTab.ptr[c - 192]; 2318 str = str.ptr[min(str.length, charWidth) .. str.length]; 2319 } 2320 else static if (is(immutable C == immutable wchar)) 2321 { 2322 immutable u = str[0]; 2323 immutable seqLen = 1 + (u >= 0xD800 && u <= 0xDBFF); 2324 str = str.ptr[min(seqLen, str.length) .. str.length]; 2325 } 2326 else static assert(0, "Bad template constraint."); 2327 } 2328 2329 @safe pure unittest 2330 { 2331 import std.meta : AliasSeq; 2332 2333 static foreach (S; AliasSeq!(string, wstring, dstring)) 2334 {{ 2335 S s = "\xC2\xA9hello"; 2336 s.popFront(); 2337 assert(s == "hello"); 2338 2339 S str = "hello\U00010143\u0100\U00010143"; 2340 foreach (dchar c; ['h', 'e', 'l', 'l', 'o', '\U00010143', '\u0100', '\U00010143']) 2341 { 2342 assert(str.front == c); 2343 str.popFront(); 2344 } 2345 assert(str.empty); 2346 2347 static assert(!is(typeof({ immutable S a; popFront(a); }))); 2348 static assert(!is(typeof({ typeof(S.init[0])[4] a; popFront(a); }))); 2349 }} 2350 2351 C[] _eatString(C)(C[] str) 2352 { 2353 while (!str.empty) 2354 str.popFront(); 2355 2356 return str; 2357 } 2358 enum checkCTFE = _eatString("ウェブサイト@La_Verité.com"); 2359 static assert(checkCTFE.empty); 2360 enum checkCTFEW = _eatString("ウェブサイト@La_Verité.com"w); 2361 static assert(checkCTFEW.empty); 2362 } 2363 2364 // https://issues.dlang.org/show_bug.cgi?id=16090 2365 @safe unittest 2366 { 2367 string s = "\u00E4"; 2368 assert(s.length == 2); 2369 s = s[0 .. 1]; 2370 assert(s.length == 1); 2371 s.popFront; 2372 assert(s.empty); 2373 } 2374 2375 @safe unittest 2376 { 2377 wstring s = "\U00010000"; 2378 assert(s.length == 2); 2379 s = s[0 .. 1]; 2380 assert(s.length == 1); 2381 s.popFront; 2382 assert(s.empty); 2383 } 2384 2385 /** 2386 Implements the range interface primitive `popBack` for built-in 2387 arrays. Due to the fact that nonmember functions can be called with 2388 the first argument using the dot notation, `array.popBack` is 2389 equivalent to `popBack(array)`. For $(GLOSSARY narrow strings), $(D 2390 popFront) automatically eliminates the last $(GLOSSARY code point). 2391 */ 2392 void popBack(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc 2393 if (!isAutodecodableString!(T[]) && !is(T[] == void[])) 2394 { 2395 assert(a.length); 2396 a = a[0 .. $ - 1]; 2397 } 2398 2399 /// 2400 @safe pure nothrow unittest 2401 { 2402 auto a = [ 1, 2, 3 ]; 2403 a.popBack(); 2404 assert(a == [ 1, 2 ]); 2405 } 2406 2407 @safe unittest 2408 { 2409 static assert(!is(typeof({ immutable int[] a; popBack(a); }))); 2410 static assert(!is(typeof({ int[4] a; popBack(a); }))); 2411 static assert(!is(typeof({ void[] a; popBack(a); }))); 2412 } 2413 2414 /// ditto 2415 void popBack(T)(scope ref inout(T)[] a) @safe pure 2416 if (isAutodecodableString!(T[])) 2417 { 2418 import std.utf : strideBack; 2419 assert(a.length, "Attempting to popBack() past the front of an array of " ~ T.stringof); 2420 a = a[0 .. $ - strideBack(a, $)]; 2421 } 2422 2423 @safe pure unittest 2424 { 2425 import std.meta : AliasSeq; 2426 2427 static foreach (S; AliasSeq!(string, wstring, dstring)) 2428 {{ 2429 S s = "hello\xE2\x89\xA0"; 2430 s.popBack(); 2431 assert(s == "hello"); 2432 S s3 = "\xE2\x89\xA0"; 2433 auto c = s3.back; 2434 assert(c == cast(dchar)'\u2260'); 2435 s3.popBack(); 2436 assert(s3 == ""); 2437 2438 S str = "\U00010143\u0100\U00010143hello"; 2439 foreach (dchar ch; ['o', 'l', 'l', 'e', 'h', '\U00010143', '\u0100', '\U00010143']) 2440 { 2441 assert(str.back == ch); 2442 str.popBack(); 2443 } 2444 assert(str.empty); 2445 2446 static assert(!is(typeof({ immutable S a; popBack(a); }))); 2447 static assert(!is(typeof({ typeof(S.init[0])[4] a; popBack(a); }))); 2448 }} 2449 } 2450 2451 /** 2452 EXPERIMENTAL: to try out removing autodecoding, set the version 2453 `NoAutodecodeStrings`. Most things are expected to fail with this version 2454 currently. 2455 */ 2456 version (NoAutodecodeStrings) 2457 { 2458 enum autodecodeStrings = false; 2459 } 2460 else 2461 { 2462 /// 2463 enum autodecodeStrings = true; 2464 } 2465 2466 /** 2467 Implements the range interface primitive `front` for built-in 2468 arrays. Due to the fact that nonmember functions can be called with 2469 the first argument using the dot notation, `array.front` is 2470 equivalent to `front(array)`. For $(GLOSSARY narrow strings), $(D 2471 front) automatically returns the first $(GLOSSARY code point) as _a $(D 2472 dchar). 2473 */ 2474 @property ref inout(T) front(T)(return scope inout(T)[] a) @safe pure nothrow @nogc 2475 if (!isAutodecodableString!(T[]) && !is(T[] == void[])) 2476 { 2477 assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof); 2478 return a[0]; 2479 } 2480 2481 /// 2482 @safe pure nothrow unittest 2483 { 2484 int[] a = [ 1, 2, 3 ]; 2485 assert(a.front == 1); 2486 } 2487 2488 @safe pure nothrow unittest 2489 { 2490 auto a = [ 1, 2 ]; 2491 a.front = 4; 2492 assert(a.front == 4); 2493 assert(a == [ 4, 2 ]); 2494 2495 immutable b = [ 1, 2 ]; 2496 assert(b.front == 1); 2497 2498 int[2] c = [ 1, 2 ]; 2499 assert(c.front == 1); 2500 } 2501 2502 /// ditto 2503 @property dchar front(T)(scope const(T)[] a) @safe pure 2504 if (isAutodecodableString!(T[])) 2505 { 2506 import std.utf : decode; 2507 assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof); 2508 size_t i = 0; 2509 return decode(a, i); 2510 } 2511 2512 /** 2513 Implements the range interface primitive `back` for built-in 2514 arrays. Due to the fact that nonmember functions can be called with 2515 the first argument using the dot notation, `array.back` is 2516 equivalent to `back(array)`. For $(GLOSSARY narrow strings), $(D 2517 back) automatically returns the last $(GLOSSARY code point) as _a $(D 2518 dchar). 2519 */ 2520 @property ref inout(T) back(T)(return scope inout(T)[] a) @safe pure nothrow @nogc 2521 if (!isAutodecodableString!(T[]) && !is(T[] == void[])) 2522 { 2523 assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof); 2524 return a[$ - 1]; 2525 } 2526 2527 /// 2528 @safe pure nothrow unittest 2529 { 2530 int[] a = [ 1, 2, 3 ]; 2531 assert(a.back == 3); 2532 a.back += 4; 2533 assert(a.back == 7); 2534 } 2535 2536 @safe pure nothrow unittest 2537 { 2538 immutable b = [ 1, 2, 3 ]; 2539 assert(b.back == 3); 2540 2541 int[3] c = [ 1, 2, 3 ]; 2542 assert(c.back == 3); 2543 } 2544 2545 /// ditto 2546 // Specialization for strings 2547 @property dchar back(T)(scope const(T)[] a) @safe pure 2548 if (isAutodecodableString!(T[])) 2549 { 2550 import std.utf : decode, strideBack; 2551 assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof); 2552 size_t i = a.length - strideBack(a, a.length); 2553 return decode(a, i); 2554 } 2555 2556 /* 2557 Implements `length` for a range by forwarding it to `member`. 2558 */ 2559 package(std) mixin template ImplementLength(alias member) 2560 { 2561 static if (hasLength!(typeof(member))) 2562 { 2563 @property auto length() 2564 { 2565 return member.length; 2566 } 2567 alias opDollar = length; 2568 } 2569 } 2570 2571 @safe unittest 2572 { 2573 import std.meta : AliasSeq; 2574 2575 foreach (alias E; AliasSeq!(noreturn, const(noreturn), immutable(noreturn) )) 2576 { 2577 alias R = E[]; 2578 2579 static assert(isInputRange!R); 2580 static assert(isForwardRange!R); 2581 static assert(isBidirectionalRange!R); 2582 static assert(isRandomAccessRange!R); 2583 } 2584 2585 static assert(isOutputRange!(noreturn[], noreturn)); 2586 } 2587