NoGCString

倾然丶 夕夏残阳落幕 提交于 2019-11-27 02:35:43

网上有大佬发过代码,如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class NoGcString  {

    static readonly char[] number = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    char[] int_parser = new char[20];
    int m_capacity;
    int count;
    string str;

    public int Length { get; private set; }

    public NoGcString(int capacity)
    {
        m_capacity = capacity;
        str = new string((char)0, m_capacity);
    }

    public override string ToString()
    {
        return GetString();
    }

    public void Clear()
    {
        Length = 0;
    }

    public void ApplyForText(Text t)
    {
        t.text = GetString();
        t.cachedTextGenerator.Invalidate();
        t.SetVerticesDirty();
    }

    public unsafe void Append( char[] value)
    {
        if (value != null && value.Length > 0)
        {
            fixed (char* ch = value)
            {
                this.Append(ch, value.Length);
            }
        }
    }

    public unsafe void Append( char *value,int count)
    {
        int num = count + Length;

        if (num <= m_capacity)
        {
            fixed (char* p = str)
            {
                wstrcpy(p + Length, value, count);
                Length = num;
                int* p2 = (int*)p;
                *(p2 - 1) = Length;
            }
        }

    }


    public unsafe void Append(char value)
    {
        if (CheckCapacityEnough())
        {
            int length = Length;
            Length++;
            fixed (char* p = str)
            {
                p[length] = value;
                int* p2 = (int*)p;
                *(p2 - 1) = Length;
            }
        }
    }

    public unsafe void Append(int value)
    {
        if (value >= 0)
        {
            count = ToCharArray((uint)value, int_parser, 0);
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((uint)-value, int_parser, 1)+1;
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }

    public unsafe void Append(uint value)
    {
        if (value >= 0)
        {
            count = ToCharArray(value, int_parser, 0);
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((uint)-value, int_parser, 1) + 1;
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }

    public unsafe void Append(long value)
    {
        if (value >= 0)
        {
            count = ToCharArray((ulong)value, int_parser, 0);
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((ulong)-value, int_parser, 1) + 1;
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }

    public unsafe void Append(ulong value)
    {
        if (value >= 0)
        {
            count = ToCharArray((ulong)value, int_parser, 0);
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }


    public unsafe void Append(float value)
    {
        int v = (int)value;
        int m = Mathf.FloorToInt((value - v) * Mathf.Pow(10, FloatMantissaSize(Mathf.Abs(value))));
        if (value >= 0)
        {
            count = ToCharArray((uint)v, int_parser, 0);
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }
            count = ToCharArray((uint)m, int_parser, 0);
            if (count > 0)
            {
                Append('.');
            }
            if (count >= 6)
            {
                count--;
            }
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((uint)-v, int_parser, 1) + 1;
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }

            count = ToCharArray((uint)Mathf.Abs(m), int_parser, 0);

            if (count > 0)
            {
                Append('.');
            }
            if (count >= 6)
            {
                count--;
            }
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }

        }

        

    }


    public void Append(string value)
    {
        for (int i = 0; i < value.Length; i++)
        {
            Append(value[i]);
        }
    }

    int FloatMantissaSize(float f)
    {
        int l = 0;
        while (f - Mathf.Floor(f) > float.Epsilon)
        {
            l++;
            f *= 10;
        }
        return l;
    }

    static int ToCharArray(ulong value, char[] buff, int buff_index)
    {
        if(value == 0)
        {
            buff[buff_index] = '0';
            return 1;
        }
        int l = 1;

        for( ulong rem = value/10;rem>0;rem/=10)
        {
            l++;
        }

        for (int i = l - 1; i >= 0; i--)
        {
            buff[buff_index + i] = number[value % 10];
            value /= 10;
        }

        return l;
    }

    static int ToCharArray(uint value, char[] buff, int buff_index)
    {
        if (value == 0)
        {
            buff[buff_index] = '0';
            return 1;
        }
        int l = 1;

        for (ulong rem = value / 10; rem > 0; rem /= 10)
        {
            l++;
        }

        for (int i = l - 1; i >= 0; i--)
        {
            buff[buff_index + i] = (char) ('0'+(value));
            value /= 10;
        }

        return l;
    }

    internal static unsafe void wstrcpy(char* des, char* src, int num)
    {
        Memcpy((byte*)des, (byte*)src, num * 2);
    }

    static unsafe void Memcpy(byte * des,byte*src,int size)
    {
        if (((((int)des) | ((int)src)) & 3) != 0)
        {
            if ((((((int)des) & 1) != 0) && ((((int)src) & 1) != 0)) && (size >= 1))
            {
                des[0] = src[0];
                des++;
                src++;
                size--;
            }

            if ((((((int)des) & 2) != 0) && ((((int)src) & 2) != 0)) && (size >= 2))
            {
                *((short*)des) = *((short*)src);

                des += 2;
                src += 2;
                size -= 2;
            }


            if (((((int)des) | ((int)src)) & 1) != 0)
            {
                memcpy1(des,src,size);
                return;
            }

            if (((((int)des) | ((int)src)) & 2) != 0)
            {
                memcpy2(des, src, size);
                return;
            }


        }

        memcpy4(des,src,size);
    }


    static unsafe void memcpy1(byte* des, byte* src, int size)
    {
        int l = 8;
        while (size >= l)
        {
            for (int i = 0; i < l; i++)
            {
                des[i] = src[i];
            }
            des += l;
            src += l;
            size -= l;
        }

        l = 2;

        while (size >= l)
        {
            for (int i = 0; i < l; i++)
            {
                des[i] = src[i];
            }
            des += l;
            src += l;
            size -= l;
        }

        if (size > 0)
        {
            des[0] = src[0];
        }

    }

    static unsafe void memcpy2(byte* des, byte* src, int size)
    {
        int l = 8;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            *((short*)(des+2)) = *((short*)(src+2));
            *((short*)(des+(2*2))) = *((short*)(src+ (2 * 2)));
            *((short*)(des+ (3*2))) = *((short*)(src + (3 * 2)));

            des += l;
            src += l;
            size -= l;
        }

        l = 2;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            des += l;
            src += l;
            size -= l;
        }

        if (size > 0)
        {
            des[0] = src[0];
        }

    }

    static unsafe void memcpy4(byte* des, byte* src, int size)
    {
        int l = 0x10;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            *((short*)(des + 4)) = *((short*)(src + 4));
            *((short*)(des + (2 * 4))) = *((short*)(src + (2 * 4)));
            *((short*)(des + (3 * 4))) = *((short*)(src + (3 * 4)));

            des += l;
            src += l;
            size -= l;
        }
        l = 4;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            des += l;
            src += l;
            size -= l;
        }

        l = 0;
        while (size > l)
        {
            des[0] = src[0];
            des++;
            src++;
            size--;
        }
    }


    unsafe string GetString()
    {
        return str;
    }

    bool CheckCapacityEnough()
    {
        return Length < m_capacity;
    }

}

