网上有大佬发过代码,如下:
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;
}
}
使用时需要先生成一个定长的字符串.超长会被裁掉.冥思苦想也没想到比较好的使用场景,希望有大佬看到之后给我留言.
来源:https://blog.csdn.net/wzh24089516/article/details/99292478