Пример #1
0
  Scriptable[] createRegExpWraps(Context cx, Scriptable scope) {
    if (idata.itsRegExpLiterals == null) Kit.codeBug();

    RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx);
    int N = idata.itsRegExpLiterals.length;
    Scriptable[] array = new Scriptable[N];
    for (int i = 0; i != N; ++i) {
      array[i] = rep.wrapRegExp(cx, scope, idata.itsRegExpLiterals[i]);
    }
    return array;
  }
Пример #2
0
  /*
   * See ECMA 15.5.4.8.  Modified to match JS 1.2 - optionally takes
   * a limit argument and accepts a regular expression as the split
   * argument.
   */
  private static Object js_split(Context cx, Scriptable scope, String target, Object[] args) {
    // create an empty Array to return;
    Scriptable top = getTopLevelScope(scope);
    Scriptable result = ScriptRuntime.newObject(cx, top, "Array", null);

    // return an array consisting of the target if no separator given
    // don't check against undefined, because we want
    // 'fooundefinedbar'.split(void 0) to split to ['foo', 'bar']
    if (args.length < 1) {
      result.put(0, result, target);
      return result;
    }

    // Use the second argument as the split limit, if given.
    boolean limited = (args.length > 1) && (args[1] != Undefined.instance);
    long limit = 0; // Initialize to avoid warning.
    if (limited) {
      /* Clamp limit between 0 and 1 + string length. */
      limit = ScriptRuntime.toUint32(args[1]);
      if (limit > target.length()) limit = 1 + target.length();
    }

    String separator = null;
    int[] matchlen = new int[1];
    Scriptable re = null;
    RegExpProxy reProxy = null;
    if (args[0] instanceof Scriptable) {
      reProxy = ScriptRuntime.getRegExpProxy(cx);
      if (reProxy != null) {
        Scriptable test = (Scriptable) args[0];
        if (reProxy.isRegExp(test)) {
          re = test;
        }
      }
    }
    if (re == null) {
      separator = ScriptRuntime.toString(args[0]);
      matchlen[0] = separator.length();
    }

    // split target with separator or re
    int[] ip = {0};
    int match;
    int len = 0;
    boolean[] matched = {false};
    String[][] parens = {null};
    int version = cx.getLanguageVersion();
    while ((match =
            find_split(
                cx, scope, target, separator, version, reProxy, re, ip, matchlen, matched, parens))
        >= 0) {
      if ((limited && len >= limit) || (match > target.length())) break;

      String substr;
      if (target.length() == 0) substr = target;
      else substr = target.substring(ip[0], match);

      result.put(len, result, substr);
      len++;
      /*
       * Imitate perl's feature of including parenthesized substrings
       * that matched part of the delimiter in the new array, after the
       * split substring that was delimited.
       */
      if (re != null && matched[0] == true) {
        int size = parens[0].length;
        for (int num = 0; num < size; num++) {
          if (limited && len >= limit) break;
          result.put(len, result, parens[0][num]);
          len++;
        }
        matched[0] = false;
      }
      ip[0] = match + matchlen[0];

      if (version < Context.VERSION_1_3 && version != Context.VERSION_DEFAULT) {
        /*
         * Deviate from ECMA to imitate Perl, which omits a final
         * split unless a limit argument is given and big enough.
         */
        if (!limited && ip[0] == target.length()) break;
      }
    }
    return result;
  }
Пример #3
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;
  }