Esempio n. 1
0
  /*
   * Used by js_split to find the next split point in target,
   * starting at offset ip and looking either for the given
   * separator substring, or for the next re match.  ip and
   * matchlen must be reference variables (assumed to be arrays of
   * length 1) so they can be updated in the leading whitespace or
   * re case.
   *
   * Return -1 on end of string, >= 0 for a valid index of the next
   * separator occurrence if found, or the string length if no
   * separator is found.
   */
  private static int find_split(
      Context cx,
      Scriptable scope,
      String target,
      String separator,
      int version,
      RegExpProxy reProxy,
      Scriptable re,
      int[] ip,
      int[] matchlen,
      boolean[] matched,
      String[][] parensp) {
    int i = ip[0];
    int length = target.length();

    /*
     * Perl4 special case for str.split(' '), only if the user has selected
     * JavaScript1.2 explicitly.  Split on whitespace, and skip leading w/s.
     * Strange but true, apparently modeled after awk.
     */
    if (version == Context.VERSION_1_2
        && re == null
        && separator.length() == 1
        && separator.charAt(0) == ' ') {
      /* Skip leading whitespace if at front of str. */
      if (i == 0) {
        while (i < length && Character.isWhitespace(target.charAt(i))) i++;
        ip[0] = i;
      }

      /* Don't delimit whitespace at end of string. */
      if (i == length) return -1;

      /* Skip over the non-whitespace chars. */
      while (i < length && !Character.isWhitespace(target.charAt(i))) i++;

      /* Now skip the next run of whitespace. */
      int j = i;
      while (j < length && Character.isWhitespace(target.charAt(j))) j++;

      /* Update matchlen to count delimiter chars. */
      matchlen[0] = j - i;
      return i;
    }

    /*
     * Stop if past end of string.  If at end of string, we will
     * return target length, so that
     *
     *  "ab,".split(',') => new Array("ab", "")
     *
     * and the resulting array converts back to the string "ab,"
     * for symmetry.  NB: This differs from perl, which drops the
     * trailing empty substring if the LIMIT argument is omitted.
     */
    if (i > length) return -1;

    /*
     * Match a regular expression against the separator at or
     * above index i.  Return -1 at end of string instead of
     * trying for a match, so we don't get stuck in a loop.
     */
    if (re != null) {
      return reProxy.find_split(cx, scope, target, separator, re, ip, matchlen, matched, parensp);
    }

    /*
     * Deviate from ECMA by never splitting an empty string by any separator
     * string into a non-empty array (an array of length 1 that contains the
     * empty string).
     */
    if (version != Context.VERSION_DEFAULT && version < Context.VERSION_1_3 && length == 0)
      return -1;

    /*
     * Special case: if sep is the empty string, split str into
     * one character substrings.  Let our caller worry about
     * whether to split once at end of string into an empty
     * substring.
     *
     * For 1.2 compatibility, at the end of the string, we return the length as
     * the result, and set the separator length to 1 -- this allows the caller
     * to include an additional null string at the end of the substring list.
     */
    if (separator.length() == 0) {
      if (version == Context.VERSION_1_2) {
        if (i == length) {
          matchlen[0] = 1;
          return i;
        }
        return i + 1;
      }
      return (i == length) ? -1 : i + 1;
    }

    /* Punt to j.l.s.indexOf; return target length if separator is
     * not found.
     */
    if (ip[0] >= length) return length;

    i = target.indexOf(separator, ip[0]);

    return (i != -1) ? i : length;
  }