1 /**
2  * Copyright: Copyright (c) 2008 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Aug 6, 2008
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  *
7  */
8 module mambo.util.Range;
9 
10 /**
11  * This stucts represents a range with a beginning and an end.
12  * The Range only workds with integer types and char types.
13  *
14  * Example:
15  * ---
16  * 		auto r = range[3..9];
17  *
18  * 		foreach (i ; r)
19  * 			println(i);
20  *
21  * 		// will print 3 up to including 8
22  *
23  * 		foreach (c ; range['a'..'h'];
24  * 			println(c);
25  *
26  * 		// will print a up to including g
27  * ---
28  */
29 struct Range (T = size_t, U = T)
30 {
31 	/// The beginning of the range
32 	T start;
33 
34 	/// The end of the range
35 	U end;
36 
37 	/**
38 	 * Creates a new Range using the following syntax
39 	 *
40 	 * Example:
41 	 *     $(D_CODE auto r = range[3..9];)
42 	 *
43 	 * Params:
44 	 *     start = the start of the range
45 	 *     end = the end of the range
46 	 *
47 	 * Returns: the created Range
48 	 */
49 	static Range!(T, U) opSlice (T start, U end)
50 	{
51 		Range!(T, U) r;
52 		r.start = start;
53 		r.end = end;
54 
55 		return r;
56 	}
57 
58 	/**
59 	 * Allows the range to work in a foreach loop
60 	 *
61 	 * Params:
62 	 *     dg =
63 	 * Returns:
64 	 */
65 	int opApply(int delegate(ref T) dg)
66     {
67 		int result = 0;
68 
69 		for (T i = start; i < end; i++)
70 		{
71 		    result = dg(i);
72 
73 		    if (result)
74 		    	break;
75 		}
76 
77 		return result;
78     }
79 
80 	/**
81 	 * Allows the range to work in a foreach_reverse loop
82 	 *
83 	 * Params:
84 	 *     dg =
85 	 * Returns:
86 	 */
87 	int opApplyReverse(int delegate(ref T) dg)
88     {
89 		int result = 0;
90 
91 		for (T i = end - 1; i >= start; i--)
92 		{
93 		    result = dg(i);
94 
95 		    if (result)
96 		    	break;
97 		}
98 
99 		return result;
100     }
101 
102 	/**
103 	 * Creates an array of the Range
104 	 *
105 	 * Returns: the created array
106 	 * See_Also: opCall
107 	 * See_Also: opSlice
108 	 */
109 	T[] toArr ()
110 	{
111 		T[] arr;
112 		arr.length = end - start;
113 		size_t index = 0;
114 		T s = start;
115 
116 		for (size_t i = start; i < end; i++)
117 			arr[index++] = s++;
118 
119 		return arr;
120 	}
121 
122 	/**
123 	 * Creates an array of the Range
124 	 *
125 	 * Returns: the created array
126 	 * See_Also: toArr
127 	 * See_Also: opSlice
128 	 */
129 	T[] opCall ()
130 	{
131 		return toArr;
132 	}
133 
134 	/**
135 	 * Creates an array of the Range
136 	 *
137 	 * Returns: the created array
138 	 * See_Also: toArr
139 	 * See_Also: opCall
140 	 */
141 	T[] opSlice ()
142 	{
143 		return toArr;
144 	}
145 
146 	/**
147 	 * Returns the element at the specified index
148 	 *
149 	 * Params:
150 	 *     index = the index of the element
151 	 *
152 	 * Returns: the element at the specified index
153 	 */
154 	T opIndex (T index)
155 	in
156 	{
157 		assert(index >= 0 && index <= (end - start) - 1);
158 	}
159 	body
160 	{
161 		if (index == 0)
162 			return start;
163 
164 		else if (index == end - start)
165 			return end;
166 
167 		else
168 		{
169 			T s = start;
170 
171 			for (size_t i = 0; i < end - 1; i++)
172 				if (i == index)
173 					return s;
174 				else
175 					s++;
176 
177 			return T.max;
178 		}
179 	}
180 
181 	/**
182 	 * Returns the number of elements in the Range
183 	 *
184 	 * Returns: the number of elements in the Range
185 	 */
186 	size_t length ()
187 	{
188 		return cast(size_t) end - start;
189 	}
190 }
191 
192 /// An alias to the default Range type which is Range!(sise_t, size_t)
193 alias Range!() range;