然后我在测试的时候遇到了bug.具体是哪我忘了.然后修改后的代码是:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class NoGcString  {

    static readonly char[] number = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    char[] int_parser = new char[20];
    int m_capacity;
    int count;
    string str;

    public int Length { get; private set; }

    public NoGcString(int capacity)
    {
        m_capacity = capacity;
        str = new string((char)0, m_capacity);
    }

    public override string ToString()
    {
        return GetString();
    }

    public void Clear()
    {
        Length = 0;
    }

    public void ApplyForText(Text t)
    {
        t.text = GetString();
        t.cachedTextGenerator.Invalidate();
        t.SetVerticesDirty();
    }

    public unsafe void Append( char[] value)
    {
        if (value != null && value.Length > 0)
        {
            fixed (char* ch = value)
            {
                this.Append(ch, value.Length);
            }
        }
    }

    public unsafe void Append( char *value,int count)
    {
        int num = count + Length;

        if (num <= m_capacity)
        {
            fixed (char* p = str)
            {
                wstrcpy(p + Length, value, count);
                Length = num;
                int* p2 = (int*)p;
                *(p2 - 1) = Length;
            }
        }

    }


    public unsafe void Append(char value)
    {
        if (CheckCapacityEnough())
        {
            int length = Length;
            Length++;
            fixed (char* p = str)
            {
                p[length] = value;
                int* p2 = (int*)p;
                *(p2 - 1) = Length;
            }
        }
    }

    public unsafe void Append(int value)
    {
        if (value >= 0)
        {
            count = ToCharArray((uint)value, int_parser, 0);
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((uint)-value, int_parser, 1)+1;
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }

    public unsafe void Append(uint value)
    {
        if (value >= 0)
        {
            count = ToCharArray(value, int_parser, 0);
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((uint)-value, int_parser, 1) + 1;
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }

    public unsafe void Append(long value)
    {
        if (value >= 0)
        {
            count = ToCharArray((ulong)value, int_parser, 0);
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((ulong)-value, int_parser, 1) + 1;
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }

    public unsafe void Append(ulong value)
    {
        if (value >= 0)
        {
            count = ToCharArray((ulong)value, int_parser, 0);
        }

        for (int i = 0; i < count; i++)
        {
            Append(int_parser[i]);
        }

    }


    public unsafe void Append(float value)
    {
        int v = (int)value;
        int m = Mathf.FloorToInt((value - v) * Mathf.Pow(10, FloatMantissaSize(Mathf.Abs(value))));
        if (value >= 0)
        {
            count = ToCharArray((uint)v, int_parser, 0);
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }
            count = ToCharArray((uint)m, int_parser, 0);
            if (count > 0)
            {
                Append('.');
            }
            if (count >= 6)
            {
                count--;
            }
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }
        }
        else
        {
            int_parser[0] = '-';
            count = ToCharArray((uint)-v, int_parser, 1) + 1;
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }

            count = ToCharArray((uint)Mathf.Abs(m), int_parser, 0);

            if (count > 0)
            {
                Append('.');
            }
            if (count >= 6)
            {
                count--;
            }
            for (int i = 0; i < count; i++)
            {
                Append(int_parser[i]);
            }

        }

        

    }


    public void Append(string value)
    {
        for (int i = 0; i < value.Length; i++)
        {
            Append(value[i]);
        }
    }

    int FloatMantissaSize(float f)
    {
        int l = 0;
        while (f - Mathf.Floor(f) > float.Epsilon)
        {
            l++;
            f *= 10;
        }
        return l;
    }

    static int ToCharArray(ulong value, char[] buff, int buff_index)
    {
        if(value == 0)
        {
            buff[buff_index] = '0';
            return 1;
        }
        int l = 1;

        for( ulong rem = value/10;rem>0;rem/=10)
        {
            l++;
        }

        for (int i = l - 1; i >= 0; i--)
        {
            buff[buff_index + i] = number[value % 10];
            value /= 10;
        }

        return l;
    }

    static int ToCharArray(uint value, char[] buff, int buff_index)
    {
        if (value == 0)
        {
            buff[buff_index] = '0';
            return 1;
        }
        int l = 1;

        for (ulong rem = value / 10; rem > 0; rem /= 10)
        {
            l++;
        }

        for (int i = l - 1; i >= 0; i--)
        {
            buff[buff_index + i] = (char) ('0'+(value));
            value /= 10;
        }

        return l;
    }

    internal static unsafe void wstrcpy(char* des, char* src, int num)
    {
        Memcpy((byte*)des, (byte*)src, num * 2);
    }

    static unsafe void Memcpy(byte * des,byte*src,int size)
    {
        if (((((int)des) | ((int)src)) & 3) != 0)
        {
            if ((((((int)des) & 1) != 0) && ((((int)src) & 1) != 0)) && (size >= 1))
            {
                des[0] = src[0];
                des++;
                src++;
                size--;
            }

            if ((((((int)des) & 2) != 0) && ((((int)src) & 2) != 0)) && (size >= 2))
            {
                *((short*)des) = *((short*)src);

                des += 2;
                src += 2;
                size -= 2;
            }


            if (((((int)des) | ((int)src)) & 1) != 0)
            {
                memcpy1(des,src,size);
                return;
            }

            if (((((int)des) | ((int)src)) & 2) != 0)
            {
                memcpy2(des, src, size);
                return;
            }


        }

        memcpy4(des,src,size);
    }


    static unsafe void memcpy1(byte* des, byte* src, int size)
    {
        int l = 8;
        while (size >= l)
        {
            for (int i = 0; i < l; i++)
            {
                des[i] = src[i];
            }
            des += l;
            src += l;
            size -= l;
        }

        l = 2;

        while (size >= l)
        {
            for (int i = 0; i < l; i++)
            {
                des[i] = src[i];
            }
            des += l;
            src += l;
            size -= l;
        }

        if (size > 0)
        {
            des[0] = src[0];
        }

    }

    static unsafe void memcpy2(byte* des, byte* src, int size)
    {
        int l = 8;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            *((short*)(des+2)) = *((short*)(src+2));
            *((short*)(des+(2*2))) = *((short*)(src+ (2 * 2)));
            *((short*)(des+ (3*2))) = *((short*)(src + (3 * 2)));

            des += l;
            src += l;
            size -= l;
        }

        l = 2;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            des += l;
            src += l;
            size -= l;
        }

        if (size > 0)
        {
            des[0] = src[0];
        }

    }

    static unsafe void memcpy4(byte* des, byte* src, int size)
    {
        int l = 0x10;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            *((short*)(des + 4)) = *((short*)(src + 4));
            *((short*)(des + (2 * 4))) = *((short*)(src + (2 * 4)));
            *((short*)(des + (3 * 4))) = *((short*)(src + (3 * 4)));

            des += l;
            src += l;
            size -= l;
        }
        l = 4;
        while (size >= l)
        {
            *((short*)des) = *((short*)src);
            des += l;
            src += l;
            size -= l;
        }

        l = 0;
        while (size > l)
        {
            des[0] = src[0];
            des++;
            src++;
            size--;
        }
    }


    unsafe string GetString()
    {
        return str;
    }

    bool CheckCapacityEnough()
    {
        return Length < m_capacity;
    }

}

使用时需要先生成一个定长的字符串.超长会被裁掉.冥思苦想也没想到比较好的使用场景,希望有大佬看到之后给我留言.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!