Esempio n. 1
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 ImplSplit(Context cx, IScriptable scope, string target, object [] args)
        {
            // create an empty Array to return;
            IScriptable top    = GetTopLevelScope(scope);
            IScriptable 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.
            bool limited = (args.Length > 1) && (args [1] != Undefined.Value);
            long limit   = 0; // Initialize to avoid warning.

            if (limited)
            {
                /* Clamp limit between 0 and 1 + string length. */
                limit = ScriptConvert.ToUint32(args [1]);
                if (limit > target.Length)
                {
                    limit = 1 + target.Length;
                }
            }

            string separator = null;

            int []      matchlen = new int [1];
            IScriptable re       = null;
            RegExpProxy reProxy  = null;

            if (args [0] is IScriptable)
            {
                reProxy = cx.RegExpProxy;
                if (reProxy != null)
                {
                    IScriptable test = (IScriptable)args [0];
                    if (reProxy.IsRegExp(test))
                    {
                        re = test;
                    }
                }
            }
            if (re == null)
            {
                separator    = ScriptConvert.ToString(args [0]);
                matchlen [0] = separator.Length;
            }

            // split target with separator or re
            int [] ip = new int [] { 0 };
            int    match;
            int    len = 0;

            bool []          matched = new bool [] { false };
            string [] []     parens  = new string [] [] { null };
            Context.Versions version = cx.Version;
            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) - (ip [0]));
                }

                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.
                 */
                // CB, 02.01.2007: Don't do this, causes bug #287630
                // https://bugzilla.mozilla.org/show_bug.cgi?query_format=specific&order=relevance+desc&bug_status=__open__&id=287630

                /*
                 * 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.Versions.JS1_3 && version != Context.Versions.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);
        }