1 // Written in the D programming language.
2 
3 /** This module contains asForwardRange().
4 
5     Authors:
6         $(WEB digitalmars.com, Walter Bright)
7     Copyright:
8         Copyright (c) 2014-, the authors. All rights reserved.
9     License:
10         $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0)
11     Source:
12         $(SARGONSRC src/sargon/_array/_asforwardrange.d)
13 */
14 module sargon.array.asforwardrange;
15 
16 import sargon.array.asinputrange;
17 
18 /**
19  * Turn an array into a ForwardRange, useful for unittesting.
20  *
21  * Params:
22  *      a = is an array of elements of type E
23  *
24  * Returns:
25  *      a ForwardRange
26  */
27 auto ref asForwardRange(E)(E[] a)
28 {
29     static struct asForwardRangeImpl
30     {
31         this(E[] a)
32         {
33             this.a = a;
34         }
35 
36         @property bool empty()
37         {
38             hasData = (a.length != 0);
39             return !hasData;
40         }
41 
42         @property ref E front()
43         {
44             assert(hasData);
45             return a[0];
46         }
47 
48         void popFront()
49         {
50             a = a[1 .. $];
51             hasData = false;
52         }
53 
54         @property asForwardRangeImpl save()
55         {
56             return this;
57         }
58 
59       private:
60         E[] a;
61         bool hasData;
62     }
63     return asForwardRangeImpl(a);
64 }
65 
66 ///
67 unittest
68 {
69     import std.range;
70 
71     static assert(isForwardRange!(typeof(asForwardRange("hello"))));
72 
73     void testrange(string f, string result)
74     {
75         char[50] s;
76         int i;
77         foreach (c; f.asForwardRange())
78         {
79             s[i++] = c;
80         }
81         assert(s[0 .. i] == result);
82     }
83     testrange("file", "file");
84 
85     {   // various boundary conditions
86         auto r = "foo".asForwardRange;
87         auto s = r.save;
88         assert(!r.empty);
89         assert(!r.empty);
90         r.popFront();
91         r.popFront();
92         r.popFront();
93         assert(r.empty);
94 
95         assert(!s.empty);
96         assert(!s.empty);
97         s.popFront();
98         s.popFront();
99         s.popFront();
100         assert(s.empty);
101     }
102 }
103 
104 private import std.range;
105 
106 /***************************************
107  * Takes an ForwardRange as input and verifies
108  * that it can be iterated following protocol.
109  *
110  * Params:
111  *      r = is a ForwardRange
112  */
113 
114 void testForwardRange(R)(R r) if (isForwardRange!R)
115 {
116     auto rsave = r.save;
117     testInputRange(rsave);
118 
119     static if (isInfinite!R)
120     {
121         foreach (i; 0 .. 10)
122         {
123             while (!r.empty)
124             {
125                 auto e = r.front;
126                 auto e2 = r.front;
127                 assert(e == e2);
128                 r.popFront();
129             }
130         }
131     }
132     else
133     {
134         while (!r.empty)
135         {
136             auto e = r.front;
137             auto e2 = r.front;
138             assert(e == e2);
139             r.popFront();
140         }
141     }
142 }
143 
144 ///
145 unittest
146 {
147     testForwardRange(asForwardRange("betty"));
148 }