rewrote hanging llParseStringKeepNulls()

avinationmerge
Mike Rieker 2010-07-06 02:22:47 +00:00
parent 6c6c7b0927
commit 90c5555d6d
1 changed files with 139 additions and 164 deletions

View File

@ -8627,130 +8627,105 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
{
int beginning = 0;
int srclen = src.Length;
int seplen = separators.Length;
object[] separray = separators.Data;
int spclen = spacers.Length;
object[] spcarray = spacers.Data;
int mlen = seplen+spclen;
int[] offset = new int[mlen+1];
bool[] active = new bool[mlen];
int outlen = 0;
LSL_String[] outarray = new LSL_String[srclen*2+1];
int best;
int j;
// Initial capacity reduces resize cost
LSL_List tokens = new LSL_List();
int i, j, lastUsed;
m_host.AddScriptLPS(1);
// All entries are initially valid
/*
* Point to beginning of current non-delimeter string.
*/
lastUsed = 0;
for (int i = 0; i < mlen; i++)
active[i] = true;
/*
* Scan through source string from beginning to end.
*/
for (i = 0; i < srclen;) {
offset[mlen] = srclen;
/*
* See if rest of string (starting at i) matches any separator.
*/
string rest = src.Substring(i);
for (j = 0; j < seplen; j ++) {
string sep = separray[j].ToString();
if ((sep.Length > 0) && rest.StartsWith(sep)) {
while (beginning < srclen)
{
/*
* Separator matched, output string from end of last delimeter to beginning of this one.
*/
outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed));
best = mlen; // as bad as it gets
/*
* Remove separator from input string.
*/
i += sep.Length;
// Scan for separators
for (j = 0; j < seplen; j++)
{
if (active[j])
{
// scan all of the markers
if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1)
{
// not present at all
active[j] = false;
}
else
{
// present and correct
if (offset[j] < offset[best])
{
// closest so far
best = j;
if (offset[best] == beginning)
break;
}
}
/*
* Next non-delimeter starts where this separator left off.
*/
lastUsed = i;
goto nextsrc;
}
}
// Scan for spacers
/*
* See if rest of string (starting at i) matches any spacer.
*/
for (j = 0; j < spclen; j ++) {
string spc = spcarray[j].ToString();
if ((spc.Length > 0) && rest.StartsWith(spc)) {
if (offset[best] != beginning)
{
for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
{
if (active[j])
{
// scan all of the markers
if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
{
// not present at all
active[j] = false;
}
else
{
// present and correct
if (offset[j] < offset[best])
{
// closest so far
best = j;
}
}
}
/*
* Spacer matched, output string from end of last delimeter to beginning of this one.
* Then output the spacer itself.
*/
outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed));
outarray[outlen++] = new LSL_String(spc);
/*
* Remove spacer from input string.
*/
i += spc.Length;
/*
* Next non-delimeter starts where this spacer left off.
*/
lastUsed = i;
goto nextsrc;
}
}
// This is the normal exit from the scanning loop
if (best == mlen)
{
// no markers were found on this pass
// so we're pretty much done
tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
break;
/*
* Didn't match any separator or spacer, skip over it and it
* becomes part of the non-delimeter string starting with
* lastUsed.
*/
i ++;
nextsrc:;
}
// Otherwise we just add the newly delimited token
// and recalculate where the search should continue.
/*
* Output last non-delimeter (including a possible null string if
* delimeter ran to end of source string).
*/
outarray[outlen++] = new LSL_String(src.Substring(lastUsed));
tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning)));
if (best < seplen)
{
beginning = offset[best] + (separray[best].ToString()).Length;
/*
* Make up an exact-sized output array suitable for an LSL_List object.
*/
object[] outlist = new object[outlen];
for (i = 0; i < outlen; i ++) {
outlist[i] = outarray[i];
}
else
{
beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
tokens.Add(new LSL_String(spcarray[best - seplen].ToString()));
}
}
// This an awkward an not very intuitive boundary case. If the
// last substring is a tokenizer, then there is an implied trailing
// null list entry. Hopefully the single comparison will not be too
// arduous. Alternatively the 'break' could be replced with a return
// but that's shabby programming.
if (beginning == srclen)
{
if (srclen != 0)
tokens.Add(new LSL_String(""));
}
return tokens;
return new LSL_List(outlist);
}
public LSL_Integer llGetObjectPermMask(int mask)