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;
valueR::Front240 @property int value() { return impl._front; }
241 alias value this;
242 }
243
244 int _front;
245
emptyR246 @property bool empty() { return _front >= 3; }
frontR247 @property auto front() { return Front(&this); }
popFrontR248 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 +/
doPut(R,E)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 +/
put(R,E)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 {
R()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 {
delegate(const (char)[])559 auto f = delegate (const(char)[]) {};
560 putChar(f, cast(dchar)'a');
561 }
562
563
564 @safe pure unittest
565 {
R()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 {
putB577 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 {
myprint(scope const (char)[]s)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 {
putLockingTextWriter711 void put(dchar c){}
712 }
713 struct RetroResult
714 {
715 bool end = false;
empty()716 @property bool empty() const { return end; }
front()717 @property dchar front(){ return 'a'; }
popFront()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
PutC(C)731 static struct PutC(C)
732 {
733 string result;
734 void put(const(C) c) { result ~= to!string((&c)[0 .. 1]); }
735 }
PutS(C)736 static struct PutS(C)
737 {
738 string result;
739 void put(const(C)[] s) { result ~= to!string(s); }
740 }
PutSS(C)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
foreach(value;tuple (type,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;
popFrontCharRange794 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