mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-05 03:55:57 -04:00
183 lines
4.4 KiB
C#
183 lines
4.4 KiB
C#
using System;
|
|
|
|
namespace ClassicalSharp {
|
|
|
|
public sealed class StringBuffer {
|
|
|
|
char[] value, wrap;
|
|
int capacity;
|
|
|
|
public StringBuffer( int capacity ) {
|
|
this.capacity = capacity;
|
|
value = new char[capacity];
|
|
wrap = new char[capacity];
|
|
}
|
|
|
|
public StringBuffer Append( int index, char c ) {
|
|
value[index] = c;
|
|
return this;
|
|
}
|
|
|
|
public StringBuffer Append( int index, string s ) {
|
|
return Append( ref index, s );
|
|
}
|
|
|
|
public StringBuffer Append( ref int index, string s ) {
|
|
for( int i = 0; i < s.Length; i++ )
|
|
value[index++] = s[i];
|
|
return this;
|
|
}
|
|
|
|
public StringBuffer Append( ref int index, char c) {
|
|
value[index++] = c;
|
|
return this;
|
|
}
|
|
|
|
static char[] numBuffer = new char[20];
|
|
public StringBuffer AppendNum( ref int index, long num ) {
|
|
int numIndex = 0;
|
|
numBuffer[numIndex++] = (char)('0' + (num % 10));
|
|
num /= 10;
|
|
|
|
while( num > 0 ) {
|
|
numBuffer[numIndex++] = (char)('0' + (num % 10));
|
|
num /= 10;
|
|
}
|
|
|
|
for( int i = numIndex - 1; i >= 0; i-- )
|
|
value[index++] = numBuffer[i];
|
|
return this;
|
|
}
|
|
|
|
public StringBuffer Clear() {
|
|
for( int i = 0; i < capacity; i++ )
|
|
value[i] = '\0';
|
|
return this;
|
|
}
|
|
|
|
public void DeleteAt( int index ) {
|
|
for( int i = index; i < capacity - 1; i++ )
|
|
value[i] = value[i + 1];
|
|
value[capacity - 1] = '\0';
|
|
}
|
|
|
|
public void InsertAt( int index, char c ) {
|
|
for( int i = capacity - 1; i > index; i-- )
|
|
value[i] = value[i - 1];
|
|
value[index] = c;
|
|
}
|
|
|
|
public bool Empty {
|
|
get {
|
|
for( int i = 0; i < capacity; i++ ) {
|
|
if( value[i] != '\0' )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public int Length {
|
|
get {
|
|
int len = capacity;
|
|
for( int i = capacity - 1; i >= 0; i-- ) {
|
|
if( value[i] != '\0' )
|
|
break;
|
|
len--;
|
|
}
|
|
return len;
|
|
}
|
|
}
|
|
|
|
public string GetString() {
|
|
return new String( value, 0, Length );
|
|
}
|
|
|
|
public string GetSubstring( int length ) {
|
|
return new String( value, 0, length );
|
|
}
|
|
|
|
public void WordWrap( ref string[] lines, ref int[] lineLens, int lineSize ) {
|
|
int len = Length;
|
|
for( int i = 0; i < lines.Length; i++ ) {
|
|
lines[i] = null;
|
|
lineLens[i] = 0;
|
|
}
|
|
|
|
// Need to make a copy because we mutate the characters.
|
|
char[] realText = value;
|
|
MakeWrapCopy();
|
|
|
|
int linesCount = 0;
|
|
for( int index = 0; index < capacity; index += lineSize ) {
|
|
if( value[index] == '\0' )
|
|
break;
|
|
|
|
int lineEnd = index + (lineSize - 1);
|
|
int nextLine = index + lineSize;
|
|
linesCount++;
|
|
|
|
// Do we need word wrapping
|
|
bool needWrap = !IsWrapper( value[lineEnd] ) && nextLine < capacity && !IsWrapper( value[nextLine] );
|
|
int wrappedLen = needWrap ? WrapLine( index, lineSize ) : lineSize;
|
|
|
|
// Calculate the maximum size of this line
|
|
int lineLen = lineSize;
|
|
for( int i = lineEnd; i >= index; i-- ) {
|
|
if( value[i] != '\0' ) break;
|
|
lineLen--;
|
|
}
|
|
lineLens[index / lineSize] = Math.Min( lineLen, wrappedLen );
|
|
}
|
|
|
|
// Output the used lines
|
|
OutputLines( ref lines, linesCount, lineSize );
|
|
value = realText;
|
|
}
|
|
|
|
void MakeWrapCopy() {
|
|
int len = Length;
|
|
for( int i = 0; i < len; i++ )
|
|
wrap[i] = value[i];
|
|
|
|
for( int i = len; i < capacity; i++ )
|
|
wrap[i] = '\0';
|
|
value = wrap;
|
|
}
|
|
|
|
void OutputLines( ref string[] lines, int linesCount, int lineSize ) {
|
|
for( int i = 0; i < capacity; i++ ) {
|
|
if( value[i] == '\0' ) value[i] = ' ';
|
|
}
|
|
|
|
for( int i = 0; i < Math.Max( 1, linesCount ); i++ ) {
|
|
lines[i] = new String( value, i * lineSize, lineSize );
|
|
}
|
|
}
|
|
|
|
int WrapLine( int index, int lineSize ) {
|
|
int lineEnd = index + (lineSize - 1);
|
|
// wrap - but we don't want to wrap if the entire line is filled.
|
|
for( int i = lineEnd; i >= index + 1; i-- ) {
|
|
if( IsWrapper( value[i] ) ) {
|
|
for( int j = lineEnd; j >= i + 1; j-- ) {
|
|
InsertAt( index + lineSize, value[j] );
|
|
value[j] = ' ';
|
|
}
|
|
return (i + 1) - index;
|
|
}
|
|
}
|
|
return lineSize;
|
|
}
|
|
|
|
bool IsWrapper( char c ) {
|
|
return c == '\0' || c == ' ' || c == '-' || c == '>'
|
|
|| c == '<' || c == '/' || c == '\\';
|
|
}
|
|
|
|
public override string ToString() {
|
|
return new String( value, 0, Length );
|
|
}
|
|
}
|
|
}
|