//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright 2011 Xamarin Inc
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
namespace System.Text {
[Serializable]
-#if NET_2_0
[ComVisible (true)]
-#endif
- [MonoTODO ("Serialization format not compatible with .NET")]
- public sealed class StringBuilder
-#if NET_2_0
- : ISerializable
-#endif
+ [MonoLimitation ("Serialization format not compatible with .NET")]
+ [StructLayout (LayoutKind.Sequential)]
+ public sealed class StringBuilder : ISerializable
{
private int _length;
private string _str;
private string _cached_str;
- private int _maxCapacity = Int32.MaxValue;
+ private int _maxCapacity;
private const int constDefaultCapacity = 16;
public StringBuilder(string value, int startIndex, int length, int capacity)
+ : this (value, startIndex, length, capacity, Int32.MaxValue)
+ {
+ }
+
+ private StringBuilder(string value, int startIndex, int length, int capacity, int maxCapacity)
{
// first, check the parameters and throw appropriate exceptions if needed
if (null == value)
if (capacity < 0)
throw new System.ArgumentOutOfRangeException ("capacity", capacity, "capacity must be greater than zero.");
+ if (maxCapacity < 1)
+ throw new System.ArgumentOutOfRangeException ("maxCapacity", "maxCapacity is less than one.");
+ if (capacity > maxCapacity)
+ throw new System.ArgumentOutOfRangeException ("capacity", "Capacity exceeds maximum capacity.");
+
// make sure startIndex and length give a valid substring of value
// re-ordered to avoid possible integer overflow
if (startIndex > value.Length - length)
throw new System.ArgumentOutOfRangeException ("startIndex", startIndex, "StartIndex and length must refer to a location within the string.");
- if (capacity == 0)
- capacity = constDefaultCapacity;
+ if (capacity == 0) {
+ if (maxCapacity > constDefaultCapacity)
+ capacity = constDefaultCapacity;
+ else
+ _str = _cached_str = String.Empty;
+ }
+ _maxCapacity = maxCapacity;
- _str = String.InternalAllocateStr ((length > capacity) ? length : capacity);
+ if (_str == null)
+ _str = String.InternalAllocateStr ((length > capacity) ? length : capacity);
if (length > 0)
String.CharCopy (_str, 0, value, startIndex, length);
public StringBuilder(int capacity) : this (String.Empty, 0, 0, capacity) {}
- public StringBuilder(int capacity, int maxCapacity) : this (String.Empty, 0, 0, capacity) {
- if (maxCapacity < 1)
- throw new System.ArgumentOutOfRangeException ("maxCapacity", "maxCapacity is less than one.");
- if (capacity > maxCapacity)
- throw new System.ArgumentOutOfRangeException ("capacity", "Capacity exceeds maximum capacity.");
-
- _maxCapacity = maxCapacity;
- }
+ public StringBuilder(int capacity, int maxCapacity) : this (String.Empty, 0, 0, capacity, maxCapacity) { }
public StringBuilder (string value)
{
_length = value.Length;
_str = _cached_str = value;
+ _maxCapacity = Int32.MaxValue;
}
- public StringBuilder( string value, int capacity) : this(value, 0, value.Length, capacity) {}
+ public StringBuilder( string value, int capacity) : this(value == null ? "" : value, 0, value == null ? 0 : value.Length, capacity) {}
public int MaxCapacity {
get {
- // MS runtime always returns Int32.MaxValue.
return _maxCapacity;
}
}
public int Capacity {
get {
if (_str.Length == 0)
- return constDefaultCapacity;
+ return Math.Min (_maxCapacity, constDefaultCapacity);
return _str.Length;
}
if (value < _length)
throw new ArgumentException( "Capacity must be larger than length" );
+ if (value > _maxCapacity)
+ throw new ArgumentOutOfRangeException ("value", "Should be less than or equal to MaxCapacity");
+
InternalEnsureCapacity(value);
}
}
return _cached_str;
// If we only have a half-full buffer we return a new string.
- if (_length < (_str.Length >> 1))
+ if (_length < (_str.Length >> 1) || (_str.Length > string.LOS_limit && _length <= string.LOS_limit))
{
// use String.SubstringUnchecked instead of String.Substring
// as the former is guaranteed to create a new string object
return this;
}
-#if NET_2_0
+#if NET_4_0 || MOONLIGHT || MOBILE
+ public StringBuilder Clear ()
+ {
+ Length = 0;
+ return this;
+ }
+#endif
+
[ComVisible (false)]
public StringBuilder AppendLine ()
{
{
return Append (value).Append (System.Environment.NewLine);
}
-#endif
public StringBuilder AppendFormat (string format, params object[] args)
{
return this;
}
-#if NET_2_1
+#if MOONLIGHT
internal
#else
public
return AppendFormat (null, format, new object [] { arg0 });
}
-#if NET_2_1
+#if MOONLIGHT
internal
#else
public
return AppendFormat (null, format, new object [] { arg0, arg1 });
}
-#if NET_2_1
+#if MOONLIGHT
internal
#else
public
_cached_str = null;
}
-#if NET_2_0
[ComVisible (false)]
public void CopyTo (int sourceIndex, char [] destination, int destinationIndex, int count)
{
_maxCapacity = Int32.MaxValue;
Capacity = info.GetInt32 ("Capacity");
}
-#endif
}
}