add StringBuilder extension methods to allow garbage-free number appends
This commit is contained in:
parent
8831788f14
commit
a7dba64e18
|
@ -134,6 +134,7 @@
|
||||||
<Compile Include="Graphics\BillboardSpriteBatch.cs" />
|
<Compile Include="Graphics\BillboardSpriteBatch.cs" />
|
||||||
<Compile Include="Graphics\Helpers\FlatWireframeGrid.cs" />
|
<Compile Include="Graphics\Helpers\FlatWireframeGrid.cs" />
|
||||||
<Compile Include="Support\FreeMovementCamera.cs" />
|
<Compile Include="Support\FreeMovementCamera.cs" />
|
||||||
|
<Compile Include="Support\StringBuilderExtensions.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
198
Blarg.GameFramework/Support/StringBuilderExtensions.cs
Normal file
198
Blarg.GameFramework/Support/StringBuilderExtensions.cs
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
#region File Description
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// StringBuilderExtensions.cs
|
||||||
|
//
|
||||||
|
// Microsoft XNA Community Game Platform
|
||||||
|
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Using Statements
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace Blarg.GameFramework.Support
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for StringBuilder extension methods.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum AppendNumberOptions
|
||||||
|
{
|
||||||
|
// Normal format.
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
// Added "+" sign for positive value.
|
||||||
|
PositiveSign = 1,
|
||||||
|
|
||||||
|
// Insert Number group separation characters.
|
||||||
|
// In Use, added "," for every 3 digits.
|
||||||
|
NumberGroup = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static class for string builder extension methods.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// You can specified StringBuilder for SpriteFont.DrawString from XNA GS 3.0.
|
||||||
|
/// And you can save unwanted memory allocations.
|
||||||
|
///
|
||||||
|
/// But there are still problems for adding numerical value to StringBuilder.
|
||||||
|
/// One of them is boxing occurred when you use StringBuilder.AppendFormat method.
|
||||||
|
/// Another issue is memory allocation occurred when you specify int or float for
|
||||||
|
/// StringBuild.Append method.
|
||||||
|
///
|
||||||
|
/// This class provides solution for those issue.
|
||||||
|
///
|
||||||
|
/// All methods are defined as extension methods as StringBuilder. So, you can use
|
||||||
|
/// those method like below.
|
||||||
|
///
|
||||||
|
/// stringBuilder.AppendNumber(12345);
|
||||||
|
///
|
||||||
|
/// </remarks>
|
||||||
|
public static class StringBuilderExtensions
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cache for NumberGroupSizes of NumberFormat class.
|
||||||
|
/// </summary>
|
||||||
|
static int[] numberGroupSizes = CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// string conversion buffer.
|
||||||
|
/// </summary>
|
||||||
|
static char[] numberString = new char[32];
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert integer to string and add to string builder.
|
||||||
|
/// </summary>
|
||||||
|
public static StringBuilder AppendNumber(this StringBuilder builder, int number)
|
||||||
|
{
|
||||||
|
return AppendNumberInternal(builder, number, 0, AppendNumberOptions.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert integer to string and add to string builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="options">Format options</param>
|
||||||
|
public static StringBuilder AppendNumber(this StringBuilder builder, int number, AppendNumberOptions options)
|
||||||
|
{
|
||||||
|
return AppendNumberInternal(builder, number, 0, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert float to string and add to string builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>It shows 2 decimal digits.</remarks>
|
||||||
|
public static StringBuilder AppendNumber(this StringBuilder builder, float number)
|
||||||
|
{
|
||||||
|
return AppendNumber(builder, number, 2, AppendNumberOptions.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert float to string and add to string builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>It shows 2 decimal digits.</remarks>
|
||||||
|
public static StringBuilder AppendNumber(this StringBuilder builder, float number, AppendNumberOptions options)
|
||||||
|
{
|
||||||
|
return AppendNumber(builder, number, 2, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert float to string and add to string builder.
|
||||||
|
/// </summary>
|
||||||
|
public static StringBuilder AppendNumber(this StringBuilder builder, float number, int decimalCount, AppendNumberOptions options = AppendNumberOptions.None)
|
||||||
|
{
|
||||||
|
// Handle NaN, Infinity cases.
|
||||||
|
if (float.IsNaN(number))
|
||||||
|
{
|
||||||
|
return builder.Append("NaN");
|
||||||
|
}
|
||||||
|
else if (float.IsNegativeInfinity(number))
|
||||||
|
{
|
||||||
|
return builder.Append("-Infinity");
|
||||||
|
}
|
||||||
|
else if (float.IsPositiveInfinity(number))
|
||||||
|
{
|
||||||
|
return builder.Append("+Infinity");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int intNumber =
|
||||||
|
(int)(number * (float)Math.Pow(10, decimalCount) + 0.5f);
|
||||||
|
|
||||||
|
return AppendNumberInternal(builder, intNumber, decimalCount, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static StringBuilder AppendNumberInternal(StringBuilder builder, int number, int decimalCount, AppendNumberOptions options)
|
||||||
|
{
|
||||||
|
// Initialize variables for conversion.
|
||||||
|
NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
|
||||||
|
|
||||||
|
int idx = numberString.Length;
|
||||||
|
int decimalPos = idx - decimalCount;
|
||||||
|
|
||||||
|
if (decimalPos == idx)
|
||||||
|
decimalPos = idx + 1;
|
||||||
|
|
||||||
|
int numberGroupIdx = 0;
|
||||||
|
int numberGroupCount = numberGroupSizes[numberGroupIdx] + decimalCount;
|
||||||
|
|
||||||
|
bool showNumberGroup = (options & AppendNumberOptions.NumberGroup) != 0;
|
||||||
|
bool showPositiveSign = (options & AppendNumberOptions.PositiveSign) != 0;
|
||||||
|
|
||||||
|
bool isNegative = number < 0;
|
||||||
|
number = Math.Abs(number);
|
||||||
|
|
||||||
|
// Converting from smallest digit.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Add decimal separator ("." in US).
|
||||||
|
if (idx == decimalPos)
|
||||||
|
{
|
||||||
|
numberString[--idx] = nfi.NumberDecimalSeparator[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Added number group separator ("," in US).
|
||||||
|
if (--numberGroupCount < 0 && showNumberGroup)
|
||||||
|
{
|
||||||
|
numberString[--idx] = nfi.NumberGroupSeparator[0];
|
||||||
|
|
||||||
|
if (numberGroupIdx < numberGroupSizes.Length - 1)
|
||||||
|
numberGroupIdx++;
|
||||||
|
|
||||||
|
numberGroupCount = numberGroupSizes[numberGroupIdx] - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert current digit to character and add to buffer.
|
||||||
|
numberString[--idx] = (char)('0' + (number % 10));
|
||||||
|
number /= 10;
|
||||||
|
|
||||||
|
} while (number > 0 || decimalPos <= idx);
|
||||||
|
|
||||||
|
|
||||||
|
// Added sign character if needed.
|
||||||
|
if (isNegative)
|
||||||
|
{
|
||||||
|
numberString[--idx] = nfi.NegativeSign[0];
|
||||||
|
}
|
||||||
|
else if (showPositiveSign)
|
||||||
|
{
|
||||||
|
numberString[--idx] = nfi.PositiveSign[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Added converted string to StringBuilder.
|
||||||
|
return builder.Append(numberString, idx, numberString.Length - idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue