From: Alan M Webb <awebb@vnet.ibm.com>

Robust implementations of GetSubString, InsertString, and
DeleteSubstring. The existing implementations only worked for arguments
consistent with the underlying .Net implementation and did not
accomodate LL's negative indices.
0.6.0-stable
Justin Clarke Casey 2008-04-18 19:03:28 +00:00
parent afb06c7b88
commit cd09677469
1 changed files with 222 additions and 45 deletions

View File

@ -1306,51 +1306,228 @@ namespace OpenSim.Region.ScriptEngine.Common
m_host.PreloadSound(sound); m_host.PreloadSound(sound);
} }
/// <summary>
/// Return a portion of the designated string bounded by
/// inclusive indices (start and end). As usual, the negative
/// indices, and the tolerance for out-of-bound values, makes
/// this more complicated than it might otherwise seem.
/// </summary>
public string llGetSubString(string src, int start, int end) public string llGetSubString(string src, int start, int end)
{ {
m_host.AddScriptLPS(1);
// substring expects length
// return src.Substring(start, end);
// if one is negative so use length of string as base m_host.AddScriptLPS(1);
// if start > end then it is exclusive
// for length add +1 for char at location=0 // Normalize indices (if negative).
if (start < 0) { start = src.Length-start; } // After normlaization they may still be
if (end < 0) { end = src.Length - end; } // negative, but that is now relative to
if (start > end) // the start, rather than the end, of the
// sequence.
if (start < 0)
{ {
return src.Substring(0, 1+end) + src.Substring(start, src.Length - start); start = src.Length+start;
} }
if (end < 0)
{
end = src.Length+end;
}
// Conventional substring
if (start <= end)
{
// Implies both bounds are out-of-range.
if(end < 0 || start >= src.Length)
{
return String.Empty;
}
// If end is positive, then it directly
// corresponds to the lengt of the substring
// needed (plus one of course). BUT, it
// must be within bounds.
if(end >= src.Length)
{
end = src.Length-1;
}
if(start < 0)
{
return src.Substring(0,end+1);
}
// Both indices are positive
return src.Substring(start, (end+1) - start);
}
// Inverted substring (end < start)
else else
{ {
return src.Substring(start, (1+end) - start); // Implies both indices are below the
// lower bound. In the inverted case, that
// means the entire string will be returned
// unchanged.
if(start < 0)
{
return src;
}
// If both indices are greater than the upper
// bound the result may seem initially counter
// intuitive.
if(end >= src.Length)
{
return src;
}
if(end < 0)
{
if(start < src.Length)
{
return src.Substring(start);
}
else
{
return String.Empty;
}
}
else
{
if(start < src.Length)
{
return src.Substring(0,end+1) + src.Substring(start);
}
else
{
return src.Substring(0,end+1);
}
}
} }
} }
/// <summary>
/// Delete substring removes the specified substring bounded
/// by the inclusive indices start and end. Indices may be
/// negative (indicating end-relative) and may be inverted,
/// i.e. end < start.
/// </summary>
public string llDeleteSubString(string src, int start, int end) public string llDeleteSubString(string src, int start, int end)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
//return src.Remove(start, end - start);
// if one is negative so use length of string as base // Normalize indices (if negative).
// if start > end then it is exclusive // After normlaization they may still be
// for length add +1 for char at location=0 // negative, but that is now relative to
if (start < 0) { start = src.Length - start; } // the start, rather than the end, of the
if (end < 0) { end = src.Length - end; } // sequence.
if (start > end) if (start < 0)
{ {
return src.Remove(0, 1 + end) + src.Remove(start, src.Length - start); start = src.Length+start;
} }
if (end < 0)
{
end = src.Length+end;
}
// Conventionally delimited substring
if (start <= end)
{
// If both bounds are outside of the existing
// string, then return unchanges.
if(end < 0 || start >= src.Length)
{
return src;
}
// At least one bound is in-range, so we
// need to clip the out-of-bound argument.
if(start < 0)
{
start = 0;
}
if(end >= src.Length)
{
end = src.Length-1;
}
return src.Remove(start,end-start+1);
}
// Inverted substring
else else
{ {
return src.Remove(start, (1 + end) - start); // In this case, out of bounds means that
// the existing string is part of the cut.
if(start < 0 || end >= src.Length)
{
return String.Empty;
}
if(end > 0)
{
if(start < src.Length)
{
return src.Remove(start).Remove(0,end+1);
}
else
{
return src.Remove(0,end+1);
}
}
else
{
if(start < src.Length)
{
return src.Remove(start);
}
else
{
return src;
}
}
} }
} }
/// <summary>
/// Insert string inserts the specified string identified by src
/// at the index indicated by index. Index may be negative, in
/// which case it is end-relative. The index may exceed either
/// string bound, with the result being a concatenation.
/// </summary>
public string llInsertString(string dst, int position, string src) public string llInsertString(string dest, int index, string src)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
return dst.Insert(position, src);
// Normalize indices (if negative).
// After normlaization they may still be
// negative, but that is now relative to
// the start, rather than the end, of the
// sequence.
if (index < 0)
{
index = dest.Length+index;
// Negative now means it is less than the lower
// bound of the string.
if(index < 0)
{
return src+dest;
}
}
if(index >= dest.Length)
{
return dest+src;
}
// The index is in bounds.
// In this case the index refers to the index that will
// be assigned to the first character of the inserted string.
// So unlike the other string operations, we do not add one
// to get the correct string length.
return dest.Substring(0,index)+src+dest.Substring(index);
} }
public string llToUpper(string src) public string llToUpper(string src)
@ -2176,7 +2353,7 @@ namespace OpenSim.Region.ScriptEngine.Common
public string llGetScriptName() public string llGetScriptName()
{ {
string result = null; string result = String.Empty;
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
@ -2184,7 +2361,7 @@ namespace OpenSim.Region.ScriptEngine.Common
{ {
if(item.Type == 10 && item.ItemID == m_itemID) if(item.Type == 10 && item.ItemID == m_itemID)
{ {
result = item.Name; result = item.Name!=null?item.Name:String.Empty;
break; break;
} }
} }
@ -2244,19 +2421,19 @@ namespace OpenSim.Region.ScriptEngine.Common
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory) foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
{ {
if(inv.Value.Name == name) if(inv.Value.Name == name)
{ {
if((inv.Value.OwnerMask & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) if((inv.Value.OwnerMask & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
{ {
return inv.Value.AssetID.ToString(); return inv.Value.AssetID.ToString();
} }
else else
{ {
return LLUUID.Zero.ToString(); return LLUUID.Zero.ToString();
} }
} }
} }
return LLUUID.Zero.ToString(); return LLUUID.Zero.ToString();
} }
public void llAllowInventoryDrop(int add) public void llAllowInventoryDrop(int add)
@ -2900,13 +3077,13 @@ namespace OpenSim.Region.ScriptEngine.Common
public string llGetObjectName() public string llGetObjectName()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
return m_host.Name; return m_host.Name!=null?m_host.Name:String.Empty;
} }
public void llSetObjectName(string name) public void llSetObjectName(string name)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.Name = name; m_host.Name = name!=null?name:String.Empty;
} }
public string llGetDate() public string llGetDate()
@ -3759,13 +3936,13 @@ namespace OpenSim.Region.ScriptEngine.Common
public string llGetObjectDesc() public string llGetObjectDesc()
{ {
return m_host.Description; return m_host.Description!=null?m_host.Description:String.Empty;
} }
public void llSetObjectDesc(string desc) public void llSetObjectDesc(string desc)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.Description = desc; m_host.Description = desc!=null?desc:String.Empty;
} }
public string llGetCreator() public string llGetCreator()