Skip to content

Commit 30dda84

Browse files
committed
Improvements in constructors
- Add private constants to remove magic numbers from code. - Improvements and simplification on parameters validations. - Remove param names from exceptions.
1 parent 4dfb99b commit 30dda84

File tree

1 file changed

+100
-50
lines changed

1 file changed

+100
-50
lines changed

nanoFramework.System.Text/Text/StringBuilder.cs

Lines changed: 100 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ namespace System.Text
1919
/// </remarks>
2020
public sealed class StringBuilder
2121
{
22+
private const int DefaultCapacity = 0x10;
23+
private const int DefaultMaxCapacity = short.MaxValue;
24+
private const int MaxChunkSize = 8000;
25+
2226
#region Fields
2327

2428
private readonly int _maxCapacity;
@@ -221,90 +225,136 @@ public int Length
221225
/// <summary>
222226
/// Initializes a new instance of the <see cref="StringBuilder"/> class from the specified substring and capacity.
223227
/// </summary>
224-
/// <param name="value">The string that contains the substring used to initialize the value of this instance. If value is null, the new StringBuilder will contain the empty string (that is, it contains Empty).</param>
228+
/// <param name="value">The string that contains the substring used to initialize the value of this instance. If value is <see langword="null"/>, the new <see cref="StringBuilder"/> will contain the empty string (that is, it contains <see cref="string.Empty"/>).</param>
225229
/// <param name="startIndex">The position within value where the substring begins.</param>
226230
/// <param name="length">The number of characters in the substring.</param>
227231
/// <param name="capacity">The suggested starting size of the <see cref="StringBuilder"/>.</param>
228-
public unsafe StringBuilder(string value, int startIndex, int length, int capacity)
232+
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="capacity"/> is less than zero, <paramref name="length"/> is less than zero, <paramref name="startIndex"/> is less than zero, or <paramref name="startIndex"/> is greater than the length of <paramref name="value"/> minus <paramref name="length"/>.</exception>
233+
public unsafe StringBuilder(
234+
string value,
235+
int startIndex,
236+
int length,
237+
int capacity)
229238
{
230-
if (capacity < 0) throw new ArgumentOutOfRangeException("capacity");
231-
if (length < 0) throw new ArgumentOutOfRangeException("length");
232-
if (startIndex < 0) throw new ArgumentOutOfRangeException("startIndex");
233-
if (value == null) value = string.Empty;
234-
if (startIndex > value.Length - length) throw new ArgumentOutOfRangeException("length");
235-
_maxCapacity = 0x7fffffff;
236-
if (capacity == 0) capacity = 0x10;
237-
if (capacity < length) capacity = length;
238-
//Allocate the chunk of capactity
239-
_chunkChars = new char[capacity];
240-
//Set the length of the chunk
241-
_chunkLength = length;
242-
//Copy the value to the chunkChars
243-
value.ToCharArray(startIndex, length).CopyTo(_chunkChars, 0);
244-
}
239+
if (capacity < 0 || length < 0 || startIndex < 0)
240+
{
241+
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
242+
throw new ArgumentOutOfRangeException();
243+
#pragma warning restore S3928 // OK to use in .NET nanoFramework context
244+
}
245245

246-
private StringBuilder(int size, int maxCapacity, StringBuilder previousBlock)
247-
{
248-
_chunkChars = new char[size];
249-
_maxCapacity = maxCapacity;
250-
_chunkPrevious = previousBlock;
251-
if (previousBlock != null)
246+
value ??= string.Empty;
247+
248+
if (startIndex > value.Length - length)
252249
{
253-
_chunkOffset = previousBlock._chunkOffset + previousBlock._chunkLength;
250+
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
251+
throw new ArgumentOutOfRangeException();
252+
#pragma warning restore S3928 // OK to use in .NET nanoFramework context
253+
}
254+
255+
_maxCapacity = DefaultMaxCapacity;
256+
257+
if (capacity == 0)
258+
{
259+
capacity = DefaultCapacity;
260+
}
261+
262+
if (capacity < length)
263+
{
264+
capacity = length;
254265
}
266+
267+
// Allocate the chunk of capactity
268+
_chunkChars = new char[capacity];
269+
270+
// Set the length of the chunk
271+
_chunkLength = length;
272+
273+
// Copy the value to the chunkChars
274+
value.ToCharArray(startIndex, length).CopyTo(_chunkChars, 0);
255275
}
256276

257277
/// <summary>
258-
/// Initializes a new instance of the <see cref="StringBuilder"/> class using the specified string and capacity.
278+
/// Initializes a new instance of the <see cref="StringBuilder"/> class using the specified string and capacity.
259279
/// </summary>
260-
/// <param name="value">The string used to initialize the value of the instance. If value is null, the new StringBuilder will contain the empty string (that is, it contains Empty).</param>
261-
/// <param name="capacity">The suggested starting size of the <see cref="StringBuilder"/>.</param>
262-
public StringBuilder(string value, int capacity)
263-
: this(value, 0, value != null ? value.Length : 0, capacity) { }
280+
/// <param name="value">The string used to initialize the value of the instance. If value is <see langword="null"/>, the new <see cref="StringBuilder"/> will contain the empty string (that is, it contains <see cref="string.Empty"/>).</param>
281+
/// <param name="capacity">The suggested starting size of the StringBuilder.</param>
282+
public StringBuilder(
283+
string value,
284+
int capacity)
285+
: this(value, 0, value
286+
!= null ? value.Length : 0, capacity)
287+
{ }
264288

265289
/// <summary>
266-
/// Initializes a new instance of the <see cref="StringBuilder"/> class that starts with a specified capacity and can grow to a specified maximum.
290+
/// Initializes a new instance of the <see cref="StringBuilder"/> class that starts with a specified capacity and can grow to a specified maximum.
267291
/// </summary>
268292
/// <param name="capacity">The suggested starting size of the <see cref="StringBuilder"/>.</param>
269293
/// <param name="maxCapacity">The maximum number of characters the current string can contain.</param>
270-
public StringBuilder(int capacity, int maxCapacity)
294+
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="capacity"/> is less than zero, <paramref name="maxCapacity"/> is less than one, or <paramref name="capacity"/> is greater than <paramref name="maxCapacity"/>.</exception>
295+
public StringBuilder(
296+
int capacity,
297+
int maxCapacity)
271298
{
272-
if (capacity > maxCapacity) throw new ArgumentOutOfRangeException("capacity");
273-
if (maxCapacity < 1) throw new ArgumentOutOfRangeException("maxCapacity");
274-
if (capacity < 0) throw new ArgumentOutOfRangeException("capacity");
275-
if (capacity == 0) capacity = MathInternal.Min(0x10, maxCapacity);
299+
if (capacity > maxCapacity || maxCapacity < 1 || capacity < 0)
300+
{
301+
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
302+
throw new ArgumentOutOfRangeException();
303+
#pragma warning restore S3928 // OK to use in .NET nanoFramework context
304+
}
305+
306+
if (capacity == 0)
307+
{
308+
capacity = MathInternal.Min(DefaultCapacity, maxCapacity);
309+
}
310+
276311
_maxCapacity = maxCapacity;
277312
_chunkChars = new char[capacity];
278313
}
279314

280-
private StringBuilder(StringBuilder from)
281-
{
282-
_chunkLength = from._chunkLength;
283-
_chunkOffset = from._chunkOffset;
284-
_chunkChars = from._chunkChars;
285-
_chunkPrevious = from._chunkPrevious;
286-
_maxCapacity = from._maxCapacity;
287-
}
288-
289315
/// <summary>
290-
/// Initializes a new instance of the <see cref="StringBuilder"/> class using the specified capacity.
316+
/// Initializes a new instance of the <see cref="StringBuilder"/> class using the specified capacity.
291317
/// </summary>
292318
/// <param name="capacity">The suggested starting size of this instance.</param>
293319
public StringBuilder(int capacity)
294320
: this(string.Empty, capacity) { }
295321

296322
/// <summary>
297-
/// Initializes a new instance of the <see cref="StringBuilder"/> class using the specified string.
323+
/// Initializes a new instance of the <see cref="StringBuilder"/> class using the specified string.
298324
/// </summary>
299-
/// <param name="value">The string used to initialize the value of the instance. If value is <see langword="null"/>, the new <see cref="StringBuilder"/> will contain the empty string (that is, it contains <see cref="String.Empty"/>).</param>
325+
/// <param name="value">The string used to initialize the value of the instance. If value is <see langword="null"/>, the new <see cref="StringBuilder"/> will contain the empty string (that is, it contains <see cref="string.Empty"/>).</param>
300326
public StringBuilder(string value)
301-
: this(value, 0x10) { }
327+
: this(value, DefaultCapacity) { }
302328

303329
/// <summary>
304-
/// Initializes a new instance of the <see cref="StringBuilder"/> class.
330+
/// Initializes a new instance of the <see cref="StringBuilder"/> class.
305331
/// </summary>
306332
public StringBuilder()
307-
: this(0x10) { }
333+
: this(DefaultCapacity) { }
334+
335+
private StringBuilder(
336+
int size,
337+
int maxCapacity,
338+
StringBuilder previousBlock)
339+
{
340+
_chunkChars = new char[size];
341+
_maxCapacity = maxCapacity;
342+
_chunkPrevious = previousBlock;
343+
344+
if (previousBlock != null)
345+
{
346+
_chunkOffset = previousBlock._chunkOffset + previousBlock._chunkLength;
347+
}
348+
}
349+
350+
private StringBuilder(StringBuilder from)
351+
{
352+
_chunkLength = from._chunkLength;
353+
_chunkOffset = from._chunkOffset;
354+
_chunkChars = from._chunkChars;
355+
_chunkPrevious = from._chunkPrevious;
356+
_maxCapacity = from._maxCapacity;
357+
}
308358

309359
#endregion
310360

0 commit comments

Comments
 (0)