Implement llListFindListNext and llListFindStrided

This commit is contained in:
Sei Lisa 2024-04-19 13:47:26 +02:00
parent 914b57f603
commit 5ee290deff
5 changed files with 188 additions and 53 deletions

View file

@ -688,6 +688,86 @@ def InternalGetDeleteSubSequence(val, start, end, isGet):
return val[:end+1] + val[start:] if isGet else val[end+1:start]
return val[start:end+1] if isGet else val[:start] + val[end+1:]
def InternalCompareElems(e1, e2):
"""Compares two list elements according to llListFindList rules."""
# NaN is found in floats, but not in vectors
if type(e1) == type(e2) == float:
if e1 == e2:
return True
# Exceptionally, NaN equals NaN
if math.isnan(e1) and math.isnan(e2):
return True
# Mismatch
return False
elif type(e1) == type(e2) in (Vector, Quaternion):
# Act as if the list's vector/quat was all floats, even if not
if type(e1) == Vector:
e1 = v2f(e1)
e2 = v2f(e2)
else:
e1 = q2f(e1)
e2 = q2f(e2)
# Unfortunately, Python fails to consider (NaN,) != (NaN,) sometimes
# so we need to implement our own test
for e1e,e2e in zip(e1,e2):
# NaNs are considered different to themselves here as normal
if e1e != e2e:
# Mismatch in vector/quaternion component
break
else:
# No mismatch in any component
return True
# Mismatch
return False
elif type(e1) != type(e2) or e1 != e2:
return False
return True
def InternalListFindList(lst, elems, start, end, stride, instance):
"""Generalizes llListFindList with start/end, stride and instance args."""
L1 = len(lst)
L2 = len(elems)
if L1 == L2 == 0:
return 0 # an empty list is always found in an empty list
if L2 > L1:
return -1 # can't find a sublist longer than the original list
if start < 0:
start += L1
if end < 0:
end += L1
if end >= L1:
end = L1 - 1
if start < 0 or start >= L1 or end < 0 or end >= L1 or start > end:
return -1
if L2 == 0:
# empty list is always found at position 0
return 0
if stride < 1:
return -1 # stride 0 or negative returns -1
if instance >= 0:
# Forward search
for i in xrange(start, end+2-L2, stride):
for j in xrange(L2):
if not InternalCompareElems(lst[i+j], elems[j]):
break # mismatch
else:
# no mismatch
if instance == 0:
return i
instance -= 1
else:
# Backward search
for i in xrange(end+1-L2, start-1, -stride):
for j in xrange(L2):
if not InternalCompareElems(lst[i+j], elems[j]):
break # mismatch
else:
# no mismatch
instance += 1
if instance == 0:
return i
return -1
def reduce(t):
t = F32(t)
if not t.is_integer():
@ -1516,64 +1596,21 @@ def llList2Vector(lst, pos):
def llListFindList(lst, elems):
lst = fl(lst)
elems = fl(elems)
# NaN is found in floats, but not in vectors
L1 = len(lst)
L2 = len(elems)
if L2 > L1:
return -1 # can't find a sublist longer than the original list
if L2 == 0:
# empty list is always found at position 0
return 0
for i in xrange(L1-L2+1):
for j in xrange(L2):
e1 = lst[i+j]
e2 = elems[j]
if type(e1) == type(e2) == float:
if e1 == e2:
continue
# Exceptionally, NaN equals NaN
if math.isnan(e1) and math.isnan(e2):
continue
# Mismatch
break
elif type(e1) == type(e2) in (Vector, Quaternion):
# Act as if the list's vector/quat was all floats, even if not
if type(e1) == Vector:
e1 = v2f(e1)
e2 = v2f(e2)
else:
e1 = q2f(e1)
e2 = q2f(e2)
# Unfortunately, Python fails to consider (NaN,) != (NaN,) sometimes
# so we need to implement our own test
for e1e,e2e in zip(e1,e2):
if e1e != e2e: # NaNs are considered different to themselves here as normal
# Mismatch in vector/quaternion sub-element
break
else:
# No mismatch in any sub-element, try next list element
continue
break # discrepancy found
elif type(e1) != type(e2) or e1 != e2:
break # mismatch
else:
# no mismatch
return i
return -1
return InternalListFindList(lst, elems, 0, -1, 1, 0)
def llListFindListNext(src, test, n):
src = fl(src)
test = fl(test)
n = fi(n)
raise eLSLCantCompute # TODO: Implement llListFindListNext
def llListFindListNext(lst, elems, instance):
lst = fl(lst)
elems = fl(elems)
instance = fi(instance)
return InternalListFindList(lst, elems, 0, -1, 1, instance)
def llListFindStrided(src, test, start, end, stride):
src = fl(src)
test = fl(test)
def llListFindStrided(lst, elems, start, end, stride):
lst = fl(lst)
elems = fl(elems)
start = fi(start)
end = fi(end)
stride = fi(stride)
raise ELSLCantCompute # TODO: Implement llListFindStrided
return InternalListFindList(lst, elems, start, end, stride, 0)
def llListInsertList(lst, elems, pos):
lst = fl(lst)

View file

@ -0,0 +1,34 @@
[ llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 0, -1, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 2, -1, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 3, -1, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 2, -1, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -1, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -2, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",2], 0, -1, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 0, -1, 2)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 0, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 0, -1, 4)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 1, -1, 2)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -1, 2)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 4, -1, 2)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 4, -2, 2)
, llListFindStrided([0,1,2,3,4,5,6], [4], 4, 0, 2)
, llListFindStrided([], [], 3, 1, 2)
, llListFindStrided([], [], 3, 1, 0)
, llListFindStrided([], [], 0, 0, 0)
, llListFindStrided([1], [], 3, 1, 2)
, llListFindStrided([1], [], 3, 1, 1)
, llListFindStrided([1], [], 0, 1, 1)
, llListFindStrided([1], [], 0, 0, 0)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, 6, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 2, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 3, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 4, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 2, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 4, -1, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], -99999, 7, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], -99999, 7, 1)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, 99999, 3)
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 0, 99999, 1)
]

View file

@ -0,0 +1,34 @@
[ 2
, 2
, 6
, 2
, 6
, -1
, -1
, 4
, -1
, 4
, -1
, -1
, 6
, -1
, -1
, 0
, 0
, 0
, -1
, -1
, 0
, 0
, -1
, 2
, 6
, -1
, 2
, 6
, -1
, -1
, -1
, 6
, 2
]

View file

@ -0,0 +1,15 @@
[ llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 0)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 1)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 2)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 3)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -1)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -2)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -3)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -4)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], [3], 0)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], [<1,2,3>], -1)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], [<1,2,3>, "c"], -1)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["c"], -1)
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["c"], 0)
, llListFindList(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["c"])
]

View file

@ -0,0 +1,15 @@
[ 0
, 6
, 11
, -1
, 11
, 6
, 0
, -1
, -1
, 13
, 13
, 14
, 14
, 14
]