a few more changes to lsl list

This commit is contained in:
UbitUmarov
2021-05-31 15:12:37 +01:00
parent 8bcebf0190
commit 3e948d8c57

View File

@@ -679,7 +679,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
get
{
if (m_data == null)
m_data=new Object[0];
m_data=new object[0];
return m_data.Length;
}
}
@@ -689,11 +689,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
get
{
if (m_data == null)
m_data=new Object[0];
return 0;
int size = 0;
foreach (Object o in m_data)
foreach (object o in m_data)
{
if (o is LSL_Types.LSLInteger)
size += 4;
@@ -730,7 +730,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
{
get {
if (m_data == null)
m_data=new Object[0];
m_data=new object[0];
return m_data;
}
@@ -765,131 +765,106 @@ namespace OpenSim.Region.ScriptEngine.Shared
/// <param name='itemIndex'></param>
public LSL_Types.LSLFloat GetLSLFloatItem(int itemIndex)
{
if (Data[itemIndex] is LSL_Types.LSLInteger)
{
return (LSL_Types.LSLInteger)Data[itemIndex];
}
else if (Data[itemIndex] is Int32)
{
return new LSL_Types.LSLFloat((int)Data[itemIndex]);
}
else if (Data[itemIndex] is float)
{
return new LSL_Types.LSLFloat((float)Data[itemIndex]);
}
else if (Data[itemIndex] is Double)
{
return new LSL_Types.LSLFloat((Double)Data[itemIndex]);
}
else if (Data[itemIndex] is LSL_Types.LSLString)
{
return new LSL_Types.LSLFloat(Data[itemIndex].ToString());
}
else
{
return (LSL_Types.LSLFloat)Data[itemIndex];
}
object o = Data[itemIndex];
if (o is LSL_Types.LSLInteger)
return (LSL_Types.LSLInteger)o;
if (o is Int32)
return new LSL_Types.LSLFloat((int)o);
if (o is float)
return new LSL_Types.LSLFloat((float)o);
if (o is Double)
return new LSL_Types.LSLFloat((Double)o);
if (o is LSL_Types.LSLString)
return new LSL_Types.LSLFloat(o.ToString());
return (LSL_Types.LSLFloat)o;
}
public LSL_Types.LSLString GetLSLStringItem(int itemIndex)
{
if (Data[itemIndex] is LSL_Types.key)
{
return (LSL_Types.key)Data[itemIndex];
}
else
{
return new LSL_Types.LSLString(Data[itemIndex].ToString());
}
object o = Data[itemIndex];
if (o is LSL_Types.key)
return (LSL_Types.key)o;
return new LSL_Types.LSLString(o.ToString());
}
public LSL_Types.LSLInteger GetLSLIntegerItem(int itemIndex)
{
if (Data[itemIndex] is LSL_Types.LSLInteger)
return (LSL_Types.LSLInteger)Data[itemIndex];
if (Data[itemIndex] is LSL_Types.LSLFloat)
return new LSLInteger((int)Data[itemIndex]);
else if (Data[itemIndex] is Int32)
return new LSLInteger((int)Data[itemIndex]);
else if (Data[itemIndex] is LSL_Types.LSLString)
return new LSLInteger(Data[itemIndex].ToString());
else
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.LSLInteger).Name,
Data[itemIndex] != null ?
Data[itemIndex].GetType().Name : "null"));
object o = Data[itemIndex];
if (o is LSL_Types.LSLInteger)
return (LSL_Types.LSLInteger)o;
if (o is LSL_Types.LSLFloat)
return new LSLInteger((int)o);
if (o is Int32)
return new LSLInteger((int)o);
if (o is LSL_Types.LSLString)
return new LSLInteger(o.ToString());
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.LSLInteger).Name,
o != null ?
o.GetType().Name : "null"));
}
public LSL_Types.Vector3 GetVector3Item(int itemIndex)
{
if (Data[itemIndex] is LSL_Types.Vector3)
{
return (LSL_Types.Vector3)Data[itemIndex];
}
else if(Data[itemIndex] is OpenMetaverse.Vector3)
{
return new LSL_Types.Vector3(
(OpenMetaverse.Vector3)Data[itemIndex]);
}
else
{
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.Vector3).Name,
Data[itemIndex] != null ?
Data[itemIndex].GetType().Name : "null"));
}
object o = Data[itemIndex];
if (o is LSL_Types.Vector3)
return (LSL_Types.Vector3)o;
if(o is OpenMetaverse.Vector3)
return new LSL_Types.Vector3((OpenMetaverse.Vector3)o);
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.Vector3).Name,
o != null ?
o.GetType().Name : "null"));
}
// use LSL_Types.Quaternion to parse and store a vector4 for lightShare
public LSL_Types.Quaternion GetVector4Item(int itemIndex)
{
if (Data[itemIndex] is LSL_Types.Quaternion)
object o = Data[itemIndex];
if (o is LSL_Types.Quaternion)
{
LSL_Types.Quaternion q = (LSL_Types.Quaternion)Data[itemIndex];
LSL_Types.Quaternion q = (LSL_Types.Quaternion)o;
return q;
}
else if(Data[itemIndex] is OpenMetaverse.Quaternion)
if(o is OpenMetaverse.Quaternion)
{
LSL_Types.Quaternion q = new LSL_Types.Quaternion(
(OpenMetaverse.Quaternion)Data[itemIndex]);
LSL_Types.Quaternion q = new LSL_Types.Quaternion((OpenMetaverse.Quaternion)o);
q.Normalize();
return q;
}
else
{
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.Quaternion).Name,
Data[itemIndex] != null ?
Data[itemIndex].GetType().Name : "null"));
}
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.Quaternion).Name,
o != null ?
o.GetType().Name : "null"));
}
public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
{
if (Data[itemIndex] is LSL_Types.Quaternion)
object o = Data[itemIndex];
if (o is LSL_Types.Quaternion)
{
LSL_Types.Quaternion q = (LSL_Types.Quaternion)Data[itemIndex];
LSL_Types.Quaternion q = (LSL_Types.Quaternion)o;
q.Normalize();
return q;
}
else if(Data[itemIndex] is OpenMetaverse.Quaternion)
if(o is OpenMetaverse.Quaternion)
{
LSL_Types.Quaternion q = new LSL_Types.Quaternion(
(OpenMetaverse.Quaternion)Data[itemIndex]);
LSL_Types.Quaternion q = new LSL_Types.Quaternion((OpenMetaverse.Quaternion)o);
q.Normalize();
return q;
}
else
{
throw new InvalidCastException(string.Format(
throw new InvalidCastException(string.Format(
"{0} expected but {1} given",
typeof(LSL_Types.Quaternion).Name,
Data[itemIndex] != null ?
Data[itemIndex].GetType().Name : "null"));
}
}
public LSL_Types.key GetKeyItem(int itemIndex)
@@ -909,10 +884,18 @@ namespace OpenSim.Region.ScriptEngine.Shared
private void ExtendAndAdd(object o)
{
object[] tmp;
tmp = new object[Data.Length + 1];
Data.CopyTo(tmp, 0);
tmp.SetValue(o, tmp.Length - 1);
Data = tmp;
if(m_data == null || m_data.Length == 0)
{
tmp = new object[1];
tmp.SetValue(o, 0);
}
else
{
tmp = new object[m_data.Length + 1];
m_data.CopyTo(tmp, 0);
tmp.SetValue(o, tmp.Length - 1);
}
m_data = tmp;
}
public static implicit operator Boolean(list l)
@@ -965,24 +948,30 @@ namespace OpenSim.Region.ScriptEngine.Shared
public void Add(object o)
{
object[] tmp;
tmp = new object[Data.Length + 1];
Data.CopyTo(tmp, 0);
tmp[Data.Length] = o; // Since this is tmp.Length - 1
Data = tmp;
if(m_data == null || m_data.Length == 0)
{
tmp = new object[1];
tmp[0] = o;
}
else
{
tmp = new object[m_data.Length + 1];
m_data.CopyTo(tmp, 0);
tmp[m_data.Length] = o; // Since this is tmp.Length - 1
}
m_data = tmp;
}
public bool Contains(object o)
{
bool ret = false;
foreach (object i in Data)
if (m_data == null)
return false;
foreach (object i in m_data)
{
if (i == o)
{
ret = true;
break;
}
return true;
}
return ret;
return false;
}
public list DeleteSublist(int start, int end)
@@ -991,67 +980,69 @@ namespace OpenSim.Region.ScriptEngine.Shared
// If start <= end, remove that part
// if either is negative, count from the end of the array
// if the resulting start > end, keep [end + 1, start - 1]
if(m_data == null || m_data.Length == 0)
return new list(new object[0]);
int len = m_data.Length;
object[] ret;
if (start < 0)
start=Data.Length + start;
start= len + start;
if (start < 0)
start=0;
if (end < 0)
end=Data.Length + end;
end= len + end;
if (end < 0)
end=0;
if (start > end)
{
end++;
if (end >= Data.Length)
if (end >= len)
return new list(new object[0]);
start--;
if (start >= Data.Length)
start = Data.Length - 1;
if (start >= len)
start = len - 1;
int num = start - end + 1;
if(num <= 0)
return new list(new object[0]);
ret = new object[num];
Array.Copy(Data, end, ret, 0, num);
Array.Copy(m_data, end, ret, 0, num);
return new list(ret);
}
// start >= 0 && end >= 0 here
if (start >= Data.Length)
if (start >= len)
{
ret = new object[Data.Length];
Array.Copy(Data, 0, ret, 0, Data.Length);
ret = new object[len];
Array.Copy(m_data, 0, ret, 0, len);
return new list(ret);
}
if (end >= Data.Length)
end = Data.Length-1;
if (end >= len)
end = len - 1;
end++;
// now, this makes the math easier
int remove = end - start;
if(remove >= Data.Length)
if(remove >= len)
return new list(new object[0]);
ret = new object[Data.Length - remove];
ret = new object[len - remove];
if (start > 0)
Array.Copy(Data, 0, ret, 0, start);
Array.Copy(m_data, 0, ret, 0, start);
if(end >= Data.Length)
if(end >= len)
return new list(ret);
Array.Copy(Data, end, ret, start, Data.Length - end);
Array.Copy(m_data, end, ret, start, len - end);
return new list(ret);
}
@@ -1132,7 +1123,6 @@ namespace OpenSim.Region.ScriptEngine.Shared
{
return this;
}
}
else
{
@@ -1206,42 +1196,155 @@ namespace OpenSim.Region.ScriptEngine.Shared
class HomogeneousComparer : IComparer
{
//both sides known to be of same type
private readonly bool ascending;
public HomogeneousComparer(bool ascend)
{
ascending = ascend;
}
public int Compare(object lhs, object rhs)
public int Compare(object left, object right)
{
return compare(lhs, rhs, ascending);
int ret = 0;
if (left is LSLInteger)
{
LSLInteger l = (LSLInteger)left;
LSLInteger r = (LSLInteger)right;
ret = Math.Sign(l.value - r.value);
}
else if (left is LSLString)
{
LSLString l = (LSLString)left;
LSLString r = (LSLString)right;
ret = string.CompareOrdinal(l.m_string, r.m_string);
}
else if (left is LSLFloat)
{
LSLFloat l = (LSLFloat)left;
LSLFloat r = (LSLFloat)right;
ret = Math.Sign(l.value - r.value);
}
else if (left is Vector3)
{
Vector3 l = (Vector3)left;
Vector3 r = (Vector3)right;
ret = Math.Sign(Vector3.MagSquare(l) - Vector3.MagSquare(r));
}
else if (left is key)
{
key l = (key)left;
key r = (key)right;
ret = string.CompareOrdinal(l.value, r.value);
}
else //if (left is Quaternion) and unknown types
{
return 0;
}
if (ascending)
return ret;
return -ret;
}
}
private static bool needSwapAscending(object left, object right)
{
if (left is LSLInteger)
{
LSLInteger l = (LSLInteger)left;
LSLInteger r = (LSLInteger)right;
return l.value > r.value;
}
else if (left is LSLString)
{
LSLString l = (LSLString)left;
LSLString r = (LSLString)right;
return string.CompareOrdinal(l.m_string, r.m_string) > 0;
}
else if (left is LSLFloat)
{
LSLFloat l = (LSLFloat)left;
LSLFloat r = (LSLFloat)right;
return l.value > r.value;
}
else if (left is Vector3)
{
Vector3 l = (Vector3)left;
Vector3 r = (Vector3)right;
return Vector3.MagSquare(l) > Vector3.Mag(r);
}
else if (left is key)
{
key l = (key)left;
key r = (key)right;
return string.CompareOrdinal(l.value, r.value) > 0;
}
return false;
}
private static bool needSwapDescending(object left, object right)
{
if (left is LSLInteger)
{
LSLInteger l = (LSLInteger)left;
LSLInteger r = (LSLInteger)right;
return l.value < r.value;
}
else if (left is LSLString)
{
LSLString l = (LSLString)left;
LSLString r = (LSLString)right;
return string.CompareOrdinal(l.m_string, r.m_string) < 0;
}
else if (left is LSLFloat)
{
LSLFloat l = (LSLFloat)left;
LSLFloat r = (LSLFloat)right;
return l.value < r.value;
}
else if (left is Vector3)
{
Vector3 l = (Vector3)left;
Vector3 r = (Vector3)right;
return Vector3.MagSquare(l) < Vector3.MagSquare(r);
}
else if (left is key)
{
key l = (key)left;
key r = (key)right;
return string.CompareOrdinal(l.value, r.value) < 0;
}
return false;
}
public list Sort(int stride, bool ascending)
{
if (Data.Length == 0)
if (m_data == null || m_data.Length == 0)
return new list(); // Don't even bother
object[] ret = new object[Data.Length];
Array.Copy(Data, 0, ret, 0, Data.Length);
object[] ret = new object[m_data.Length];
Array.Copy(m_data, 0, ret, 0, m_data.Length);
if (stride <= 0)
stride = 1;
if ((ret.Length % stride) != 0)
if ((ret.Length <= stride) || (ret.Length % stride) != 0)
return new list(ret);
// we can optimize here in the case where stride == 1 and the list
// consists of homogeneous types
// if list does not consists of homogeneous types
// and because of the desired type specific feathered sorting behavior
// requeried by the spec, we MUST use a non-optimized bubble sort
// Anything else will give you the incorrect behavior.
// we can optimize the case where stride == 1
if (stride == 1)
{
bool homogeneous = true;
Type firstType = ret[0].GetType();
for (int index = 1; index < ret.Length; index++)
for (int i = 1; i < ret.Length; ++i)
{
if (!firstType.Equals(ret[index].GetType()))
if (!firstType.Equals(ret[i].GetType()))
{
homogeneous = false;
break;
@@ -1249,36 +1352,105 @@ namespace OpenSim.Region.ScriptEngine.Shared
}
if (homogeneous)
{
// big boost using native Sort with its faster sorting methods.
Array.Sort(ret, new HomogeneousComparer(ascending));
return new list(ret);
else
{
if (ascending)
{
for (int i = 0; i < ret.Length - 1; ++i)
{
object pivot = ret[i];
Type pivotType = pivot.GetType();
for (int j = i + 1; j < ret.Length; ++j)
{
object tmp = ret[j];
if (tmp.GetType() == pivotType && needSwapAscending(pivot, tmp))
{
ret[j] = pivot;
ret[i] = tmp;
pivot = tmp;
}
}
}
}
else
{
for (int i = 0; i < ret.Length - 1; ++i)
{
object pivot = ret[i];
Type pivotType = pivot.GetType();
for (int j = i + 1; j < ret.Length; ++j)
{
object tmp = ret[j];
if (tmp.GetType() == pivotType && needSwapDescending(pivot, tmp))
{
ret[j] = pivot;
ret[i] = tmp;
pivot = tmp;
for (int k = 1; k < stride; k++)
{
tmp = ret[i + k];
ret[i + k] = ret[j + k];
ret[j + k] = tmp;
}
}
}
}
}
}
return new list(ret);
}
// Because of the desired type specific feathered sorting behavior
// requried by the spec, we MUST use a non-optimized bubble sort here.
// Anything else will give you the incorrect behavior.
for (int i = 0; i < ret.Length - stride; i += stride)
if (ascending)
{
object o = ret[i];
for (int j = i + stride; j < ret.Length; j += stride)
for (int i = 0; i < ret.Length - stride; i += stride)
{
if (compare(o, ret[j], ascending) > 0)
object pivot = ret[i];
Type pivotType = pivot.GetType();
for (int j = i + stride; j < ret.Length; j += stride)
{
ret[i] = ret[j];
ret[j] = o;
o = ret[i];
for (int k = 1; k < stride; k++)
object tmp = ret[j];
if (tmp.GetType() == pivotType && needSwapAscending(pivot, tmp))
{
object tmp = ret[i + k];
ret[i + k] = ret[j + k];
ret[j + k] = tmp;
ret[j] = pivot;
ret[i] = tmp;
pivot = tmp;
for (int k = 1; k < stride; k++)
{
tmp = ret[i + k];
ret[i + k] = ret[j + k];
ret[j + k] = tmp;
}
}
}
}
}
else
{
for (int i = 0; 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 (tmp.GetType() == pivotType && needSwapDescending(pivot, tmp))
{
ret[j] = pivot;
ret[i] = tmp;
pivot = tmp;
for (int k = 1; k < stride; k++)
{
tmp = ret[i + k];
ret[i + k] = ret[j + k];
ret[j + k] = tmp;
}
}
}
}
}
// end bubble sort
return new list(ret);
}
@@ -1348,7 +1520,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
if (double.TryParse(m_data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
if (entry < minimum) minimum = entry;
}
@@ -1362,7 +1534,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
if (double.TryParse(m_data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
if (entry > maximum) maximum = entry;
}
@@ -1381,7 +1553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
if (double.TryParse(m_data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
count++;
}
@@ -1395,7 +1567,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
double entry;
for (int i = 0; i < src.Data.Length; i++)
{
if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
if (double.TryParse(src.m_data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
ret.Add(entry);
}
@@ -1409,7 +1581,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
if (double.TryParse(m_data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
sum = sum + entry;
}
@@ -1423,7 +1595,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
if (double.TryParse(m_data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
sum = sum + Math.Pow(entry, 2);
}