mirror of
https://github.com/opensim/opensim.git
synced 2026-07-31 22:05:36 +08:00
add llListFindStrided; llListFindList change to be more as spec
This commit is contained in:
@@ -5596,6 +5596,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return 0;
|
||||
|
||||
object o = src.Data[index];
|
||||
if (o is null)
|
||||
return 0;
|
||||
if (o is LSL_Integer || o is Int32)
|
||||
return 1;
|
||||
if (o is LSL_Float || o is Single || o is Double)
|
||||
@@ -5611,9 +5613,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
if (o is LSL_List)
|
||||
return 7;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Process the supplied list and return the
|
||||
/// content of the list formatted as a comma
|
||||
@@ -6021,6 +6023,105 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
}
|
||||
|
||||
private bool ListFind_areEqual(object l, object r)
|
||||
{
|
||||
if (l is null || r is null)
|
||||
return false;
|
||||
|
||||
if (l is LSL_Integer lli)
|
||||
{
|
||||
if (r is LSL_Integer rli)
|
||||
return lli.value == rli.value;
|
||||
if (r is int ri)
|
||||
return lli.value == ri;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (l is int li)
|
||||
{
|
||||
if (r is LSL_Integer rli)
|
||||
return li == rli.value;
|
||||
if (r is int ri)
|
||||
return li == ri;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (l is LSL_Float llf)
|
||||
{
|
||||
if (r is LSL_Float rlf)
|
||||
return llf.value == rlf.value;
|
||||
if (r is float rf)
|
||||
return llf.value == (double)rf;
|
||||
if (r is double rd)
|
||||
return llf.value == rd;
|
||||
return false;
|
||||
}
|
||||
if (l is double ld)
|
||||
{
|
||||
if (r is LSL_Float rlf)
|
||||
return ld == rlf.value;
|
||||
if (r is float rf)
|
||||
return ld == (double)rf;
|
||||
if (r is double rd)
|
||||
return ld == rd;
|
||||
return false;
|
||||
}
|
||||
if (l is float lf)
|
||||
{
|
||||
if (r is LSL_Float rlf)
|
||||
return lf == (float)rlf.value;
|
||||
if (r is float rf)
|
||||
return lf == rf;
|
||||
if (r is double rd)
|
||||
return lf == (float)rd;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (l is LSL_String lls)
|
||||
{
|
||||
if (r is LSL_String rls)
|
||||
return lls.m_string.Equals(rls.m_string, StringComparison.Ordinal);
|
||||
if (r is string rs)
|
||||
return lls.m_string.Equals(rs, StringComparison.Ordinal);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (l is string ls)
|
||||
{
|
||||
if (r is LSL_String rls)
|
||||
return ls.Equals(rls.m_string, StringComparison.Ordinal);
|
||||
if (r is string rs)
|
||||
return ls.Equals(rs, StringComparison.Ordinal);
|
||||
if (r is LSL_Key rlk)
|
||||
return ls.Equals(rlk.m_string, StringComparison.OrdinalIgnoreCase);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(l is LSL_Key llk)
|
||||
{
|
||||
if (r is LSL_Key rlk)
|
||||
return llk.m_string.Equals(rlk.m_string, StringComparison.OrdinalIgnoreCase);
|
||||
if (r is string rk)
|
||||
return llk.m_string.Equals(rk, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
if (l is LSL_Vector llv)
|
||||
{
|
||||
if(r is LSL_Vector rlv)
|
||||
return llv.Equals(rlv);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (l is LSL_Rotation llr)
|
||||
{
|
||||
if(r is LSL_Rotation rlr)
|
||||
return llr.Equals(rlr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the first occurrence of test
|
||||
/// in src.
|
||||
@@ -6033,45 +6134,89 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
/// </returns>
|
||||
public LSL_Integer llListFindList(LSL_List src, LSL_List test)
|
||||
{
|
||||
int index = -1;
|
||||
int length = src.Length - test.Length + 1;
|
||||
if (src.Length == 0)
|
||||
return -1;
|
||||
if (test.Length == 0)
|
||||
return 0;
|
||||
if (test.Length > src.Length)
|
||||
return -1;
|
||||
|
||||
|
||||
// If either list is empty, do not match
|
||||
if (src.Length != 0 && test.Length != 0)
|
||||
object test0 = test[0];
|
||||
for (int i = 0; i <= src.Length - test.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
if (ListFind_areEqual(test0, src[i]))
|
||||
{
|
||||
int needle = llGetListEntryType(test, 0).value;
|
||||
int haystack = llGetListEntryType(src, i).value;
|
||||
|
||||
// Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
|
||||
// rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
|
||||
// and so the comparison fails even if the LSL_Integer conceptually has the same value.
|
||||
// Therefore, here we test Equals on both the source and destination objects.
|
||||
// However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
|
||||
if ((needle == haystack) && (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])))
|
||||
int k = i + 1;
|
||||
int j = 1;
|
||||
while(j < test.Length)
|
||||
{
|
||||
int j;
|
||||
for (j = 1; j < test.Length; j++)
|
||||
{
|
||||
needle = llGetListEntryType(test, j).value;
|
||||
haystack = llGetListEntryType(src, i+j).value;
|
||||
|
||||
if ((needle != haystack) || (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))))
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == test.Length)
|
||||
{
|
||||
index = i;
|
||||
if (!ListFind_areEqual(test[j], src[k]))
|
||||
break;
|
||||
}
|
||||
++j;
|
||||
++k;
|
||||
}
|
||||
|
||||
if (j == test.Length)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public LSL_Integer llListFindStrided(LSL_List src, LSL_List test, LSL_Integer lstart, LSL_Integer lend, LSL_Integer lstride)
|
||||
{
|
||||
if (src.Length == 0)
|
||||
return -1;
|
||||
if (test.Length == 0)
|
||||
return 0;
|
||||
if (test.Length > src.Length)
|
||||
return -1;
|
||||
|
||||
int start = lstart.value;
|
||||
if (start < 0)
|
||||
{
|
||||
start += src.Length;
|
||||
if (start < 0)
|
||||
return -1;
|
||||
}
|
||||
else if (start >= src.Length)
|
||||
return -1;
|
||||
|
||||
int end = lend.value;
|
||||
if (end < 0)
|
||||
{
|
||||
end += src.Length;
|
||||
if (end < 0)
|
||||
return -1;
|
||||
end -= test.Length - 1;
|
||||
}
|
||||
else if (end >= src.Length)
|
||||
end = src.Length - test.Length;
|
||||
|
||||
int stride = lstride.value;
|
||||
if (stride < 1)
|
||||
stride = 1;
|
||||
|
||||
object test0 = test[0];
|
||||
for (int i = start; i <= end; i += stride)
|
||||
{
|
||||
if (ListFind_areEqual(test0, src[i]))
|
||||
{
|
||||
int k = i + 1;
|
||||
int j = 1;
|
||||
while (j < test.Length)
|
||||
{
|
||||
if (!ListFind_areEqual(test[j], src[k]))
|
||||
break;
|
||||
++j;
|
||||
++k;
|
||||
}
|
||||
|
||||
if (j == test.Length)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public LSL_String llGetObjectName()
|
||||
|
||||
@@ -256,6 +256,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
void llListenControl(int number, int active);
|
||||
void llListenRemove(int number);
|
||||
LSL_Integer llListFindList(LSL_List src, LSL_List test);
|
||||
LSL_Integer llListFindStrided(LSL_List src, LSL_List test, LSL_Integer lstart, LSL_Integer lend, LSL_Integer lstride);
|
||||
LSL_List llListInsertList(LSL_List dest, LSL_List src, int start);
|
||||
LSL_List llListRandomize(LSL_List src, int stride);
|
||||
LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end);
|
||||
|
||||
@@ -1262,6 +1262,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
return m_LSL_Functions.llListFindList(src, test);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public LSL_Integer llListFindStrided(LSL_List src, LSL_List test, LSL_Integer lstart, LSL_Integer lend, LSL_Integer lstride)
|
||||
{
|
||||
return m_LSL_Functions.llListFindStrided(src, test, lstart, lend, lstride);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public LSL_List llListInsertList(LSL_List dest, LSL_List src, int start)
|
||||
{
|
||||
|
||||
@@ -824,32 +824,35 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
|
||||
foreach (object o in m_data)
|
||||
{
|
||||
if (o is LSL_Types.LSLInteger)
|
||||
size += 4;
|
||||
else if (o is LSL_Types.LSLFloat)
|
||||
size += 8;
|
||||
else if (o is LSL_Types.LSLString lso)
|
||||
size += lso.m_string is null ? 0 : lso.m_string.Length * sizeof(char);
|
||||
else if (o is LSL_Types.key ko)
|
||||
size += ko.value.Length;
|
||||
else if (o is LSL_Types.Vector3)
|
||||
size += 32;
|
||||
else if (o is LSL_Types.Quaternion)
|
||||
size += 64;
|
||||
else if (o is int)
|
||||
size += 4;
|
||||
else if (o is uint)
|
||||
size += 4;
|
||||
else if (o is string so)
|
||||
size += so.Length * sizeof(char);
|
||||
else if (o is float)
|
||||
size += 8;
|
||||
else if (o is double)
|
||||
size += 16;
|
||||
else if (o is list lo)
|
||||
size += lo.Size;
|
||||
else
|
||||
throw new Exception("Unknown type in List.Size: " + o.GetType().ToString());
|
||||
// here modern sugar alternatives with switch or switch statement generate crap code on dotnet6
|
||||
if (o is null) // this explicit test does improve release jit code, otherwise it is present on ALL its
|
||||
throw new Exception("null entry in List.Size");
|
||||
else if (o is LSL_Types.LSLInteger)
|
||||
size += sizeof(int);
|
||||
else if (o is LSL_Types.LSLFloat)
|
||||
size += sizeof(double);
|
||||
else if (o is LSL_Types.LSLString lso)
|
||||
size += lso.m_string is null ? 0 : lso.m_string.Length * sizeof(char);
|
||||
else if (o is LSL_Types.key ko)
|
||||
size += ko.value.Length;
|
||||
else if (o is LSL_Types.Vector3)
|
||||
size += 3 * sizeof(double);
|
||||
else if (o is LSL_Types.Quaternion)
|
||||
size += 4 * sizeof(double);
|
||||
else if (o is int)
|
||||
size += sizeof(int);
|
||||
else if (o is uint)
|
||||
size += sizeof(uint);
|
||||
else if (o is string so)
|
||||
size += so.Length * sizeof(char);
|
||||
else if (o is float)
|
||||
size += sizeof(float);
|
||||
else if (o is double)
|
||||
size += sizeof(double);
|
||||
else if (o is list lo)
|
||||
size += lo.Size;
|
||||
else
|
||||
throw new Exception("Unknown type in List.Size: " + o.GetType().ToString());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@@ -1133,6 +1136,22 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
m_data = tmp;
|
||||
}
|
||||
|
||||
public object this[int i]
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_data is null || i >= m_data.Length)
|
||||
return null;
|
||||
return m_data[i];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_data is null || i >= m_data.Length)
|
||||
return;
|
||||
m_data[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator Boolean(list l)
|
||||
{
|
||||
return l.Length != 0;
|
||||
@@ -1358,6 +1377,9 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
|
||||
private static int compare(object left, object right, bool ascending)
|
||||
{
|
||||
if(left is null)
|
||||
return 0;
|
||||
|
||||
if (!left.GetType().Equals(right.GetType()))
|
||||
{
|
||||
// unequal types are always "equal" for comparison purposes.
|
||||
@@ -1415,6 +1437,9 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
|
||||
public int Compare(object left, object right)
|
||||
{
|
||||
if (left is null)
|
||||
return 0;
|
||||
|
||||
int ret;
|
||||
if (left is LSLInteger il)
|
||||
{
|
||||
@@ -1455,27 +1480,30 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
|
||||
private static bool needSwapAscending(object left, object right)
|
||||
{
|
||||
if (left is null)
|
||||
return false;
|
||||
|
||||
if (left is LSLInteger li)
|
||||
{
|
||||
LSLInteger r = (LSLInteger)right;
|
||||
return li.value > r.value;
|
||||
}
|
||||
else if (left is LSLString lsl)
|
||||
if (left is LSLString lsl)
|
||||
{
|
||||
LSLString r = (LSLString)right;
|
||||
return string.CompareOrdinal(lsl.m_string, r.m_string) > 0;
|
||||
}
|
||||
else if (left is LSLFloat lf)
|
||||
if (left is LSLFloat lf)
|
||||
{
|
||||
LSLFloat r = (LSLFloat)right;
|
||||
return lf.value > r.value;
|
||||
}
|
||||
else if (left is Vector3 lv)
|
||||
if (left is Vector3 lv)
|
||||
{
|
||||
Vector3 r = (Vector3)right;
|
||||
return Vector3.MagSquare(lv) > Vector3.MagSquare(r);
|
||||
}
|
||||
else if (left is key lk)
|
||||
if (left is key lk)
|
||||
{
|
||||
key r = (key)right;
|
||||
return string.CompareOrdinal(lk.value, r.value) > 0;
|
||||
@@ -1485,27 +1513,30 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
|
||||
private static bool needSwapDescending(object left, object right)
|
||||
{
|
||||
if (left is null)
|
||||
return false;
|
||||
|
||||
if (left is LSLInteger li)
|
||||
{
|
||||
LSLInteger r = (LSLInteger)right;
|
||||
return li.value < r.value;
|
||||
}
|
||||
else if (left is LSLString lsl)
|
||||
if (left is LSLString lsl)
|
||||
{
|
||||
LSLString r = (LSLString)right;
|
||||
return string.CompareOrdinal(lsl.m_string, r.m_string) < 0;
|
||||
}
|
||||
else if (left is LSLFloat lf)
|
||||
if (left is LSLFloat lf)
|
||||
{
|
||||
LSLFloat r = (LSLFloat)right;
|
||||
return lf.value < r.value;
|
||||
}
|
||||
else if (left is Vector3 lv)
|
||||
if (left is Vector3 lv)
|
||||
{
|
||||
Vector3 r = (Vector3)right;
|
||||
return Vector3.MagSquare(lv) < Vector3.MagSquare(r);
|
||||
}
|
||||
else if (left is key lk)
|
||||
if (left is key lk)
|
||||
{
|
||||
key r = (key)right;
|
||||
return string.CompareOrdinal(lk.value, r.value) < 0;
|
||||
|
||||
Reference in New Issue
Block a user