Created
September 23, 2020 04:08
-
-
Save Kein/1d25232c45879482597354d94d303dbc to your computer and use it in GitHub Desktop.
First pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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