loop function
Loops over s
and returns traversed characters. Takes arbitrary from
and
to
indices. Works as a substitute for String.substring, except it never
throws RangeError. Supports negative indices. Think of an index as a
coordinate in an infinite in both directions vector filled with repeating
string s
, whose 0-th coordinate coincides with the 0-th character in s
.
Then loop returns the sub-vector defined by the interval (from
, to
).
from
is inclusive. to
is exclusive.
This method throws exceptions on null
and empty strings.
If to
is omitted or is null
the traversing ends at the end of the loop.
If to
< from
, traverses s
in the opposite direction.
For example:
loop('Hello, World!', 7) == 'World!' loop('ab', 0, 6) == 'ababab' loop('test.txt', -3) == 'txt' loop('ldwor', -3, 2) == 'world'
Implementation
String loop(String s, int from, [int? to]) {
if (s.isEmpty) {
throw ArgumentError('Input string cannot be empty');
}
if (to != null && to < from) {
// TODO(cbracken): throw ArgumentError in this case.
return loop(_reverse(s), -from, -to);
}
int len = s.length;
int leftFrag = from >= 0 ? from ~/ len : ((from - len) ~/ len);
to ??= (leftFrag + 1) * len;
int rightFrag = to - 1 >= 0 ? to ~/ len : ((to - len) ~/ len);
int fragOffset = rightFrag - leftFrag - 1;
if (fragOffset == -1) {
return s.substring(from - leftFrag * len, to - rightFrag * len);
}
StringBuffer sink = StringBuffer(s.substring(from - leftFrag * len));
_repeat(sink, s, fragOffset);
sink.write(s.substring(0, to - rightFrag * len));
return sink.toString();
}