Browse Source

Improving performance of lastIndexOf

Sebastien Ros 10 years ago
parent
commit
0e80b6c67b
1 changed files with 30 additions and 59 deletions
  1. 30 59
      Jint/Native/String/StringPrototype.cs

+ 30 - 59
Jint/Native/String/StringPrototype.cs

@@ -614,80 +614,51 @@ namespace Jint.Native.String
             return string.CompareOrdinal(s, that);
             return string.CompareOrdinal(s, that);
         }
         }
 
 
-        private static List<int> AllIndexesOf(string str, string value)
+        private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         {
         {
-            if (string.IsNullOrEmpty(value))
-                return new List<int>();
+            TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
 
-            var indexes = new List<int>();
-            for (int index = 0; ; index += value.Length)
+            var s = TypeConverter.ToString(thisObj);
+            var searchStr = TypeConverter.ToString(arguments.At(0));
+            double numPos = double.NaN;
+            if (arguments.Length > 1 && arguments[1] != Undefined.Instance)
             {
             {
-                index = str.IndexOf(value, index);
-                if (index == -1) // no more fond
-                    return indexes;
-                indexes.Add(index);
+                numPos = TypeConverter.ToNumber(arguments[1]);
             }
             }
-        }
 
 
-        private int LastIndexJavaScriptImplementation(string s, string searchStr, int pos = -1)
-        {
-            if (pos == -1)
-                pos = s.Length;
+            var pos = double.IsNaN(numPos) ? double.PositiveInfinity : TypeConverter.ToInteger(numPos);
 
 
-            var len          = s.Length;
-            var start        = System.Math.Min(System.Math.Max(pos, 0), len);
-            var searchLen    = searchStr.Length;
-            var kPositions   = AllIndexesOf(s, searchStr);
+            var len = s.Length;
+            var start = (int)System.Math.Min(System.Math.Max(pos, 0), len);
+            var searchLen = searchStr.Length;
 
 
-            if (kPositions.Count == 0) // Nothing found
-            {
-                return -1;
-            }
-            else if (kPositions.Count == 1) // Only one found
-            {
-                return kPositions[0] <= start ? kPositions[0] : -1;
-            }
+            var i = start;
+            bool found;
 
 
-            // Return the largest possible nonnegative integer k not larger than start 
-            // such that k+ searchLen is not greater than len
-            for (var i = 0; i < kPositions.Count; i++)
+            do
             {
             {
-                if (kPositions[i] <= start)
+                found = true;
+                var j = 0;
+
+                while (found && j < searchLen)
                 {
                 {
-                    // ok move to the next one to find a greater pos
+                    if ((i + searchLen > len) || (s[i + j] != searchStr[j]))
+                    {
+                        found = false;
+                    }
+                    else
+                    {
+                        j++;
+                    }
                 }
                 }
-                else
+                if (!found)
                 {
                 {
-                    if ((i > 0) && ((kPositions[i - 1] + searchLen) <= len))
-                        return kPositions[i - 1];
-                    else
-                        return -1;
+                    i--;
                 }
                 }
-            }
-            return kPositions[kPositions.Count - 1];
-        }
 
 
-        private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
-        {
-            TypeConverter.CheckObjectCoercible(Engine, thisObj);
+            } while (!found && i >= 0);
 
 
-            var s = TypeConverter.ToString(thisObj);
-            var searchStr = TypeConverter.ToString(arguments.At(0));
-            double numPos = arguments.At(1) == Undefined.Instance ? s.Length : TypeConverter.ToNumber(arguments.At(1));
-            double pos = double.IsNaN(numPos) ? double.PositiveInfinity : TypeConverter.ToInteger(numPos);
-            var len = s.Length;
-            var start = System.Math.Min(len, System.Math.Max(pos, 0));
-
-            // The JavaScript spec of string.lastIndexOf does match the C# spec
-            // Therefore we need to write our own specific implementation.
-            // Enjoy the fact that Ecma spec and Mozilla spec have different definition which
-            // I guess mean the same thing.
-            // Ecma spec
-            // http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4.8
-            // Mozilla spec
-            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf
-
-            return LastIndexJavaScriptImplementation(s, searchStr, (int)start);
+            return i;
         }
         }
 
 
         private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)
         private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)