//---------------------------------------------------------------------
//
// Copyright (C) 2004 Yingle Jia
//
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
#include "stdafx.h"
namespace Acf {
namespace Text {
// Constructors
StringBuilder::StringBuilder(int capacity)
{
if (capacity < 0)
throw ArgumentOutOfRangeException();
if (capacity == 0)
capacity = DefaultCapacity;
this->_buffer.SetLength(capacity);
}
StringBuilder::StringBuilder(String* value)
{
new(this) StringBuilder();
this->_refCount = 1; // prevent from deletion because Append will call AddRef/Release
Append(value);
this->_refCount = 0; // restore reference count
}
StringBuilder::StringBuilder(const wchar_t* value)
{
new(this) StringBuilder();
this->_refCount = 1; // prevent from deletion because Append will call AddRef/Release
Append(value);
this->_refCount = 0; // restore reference count
}
// Properties
wchar_t StringBuilder::get_Chars(int index)
{
if (index < 0 || index >= this->_length)
throw ArgumentOutOfRangeException();
return this->_buffer[index];
}
void StringBuilder::set_Chars(int index, wchar_t value)
{
if (index < 0 || index >= this->_length)
throw ArgumentOutOfRangeException();
this->_buffer[index] = value;
}
void StringBuilder::set_Length(int value)
{
if (value < 0)
throw ArgumentOutOfRangeException();
if (value > this->Length)
{
EnsureCapacity(value);
// Pad the string with spaces
wchar_t* p = InternalGetBuffer();
for (int i = this->Length; i < value; i++)
p[i] = L' ';
}
this->_length = value;
}
void StringBuilder::set_Capacity(int value)
{
if (value < this->Length)
throw ArgumentOutOfRangeException();
if (value == 0)
value = DefaultCapacity;
this->_buffer.SetLength(value);
}
// Methods
StringBuilderPtr StringBuilder::Append(bool value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(sbyte value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(byte value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(wchar_t value, int repeatCount)
{
if (repeatCount < 0)
throw ArgumentOutOfRangeException();
int newLength = this->Length + repeatCount;
if (newLength < 0)
throw OutOfMemoryException();
// Check capacity
if (newLength > this->Capacity)
{
int newCapacity = this->Capacity * 2;
if (newCapacity < newLength)
newCapacity = newLength;
this->Capacity = newCapacity;
}
// Append the chars
wchar_t* p = InternalGetBuffer() + this->Length;
for (int i = 0; i < repeatCount; i++)
*p++ = value;
this->_length += repeatCount;
return this;
}
StringBuilderPtr StringBuilder::Append(short value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(ushort value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(int value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(uint value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(int64 value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(uint64 value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(float value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(double value)
{
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(Object* value)
{
if (value == null)
return this;
return Append(value->ToString());
}
StringBuilderPtr StringBuilder::Append(String* value)
{
if (value == null)
return this;
return Insert(this->Length, value);
}
StringBuilderPtr StringBuilder::Append(const wchar_t* value, int length)
{
return Insert(this->Length, value, length);
}
StringBuilderPtr StringBuilder::Append(String* value, int startIndex, int charCount)
{
return Insert(this->Length, value, startIndex, charCount);
}
StringBuilderPtr StringBuilder::Append(Array<wchar_t>* value)
{
if (value == null)
throw ArgumentNullException();
return Append(value, 0, value->Length);
}
StringBuilderPtr StringBuilder::Append(Array<wchar_t>* value, int index, int charCount)
{
Acf::VerifyArrayRange(value, index, charCount);
if (charCount != 0)
return Insert(this->Length, value->GetItemAddress(index), charCount);
return this;
}
StringBuilderPtr StringBuilder::AppendFormat(String* format, Object* arg0)
{
StringPtr s = String::Format(format, arg0);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(String* format, Object* arg0, Object* arg1)
{
StringPtr s = String::Format(format, arg0, arg1);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(String* format, Object* arg0, Object* arg1, Object* arg2)
{
StringPtr s = String::Format(format, arg0, arg1, arg2);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(String* format, Array< RefPtr<Object> >* args)
{
StringPtr s = String::Format(format, args);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(const wchar_t* format, Object* arg0)
{
StringPtr s = String::Format(format, arg0);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(const wchar_t* format, Object* arg0, Object* arg1)
{
StringPtr s = String::Format(format, arg0, arg1);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(const wchar_t* format, Object* arg0, Object* arg1, Object* arg2)
{
StringPtr s = String::Format(format, arg0, arg1, arg2);
return Append(s);
}
StringBuilderPtr StringBuilder::AppendFormat(const wchar_t* format, Array< RefPtr<Object> >* args)
{
StringPtr s = String::Format(format, args);
return Append(s);
}
StringBuilderPtr StringBuilder::Insert(int index, bool value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, sbyte value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, byte value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, wchar_t value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, short value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, ushort value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, int value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, uint value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, int64 value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, uint64 value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, float value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, double value)
{
return Insert(index, str(value));
}
StringBuilderPtr StringBuilder::Insert(int index, Object* value)
{
return Insert(index, value->ToString());
}
StringBuilderPtr StringBuilder::Insert(int index, String* value)
{
if (value == null)
throw ArgumentNullException();
if (value->Length != 0)
return Insert(index, value->GetCString(), value->Length);
return this;
}
StringBuilderPtr StringBuilder::Insert(int index, String* value, int startIndex, int charCount)
{
Acf::VerifyStringRange(value, startIndex, charCount);
if (charCount != 0)
return Insert(index, value->GetCString() + startIndex, charCount);
return this;
}
StringBuilderPtr StringBuilder::Insert(int index, Array<wchar_t>* value)
{
return Insert(index, value->GetBuffer(), value->Length);
}
StringBuilderPtr StringBuilder::Insert(int index, Array<wchar_t>* value, int startIndex, int charCount)
{
Acf::VerifyArrayRange(value, startIndex, charCount);
if (charCount != 0)
return Insert(index, value->GetItemAddress(startIndex), charCount);
return this;
}
StringBuilderPtr StringBuilder::Insert(int index, const wchar_t* value, int length)
{
if (index < 0 || index > this->Length)
throw ArgumentOutOfRangeException();
if (length == -1)
length = (int) wcslen(value);
if (length < 0)
throw ArgumentOutOfRangeException();
if (length == 0)
return this;
int newLength = this->Length + length;
if (newLength < 0)
throw OutOfMemoryException();
// Check capacity
if (newLength > this->Capacity)
{
int newCapacity = this->Capacity * 2;
if (newCapacity < newLength)
newCapacity = newLength;
this->Capacity = newCapacity;
}
// Insert the string
wchar_t* buffer = InternalGetBuffer();
if (index != this->Length)
memmove(buffer + index + length, buffer + index, (this->Length - index) * sizeof(wchar_t));
memcpy(buffer + index, value, length * sizeof(wchar_t));
this->_length += length;
return this;
}
StringBuilderPtr StringBuilder::Remove(int startIndex, int length)
{
if (startIndex < 0)
throw ArgumentOutOfRangeException();
if (length < 0)
throw ArgumentOutOfRangeException();
if (startIndex + length > this->Length)
throw ArgumentException();
// Remove the chars
if (startIndex + length != this->Length)
{
wchar_t* buffer = InternalGetBuffer();
memcpy(buffer + startIndex, buffer + startIndex + length,
(this->Length - length) * sizeof(wchar_t));
}
this->_length -= length;
return this;
}
StringBuilderPtr StringBuilder::Replace(wchar_t oldChar, wchar_t newChar)
{
return Replace(oldChar, newChar, 0, this->Length);
}
StringBuilderPtr StringBuilder::Replace(wchar_t oldChar, wchar_t newChar, int startIndex, int count)
{
if (startIndex < 0 || startIndex >= this->Length)
throw ArgumentOutOfRangeException();
if (startIndex + count > this->Length)
throw ArgumentOutOfRangeException();
if (count != 0)
{
wchar_t* buffer = InternalGetBuffer();
for (int i = startIndex; i < startIndex + count; i++)
{
if (buffer[i] == oldChar)
buffer[i] = newChar;
}
}
return this;
}
StringBuilderPtr StringBuilder::Replace(String* oldValue, String* newValue)
{
return Replace(oldValue, newValue, 0, this->Length);
}
StringBuilderPtr StringBuilder::Replace(String* oldValue, String* newValue, int startIndex, int count)
{
if (startIndex < 0 || startIndex >= this->Length)
throw ArgumentOutOfRangeException();
if (startIndex + count > this->Length)
throw ArgumentOutOfRangeException();
StringPtr s = ToString(startIndex, count);
StringPtr s2 = s->Replace(oldValue, newValue);
if ((Object*)s == (Object*)s2)
return this; // nothing replaced
Remove(startIndex, count);
Insert(startIndex, s2);
return this;
}
StringBuilderPtr StringBuilder::Replace(const wchar_t* oldValue, const wchar_t* newValue)
{
return Replace(str(oldValue), str(newValue));
}
StringBuilderPtr StringBuilder::Replace(const wchar_t* oldValue, const wchar_t* newValue, int startIndex, int count)
{
return Replace(str(oldValue), str(newValue), startIndex, count);
}
int StringBuilder::EnsureCapacity(int capacity)
{
if (capacity < 0)
throw ArgumentOutOfRangeException();
if (capacity > this->Capacity)
this->Capacity = capacity;
return this->Capacity;
}
bool StringBuilder::Equals(StringBuilder* sb)
{
if (sb == null)
return false;
return ToString() == sb->ToString();
}
StringPtr StringBuilder::ToString()
{
return ToString(0, this->Length);
}
StringPtr StringBuilder::ToString(int startIndex, int length)
{
if (startIndex < 0 || length < 0)
throw ArgumentOutOfRangeException();
if (startIndex + length > this->Length)
throw ArgumentException();
if (length == 0)
return String::Empty;
else
return new String(InternalGetBuffer() + startIndex, length);
}
wchar_t* StringBuilder::InternalGetBuffer()
{
return this->_buffer.GetBuffer();
}
} // namespace Text
} // namespace Acf