code: public static List<Range> splitRanges(byte[] source, byte[] separator, int limit) {
      List<Range> segments = new ArrayList<Range>();
      int start = 0;
      itersource: for (int i = 0; i < source.length; i++) {
        for (int j = 0; j < separator.length; j++) {
          if (source[i + j] != separator[j]) {
            continue itersource;
          }
        }
        // all separator elements matched
        if (limit > 0 && segments.size() >= (limit-1)) {
          // everything else goes in one final segment
          break;
        }
  
        segments.add(new Range(start, i));
        start = i + separator.length;
        // i will be incremented again in outer for loop
        i += separator.length-1;
      }
      // add in remaining to a final range
      if (start <= source.length) {
        segments.add(new Range(start, source.length));
      }
      return segments;
    }
docs: Returns a list of ranges identifying [start, end) -- closed, open --
  positions within the source byte array that would be split using the
  separator byte array.
  @param source the source data
  @param separator the separator pattern to look for
  @param limit the maximum number of splits to identify in the source