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;