diff --git a/src/Peachpie.Library/Miscellaneous.cs b/src/Peachpie.Library/Miscellaneous.cs
index df6e26ae45..c40ff8d214 100644
--- a/src/Peachpie.Library/Miscellaneous.cs
+++ b/src/Peachpie.Library/Miscellaneous.cs
@@ -519,20 +519,21 @@ static int CompareParts(string part1, string part2)
/// Parses a version and splits it into an array of parts.
///
/// The version to be parsed (can be a null reference).
- /// An array of parts.
+ /// Version parts will be added there.
+ /// If we collected version parts.
///
/// Non-alphanumeric characters are eliminated.
/// The version is split in between a digit following a non-digit and by
/// characters '.', '-', '+', '_'.
///
- static string[] VersionToArray(string version)
+ static bool VersionToArray(string version, List result)
{
if (string.IsNullOrEmpty(version))
{
- return Array.Empty();
+ return false;
}
- var sb = new StringBuilder(version.Length);
+ var sb = ObjectPools.GetStringBuilder();
char last = '\0';
for (int i = 0; i < version.Length; i++)
@@ -566,12 +567,25 @@ static string[] VersionToArray(string version)
}
}
- if (last == '.')
+ // split into {result}
+ int from = 0;
+ for (int i = 0; i < sb.Length; i++)
{
- sb.Length--;
+ if (sb[i] == '.')
+ {
+ result.Add(sb.ToString(from, i - from));
+ from = i + 1;
+ }
}
-
- return sb.ToString().Split('.');
+
+ if (from < sb.Length)
+ {
+ result.Add(sb.ToString(from, sb.Length - from));
+ }
+
+ //
+ ObjectPools.Return(sb);
+ return true;
}
#endregion
@@ -593,31 +607,45 @@ static string[] VersionToArray(string version)
///
public static int version_compare(string version1, string version2)
{
- string[] v1 = VersionToArray(version1);
- string[] v2 = VersionToArray(version2);
- int result;
+ var v1 = ListPool.Pool.Get();
+ var v2 = ListPool.Pool.Get();
- for (int i = 0; i < Math.Max(v1.Length, v2.Length); i++)
+ try
{
- string item1 = (i < v1.Length) ? v1[i] : " ";
- string item2 = (i < v2.Length) ? v2[i] : " ";
- if (item1.Length == 0) item1 = "0";
- if (item2.Length == 0) item2 = "0";
+ VersionToArray(version1, v1);
+ VersionToArray(version2, v2);
- if (char.IsDigit(item1[0]) && char.IsDigit(item2[0]))
- {
- result = Comparison.Compare(Pchp.Core.Convert.StringToLongInteger(item1), Pchp.Core.Convert.StringToLongInteger(item2));
- }
- else
- {
- result = CompareParts(char.IsDigit(item1[0]) ? "#" : item1, char.IsDigit(item2[0]) ? "#" : item2);
- }
+ int result;
- if (result != 0)
+ for (int i = 0; i < Math.Max(v1.Count, v2.Count); i++)
{
- return result;
+ string item1 = (i < v1.Count) ? v1[i] : " ";
+ string item2 = (i < v2.Count) ? v2[i] : " ";
+
+ if (item1.Length == 0) item1 = "0";
+ if (item2.Length == 0) item2 = "0";
+
+ if (char.IsDigit(item1[0]) && char.IsDigit(item2[0]))
+ {
+ result = Comparison.Compare(Pchp.Core.Convert.StringToLongInteger(item1), Pchp.Core.Convert.StringToLongInteger(item2));
+ }
+ else
+ {
+ result = CompareParts(char.IsDigit(item1[0]) ? "#" : item1, char.IsDigit(item2[0]) ? "#" : item2);
+ }
+
+ if (result != 0)
+ {
+ return result;
+ }
}
+
+ }
+ finally
+ {
+ ListPool.Pool.Return(v1);
+ ListPool.Pool.Return(v2);
}
return 0;
@@ -626,11 +654,11 @@ public static int version_compare(string version1, string version2)
///
/// Compares two "PHP-standardized" version number strings.
///
- public static bool version_compare(string version1, string version2, string op)
+ public static bool version_compare(string version1, string version2, string @operator)
{
var compare = version_compare(version1, version2);
- switch (op)
+ switch (@operator)
{
case "<":
case "lt": return compare < 0;
diff --git a/src/Peachpie.Runtime/Utilities/ListPool.cs b/src/Peachpie.Runtime/Utilities/ListPool.cs
new file mode 100644
index 0000000000..a26dd0a451
--- /dev/null
+++ b/src/Peachpie.Runtime/Utilities/ListPool.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Extensions.ObjectPool;
+
+namespace Pchp.Core.Utilities
+{
+ public class ListPool
+ {
+ sealed class ListPoolPolicy : PooledObjectPolicy>
+ {
+ public override List Create() => new List();
+
+ public override bool Return(List obj)
+ {
+ if (obj.Count > 1024*1024)
+ {
+ return false;
+ }
+
+ obj.Clear();
+ return true;
+ }
+ }
+
+ public static readonly ObjectPool> Pool = new DefaultObjectPool>(new ListPoolPolicy());
+ }
+}
diff --git a/src/Peachpie.Runtime/Utilities/ObjectPools.cs b/src/Peachpie.Runtime/Utilities/ObjectPools.cs
index 611070f805..89e9ca2528 100644
--- a/src/Peachpie.Runtime/Utilities/ObjectPools.cs
+++ b/src/Peachpie.Runtime/Utilities/ObjectPools.cs
@@ -16,6 +16,8 @@ public static class ObjectPools
///
public static ObjectPool StringBuilderPool { get; } = new DefaultObjectPoolProvider().Create(new StringBuilderPooledObjectPolicy());
+ public static ObjectPool> GetListPool() => ListPool.Pool;
+
/// Gets pooled instance of .
public static StringBuilder GetStringBuilder() => StringBuilderPool.Get();