网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1020 lines
40 KiB

#if NET20 || NET30 || NET35 || !NET_4_6
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text;
using LinqInternal.Collections.Specialized;
using LinqInternal.Core;
namespace System.Numerics
{
public partial struct BigInteger
{
internal static string FormatBigInteger(BigInteger value, string format, NumberFormatInfo info)
{
int digits;
var fmt = ParseFormatSpecifier(format, out digits);
if (fmt == 'x' || fmt == 'X')
{
return FormatBigIntegerToHexString(value, fmt, digits, info);
}
if (fmt == 'e' || fmt == 'E')
{
var precision = digits != -1 ? digits : 6;
if (value.InternalBits == null)
{
return value.InternalSign.ToString(format, info);
}
var scale = (int)Math.Floor(Log10(value));
// ---
if (scale > precision + 10)
{
do
{
value /= 1000000000;
} while (Log10(value) > precision + 10);
}
while (Log10(value) > precision + 2)
{
value /= 10;
}
if ((Log10(value) > precision + 1))
{
var round = value % 10 >= 5;
value = (value / 10) + (round ? One : Zero);
}
ReverseStringBuilder builder;
if (value.InternalBits == null)
{
builder = new ReverseStringBuilder(10);
builder.Prepend(value.InternalSign.ToString("D"));
}
else
{
builder = CreateBuilder(value, info, false, 0);
}
// ---
var decimalSeparator = info.NumberDecimalSeparator;
var result = new StringBuilder(builder.Length + 6);
var extra = 0;
if (precision >= builder.Length)
{
extra = precision - (builder.Length - 1);
precision = builder.Length - 1;
}
result.Append(builder.ToString(builder.Length, 1));
result.Append(decimalSeparator);
result.Append(builder.ToString(builder.Length - 1, precision));
result.Append(new string('0', extra));
result.Append(fmt);
result.Append(info.PositiveSign);
if (scale < 10)
{
result.Append("00");
}
else if (scale < 100)
{
result.Append('0');
}
result.Append(scale);
return result.ToString();
}
else
{
var decimalFmt = (fmt == 'g' || fmt == 'G' || fmt == 'd' || fmt == 'D' || fmt == 'r' || fmt == 'R');
if (value.InternalBits == null)
{
if (fmt == 'g' || fmt == 'G' || fmt == 'r' || fmt == 'R')
{
if (digits > 0)
{
format = "D" + digits.ToString(CultureInfo.InvariantCulture);
}
else
{
format = "D";
}
}
return value.InternalSign.ToString(format, info);
}
var builder = CreateBuilder(value, info, decimalFmt, digits);
if (decimalFmt)
{
// Format Round-trip decimal
// This format is supported for integral types only. The number is converted to a string of
// decimal digits (0-9), prefixed by a minus sign if the number is negative. The precision
// specifier indicates the minimum number of digits desired in the resulting string. If required,
// the number is padded with zeros to its left to produce the number of digits given by the
// precision specifier.
while (digits > 0 && digits >= builder.Length)
{
builder.Prepend('0');
digits--;
}
if (value.InternalSign < 0)
{
builder.Prepend(info.NegativeSign);
}
return builder.ToString();
}
// 'c', 'C', 'e', 'E', 'f', 'F', 'n', 'N', 'p', 'P', custom
var precision = -1;
var groupingSizes = new[] { 3 };
var groupingSeparator = info.NumberGroupSeparator;
var decimalSeparator = info.NumberDecimalSeparator;
var groups = false;
var type = 0;
if (fmt == '\0')
{
// parse custom
}
else
{
if (fmt == 'c' || fmt == 'C')
{
decimalSeparator = info.CurrencyDecimalSeparator;
precision = digits != -1 ? digits : info.CurrencyDecimalDigits;
groupingSeparator = info.CurrencyGroupSeparator;
groupingSizes = info.CurrencyGroupSizes;
groups = true;
type = 1;
}
else if (fmt == 'f' || fmt == 'F')
{
precision = digits != -1 ? digits : info.NumberDecimalDigits;
}
else if (fmt == 'n' || fmt == 'N')
{
precision = digits != -1 ? digits : info.NumberDecimalDigits;
groups = true;
}
else if (fmt == 'p' || fmt == 'P')
{
decimalSeparator = info.PercentDecimalSeparator;
precision = digits != -1 ? digits : info.PercentDecimalDigits;
groups = true;
type = 2;
}
else
{
throw new NotImplementedException();
}
}
var result = new StringBuilder(builder.Length + 20);
var close = SetWrap(value, info, type, result);
var append = builder;
if (groups)
{
var extra = groupingSizes.Length - 1;
if (groupingSizes[groupingSizes.Length - 1] != 0)
{
var totalDigits = builder.Length;
extra += (int)Math.Ceiling(totalDigits * 1.0 / groupingSizes[groupingSizes.Length - 1]);
}
var length = extra + builder.Length;
if (type == 2)
{
length += 2;
append = StringWithGroups(length, new ExtendedEnumerable<char>(new[] { '0', '0' }, builder), groupingSizes, groupingSeparator);
}
else
{
append = StringWithGroups(extra + builder.Length, builder, groupingSizes, groupingSeparator);
}
}
result.Append(append);
if (precision > 0)
{
result.Append(decimalSeparator);
result.Append(new string('0', precision));
}
result.Append(close);
return result.ToString();
}
}
internal static BigInteger ParseBigInteger(string value, NumberStyles style, NumberFormatInfo info)
{
ArgumentException argumentException;
if (value == null)
{
throw new ArgumentNullException("value");
}
if (!TryValidateParseStyleInteger(style, out argumentException))
{
throw argumentException;
}
BigInteger zero;
if (!TryParseBigInteger(value, style, info, out zero))
{
throw new FormatException("The value could not be parsed.");
}
return zero;
}
internal static char ParseFormatSpecifier(string format, out int digits)
{
digits = -1;
if (string.IsNullOrEmpty(format))
{
return 'R';
}
var index = 0;
var chr = format[index];
if (chr >= 'A' && chr <= 'Z' || chr >= 'a' && chr <= 'z')
{
index++;
if (index < format.Length)
{
var tmp = format[index];
if (tmp >= '0' && tmp <= '9')
{
index++;
digits = tmp - '0';
do
{
if (index >= format.Length || format[index] < '0' || format[index] > '9')
{
break;
}
digits = digits * 10 + (format[index] - '0');
index++;
} while (digits < 10);
}
}
if (index >= format.Length || format[index] == 0)
{
return chr;
}
}
return '\0';
}
internal static bool ParseNumber(StringProcessor reader, NumberStyles options, BigNumberBuffer number, NumberFormatInfo info)
{
// Percent intentionally not supported
// After testig with .NET the patterns are ignored... all patterns are welcome
var currencySymbol = info.CurrencySymbol;
var numberGroupSeparator = info.NumberGroupSeparator;
var currencyGroupSeparator = info.CurrencyGroupSeparator;
var positiveSign = info.PositiveSign;
var negativeSign = info.NegativeSign;
if ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
{
var allowLeadingWhite = (options & NumberStyles.AllowLeadingWhite) != NumberStyles.None;
var allowTrailingWhite = (options & NumberStyles.AllowTrailingWhite) != NumberStyles.None;
/*
// Assume validated
if (
(options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None
|| (options & NumberStyles.AllowLeadingSign) != NumberStyles.None
|| (options & NumberStyles.AllowParentheses) != NumberStyles.None
|| (options & NumberStyles.AllowThousands) != NumberStyles.None
|| (options & NumberStyles.AllowExponent) != NumberStyles.None
|| (options & NumberStyles.AllowTrailingSign) != NumberStyles.None
)
{
return false;
}*/
number.Negative = false;
if (allowLeadingWhite)
{
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
while (true)
{
var input =
reader.ReadWhile(new[]
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C',
'D', 'E', 'F'
});
if (input == string.Empty)
{
break;
}
number.Scale += input.Length;
number.Digits.Append(input.ToUpperInvariant());
}
if (allowTrailingWhite)
{
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
return reader.EndOfString;
}
else
{
var allowCurrencySymbol = (options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None;
var allowLeadingWhite = (options & NumberStyles.AllowLeadingWhite) != NumberStyles.None;
var allowLeadingSign = (options & NumberStyles.AllowLeadingSign) != NumberStyles.None;
var allowParentheses = (options & NumberStyles.AllowParentheses) != NumberStyles.None;
var allowThousands = (options & NumberStyles.AllowThousands) != NumberStyles.None;
var allowExponent = (options & NumberStyles.AllowExponent) != NumberStyles.None;
var allowTrailingWhite = (options & NumberStyles.AllowTrailingWhite) != NumberStyles.None;
var allowTrailingSign = (options & NumberStyles.AllowTrailingSign) != NumberStyles.None;
var allowDecimalPoint = (options & NumberStyles.AllowDecimalPoint) != NumberStyles.None;
var isCurrency = false;
number.Negative = false;
var waitingParentheses = false;
var positive = false;
// [ws][$][sign][digits,]digits[E[sign]exponential_digits][ws]
if (allowLeadingWhite)
{
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
// [$][sign][digits,]digits[E[sign]exponential_digits][ws]
if (allowCurrencySymbol && reader.Read(currencySymbol))
{
isCurrency = true;
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
// [sign][digits,]digits[E[sign]exponential_digits][ws
if (allowLeadingSign)
{
number.Negative |= reader.Read(negativeSign);
positive |= reader.Read(positiveSign);
}
if (!number.Negative && allowParentheses && reader.Read('('))
{
// Testing on .NET show that $(n) is allowed, even tho there is no CurrencyNegativePattern for it
number.Negative = true;
waitingParentheses = true;
}
// ---
if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol)) // If the currency symbol is after the negative sign
{
isCurrency = true;
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
// [digits,]digits[E[sign]exponential_digits][ws]
var failure = true;
var digits = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
var decimalFound = false;
while (true)
{
var input = reader.ReadWhile(digits);
if (input == string.Empty)
{
if (allowDecimalPoint && !decimalFound)
{
if (reader.Read(info.CurrencyDecimalSeparator))
{
decimalFound = true;
continue;
}
if (reader.Read(info.NumberDecimalSeparator))
{
if (isCurrency)
{
return false;
}
decimalFound = true;
continue;
}
}
break;
}
failure = false;
if (!decimalFound)
{
number.Scale += input.Length;
}
number.Digits.Append(input);
if (allowThousands)
{
// Testing on .NET show that combining currency and number group separators is allowed
// But not if the currency symbol has already appeared
reader.SkipWhile(currencyGroupSeparator);
if (!isCurrency)
{
reader.SkipWhile(numberGroupSeparator);
}
}
}
if (failure)
{
return false;
}
// [E[sign]exponential_digits][ws]
if (allowExponent && (reader.Read('E') || reader.Read('e')))
{
// [sign]exponential_digits
// Testing on .NET show that no pattern is used here, also no parentheses nor group separators supported
// The exponent can be big - but anything beyond 9999 is ignored
var exponentNegative = reader.Read(negativeSign);
if (!exponentNegative)
{
reader.Read(positiveSign);
}
var input = reader.ReadWhile(digits);
var exponentMagnitude = int.Parse(input, CultureInfo.InvariantCulture);
number.Scale += (exponentNegative ? -1 : 1) * (input.Length > 4 ? 9999 : exponentMagnitude);
if (number.Scale < 0)
{
return false;
}
}
// ---
if (allowTrailingWhite)
{
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol))
{
isCurrency = true;
}
// ---
if (!number.Negative && !positive && allowTrailingSign)
{
number.Negative |= reader.Read(negativeSign);
positive |= reader.Read(positiveSign);
}
if (waitingParentheses && !reader.Read(')'))
{
return false;
}
// ---
if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol)) // If the currency symbol is after the negative sign
{
isCurrency = true; // For completeness sake
}
// [ws]
if (allowTrailingWhite)
{
reader.SkipWhile(CharHelper.IsClassicWhitespace);
}
return reader.EndOfString;
}
}
internal static bool TryParseBigInteger(string value, NumberStyles style, NumberFormatInfo info, out BigInteger result)
{
result = Zero;
ArgumentException e;
if (!TryValidateParseStyleInteger(style, out e))
{
throw e; // TryParse still throws ArgumentException on invalid NumberStyles
}
if (value == null)
{
return false;
}
var number = BigNumberBuffer.Create();
if (!ParseNumber(new StringProcessor(value), style, number, info))
{
return false;
}
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{
if (!HexNumberToBigInteger(number, ref result))
{
return false;
}
}
else
{
if (!NumberToBigInteger(number, out result))
{
return false;
}
}
return true;
}
internal static bool TryValidateParseStyleInteger(NumberStyles style, out ArgumentException e)
{
if (((int)style & -1024) != (int)NumberStyles.None)
{
e = new ArgumentException("An undefined NumberStyles value is being used.", "style");
return false;
}
if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.None || (style & (NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign | NumberStyles.AllowParentheses | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowExponent | NumberStyles.AllowCurrencySymbol)) == NumberStyles.None)
{
e = null;
return true;
}
e = new ArgumentException("With the AllowHexSpecifier bit set in the enum bit field, the only other valid bits that can be combined into the enum value must be a subset of those in HexNumber.");
return false;
}
private static ReverseStringBuilder CreateBuilder(BigInteger value, NumberFormatInfo info, bool decimalFmt, int digits)
{
// First convert to base 10^9.
const uint NumericBase = 1000000000; // 10^9
const int NumericBaseLog10 = 9;
var sourceLength = Length(value.InternalBits);
int maxConvertedLength;
try
{
maxConvertedLength = checked(sourceLength * 10 / 9 + 2);
}
catch (OverflowException e)
{
throw new FormatException("The value is too large to be represented by this format specifier.", e);
}
var converted = new uint[maxConvertedLength];
var convertedLength = 0;
for (var sourceIndex = sourceLength; --sourceIndex >= 0;)
{
// Take a cipher from the source
var carry = value.InternalBits[sourceIndex];
// Add it to converted
for (var convertedIndex = 0; convertedIndex < convertedLength; convertedIndex++)
{
var cipherBlock = NumericsHelpers.MakeUlong(converted[convertedIndex], carry);
converted[convertedIndex] = (uint)(cipherBlock % NumericBase);
carry = (uint)(cipherBlock / NumericBase);
}
if (carry != 0)
{
converted[convertedLength++] = carry % NumericBase;
carry /= NumericBase;
if (carry != 0)
{
converted[convertedLength++] = carry;
}
}
}
int stringCapacity;
try
{
// Each uint contributes at most 9 digits to the decimal representation.
stringCapacity = checked(convertedLength * NumericBaseLog10);
}
catch (OverflowException e)
{
throw new FormatException("The value is too large to be represented by this format specifier.", e);
}
if (decimalFmt)
{
if (digits > 0 && stringCapacity < digits)
{
stringCapacity = digits;
}
if (value.InternalSign < 0)
{
try
{
// Leave an extra slot for a minus sign.
stringCapacity = checked(stringCapacity + info.NegativeSign.Length);
}
catch (OverflowException e)
{
throw new FormatException("The value is too large to be represented by this format specifier.", e);
}
}
}
var result = new ReverseStringBuilder(stringCapacity);
for (var stringIndex = 0; stringIndex < convertedLength - 1; stringIndex++)
{
var cipherBlock = converted[stringIndex];
for (var cch = NumericBaseLog10; --cch >= 0;)
{
result.Prepend((char)('0' + cipherBlock % 10));
cipherBlock /= 10;
}
}
for (var cipherBlock = converted[convertedLength - 1]; cipherBlock != 0;)
{
result.Prepend((char)('0' + cipherBlock % 10));
cipherBlock /= 10;
}
return result;
}
private static string FormatBigIntegerToHexString(BigInteger value, char format, int digits, NumberFormatInfo info)
{
var stringBuilder = new StringBuilder();
var byteArray = value.ToByteArray();
string str1;
var length = byteArray.Length - 1;
if (length > -1)
{
var flag = false;
var num = byteArray[length];
if (num > 247)
{
num = (byte)(num - 240);
flag = true;
}
if (num < 8 || flag)
{
str1 = string.Format(CultureInfo.InvariantCulture, "{0}1", format);
stringBuilder.Append(num.ToString(str1, info));
length--;
}
}
if (length > -1)
{
str1 = string.Format(CultureInfo.InvariantCulture, "{0}2", format);
while (length > -1)
{
var num1 = length;
length = num1 - 1;
stringBuilder.Append(byteArray[num1].ToString(str1, info));
}
}
if (digits > 0 && digits > stringBuilder.Length)
{
var stringBuilder1 = stringBuilder;
string str;
if (value.InternalSign < 0)
{
str = (format != 'x' ? "F" : "f");
}
else
{
str = "0";
}
stringBuilder1.Insert(0, str, digits - stringBuilder.Length);
}
return stringBuilder.ToString();
}
private static bool HexNumberToBigInteger(BigNumberBuffer number, ref BigInteger value)
{
if (number.Digits == null || number.Digits.Length == 0)
{
return false;
}
var len = number.Digits.Length; // there is no trailing '\0'
var bits = new byte[(len / 2) + (len % 2)];
var shift = false;
var isNegative = false;
var bitIndex = 0;
// parse the string into a little-endian two's complement byte array
// string value : O F E B 7 \0
// string index (i) : 0 1 2 3 4 5 <--
// byte[] (bitIndex): 2 1 1 0 0 <--
//
for (var i = len - 1; i > -1; i--)
{
var c = number.Digits[i];
byte b;
if (c >= '0' && c <= '9')
{
b = (byte)(c - '0');
}
else if (c >= 'A' && c <= 'F')
{
b = (byte)((c - 'A') + 10);
}
else
{
Contract.Assert(c >= 'a' && c <= 'f');
b = (byte)((c - 'a') + 10);
}
isNegative |= (i == 0 && (b & 0x08) == 0x08);
if (shift)
{
bits[bitIndex] = (byte)(bits[bitIndex] | (b << 4));
bitIndex++;
}
else
{
bits[bitIndex] = isNegative ? (byte)(b | 0xF0) : (b);
}
shift = !shift;
}
value = new BigInteger(bits);
return true;
}
private static bool NumberToBigInteger(BigNumberBuffer number, out BigInteger value)
{
var cur = 0;
if (number.Scale > number.Digits.Length)
{
var i = number.Digits.Length;
value = 0;
while (--i >= 0)
{
value *= 10;
value += (number.Digits[cur++] - '0');
}
var adjust = number.Scale - number.Digits.Length;
while (adjust > 9)
{
value *= 1000000000;
adjust -= 9;
}
while (adjust > 0)
{
value *= 10;
adjust--;
}
}
else
{
var i = number.Scale;
value = 0;
while (--i >= 0)
{
value *= 10;
value += (number.Digits[cur++] - '0');
}
for (; cur < number.Digits.Length - 1; cur++)
{
if (number.Digits[cur++] != '0')
{
return false;
}
}
}
if (number.Negative)
{
value = -value;
}
return true;
}
private static string SetWrap(BigInteger value, NumberFormatInfo info, int type, StringBuilder result)
{
var close = string.Empty;
switch (type)
{
case 1:
if (value.InternalSign < 0)
{
switch (info.CurrencyNegativePattern)
{
case 0:
result.Append('(');
result.Append(info.CurrencySymbol);
close = ")";
break;
case 1:
result.Append(info.NegativeSign);
result.Append(info.CurrencySymbol);
break;
case 2:
result.Append(info.CurrencySymbol);
result.Append(info.NegativeSign);
break;
case 3:
result.Append(info.CurrencySymbol);
close = info.NegativeSign;
break;
case 4:
result.Append('(');
close = info.CurrencySymbol + ")";
break;
case 5:
result.Append(info.NegativeSign);
close = info.CurrencySymbol;
break;
case 6:
close = info.NegativeSign + info.CurrencySymbol;
break;
case 7:
close = info.CurrencySymbol + info.NegativeSign;
break;
case 8:
result.Append(info.NegativeSign);
close = " " + info.CurrencySymbol;
break;
case 9:
result.Append(info.NegativeSign);
result.Append(info.CurrencySymbol);
result.Append(" ");
break;
case 10:
close = " " + info.CurrencySymbol + info.NegativeSign;
break;
case 11:
result.Append(info.CurrencySymbol);
result.Append(" ");
close = info.NegativeSign;
break;
case 12:
result.Append(info.CurrencySymbol);
result.Append(" ");
result.Append(info.NegativeSign);
break;
case 13:
result.Append(info.CurrencySymbol);
result.Append(info.NegativeSign);
result.Append(" ");
break;
case 14:
result.Append('(');
result.Append(info.CurrencySymbol);
result.Append(" ");
close = ")";
break;
case 15:
result.Append('(');
close = " " + info.CurrencySymbol + ")";
break;
}
}
else
{
switch (info.CurrencyPositivePattern)
{
case 0:
result.Append(info.CurrencySymbol);
break;
case 1:
close = info.CurrencySymbol;
break;
case 2:
result.Append(info.CurrencySymbol);
result.Append(" ");
break;
case 3:
close = " " + info.CurrencySymbol;
break;
}
}
break;
case 2:
if (value.InternalSign < 0)
{
switch (info.PercentNegativePattern)
{
case 0:
result.Append(info.NegativeSign);
close = " " + info.PercentSymbol;
break;
case 1:
result.Append(info.NegativeSign);
close = info.PercentSymbol;
break;
case 2:
result.Append(info.NegativeSign);
result.Append(info.PercentSymbol);
break;
case 3:
result.Append(info.PercentSymbol);
result.Append(info.NegativeSign);
break;
case 4:
result.Append(info.PercentSymbol);
close = info.NegativeSign;
break;
case 5:
close = info.NegativeSign + info.PercentSymbol;
break;
case 6:
close = info.PercentSymbol + info.NegativeSign;
break;
case 7:
result.Append(info.NegativeSign);
result.Append(info.PercentSymbol);
result.Append(" ");
break;
case 8:
close = " " + info.PercentSymbol + info.NegativeSign;
break;
case 9:
result.Append(info.PercentSymbol);
result.Append(" ");
close = info.NegativeSign;
break;
case 10:
result.Append(info.PercentSymbol);
result.Append(" ");
result.Append(info.NegativeSign);
break;
case 11:
close = info.NegativeSign + " " + info.PercentSymbol;
break;
}
}
else
{
switch (info.CurrencyPositivePattern)
{
case 0:
close = " " + info.PercentSymbol;
break;
case 1:
close = info.PercentSymbol;
break;
case 2:
result.Append(info.PercentSymbol);
break;
case 3:
result.Append(info.PercentSymbol);
result.Append(" ");
break;
}
}
break;
default:
if (value.InternalSign < 0)
{
result.Append(info.NegativeSign);
}
break;
}
return close;
}
private static ReverseStringBuilder StringWithGroups(int capacity, IEnumerable<char> builder, int[] groupingSizes, string groupingSeparator)
{
var newBuffer = new ReverseStringBuilder(capacity);
using (var enumerator = builder.GetEnumerator())
{
if (!enumerator.MoveNext())
{
return newBuffer;
}
foreach (var size in groupingSizes)
{
for (var count = size - 1; count >= 0; count--)
{
newBuffer.Prepend(enumerator.Current);
if (!enumerator.MoveNext())
{
return newBuffer;
}
}
newBuffer.Prepend(groupingSeparator);
}
{
var size = groupingSizes[groupingSizes.Length - 1];
if (size != 0)
{
while (true)
{
for (var count = size - 1; count >= 0; count--)
{
newBuffer.Prepend(enumerator.Current);
if (!enumerator.MoveNext())
{
return newBuffer;
}
}
newBuffer.Prepend(groupingSeparator);
}
}
while (true)
{
newBuffer.Prepend(enumerator.Current);
if (!enumerator.MoveNext())
{
return newBuffer;
}
}
}
}
}
}
}
#endif