Skip to content

Instantly share code, notes, and snippets.

@dburner
Forked from dtao/EvilStringHelper.cs
Created March 12, 2018 13:26
Show Gist options
  • Select an option

  • Save dburner/9ff9e9da7346cfa9d7f833232b5f6952 to your computer and use it in GitHub Desktop.

Select an option

Save dburner/9ff9e9da7346cfa9d7f833232b5f6952 to your computer and use it in GitHub Desktop.

Revisions

  1. dburner revised this gist Mar 12, 2018. No changes.
  2. @dtao dtao created this gist Aug 16, 2012.
    97 changes: 97 additions & 0 deletions EvilStringHelper.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    public static class EvilStringHelper
    {
    private static readonly Action<string, int, char> _setChar;
    private static readonly Action<string, int> _setLength;

    static EvilStringHelper()
    {
    if (Environment.Version.Major < 4)
    {
    MethodInfo setCharMethod = typeof(string).GetMethod(
    "SetChar",
    BindingFlags.Instance | BindingFlags.NonPublic
    );

    _setChar = (Action<string, int, char>)Delegate.CreateDelegate(typeof(Action<string, int, char>), setCharMethod);

    MethodInfo setLengthMethod = typeof(string).GetMethod(
    "SetLength",
    BindingFlags.Instance | BindingFlags.NonPublic
    );

    _setLength = (Action<string, int>)Delegate.CreateDelegate(typeof(Action<string, int>), setLengthMethod);
    }
    else
    {
    MethodInfo fillStringCheckedMethod = typeof(string).GetMethod(
    "FillStringChecked",
    BindingFlags.Static | BindingFlags.NonPublic
    );

    Action<string, int, string> fillStringCheckedDelegate = (Action<string, int, string>)Delegate.CreateDelegate(
    typeof(Action<string, int, string>), fillStringCheckedMethod
    );

    _setChar = (str, i, c) => fillStringCheckedDelegate(str, i, c.ToString());

    FieldInfo stringLengthField = typeof(string).GetField(
    "m_stringLength",
    BindingFlags.Instance | BindingFlags.NonPublic
    );

    var input = Expression.Parameter(typeof(string), "input");
    var length = Expression.Parameter(typeof(int), "length");

    var setLengthLambda = Expression.Lambda<Action<string, int>>(
    Expression.Assign(Expression.Field(input, stringLengthField), length),
    input,
    length
    );

    _setLength = setLengthLambda.Compile();
    }
    }

    public static void ChangeTo(this string text, string value)
    {
    _setLength(text, value.Length);
    for (int i = 0; i < value.Length; ++i)
    text.SetChar(i, value[i]);
    }

    public static void SetChar(this string text, int index, char value)
    {
    _setChar(text, index, value);
    }

    public static void ReverseInPlace(this string text)
    {
    int i = 0;
    int j = text.Length - 1;

    while (i < j)
    {
    char temp = text[j];

    _setChar(text, j--, text[i]);
    _setChar(text, i++, temp);
    }
    }

    public static unsafe string ReverseOutOfPlace(this string text)
    {
    int length = text.Length;
    char* reversed = stackalloc char[length];

    int i = 0, j = length - 1;
    fixed (char* p = text)
    {
    while (i < length)
    {
    reversed[i++] = p[j--];
    }
    }

    return new string(reversed, 0, length);
    }
    }