Skip to content

Instantly share code, notes, and snippets.

@Kein
Created September 23, 2020 04:08
Show Gist options
  • Save Kein/1d25232c45879482597354d94d303dbc to your computer and use it in GitHub Desktop.
Save Kein/1d25232c45879482597354d94d303dbc to your computer and use it in GitHub Desktop.
First pass
public class MutableString
{
// Setup fields
private int m_Pos;
private string m_valueStr;
private readonly bool dontThrow = false;
// Publics
public int Capacity { get { return m_valueStr.Length; } }
public int Length { get { return m_Pos; } }
public MutableString(int size) : this(size, '\0', false) { }
public MutableString(int size, bool ignoreOverflow) : this(size, '\0', ignoreOverflow) { }
public MutableString(int size, char fillChar) : this(size, fillChar, false) { }
public MutableString(int size, char fillChar, bool ignoreOverflow)
{
if (size < 1)
throw new ArgumentException("Size cannot be 0 or less");
m_valueStr = new string(fillChar, size);
dontThrow = ignoreOverflow;
}
public override string ToString()
{
if (m_Pos == 0)
return string.Empty;
var free = m_valueStr.Length - m_Pos;
if (free > 0)
repeatChar('\0', free);
m_Pos = 0;
return m_valueStr;
}
//
// LOGIC
//
#region CHARS
public void Append(char[] value, int indx, int count)
{
if (value == null)
return;
var len = value.Length;
if (len == 0 || count < 1 || indx < 0 || (count > len - indx))
return;
if (len > 1)
AppendInternal(value, indx, count);
else
Append(value[0]);
}
public void Append(char[] value)
{
if (value == null)
return;
var len = value.Length;
if (len > 1)
AppendInternal(value, 0, len);
else
Append(value[0]);
}
public void Append(char value)
{
if (m_Pos >= m_valueStr.Length)
{
if (dontThrow)
return;
else
throw new ArgumentException("Not enough free space to accomodate element!");
}
singleChar(value);
m_Pos++;
}
private void AppendInternal(char[] value, int indx, int count)
{
var free = m_valueStr.Length - m_Pos;
if (count > free)
{
if (dontThrow)
return;
else
throw new ArgumentException(string.Format("Not enough free space to accomodate {0} elements!", count));
}
charCopy(value, indx, count);
m_Pos = m_Pos + count;
}
#endregion
#region STRINGS
private void AppendInternal(string value, int indx, int count)
{
var free = m_valueStr.Length - m_Pos;
if (count > free)
{
if (dontThrow == true)
return;
else
throw new ArgumentOutOfRangeException(string.Format("Not enough free space to accomodate {0} elements!", count));
}
stringCopy(value, indx, count);
m_Pos = m_Pos + count;
}
public void Append(string value, int indx, int count)
{
if (value == null)
return;
var len = value.Length;
if (count < 1 || indx < 0 || (count > len - indx))
return;
if (len > 1)
AppendInternal(value, indx, count);
else
Append(value[0]);
}
public void Append(string value)
{
if (value == null)
return;
var len = value.Length;
if (len > 1)
AppendInternal(value, 0, len);
else
Append(value[0]);
}
#endregion
// Copy logic
private unsafe void stringCopy(string value, int indx, int charCount)
{
fixed (char* ptrDest = m_valueStr)
{
fixed (char* ptrSrc = value)
{
wstrcpy(ptrDest + m_Pos, ptrSrc + indx, charCount);
}
}
}
private unsafe void charCopy(char[] value, int indx, int charCount)
{
fixed (char* ptrDest = m_valueStr)
{
fixed (char* ptrSrc = value)
{
wstrcpy(ptrDest + m_Pos, ptrSrc + indx, charCount);
}
}
}
private unsafe void singleChar(char value)
{
fixed (char* ptrDest = m_valueStr)
{
ptrDest[m_Pos] = value;
}
}
private unsafe void repeatChar(char value, int count)
{
var fin = m_Pos + count;
fixed (char* ptrDest = m_valueStr)
{
while (m_Pos < fin)
{
ptrDest[m_Pos] = value;
m_Pos++;
}
}
}
private unsafe void rawCopy(char* dest, char* src, int charCount)
{
for (int i = 0; i < charCount; i++)
dest[i] = src[i];
}
private unsafe static void wstrcpy(char* dmem, char* smem, int charCount)
{
if (((int)dmem & 2) != 0)
{
*dmem = *smem;
dmem++;
smem++;
charCount--;
}
while (charCount >= 8)
{
*(uint*)dmem = *(uint*)smem;
*(uint*)(dmem + 2) = *(uint*)(smem + 2);
*(uint*)(dmem + 4) = *(uint*)(smem + 4);
*(uint*)(dmem + 6) = *(uint*)(smem + 6);
dmem += 8;
smem += 8;
charCount -= 8;
}
if ((charCount & 4) != 0)
{
*(uint*)dmem = *(uint*)smem;
*(uint*)(dmem + 2) = *(uint*)(smem + 2);
dmem += 4;
smem += 4;
}
if ((charCount & 2) != 0)
{
*(uint*)dmem = *(uint*)smem;
dmem += 2;
smem += 2;
}
if ((charCount & 1) != 0)
{
*dmem = *smem;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment