loop function

String loop (String s, int from, [ int to ])

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 == null || s == '') {
    throw new ArgumentError('Input string cannot be null or 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);
  if (to == null) {
    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 = new StringBuffer(s.substring(from - leftFrag * len));
  _repeat(sink, s, fragOffset);
  sink.write(s.substring(0, to - rightFrag * len));
  return sink.toString();
}