Introduction
These extension methods are adapted from those recently added to the LoycCore libraries. This set is more similar to the methods of System.String
than the original article was. Not all methods of string
are included - this set focuses more on searching than changing the string
. LINQ-like O(1) Last()
and LastOrDefault()
methods are also included.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Loyc
{
public static class StringBuilderExt
{
public static string Substring(this StringBuilder sb, int startIndex, int length)
{
return sb.ToString(startIndex, length);
}
public static char Last(this StringBuilder str)
{
if (str.Length == 0)
throw new InvalidOperationException("Empty string has no last character");
return str[str.Length - 1];
}
public static char LastOrDefault(this StringBuilder str, char @default = '\0')
{
if (str.Length == 0)
return @default;
return str[str.Length - 1];
}
static char[] _defaultTrimChars = new[] { ' ', '\t' };
public static StringBuilder TrimStart(this StringBuilder sb)
{ return TrimStart(sb, _defaultTrimChars); }
public static StringBuilder TrimStart(this StringBuilder sb, params char[] trimChars)
{
int i = 0;
while (i < sb.Length && trimChars.Contains(sb[i]))
i++;
sb.Remove(0, i);
return sb;
}
public static StringBuilder TrimEnd(this StringBuilder sb)
{ return TrimEnd(sb, _defaultTrimChars); }
public static StringBuilder TrimEnd(this StringBuilder sb, params char[] trimChars)
{
int i = sb.Length;
while (i > 0 && trimChars.Contains(sb[i - 1]))
i--;
sb.Remove(i, sb.Length - i);
return sb;
}
public static StringBuilder Trim(this StringBuilder sb)
{ return Trim(sb, _defaultTrimChars); }
public static StringBuilder Trim(this StringBuilder sb, params char[] trimChars)
{
return TrimStart(TrimEnd(sb, trimChars), trimChars);
}
public static int IndexOf(this StringBuilder sb, char value, int startIndex = 0)
{
for (int i = startIndex; i < sb.Length; i++)
if (sb[i] == value)
return i;
return -1;
}
public static int IndexOf(this StringBuilder sb, string searchStr,
int startIndex = 0, bool ignoreCase = false)
{
var stopAt = sb.Length - searchStr.Length;
for (int i = startIndex; i <= stopAt; i++)
if (SubstringEqualHelper(sb, i, searchStr, ignoreCase))
return i;
return -1;
}
public static int LastIndexOf(this StringBuilder sb, char searchChar,
int startIndex = int.MaxValue)
{
if (startIndex > sb.Length - 1)
startIndex = sb.Length - 1;
for (int i = startIndex; i >= 0; i--)
if (sb[i] == searchChar)
return i;
return -1;
}
public static int LastIndexOf(this StringBuilder sb,
string searchStr, int startIndex = int.MaxValue, bool ignoreCase = false)
{
if (startIndex > sb.Length - searchStr.Length)
startIndex = sb.Length - searchStr.Length;
for (int i = startIndex; i >= 0; i--)
if (SubstringEqualHelper(sb, i, searchStr, ignoreCase))
return i;
return -1;
}
public static bool EndsWith(this StringBuilder sb, string what, bool ignoreCase = false)
{
if (what.Length > sb.Length)
return false;
return SubstringEqualHelper(sb, sb.Length - what.Length, what, ignoreCase);
}
public static bool StartsWith(this StringBuilder sb, string what, bool ignoreCase = false)
{
if (what.Length > sb.Length)
return false;
return SubstringEqualHelper(sb, 0, what, ignoreCase);
}
public static bool SubstringEquals
(StringBuilder sb, int start, string what, bool ignoreCase = false)
{
if (start < 0)
throw new ArgumentException("Invalid starting index for comparison");
if (start > sb.Length - what.Length)
return false;
return SubstringEqualHelper(sb, start, what, ignoreCase);
}
static bool SubstringEqualHelper
(StringBuilder sb, int start, string what, bool ignoreCase = false)
{
if (ignoreCase)
for (int i = 0; i < what.Length; i++) {
if (char.ToUpperInvariant(sb[start + i]) != char.ToUpperInvariant(what[i]))
return false;
}
else
for (int i = 0; i < what.Length; i++) {
if (sb[start + i] != what[i])
return false;
}
return true;
}
}
}