From e050c89484d868292351a12ae7748eae9c1bd6b9 Mon Sep 17 00:00:00 2001 From: Alexander Radchenko Date: Mon, 12 Dec 2016 23:09:20 +0700 Subject: [PATCH] StringBuilder AppendJoin --- .../src/System/Text/StringBuilder.cs | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/src/System/Text/StringBuilder.cs index 4760d478f19..f325dacf15d 100644 --- a/src/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -17,6 +17,8 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Globalization; +using System.Diagnostics.Contracts; +using System.Collections.Generic; namespace System.Text { @@ -1050,6 +1052,88 @@ public StringBuilder Append(char[] value) return this; } + // Append joined values with a separator between each value. + public unsafe StringBuilder AppendJoin(char separator, params T[] values) + { + // Defer argument validation to the internal function + return AppendJoinCore(&separator, 1, values); + } + + public unsafe StringBuilder AppendJoin(string separator, params T[] values) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = separator) + { + // Defer argument validation to the internal function + return AppendJoinCore(pSeparator, separator.Length, values); + } + } + + public unsafe StringBuilder AppendJoin(char separator, IEnumerable values) + { + // Defer argument validation to the internal function + return AppendJoinCore(&separator, 1, values); + } + + public unsafe StringBuilder AppendJoin(string separator, IEnumerable values) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = separator) + { + // Defer argument validation to the internal function + return AppendJoinCore(pSeparator, separator.Length, values); + } + } + + private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, params T[] values) + { + if (values == null) + throw new ArgumentNullException(nameof(values)); + Contract.Ensures(Contract.Result() != null); + + if (values.Length == 0) + return this; + + var value = values[0]; + if (value != null) + Append(value.ToString()); + + for (var i = 1; i < values.Length; i++) + { + Append(separator, separatorLength); + value = values[i]; + if (value != null) + Append(value.ToString()); + } + return this; + } + + private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, IEnumerable values) + { + if (values == null) + throw new ArgumentNullException(nameof(values)); + Contract.Ensures(Contract.Result() != null); + + using (var en = values.GetEnumerator()) + { + if (!en.MoveNext()) + return this; + + var value = en.Current; + if (value != null) + Append(value.ToString()); + + while (en.MoveNext()) + { + Append(separator, separatorLength); + value = en.Current; + if (value != null) + Append(value.ToString()); + } + } + return this; + } + /*====================================Insert==================================== ** ==============================================================================*/