minimizes temp garbage for llParseStringKeepNulls()

and uses common routine for llParseStringKeepNulls()/llParseString2List()
avinationmerge
Mike Rieker 2010-07-06 23:59:06 +00:00
parent 6e7f1a3ac1
commit faaef1b498
1 changed files with 67 additions and 134 deletions

View File

@ -5877,74 +5877,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers) public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
{ {
m_host.AddScriptLPS(1); return ParseString2List(str, separators, in_spacers, false);
LSL_List ret = new LSL_List();
LSL_List spacers = new LSL_List();
if (in_spacers.Length > 0 && separators.Length > 0)
{
for (int i = 0; i < in_spacers.Length; i++)
{
object s = in_spacers.Data[i];
for (int j = 0; j < separators.Length; j++)
{
if (separators.Data[j].ToString() == s.ToString())
{
s = null;
break;
}
}
if (s != null)
{
spacers.Add(s);
}
}
}
object[] delimiters = new object[separators.Length + spacers.Length];
separators.Data.CopyTo(delimiters, 0);
spacers.Data.CopyTo(delimiters, separators.Length);
bool dfound = false;
do
{
dfound = false;
int cindex = -1;
string cdeli = "";
for (int i = 0; i < delimiters.Length; i++)
{
int index = str.IndexOf(delimiters[i].ToString());
bool found = index != -1;
if (found && String.Empty != delimiters[i].ToString())
{
if ((cindex > index) || (cindex == -1))
{
cindex = index;
cdeli = delimiters[i].ToString();
}
dfound = dfound || found;
}
}
if (cindex != -1)
{
if (cindex > 0)
{
ret.Add(new LSL_String(str.Substring(0, cindex)));
}
// Cannot use spacers.Contains() because spacers may be either type String or LSLString
for (int j = 0; j < spacers.Length; j++)
{
if (spacers.Data[j].ToString() == cdeli)
{
ret.Add(new LSL_String(cdeli));
break;
}
}
str = str.Substring(cindex + cdeli.Length);
}
} while (dfound);
if (str != "")
{
ret.Add(new LSL_String(str));
}
return ret;
} }
public LSL_Integer llOverMyLand(string id) public LSL_Integer llOverMyLand(string id)
@ -8616,8 +8549,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// The function returns an ordered list // The function returns an ordered list
// representing the tokens found in the supplied // representing the tokens found in the supplied
// sources string. If two successive tokenizers // sources string. If two successive tokenizers
// are encountered, then a NULL entry is added // are encountered, then a null-string entry is
// to the list. // added to the list.
// //
// It is a precondition that the source and // It is a precondition that the source and
// toekizer lisst are non-null. If they are null, // toekizer lisst are non-null. If they are null,
@ -8625,7 +8558,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// while their lengths are being determined. // while their lengths are being determined.
// //
// A small amount of working memoryis required // A small amount of working memoryis required
// of approximately 8*#tokenizers. // of approximately 8*#tokenizers + 8*srcstrlen.
// //
// There are many ways in which this function // There are many ways in which this function
// can be implemented, this implementation is // can be implemented, this implementation is
@ -8641,109 +8574,109 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// and eliminates redundant tokenizers as soon // and eliminates redundant tokenizers as soon
// as is possible. // as is possible.
// //
// The implementation tries to avoid any copying // The implementation tries to minimize temporary
// of arrays or other objects. // garbage generation.
// </remarks> // </remarks>
public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
{
return ParseString2List(src, separators, spacers, true);
}
private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
{ {
int srclen = src.Length; int srclen = src.Length;
int seplen = separators.Length; int seplen = separators.Length;
object[] separray = separators.Data; object[] separray = separators.Data;
int spclen = spacers.Length; int spclen = spacers.Length;
object[] spcarray = spacers.Data; object[] spcarray = spacers.Data;
int dellen = 0;
string[] delarray = new string[seplen+spclen];
int outlen = 0; int outlen = 0;
LSL_String[] outarray = new LSL_String[srclen*2+1]; string[] outarray = new string[srclen*2+1];
int i, j, lastUsed; int i, j;
string d;
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
/* /*
* Point to beginning of current non-delimeter string. * Convert separator and spacer lists to C# strings.
* Also filter out null strings so we don't hang.
*/ */
lastUsed = 0; for (i = 0; i < seplen; i ++) {
d = separray[i].ToString();
if (d.Length > 0) {
delarray[dellen++] = d;
}
}
seplen = dellen;
for (i = 0; i < spclen; i ++) {
d = spcarray[i].ToString();
if (d.Length > 0) {
delarray[dellen++] = d;
}
}
/* /*
* Scan through source string from beginning to end. * Scan through source string from beginning to end.
*/ */
for (i = 0; i < srclen;) { for (i = 0;;) {
/* /*
* See if rest of string (starting at i) matches any separator. * Find earliest delimeter in src starting at i (if any).
*/ */
string rest = src.Substring(i); int earliestDel = -1;
for (j = 0; j < seplen; j ++) { int earliestSrc = srclen;
string sep = separray[j].ToString(); string earliestStr = null;
if ((sep.Length > 0) && rest.StartsWith(sep)) { for (j = 0; j < dellen; j ++) {
d = delarray[j];
/* if (d != null) {
* Separator matched, output string from end of last delimeter to beginning of this one. int index = src.IndexOf(d, i);
*/ if (index < 0) {
outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed)); delarray[j] = null; // delim nowhere in src, don't check it anymore
} else if (index < earliestSrc) {
/* earliestSrc = index; // where delimeter starts in source string
* Remove separator from input string. earliestDel = j; // where delimeter is in delarray[]
*/ earliestStr = d; // the delimeter string from delarray[]
i += sep.Length; if (index == i) break; // can't do any better than found at beg of string
}
/*
* Next non-delimeter starts where this separator left off.
*/
lastUsed = i;
goto nextsrc;
} }
} }
/* /*
* See if rest of string (starting at i) matches any spacer. * Output source string starting at i through start of earliest delimeter.
*/ */
for (j = 0; j < spclen; j ++) { if (keepNulls || (earliestSrc > i)) {
string spc = spcarray[j].ToString(); outarray[outlen++] = src.Substring(i, earliestSrc - i);
if ((spc.Length > 0) && rest.StartsWith(spc)) {
/*
* 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;
}
} }
/* /*
* Didn't match any separator or spacer, skip over it and it * If no delimeter found at or after i, we're done scanning.
* becomes part of the non-delimeter string starting with
* lastUsed.
*/ */
i ++; if (earliestDel < 0) break;
nextsrc:;
/*
* If delimeter was a spacer, output the spacer.
*/
if (earliestDel >= seplen) {
outarray[outlen++] = earliestStr;
} }
/* /*
* Output last non-delimeter (including a possible null string if * Look at rest of src string following delimeter.
* delimeter ran to end of source string).
*/ */
outarray[outlen++] = new LSL_String(src.Substring(lastUsed)); i = earliestSrc + earliestStr.Length;
}
/* /*
* Make up an exact-sized output array suitable for an LSL_List object. * Make up an exact-sized output array suitable for an LSL_List object.
*/ */
object[] outlist = new object[outlen]; object[] outlist = new object[outlen];
for (i = 0; i < outlen; i ++) { for (i = 0; i < outlen; i ++) {
outlist[i] = outarray[i]; outlist[i] = new LSL_String(outarray[i]);
} }
return new LSL_List(outlist); return new LSL_List(outlist);
} }