| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 |
- // -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- //
- // System.Text.StringBuilder
- //
- // Authors:
- // Marcin Szczepanski ([email protected])
- // Paolo Molaro ([email protected])
- // Patrik Torstensson
- //
- // NOTE: In the case the buffer is only filled by 50% a new string
- // will be returned by ToString() is cached in the '_cached_str'
- // cache_string will also control if a string has been handed out
- // to via ToString(). If you are chaning the code make sure that
- // if you modify the string data set the cache_string to null.
- //
- using System.Runtime.CompilerServices;
- namespace System.Text {
-
- [Serializable]
- public sealed class StringBuilder
- {
- private int _length;
- private string _str = null;
- private string _cached_str = null;
-
- private int _maxCapacity = Int32.MaxValue;
- private const int constDefaultCapacity = 16;
- public StringBuilder(string value, int startIndex, int length, int capacity)
- {
- // first, check the parameters and throw appropriate exceptions if needed
- if (null == value)
- value = "";
- // make sure startIndex is zero or positive
- if (startIndex < 0)
- throw new System.ArgumentOutOfRangeException ("startIndex", startIndex, "StartIndex cannot be less than zero.");
- // make sure length is zero or positive
- if(length < 0)
- throw new System.ArgumentOutOfRangeException ("length", length, "Length cannot be less than zero.");
- if (capacity < 0)
- throw new System.ArgumentOutOfRangeException ("capacity", capacity, "capacity must be greater than zero.");
- // make sure startIndex and length give a valid substring of value
- if (startIndex + (length -1) > (value.Length - 1) )
- throw new System.ArgumentOutOfRangeException ("startIndex", startIndex, "StartIndex and length must refer to a location within the string.");
- if (capacity == 0)
- capacity = constDefaultCapacity;
- _str = String.InternalAllocateStr ((length > capacity) ? length : capacity);
- if (length > 0)
- String.InternalStrcpy(_str, 0, value, startIndex, length);
-
- _length = length;
- }
- public StringBuilder () : this (String.Empty, 0, 0, 0) {}
- public StringBuilder(int capacity) : this (String.Empty, 0, 0, capacity) {}
- public StringBuilder(int capacity, int maxCapacity) : this (String.Empty, 0, 0, capacity) {
- if (capacity > maxCapacity)
- throw new System.ArgumentOutOfRangeException ("capacity", "Capacity exceeds maximum capacity.");
- _maxCapacity = maxCapacity;
- }
- public StringBuilder( string value ) : this(value, 0, value == null ? 0 : value.Length, value == null? 0 : value.Length) {
- }
-
- public StringBuilder( string value, int capacity) : this(value, 0, value.Length, capacity) {}
-
- public int MaxCapacity {
- get {
- // MS runtime always returns Int32.MaxValue.
- return _maxCapacity;
- }
- }
- public int Capacity {
- get {
- return _str.Length;
- }
- set {
- if (value < _length)
- throw new ArgumentException( "Capacity must be larger than length" );
- InternalEnsureCapacity(value);
- }
- }
- public int Length {
- get {
- return _length;
- }
- set {
- if( value < 0 || value > _maxCapacity)
- throw new ArgumentOutOfRangeException();
- if (value == _length)
- return;
- if( value < _length )
- {
- // LAMESPEC: The spec is unclear as to what to do
- // with the capacity when truncating the string.
- // Do as MS, keep the capacity
- _length = value;
- } else
- {
- // Expand the capacity to the new length and
- // pad the string with spaces.
-
- // LAMESPEC: The spec says to put the spaces on the
- // left of the string however the MS implementation
- // puts them on the right. We'll do that for
- // compatibility (!)
- Append(' ', value - _length);
- }
- }
- }
- [IndexerName("Chars")]
- public char this [int index] {
- get {
- if (index >= _length || index < 0)
- throw new IndexOutOfRangeException();
- return _str [index];
- }
- set {
- if (index >= _length || index < 0)
- throw new IndexOutOfRangeException();
- if (null != _cached_str)
- InternalEnsureCapacity (_length);
-
- _str.InternalSetChar (index, value);
- }
- }
- public override string ToString ()
- {
- if (_length == 0)
- return String.Empty;
- if (null != _cached_str)
- return _cached_str;
- // If we only have a half-full buffer we return a new string.
- if (_length < (_str.Length >> 1))
- {
- _cached_str = _str.Substring(0, _length);
- return _cached_str;
- }
- _cached_str = _str;
- _str.InternalSetLength(_length);
- return _str;
- }
- public string ToString (int startIndex, int length)
- {
- if( startIndex < 0 || length < 0 || startIndex + length > _length )
- throw new ArgumentOutOfRangeException();
- return _str.Substring (startIndex, length);
- }
- public int EnsureCapacity (int capacity)
- {
- if (capacity < 0)
- throw new ArgumentOutOfRangeException ("Capacity must be greater than 0." );
- if( capacity <= _str.Length )
- return _str.Length;
- InternalEnsureCapacity (capacity);
- return _str.Length;
- }
- public bool Equals (StringBuilder sb)
- {
- if (_length == sb.Length && _str == sb._str )
- return true;
- return false;
- }
- public StringBuilder Remove (int startIndex, int length)
- {
- if( startIndex < 0 || length < 0 || startIndex + length > _length )
- throw new ArgumentOutOfRangeException();
- // Copy everything after the 'removed' part to the start
- // of the removed part and truncate the sLength
- if (_length - (startIndex + length) > 0)
- String.InternalStrcpy (_str, startIndex, _str, startIndex + length, _length - (startIndex + length));
- _length -= length;
- if (null != _cached_str)
- InternalEnsureCapacity (_length);
- return this;
- }
- public StringBuilder Replace (char oldChar, char newChar)
- {
- return Replace( oldChar, newChar, 0, _length);
- }
- public StringBuilder Replace (char oldChar, char newChar, int startIndex, int count)
- {
- if( startIndex + count > _length || startIndex < 0 || count < 0 )
- throw new ArgumentOutOfRangeException();
- if (null != _cached_str)
- InternalEnsureCapacity (_str.Length);
- for (int replaceIterate = startIndex; replaceIterate < startIndex + count; replaceIterate++ ) {
- if( _str [replaceIterate] == oldChar )
- _str.InternalSetChar (replaceIterate, newChar);
- }
- return this;
- }
- public StringBuilder Replace( string oldValue, string newValue ) {
- return Replace (oldValue, newValue, 0, _length);
- }
- public StringBuilder Replace( string oldValue, string newValue, int startIndex, int count )
- {
- if (oldValue == null)
- throw new ArgumentNullException ("The old value cannot be null.");
- if (startIndex < 0 || count < 0 || startIndex + count > _length)
- throw new ArgumentOutOfRangeException ();
- if (oldValue.Length == 0)
- throw new ArgumentException ("The old value cannot be zero length.");
- // TODO: OPTIMIZE!
- string replace = _str.Substring(startIndex, count).Replace(oldValue, newValue);
- InternalEnsureCapacity (replace.Length + (_length - count));
- String.InternalStrcpy (_str, startIndex, replace);
-
- _length = replace.Length + (_length - count);
- return this;
- }
-
- /* The Append Methods */
- public StringBuilder Append (char[] value)
- {
- if (value == null)
- return this;
- int needed_cap = _length + value.Length;
- if (null != _cached_str || _str.Length < needed_cap)
- InternalEnsureCapacity (needed_cap);
-
- for (int i = 0; i != value.Length; i++)
- _str.InternalSetChar (i + _length, value[i]);
- _length += value.Length;
- return this;
- }
-
- public StringBuilder Append (string value)
- {
- if (value == null)
- return this;
- int needed_cap = _length + value.Length;
- if (null != _cached_str || _str.Length < needed_cap)
- InternalEnsureCapacity (needed_cap);
- String.InternalStrcpy (_str, _length, value);
- _length += value.Length;
- return this;
- }
- public StringBuilder Append (bool value) {
- return Append (value.ToString());
- }
-
- public StringBuilder Append (byte value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (decimal value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (double value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (short value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (int value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (long value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (object value) {
- if (value == null)
- return this;
- return Append (value.ToString());
- }
- [CLSCompliant(false)]
- public StringBuilder Append (sbyte value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (float value) {
- return Append (value.ToString());
- }
- [CLSCompliant(false)]
- public StringBuilder Append (ushort value) {
- return Append (value.ToString());
- }
-
- [CLSCompliant(false)]
- public StringBuilder Append (uint value) {
- return Append (value.ToString());
- }
- [CLSCompliant(false)]
- public StringBuilder Append (ulong value) {
- return Append (value.ToString());
- }
- public StringBuilder Append (char value)
- {
- int needed_cap = _length + 1;
- if (null != _cached_str || _str.Length < needed_cap)
- InternalEnsureCapacity (needed_cap);
- _str.InternalSetChar(_length, value);
- _length++;
- return this;
- }
- public StringBuilder Append (char value, int repeatCount)
- {
- if( repeatCount < 0 )
- throw new ArgumentOutOfRangeException();
- InternalEnsureCapacity (_length + repeatCount);
-
- for (int i = 0; i < repeatCount; i++)
- _str.InternalSetChar (_length++, value);
- return this;
- }
- public StringBuilder Append( char[] value, int startIndex, int charCount )
- {
- if (value == null) {
- if (!(startIndex == 0 && charCount == 0))
- throw new ArgumentNullException ("value");
- return this;
- }
- if ((charCount < 0 || startIndex < 0) || (charCount + startIndex > value.Length))
- throw new ArgumentOutOfRangeException();
-
-
- InternalEnsureCapacity (_length + charCount);
-
- int endPos = charCount + startIndex;
- for (int i = startIndex; i != endPos; i++)
- _str.InternalSetChar (_length++, value[i]);
- return this;
- }
- public StringBuilder Append (string value, int startIndex, int count)
- {
- if (value == null) {
- if (startIndex != 0 && count != 0)
- throw new ArgumentNullException ("value");
-
- return this;
- }
- if ((count < 0 || startIndex < 0) || (startIndex + count > value.Length))
- throw new ArgumentOutOfRangeException();
-
- int needed_cap = _length + count;
- if (null != _cached_str || _str.Length < needed_cap)
- InternalEnsureCapacity (needed_cap);
- String.InternalStrcpy (_str, _length, value, startIndex, count);
-
- _length += count;
- return this;
- }
- public StringBuilder AppendFormat (string format, object arg0)
- {
- return AppendFormat (null, format, new object [] { arg0 });
- }
- public StringBuilder AppendFormat (string format, params object[] args)
- {
- return AppendFormat (null, format, args);
- }
- public StringBuilder AppendFormat (IFormatProvider provider,
- string format,
- params object[] args)
- {
- String.FormatHelper (this, provider, format, args);
- return this;
- }
- public StringBuilder AppendFormat (string format, object arg0, object arg1)
- {
- return AppendFormat (null, format, new object [] { arg0, arg1 });
- }
- public StringBuilder AppendFormat (string format, object arg0, object arg1, object arg2)
- {
- return AppendFormat (null, format, new object [] { arg0, arg1, arg2 });
- }
- /* The Insert Functions */
-
- public StringBuilder Insert (int index, char[] value)
- {
- return Insert (index, new string (value));
- }
-
- public StringBuilder Insert (int index, string value)
- {
- if( index > _length || index < 0)
- throw new ArgumentOutOfRangeException();
- if (value == null || value.Length == 0)
- return this;
- InternalEnsureCapacity (_length + value.Length);
- // Move everything to the right of the insert point across
- String.InternalStrcpy (_str, index + value.Length, _str, index, _length - index);
-
- // Copy in stuff from the insert buffer
- String.InternalStrcpy (_str, index, value);
-
- _length += value.Length;
- return this;
- }
- public StringBuilder Insert( int index, bool value ) {
- return Insert (index, value.ToString());
- }
-
- public StringBuilder Insert( int index, byte value ) {
- return Insert (index, value.ToString());
- }
- public StringBuilder Insert( int index, char value)
- {
- if (index > _length || index < 0)
- throw new ArgumentOutOfRangeException ("index");
- InternalEnsureCapacity (_length + 1);
-
- // Move everything to the right of the insert point across
- String.InternalStrcpy (_str, index + 1, _str, index, _length - index);
-
- _str.InternalSetChar (index, value);
- _length++;
- return this;
- }
- public StringBuilder Insert( int index, decimal value ) {
- return Insert (index, value.ToString());
- }
- public StringBuilder Insert( int index, double value ) {
- return Insert (index, value.ToString());
- }
-
- public StringBuilder Insert( int index, short value ) {
- return Insert (index, value.ToString());
- }
- public StringBuilder Insert( int index, int value ) {
- return Insert (index, value.ToString());
- }
- public StringBuilder Insert( int index, long value ) {
- return Insert (index, value.ToString());
- }
-
- public StringBuilder Insert( int index, object value ) {
- return Insert (index, value.ToString());
- }
-
- [CLSCompliant(false)]
- public StringBuilder Insert( int index, sbyte value ) {
- return Insert (index, value.ToString() );
- }
- public StringBuilder Insert (int index, float value) {
- return Insert (index, value.ToString() );
- }
- [CLSCompliant(false)]
- public StringBuilder Insert (int index, ushort value) {
- return Insert (index, value.ToString() );
- }
- [CLSCompliant(false)]
- public StringBuilder Insert (int index, uint value) {
- return Insert ( index, value.ToString() );
- }
-
- [CLSCompliant(false)]
- public StringBuilder Insert (int index, ulong value) {
- return Insert ( index, value.ToString() );
- }
- public StringBuilder Insert (int index, string value, int count)
- {
- // LAMESPEC: The spec says to throw an exception if
- // count < 0, while MS throws even for count < 1!
- if ( count < 0 )
- throw new ArgumentOutOfRangeException();
- if (value != null && value != String.Empty)
- for (int insertCount = 0; insertCount < count; insertCount++)
- Insert( index, value );
- return this;
- }
- public StringBuilder Insert (int index, char [] value, int startIndex, int charCount)
- {
- if (value == null) {
- if (startIndex == 0 && charCount == 0)
- return this;
- throw new ArgumentNullException ("value");
- }
- if (charCount < 0 || startIndex < 0 || startIndex + charCount > value.Length)
- throw new ArgumentOutOfRangeException ();
- return Insert (index, new String (value, startIndex, charCount));
- }
-
- private void InternalEnsureCapacity (int size)
- {
- if (size > _str.Length || _cached_str == _str)
- {
- int capacity = _str.Length;
- // Try double buffer, if that doesn't work, set the length as capacity
- if (size > capacity)
- {
- capacity = capacity << 1;
- if (size > capacity)
- capacity = size;
- if (capacity >= Int32.MaxValue || capacity < 0)
- capacity = Int32.MaxValue;
- }
- string tmp = String.InternalAllocateStr (capacity);
- if (_length > 0)
- String.InternalStrcpy (tmp, 0, _str, 0, _length);
- _str = tmp;
- }
- _cached_str = null;
- }
- }
- }
|