From 4c061a0602a27a4185aef82999c0953268bbbf43 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 26 Apr 2023 20:26:01 +0100 Subject: [PATCH] add llListSortStrided and osListSortInPlaceStrided --- .../Shared/Api/Implementation/LSL_Api.cs | 5 + .../Shared/Api/Implementation/OSSL_Api.cs | 5 + .../Shared/Api/Interface/ILSL_Api.cs | 1 + .../Shared/Api/Interface/IOSSL_Api.cs | 2 +- .../Shared/Api/Runtime/LSL_Stub.cs | 6 + .../Shared/Api/Runtime/OSSL_Stub.cs | 6 + .../Region/ScriptEngine/Shared/LSL_Types.cs | 136 +++++++++++++++++- 7 files changed, 156 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1121ec72ae..d4469bcf5c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5407,6 +5407,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return src.Sort(stride, ascending == 1); } + public LSL_List llListSortStrided(LSL_List src, int stride, int stride_index, int ascending) + { + return src.Sort(stride, stride_index, ascending == 1); + } + public LSL_Integer llGetListLength(LSL_List src) { return src.Length; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index cf468b8ff5..91caeb9447 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -5997,6 +5997,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api src.SortInPlace(stride, ascending == 1); } + public void osListSortInPlaceStrided(LSL_List src, LSL_Integer stride, LSL_Integer stride_index, LSL_Integer ascending) + { + src.SortInPlace(stride, stride_index, ascending == 1); + } + public LSL_List osGetParcelDetails(LSL_Key id, LSL_List param) { if (!UUID.TryParse(id, out UUID parcelID)) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 806143ee9e..9cf7db8238 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -259,6 +259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_List llListRandomize(LSL_List src, int stride); LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end); LSL_List llListSort(LSL_List src, int stride, int ascending); + LSL_List llListSortStrided(LSL_List src, int stride, int stride_index, int ascending); LSL_Float llListStatistics(int operation, LSL_List src); void llLoadURL(string avatar_id, string message, string url); LSL_Float llLog(double val); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 9436359429..6fb440c1db 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -598,7 +598,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Integer osAvatarType(LSL_Key avkey); LSL_Integer osAvatarType(LSL_String sFirstName, LSL_String sLastName); void osListSortInPlace(LSL_List src, LSL_Integer stride, LSL_Integer ascending); - + void osListSortInPlaceStrided(LSL_List src, LSL_Integer stride, LSL_Integer stride_index, LSL_Integer ascending); LSL_List osGetParcelDetails(LSL_Key id, LSL_List param); public LSL_List osGetParcelIDs(); public LSL_Key osGetParcelID(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index b499bbdf5d..a85c4bf37a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -1280,6 +1280,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llListSort(src, stride, ascending); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public LSL_List llListSortStrided(LSL_List src, int stride, int stride_index, int ascending) + { + return m_LSL_Functions.llListSortStrided(src, stride, stride_index, ascending); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public LSL_Float llListStatistics(int operation, LSL_List src) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index ddbc3027c2..705ebd3eae 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -1636,6 +1636,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osListSortInPlace(src, stride, ascending); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void osListSortInPlaceStrided(LSL_List src, LSL_Integer stride, LSL_Integer stride_index, LSL_Integer ascending) + { + m_OSSL_Functions.osListSortInPlaceStrided(src, stride, stride_index, ascending); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public LSL_List osGetParcelDetails(LSL_Key id, LSL_List param) { diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 807773b9f0..545d2e7a74 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1483,7 +1483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared else if (left is Vector3 lv) { Vector3 r = (Vector3)right; - return Vector3.MagSquare(lv) > Vector3.Mag(r); + return Vector3.MagSquare(lv) > Vector3.MagSquare(r); } else if (left is key lk) { @@ -1533,7 +1533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(); // Don't even bother object[] ret = new object[len]; - Array.Copy(m_data, 0, ret, 0, len); + m_data.CopyTo(ret, 0); if (stride < 1) stride = 1; @@ -1545,6 +1545,49 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(ret); } + public list Sort(int stride, int stride_index, bool ascending) + { + if (m_data is null) + return new list(); // Don't even bother + + int len = m_data.Length; + if (len == 0) + return new list(); // Don't even bother + + if (stride < 1) + stride = 1; + + if (stride_index < 0) + { + stride_index = stride + stride_index; + if (stride_index < 0) + return new list(); + } + else if (stride_index >= stride) + return new list(); + + object[] ret = new object[len]; + m_data.CopyTo(ret, 0); + + if (len <= stride) + return new list(ret); + + if (stride == 1) + { + Sort(ret, stride, ascending); + return new list(ret); + } + + if (len % stride == 0) + { + if (stride_index == 0) + Sort(ret, stride, ascending); + else + Sort(ret, stride, stride_index, ascending); + } + return new list(ret); + } + public void SortInPlace(int stride, bool ascending) { if (m_data is null) @@ -1560,6 +1603,33 @@ namespace OpenSim.Region.ScriptEngine.Shared Sort(m_data, stride, ascending); } + public void SortInPlace(int stride, int stride_index, bool ascending) + { + if (m_data is null) + return; // Don't even bother + + if (stride < 1) + stride = 1; + + if (stride_index < 0) + { + stride_index = stride + stride_index; + if (stride_index < 0) + return; + } + else if (stride_index >= stride) + return; + + int len = m_data.Length; + if ((len <= stride) || (len % stride) != 0) + return; + + if(stride_index == 0) + Sort(m_data, stride, ascending); + else + Sort(m_data, stride,stride_index, ascending); + } + public void Sort(object[] ret, int stride, bool ascending) { // if list does not consists of homogeneous types @@ -1595,7 +1665,7 @@ namespace OpenSim.Region.ScriptEngine.Shared for (int j = i + 1; j < ret.Length; ++j) { object tmp = ret[j]; - if (tmp.GetType() == pivotType && needSwapAscending(pivot, tmp)) + if (pivotType.Equals(tmp.GetType()) && needSwapAscending(pivot, tmp)) { ret[j] = pivot; pivot = tmp; @@ -1613,7 +1683,7 @@ namespace OpenSim.Region.ScriptEngine.Shared for (int j = i + 1; j < ret.Length; ++j) { object tmp = ret[j]; - if (tmp.GetType() == pivotType && needSwapDescending(pivot, tmp)) + if (pivotType.Equals(tmp.GetType()) && needSwapDescending(pivot, tmp)) { ret[j] = pivot; pivot = tmp; @@ -1688,6 +1758,64 @@ namespace OpenSim.Region.ScriptEngine.Shared } } + public void Sort(object[] ret, int stride, int stride_index, bool ascending) + { + if (ascending) + { + for (int i = stride_index; i < ret.Length - stride; i += stride) + { + object pivot = ret[i]; + Type pivotType = pivot.GetType(); + for (int j = i + stride; j < ret.Length; j += stride) + { + object tmp = ret[j]; + if (pivotType.Equals(tmp.GetType()) && needSwapAscending(pivot, tmp)) + { + pivot = tmp; + int ik = i - stride_index; + int end = ik + stride; + int jk = j - stride_index; + while (ik < end) + { + tmp = ret[ik]; + ret[ik] = ret[jk]; + ret[jk] = tmp; + ++ik; + ++jk; + } + } + } + } + } + else + { + for (int i = stride_index; i < ret.Length - stride; i += stride) + { + object pivot = ret[i]; + Type pivotType = pivot.GetType(); + for (int j = i + stride; j < ret.Length; j += stride) + { + object tmp = ret[j]; + if (pivotType.Equals(tmp.GetType()) && needSwapDescending(pivot, tmp)) + { + pivot = tmp; + int ik = i - stride_index; + int end = ik + stride; + int jk = j - stride_index; + while (ik < end) + { + tmp = ret[ik]; + ret[ik] = ret[jk]; + ret[jk] = tmp; + ++ik; + ++jk; + } + } + } + } + } + } + #region CSV Methods public static list FromCSV(string csv)