Changeset 1566
- Timestamp:
- 05/29/10 13:43:59 (15 years ago)
- Files:
-
- trunk/docsrc/changelog.dd (modified) (1 diff)
- trunk/phobos/std/range.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/docsrc/changelog.dd
r1560 r1566 12 12 ) 13 13 $(BUGSFIXED 14 14 $(LI $(BUGZILLA 2738): Rebindable should work for interfaces.) 15 15 $(LI $(BUGZILLA 2835): std.socket.TcpSocket doesn't actually connect) 16 16 $(LI $(BUGZILLA 3088): std.xml.check() fails on xml comments) 17 17 $(LI $(BUGZILLA 3200): std.xml doesn't follow spec for Tag.text) 18 18 $(LI $(BUGZILLA 3465): isIdeographic can be wrong in std.xml) 19 19 $(LI $(BUGZILLA 3653): Problem sorting array of Rebindable) 20 20 $(LI $(BUGZILLA 3786): bug in std.string.removechars) 21 21 $(LI $(BUGZILLA 3873): std.range.repeat should have popBack defined) 22 $(LI $(BUGZILLA 3876): std.range.Take back/popBack methods don't work correctly) 22 23 $(LI $(BUGZILLA 3880): std.regex functions with const/immutable Regex object) 23 24 $(LI $(BUGZILLA 4109): writeln doesn't work with empty static array) 24 25 $(LI $(BUGZILLA 4188): std.file.remove throws Exception on success) 25 26 $(LI $(BUGZILLA 4202): Changset 1517 doesn't compile) 26 27 $(LI $(BUGZILLA 4228): std.array.replace contains 2 bugs) 27 28 $(LI $(BUGZILLA 4219): hasAliasing does not care about immutable) 28 29 ) 29 30 ) 30 31 31 32 <div id=version> trunk/phobos/std/range.d
r1536 r1566 1188 1188 assert(s[4] == 5); 1189 1189 assert(equal(s, [ 1, 2, 3, 4, 5 ][])); 1190 1190 ---- 1191 1191 */ 1192 1192 1193 1193 struct Take(R) if (isInputRange!(R)) 1194 1194 { 1195 1195 private: 1196 1196 R _input; 1197 1197 size_t _maxAvailable; 1198 enum bool byRef = is(typeof(&(R.init[0]))); 1198 enum bool byRef = is(typeof(&_input.front) == ElementType!(R)*); 1199 1200 enum bool backByIndex = // Take.back = input[min(n,$) - 1] 1201 isRandomAccessRange!(R) && (hasLength!(R) || isInfinite!(R)); 1202 1203 enum bool backByBack = // Take.back = input.back 1204 !backByIndex && isBidirectionalRange!(R) && hasLength!(R); 1199 1205 1200 1206 public: 1201 1207 alias R Source; 1202 1208 1203 1209 static if (byRef) 1204 1210 alias ref .ElementType!(R) ElementType; 1205 1211 else 1206 1212 alias .ElementType!(R) ElementType; 1207 1213 1214 this(R input, size_t maxAvailable) 1215 { 1216 static if (backByBack) 1217 { 1218 while (input.length > maxAvailable) 1219 input.popBack; 1220 } 1221 _input = input; 1222 _maxAvailable = maxAvailable; 1223 } 1224 1208 1225 bool empty() 1209 1226 { 1210 1227 return _maxAvailable == 0 || _input.empty; 1211 1228 } 1212 1229 1213 1230 void popFront() 1214 1231 { 1215 enforce(_maxAvailable > 0); 1232 enforce(_maxAvailable > 0, 1233 "Attenpting to popFront() past the end of a " 1234 ~ Take.stringof); 1216 1235 _input.popFront; 1217 1236 --_maxAvailable; 1218 1237 } 1219 1238 1220 1239 // @@@@@@@@@@@ UGLY @@@@@@@@@@@@@@@ 1221 1240 mixin( 1222 1241 (byRef ? "ref " : "")~ 1223 1242 q{ElementType front() 1224 1243 { 1225 enforce(_maxAvailable > 0); 1244 enforce(_maxAvailable > 0, 1245 "Attempting to fetch the front of an empty " 1246 ~ Take.stringof); 1226 1247 return _input.front; 1227 1248 }}); 1228 1249 1229 1250 static if (isInfinite!(R)) 1230 1251 { 1231 1252 @property size_t length() const 1232 1253 { 1233 1254 return _maxAvailable; 1234 1255 } 1235 1256 } 1257 else static if (hasLength!(R)) 1258 { 1259 @property size_t length() 1260 { 1261 return min(_maxAvailable, _input.length); 1262 } 1263 } 1264 1265 static if (backByIndex) 1266 { 1236 1267 void popBack() 1237 1268 { 1238 enforce(_maxAvailable); 1269 enforce(_maxAvailable > 0, 1270 "Attenpting to popBack() past the beginning of a " 1271 ~ Take.stringof); 1239 1272 --_maxAvailable; 1240 1273 } 1241 } 1242 else static if (hasLength!(R)) 1243 { 1244 @property size_t length() 1245 { 1246 return min(_maxAvailable, _input.length); 1247 } 1248 1249 static if (isBidirectionalRange!(R)) 1250 { 1251 void popBack() 1252 { 1253 if (_maxAvailable > _input.length) 1254 { 1255 --_maxAvailable; 1256 } 1257 else 1258 { 1259 _input.popBack; 1260 } 1261 } 1262 } 1263 } 1264 1265 static if (isRandomAccessRange!(R)) 1266 { 1274 1267 1275 mixin( 1268 1276 (byRef ? "ref " : "")~ 1269 q{ElementType opIndex(uint index) 1270 { 1271 enforce(_maxAvailable > index); 1272 return _input[index]; 1273 } 1274 }); 1275 } 1276 1277 static if (isBidirectionalRange!(R)) 1278 { 1277 q{/+auto ref+/ ElementType back() 1278 { 1279 return _input[this.length - 1]; 1280 }}); 1281 } 1282 else static if (backByBack) 1283 { 1284 invariant() 1285 { 1286 assert(_input.length <= _maxAvailable); 1287 } 1288 1289 void popBack() 1290 { 1291 enforce(_maxAvailable > 0, 1292 "Attenpting to popBack() past the beginning of a " 1293 ~ Take.stringof); 1294 --_maxAvailable; 1295 _input.popBack; 1296 } 1297 1279 1298 mixin( 1280 1299 (byRef ? "ref " : "")~ 1281 q{ElementType back() 1282 { 1283 return _input.back; 1284 } 1285 }); 1286 } 1287 else static if (isRandomAccessRange!(R) && isInfinite!(R)) 1288 { 1289 // Random access but not bidirectional could happen in the 1290 // case of e.g. some infinite ranges 1300 q{/+auto ref+/ ElementType back() 1301 { 1302 return _input.back; 1303 }}); 1304 } 1305 1306 static if (isRandomAccessRange!(R)) 1307 { 1291 1308 mixin( 1292 1309 (byRef ? "ref " : "")~ 1293 q{ElementType back() 1294 { 1295 return _input[length - 1]; 1296 } 1297 }); 1298 } 1310 q{/+auto ref+/ ElementType opIndex(size_t index) 1311 { 1312 enforce(index < this.length, 1313 "Attempting to index out of the bounds of a " 1314 ~ Take.stringof); 1315 return _input[index]; 1316 }}); 1317 } 1318 1319 Take opSlice() { return this; } 1299 1320 } 1300 1321 1301 1322 /// Ditto 1302 1323 Take!(R) take(R)(R input, size_t n) if (isInputRange!(R)) 1303 1324 { 1304 1325 return Take!(R)(input, n); 1305 1326 } 1306 1327 1307 1328 unittest 1308 1329 { 1309 1330 int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 1310 1331 auto s = take(arr1, 5); 1311 1332 assert(s.length == 5); 1312 1333 assert(s[4] == 5); 1313 1334 assert(equal(s, [ 1, 2, 3, 4, 5 ][])); 1335 assert(equal(retro(s), [ 5, 4, 3, 2, 1 ][])); 1314 1336 } 1315 1337 1316 1338 /** 1317 1339 Eagerly advances $(D r) itself (not a copy) $(D n) times (by calling 1318 1340 $(D r.popFront) $(D n) times). The pass of $(D r) into $(D popFrontN) 1319 1341 is by reference, so the original range is affected. Completes in 1320 1342 $(BIGOH 1) steps for ranges that support slicing, and in $(BIGOH n) 1321 1343 time for all other ranges. 1322 1344 1323 1345 Example:
