From 5ed5d0788b339978e28e1be1682a9c8282297c67 Mon Sep 17 00:00:00 2001 From: Charles Krinke Date: Sat, 16 Aug 2008 02:39:46 +0000 Subject: Mantis#1890. Thank you kindly, Godfrey, for a patch that addresses: llListSort() sorts integers and floats in ASCII order rather than numeric order --- OpenSim/Region/ScriptEngine/Common/LSL_Types.cs | 96 ++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ScriptEngine') diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs index 4fff717..3b2594d 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs @@ -634,6 +634,98 @@ namespace OpenSim.Region.ScriptEngine.Common } } + private class AlphanumComparatorFast : IComparer + { + public int Compare(object x, object y) + { + string s1 = x as string; + if (s1 == null) + { + return 0; + } + string s2 = y as string; + if (s2 == null) + { + return 0; + } + + int len1 = s1.Length; + int len2 = s2.Length; + int marker1 = 0; + int marker2 = 0; + + // Walk through two the strings with two markers. + while (marker1 < len1 && marker2 < len2) + { + char ch1 = s1[marker1]; + char ch2 = s2[marker2]; + + // Some buffers we can build up characters in for each chunk. + char[] space1 = new char[len1]; + int loc1 = 0; + char[] space2 = new char[len2]; + int loc2 = 0; + + // Walk through all following characters that are digits or + // characters in BOTH strings starting at the appropriate marker. + // Collect char arrays. + do + { + space1[loc1++] = ch1; + marker1++; + + if (marker1 < len1) + { + ch1 = s1[marker1]; + } + else + { + break; + } + } while (char.IsDigit(ch1) == char.IsDigit(space1[0])); + + do + { + space2[loc2++] = ch2; + marker2++; + + if (marker2 < len2) + { + ch2 = s2[marker2]; + } + else + { + break; + } + } while (char.IsDigit(ch2) == char.IsDigit(space2[0])); + + // If we have collected numbers, compare them numerically. + // Otherwise, if we have strings, compare them alphabetically. + string str1 = new string(space1); + string str2 = new string(space2); + + int result; + + if (char.IsDigit(space1[0]) && char.IsDigit(space2[0])) + { + int thisNumericChunk = int.Parse(str1); + int thatNumericChunk = int.Parse(str2); + result = thisNumericChunk.CompareTo(thatNumericChunk); + } + else + { + result = str1.CompareTo(str2); + } + + if (result != 0) + { + return result; + } + } + return len1 - len2; + } + } + public list Sort(int stride, int ascending) { if (Data.Length == 0) @@ -652,7 +744,7 @@ namespace OpenSim.Region.ScriptEngine.Common for (int k = 0; k < Data.Length; k++) keys[k] = Data[k].ToString(); - Array.Sort(keys, ret); + Array.Sort( keys, ret, new AlphanumComparatorFast() ); if (ascending == 0) Array.Reverse(ret); @@ -688,7 +780,7 @@ namespace OpenSim.Region.ScriptEngine.Common vals[idx]=o; } - Array.Sort(keys, vals); + Array.Sort(keys, vals, new AlphanumComparatorFast()); if (ascending == 0) { Array.Reverse(vals); -- cgit v1.1